d47b6f49825b12b1767bbb6835f12891869371ba
[utils] / system / general / src / main / java / org / wamblee / system / core / DefaultRequiredInterface.java
1 /*
2  * Copyright 2007 the original author or authors.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package org.wamblee.system.core;
17
18 import org.wamblee.reflection.ReflectionUtils;
19
20 import java.util.Arrays;
21
22
23 /**
24  * DOCUMENT ME!
25  *
26  * @author $author$
27  * @version $Revision$
28  */
29 public class DefaultRequiredInterface implements RequiredInterface {
30     /**
31      * DOCUMENT ME!
32      */
33     private String name;
34
35     /**
36      * DOCUMENT ME!
37      */
38     private boolean optional;
39
40     /**
41      * DOCUMENT ME!
42      */
43     private Class[] required;
44
45     /**
46      * DOCUMENT ME!
47      */
48     private ProvidedInterface provider;
49
50 /**
51      * Creates a new DefaultRequiredInterface object.
52      *
53      * @param aName DOCUMENT ME!
54      * @param aInterface DOCUMENT ME!
55      */
56     public DefaultRequiredInterface(String aName, Class aInterface) {
57         this(aName, new Class[] { aInterface });
58     }
59
60 /**
61      * Creates a new DefaultRequiredInterface object.
62      *
63      * @param aName DOCUMENT ME!
64      * @param aInterfaces DOCUMENT ME!
65      */
66     public DefaultRequiredInterface(String aName, Class[] aInterfaces) {
67         this(aName, aInterfaces, false);
68     }
69
70 /**
71      * Creates a new DefaultRequiredInterface object.
72      *
73      * @param aName DOCUMENT ME!
74      * @param aInterface DOCUMENT ME!
75      * @param aIsOptional DOCUMENT ME!
76      */
77     public DefaultRequiredInterface(String aName, Class aInterface,
78         boolean aIsOptional) {
79         this(aName, new Class[] { aInterface }, aIsOptional);
80     }
81
82 /**
83      * Creates a new DefaultRequiredInterface object.
84      *
85      * @param aName DOCUMENT ME!
86      * @param aInterfaces DOCUMENT ME!
87      * @param aIsOptional DOCUMENT ME!
88      */
89     public DefaultRequiredInterface(String aName, Class[] aInterfaces,
90         boolean aIsOptional) {
91         name         = aName;
92         optional     = aIsOptional;
93         required     = aInterfaces;
94     }
95
96     /**
97      * DOCUMENT ME!
98      *
99      * @return DOCUMENT ME!
100      */
101     @Override
102     public String getName() {
103         return name;
104     }
105
106     /**
107      * DOCUMENT ME!
108      *
109      * @return DOCUMENT ME!
110      */
111     @Override
112     public boolean isOptional() {
113         return optional;
114     }
115
116     /**
117      * DOCUMENT ME!
118      *
119      * @param aDescriptor DOCUMENT ME!
120      *
121      * @return DOCUMENT ME!
122      */
123     @Override
124     public boolean implementedBy(ProvidedInterface aDescriptor) {
125         Class[] provided = aDescriptor.getInterfaceTypes();
126
127         for (Class requiredIntf : required) {
128             if (!serviceProvided(requiredIntf, provided)) {
129                 return false;
130             }
131         }
132
133         // all required interfaces are provided.
134         return true;
135     }
136
137     /**
138      * Check if the required interface is implemented by one of the
139      * provided interfaces.
140      *
141      * @param aRequired required interface
142      * @param aProvided Provided interfaces.
143      *
144      * @return
145      */
146     private boolean serviceProvided(Class aRequired, Class[] aProvided) {
147         for (Class provided : aProvided) {
148             try {
149                 provided      = ReflectionUtils.wrapIfNeeded(provided);
150                 aRequired     = ReflectionUtils.wrapIfNeeded(aRequired);
151                 provided.asSubclass(aRequired);
152
153                 return true;
154             } catch (ClassCastException e) {
155                 // No match, try the next one.
156             }
157         }
158
159         return false;
160     }
161
162     /**
163      * DOCUMENT ME!
164      *
165      * @return DOCUMENT ME!
166      */
167     @Override
168     public ProvidedInterface getProvider() {
169         return provider;
170     }
171
172     /**
173      * DOCUMENT ME!
174      *
175      * @param aProvider DOCUMENT ME!
176      */
177     @Override
178     public void setProvider(ProvidedInterface aProvider) {
179         assert aProvider != null;
180         assert implementedBy(aProvider);
181         provider = aProvider;
182     }
183
184     /**
185      * DOCUMENT ME!
186      *
187      * @param obj DOCUMENT ME!
188      *
189      * @return DOCUMENT ME!
190      */
191     @Override
192     public boolean equals(Object obj) {
193         return this == obj;
194     }
195
196     /**
197      * DOCUMENT ME!
198      *
199      * @param obj DOCUMENT ME!
200      *
201      * @return DOCUMENT ME!
202      */
203     @Override
204     public boolean covers(RequiredInterface obj) {
205         // TODO do more than equals. 
206         if (!(obj instanceof DefaultRequiredInterface)) {
207             return false;
208         }
209
210         DefaultRequiredInterface descr = (DefaultRequiredInterface) obj;
211
212         if (required.length != descr.required.length) {
213             return false;
214         }
215
216         String[] interfaces1 = new String[required.length];
217         String[] interfaces2 = new String[required.length];
218
219         for (int i = 0; i < required.length; i++) {
220             interfaces1[i]     = required[i].getName();
221             interfaces2[i]     = descr.required[i].getName();
222         }
223
224         Arrays.sort(interfaces1);
225         Arrays.sort(interfaces2);
226
227         return Arrays.equals(interfaces1, interfaces2);
228     }
229
230     /**
231      * DOCUMENT ME!
232      *
233      * @return DOCUMENT ME!
234      */
235     @Override
236     public int hashCode() {
237         return required.hashCode();
238     }
239
240     /**
241      * DOCUMENT ME!
242      *
243      * @return DOCUMENT ME!
244      */
245     @Override
246     public String toString() {
247         StringBuffer buf = new StringBuffer();
248         buf.append("." + getName() + ":");
249
250         for (Class intf : required) {
251             buf.append("." + intf.getName());
252         }
253
254         return buf.toString();
255     }
256 }