+ private String name;
+
+ private boolean optional;
+
+ private Class[] required;
+
+ private ProvidedInterface provider;
+
+ /**
+ * Creates a new DefaultRequiredInterface object.
+ *
+ */
+ public DefaultRequiredInterface(String aName, Class aInterface) {
+ this(aName, new Class[] { aInterface });
+ }
+
+ /**
+ * Creates a new DefaultRequiredInterface object.
+ *
+ */
+ public DefaultRequiredInterface(String aName, Class[] aInterfaces) {
+ this(aName, aInterfaces, false);
+ }
+
+ /**
+ * Creates a new DefaultRequiredInterface object.
+ *
+ */
+ public DefaultRequiredInterface(String aName, Class aInterface,
+ boolean aIsOptional) {
+ this(aName, new Class[] { aInterface }, aIsOptional);
+ }
+
+ /**
+ * Creates a new DefaultRequiredInterface object.
+ *
+ */
+ public DefaultRequiredInterface(String aName, Class[] aInterfaces,
+ boolean aIsOptional) {
+ name = aName;
+ optional = aIsOptional;
+ required = aInterfaces;
+ }
+
+ @Override
+ public String getName() {
+ return name;
+ }
+
+ @Override
+ public boolean isOptional() {
+ return optional;
+ }
+
+ @Override
+ public boolean implementedBy(ProvidedInterface aDescriptor) {
+ Class[] provided = aDescriptor.getInterfaceTypes();
+
+ for (Class requiredIntf : required) {
+ if (!serviceProvided(requiredIntf, provided)) {
+ return false;
+ }
+ }
+
+ // all required interfaces are provided.
+ return true;
+ }
+
+ /**
+ * Check if the required interface is implemented by one of the provided
+ * interfaces.
+ *
+ * @param aRequired
+ * required interface
+ * @param aProvided
+ * Provided interfaces.
+ *
+ * @return
+ */
+ private boolean serviceProvided(Class aRequired, Class[] aProvided) {
+ for (Class provided : aProvided) {
+ try {
+ provided = ReflectionUtils.wrapIfNeeded(provided);
+ aRequired = ReflectionUtils.wrapIfNeeded(aRequired);
+ provided.asSubclass(aRequired);
+
+ return true;
+ } catch (ClassCastException e) {
+ // No match, try the next one.
+ }
+ }
+
+ return false;
+ }
+
+ @Override
+ public ProvidedInterface getProvider() {
+ return provider;
+ }
+
+ @Override
+ public void setProvider(ProvidedInterface aProvider) {
+ assert aProvider != null;
+ assert implementedBy(aProvider);
+ provider = aProvider;
+ }
+
+ @Override
+ public boolean equals(Object aObject) {
+ return this == aObject;
+ }
+
+ @Override
+ public boolean covers(RequiredInterface aObject) {
+ // TODO do more than equals.
+ if (!(aObject instanceof DefaultRequiredInterface)) {
+ return false;
+ }
+
+ DefaultRequiredInterface descr = (DefaultRequiredInterface) aObject;
+
+ if (required.length != descr.required.length) {
+ return false;
+ }
+
+ String[] interfaces1 = new String[required.length];
+ String[] interfaces2 = new String[required.length];
+
+ for (int i = 0; i < required.length; i++) {
+ interfaces1[i] = required[i].getName();
+ interfaces2[i] = descr.required[i].getName();
+ }
+
+ Arrays.sort(interfaces1);
+ Arrays.sort(interfaces2);
+
+ return Arrays.equals(interfaces1, interfaces2);
+ }
+
+ @Override
+ public int hashCode() {
+ return Arrays.hashCode(required);
+ }
+
+ @Override
+ public String toString() {
+ StringBuffer buf = new StringBuffer();
+ buf.append("." + getName() + ":");
+
+ for (Class intf : required) {
+ buf.append("." + intf.getName());
+ }