/**
   * Follow a service promotion chain down to the inner most (non composite) component service.
   *
   * @param topCompositeService
   * @return
   */
  private ComponentService getPromotedComponentService(CompositeService compositeService) {
    ComponentService componentService = compositeService.getPromotedService();
    if (componentService != null) {
      Service service = componentService.getService();
      if (componentService.getName() != null && service instanceof CompositeService) {

        // Continue to follow the service promotion chain
        return getPromotedComponentService((CompositeService) service);

      } else {

        // Found a non-composite service
        return componentService;
      }
    } else {

      // No promoted service
      return null;
    }
  }
  void start() {
    List<JavaElementImpl> callbackInjectionList = null;

    // If the component implementation is stateless, we need to inject the callbacks on service
    // invocation
    // rather than doing it once at the component level.
    if (scope.equals(JavaScopeImpl.STATELESS)) {
      callbackInjectionList = instanceFactoryProvider.getCallbackInjectionSites();
    } else {
      callbackInjectionList = instanceFactoryProvider.getInjectionSites();
    }

    if (!instanceFactoryProvider.getImplementation().getCallbackMembers().isEmpty()) {
      Map<String, List<EndpointReference>> callbackWires =
          new HashMap<String, List<EndpointReference>>();
      for (ComponentService service : component.getServices()) {

        RuntimeComponentReference callbackReference =
            (RuntimeComponentReference) service.getCallbackReference();
        if (callbackReference != null) {
          List<EndpointReference> wires = callbackReference.getEndpointReferences();
          if (!wires.isEmpty()) {
            RuntimeEndpointReference epr = (RuntimeEndpointReference) wires.get(0);
            callbackWires.put(
                epr.getComponentTypeReferenceInterfaceContract().getInterface().toString(), wires);
          }
        }
      }

      for (Map.Entry<String, Collection<JavaElementImpl>> entry :
          instanceFactoryProvider.getImplementation().getCallbackMembers().entrySet()) {
        List<EndpointReference> wires = callbackWires.get(entry.getKey());
        if (wires == null) {
          // this can happen when there are no client wires to a
          // component that has a callback
          continue;
        }
        for (JavaElementImpl element : entry.getValue()) {
          Class<?> businessInterface = element.getType();
          ObjectFactory<?> factory = null;
          if (ServiceReference.class.isAssignableFrom(element.getType())) {
            businessInterface =
                JavaIntrospectionHelper.getBusinessInterface(
                    element.getType(), element.getGenericType());
            factory = new CallbackReferenceObjectFactory(businessInterface, proxyFactory, wires);
          } else {
            factory = new CallbackWireObjectFactory(businessInterface, proxyFactory, wires);
          }
          if (!(element.getAnchor() instanceof Constructor)) {
            callbackInjectionList.add(element);
          }
          instanceFactoryProvider.setObjectFactory(element, factory);
        }
      }
    }
    for (Reference ref : instanceFactoryProvider.getImplementation().getReferences()) {
      JavaElementImpl element =
          instanceFactoryProvider.getImplementation().getReferenceMembers().get(ref.getName());
      if (element != null) {
        if (!(element.getAnchor() instanceof Constructor)) {
          if (element.getElementType() == ElementType.FIELD) {
            Field field = (Field) element.getAnchor();
            if (Modifier.isPublic(field.getModifiers())) {
              instanceFactoryProvider.getInjectionSites().add(element);
            } else if (field.getAnnotation(org.oasisopen.sca.annotation.Reference.class) != null) {
              instanceFactoryProvider.getInjectionSites().add(element);
            }
          } else {
            instanceFactoryProvider.getInjectionSites().add(element);
          }
        }
        ComponentReference componentReference = null;
        List<EndpointReference> wireList = null;
        for (ComponentReference reference : component.getReferences()) {
          if (reference.getName().equals(ref.getName())) {
            wireList = ((RuntimeComponentReference) reference).getEndpointReferences();
            componentReference = reference;
            break;
          }
        }
        if (ref.getMultiplicity() == Multiplicity.ONE_N
            || ref.getMultiplicity() == Multiplicity.ZERO_N) {
          List<ObjectFactory<?>> factories = new ArrayList<ObjectFactory<?>>();
          Class<?> baseType =
              JavaIntrospectionHelper.getBaseType(element.getType(), element.getGenericType());
          for (int i = 0; i < wireList.size(); i++) {
            ObjectFactory<?> factory = null;
            if (ServiceReference.class.isAssignableFrom(baseType)) {
              Type callableRefType =
                  JavaIntrospectionHelper.getParameterType(element.getGenericType());
              // Type businessType = JavaIntrospectionHelper.getParameterType(callableRefType);
              Class<?> businessInterface =
                  JavaIntrospectionHelper.getBusinessInterface(baseType, callableRefType);
              factory =
                  new CallableReferenceObjectFactory(
                      businessInterface, (RuntimeEndpointReference) wireList.get(i));
            } else {
              factory = createObjectFactory(baseType, wireList.get(i));
            }
            factories.add(factory);
          }
          instanceFactoryProvider.setObjectFactories(element, factories);
          JavaConstructorImpl<?> constructor =
              instanceFactoryProvider.getImplementation().getConstructor();
          for (JavaElementImpl p : constructor.getParameters()) {
            if (element.getName().equals(p.getName())) {
              instanceFactoryProvider.setObjectFactories(p, factories);
            }
          }
        } else {
          if (wireList == null && ref.getMultiplicity() == Multiplicity.ONE_ONE) {
            throw new IllegalStateException("Required reference is missing: " + ref.getName());
          }
          if (wireList != null && !wireList.isEmpty()) {
            ObjectFactory<?> factory = null;
            if (ServiceReference.class.isAssignableFrom(element.getType())) {
              Class<?> businessInterface =
                  JavaIntrospectionHelper.getBusinessInterface(
                      element.getType(), element.getGenericType());
              factory =
                  new CallableReferenceObjectFactory(
                      businessInterface, (RuntimeEndpointReference) wireList.get(0));
            } else {
              factory = createObjectFactory(element.getType(), wireList.get(0));
            }
            instanceFactoryProvider.setObjectFactory(element, factory);
            JavaConstructorImpl<?> constructor =
                instanceFactoryProvider.getImplementation().getConstructor();
            for (JavaElementImpl p : constructor.getParameters()) {
              if (element.getName().equals(p.getName())) {
                instanceFactoryProvider.setObjectFactory(p, factory);
              }
            }
          }
        }
      }
    }

    // setUpPolicyHandlers();
    this.instanceFactory = instanceFactoryProvider.createFactory();
  }