Package org.apache.tuscany.sca.assembly.builder.impl

Source Code of org.apache.tuscany.sca.assembly.builder.impl.CompositeConfigurationBuilderImpl

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.   
*/

package org.apache.tuscany.sca.assembly.builder.impl;

import java.net.URI;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.xml.namespace.QName;

import org.apache.tuscany.sca.assembly.AssemblyFactory;
import org.apache.tuscany.sca.assembly.Binding;
import org.apache.tuscany.sca.assembly.Component;
import org.apache.tuscany.sca.assembly.ComponentProperty;
import org.apache.tuscany.sca.assembly.ComponentReference;
import org.apache.tuscany.sca.assembly.ComponentService;
import org.apache.tuscany.sca.assembly.Composite;
import org.apache.tuscany.sca.assembly.CompositeService;
import org.apache.tuscany.sca.assembly.Implementation;
import org.apache.tuscany.sca.assembly.Property;
import org.apache.tuscany.sca.assembly.Reference;
import org.apache.tuscany.sca.assembly.SCABinding;
import org.apache.tuscany.sca.assembly.SCABindingFactory;
import org.apache.tuscany.sca.assembly.Service;
import org.apache.tuscany.sca.assembly.builder.ComponentPreProcessor;
import org.apache.tuscany.sca.assembly.builder.CompositeBuilderMonitor;
import org.apache.tuscany.sca.assembly.builder.Problem.Severity;
import org.apache.tuscany.sca.interfacedef.InterfaceContract;
import org.apache.tuscany.sca.interfacedef.InterfaceContractMapper;
import org.apache.tuscany.sca.policy.IntentAttachPointType;
import org.apache.tuscany.sca.policy.IntentAttachPointTypeFactory;
import org.apache.tuscany.sca.policy.PolicySetAttachPoint;

public class CompositeConfigurationBuilderImpl {
    String SCA10_NS = "http://www.osoa.org/xmlns/sca/1.0";
    String BINDING_SCA = "binding.sca";
    QName BINDING_SCA_QNAME = new QName(SCA10_NS, BINDING_SCA);

    private AssemblyFactory assemblyFactory;
    private SCABindingFactory scaBindingFactory;
    private CompositeBuilderMonitor monitor;
    private InterfaceContractMapper interfaceContractMapper;
    private IntentAttachPointTypeFactory  intentAttachPointTypeFactory;
   

    public CompositeConfigurationBuilderImpl(AssemblyFactory assemblyFactory,
                                             SCABindingFactory scaBindingFactory,
                                             IntentAttachPointTypeFactory  intentAttachPointTypeFactory,
                                             InterfaceContractMapper interfaceContractMapper,
                                             CompositeBuilderMonitor monitor) {
        this.assemblyFactory = assemblyFactory;
        this.scaBindingFactory = scaBindingFactory;
        this.intentAttachPointTypeFactory = intentAttachPointTypeFactory;
        this.interfaceContractMapper = interfaceContractMapper;
        this.monitor = monitor;
    }

    /**
     * Configure components in the composite.
     *
     * @param composite
     * @param problems
     */
    public void configureComponents(Composite composite) {
        configureComponents(composite, null);
        configureSourcedProperties(composite, null);
    }

    /**
     * Configure components in the composite.
     *
     * @param composite
     * @param uri
     * @param problems
     */
    private void configureComponents(Composite composite, String uri) {
        String parentURI = uri;

        // Process nested composites recursively
        for (Component component : composite.getComponents()) {

            // Initialize component URI
            String componentURI;
            if (parentURI == null) {
                componentURI = component.getName();
            } else {
                componentURI = URI.create(parentURI + '/').resolve(component.getName()).toString();
            }
            component.setURI(componentURI);

            Implementation implementation = component.getImplementation();
            if (implementation instanceof Composite) {

                // Process nested composite
                configureComponents((Composite)implementation, componentURI);
            }
        }

        // Initialize service bindings
        List<Service> compositeServices = composite.getServices();
        for (Service service : compositeServices) {
            // Set default binding names
           
            // Create default SCA binding
            if (service.getBindings().isEmpty()) {
                SCABinding scaBinding = createSCABinding();
               
               
                service.getBindings().add(scaBinding);
            }

            // Initialize binding names and URIs
            for (Binding binding : service.getBindings()) {
               
                // Binding name defaults to the service name
                if (binding.getName() == null) {
                    binding.setName(service.getName());
                }
               
                String bindingURI;
                if (binding.getURI() == null) {
                    if (compositeServices.size() > 1) {
                        // Binding URI defaults to parent URI / binding name
                        bindingURI = String.valueOf(binding.getName());
                        if (parentURI != null) {
                            bindingURI = URI.create(parentURI + '/').resolve(bindingURI).toString();
                        }
                    } else {
                        // If there's only one service then binding URI defaults
                        // to the parent URI
                        if (parentURI != null) {
                            bindingURI = parentURI;
                        } else {
                            bindingURI = String.valueOf(binding.getName());
                        }
                    }
                } else {
                    // Combine the specified binding URI with the component URI
                    bindingURI = binding.getURI();
                    if (parentURI != null) {
                        bindingURI = URI.create(parentURI + '/').resolve(bindingURI).toString();
                    }
                }

                binding.setURI(bindingURI);
            }
           
            if (service.getCallback() != null) {
                for (Binding binding : service.getCallback().getBindings()) {
                    if (binding.getName() == null) {
                        binding.setName(service.getName());
                    }
                }
            }
        }

        // Initialize reference bindings
        for (Reference reference : composite.getReferences()) {
            // Create default SCA binding
            if (reference.getBindings().isEmpty()) {
                SCABinding scaBinding = createSCABinding();
                reference.getBindings().add(scaBinding);
            }

            // Set binding names
            for (Binding binding : reference.getBindings()) {
                if (binding.getName() == null) {
                    binding.setName(reference.getName());
                }
            }

            if (reference.getCallback() != null) {
                for (Binding binding : reference.getCallback().getBindings()) {
                    if (binding.getName() == null) {
                        binding.setName(reference.getName());
                    }
                }
            }
        }

        // Initialize all component services and references
        Map<String, Component> components = new HashMap<String, Component>();
        for (Component component : composite.getComponents()) {

            // Index all components and check for duplicates
            if (components.containsKey(component.getName())) {
                warning("Duplicate component name: " + composite.getName()
                    + " : "
                    + component.getName(), composite);
            } else {
                components.put(component.getName(), component);
            }

            // Propagate the autowire flag from the composite to components
            if (component.getAutowire() == null) {
                component.setAutowire(composite.getAutowire());
            }

            if (component.getImplementation() instanceof ComponentPreProcessor) {
                ((ComponentPreProcessor)component.getImplementation()).preProcess(component);
            }

            // Index properties, services and references
            Map<String, Service> services = new HashMap<String, Service>();
            Map<String, Reference> references = new HashMap<String, Reference>();
            Map<String, Property> properties = new HashMap<String, Property>();
            indexImplementationPropertiesServicesAndReferences(component,
                                                               services,
                                                               references,
                                                               properties);

            // Index component services, references and properties
            // Also check for duplicates
            Map<String, ComponentService> componentServices =
                new HashMap<String, ComponentService>();
            Map<String, ComponentReference> componentReferences =
                new HashMap<String, ComponentReference>();
            Map<String, ComponentProperty> componentProperties =
                new HashMap<String, ComponentProperty>();
            indexComponentPropertiesServicesAndReferences(component,
                                                          componentServices,
                                                          componentReferences,
                                                          componentProperties);

            // Reconcile component services/references/properties and
            // implementation services/references and create component
            // services/references/properties for the services/references
            // declared by the implementation
            reconcileServices(component, services, componentServices);
            reconcileReferences(component, references, componentReferences);
            reconcileProperties(component, properties, componentProperties);

            // Configure or create callback services for component's references
            // with callbacks
            configureCallbackServices(component, componentServices);

            // Configure or create callback references for component's services
            // with callbacks
            configureCallbackReferences(component, componentReferences);

            // Create self references to the component's services
//            if (!(component.getImplementation() instanceof Composite)) {
//                createSelfReferences(component);
//            }

            // Initialize service bindings
            for (ComponentService componentService : component.getServices()) {

                // Create default SCA binding
                if (componentService.getBindings().isEmpty()) {
                    SCABinding scaBinding = createSCABinding();
                    componentService.getBindings().add(scaBinding);
                }

                // Set binding names and URIs
                for (Binding binding : componentService.getBindings()) {
                   
                    // Binding name defaults to the service name
                    if (binding.getName() == null) {
                        binding.setName(componentService.getName());
                    }

                    String bindingURI;
                    if (binding.getURI() == null) {
                        //if (componentServices.size() > 1) {
                        if (component.getServices().size() > 1) {
                            // Binding URI defaults to component URI / binding name
                            bindingURI = String.valueOf(binding.getName());
                            bindingURI = URI.create(component.getURI() + '/').resolve(bindingURI).toString();
                        } else {
                            // If there's only one service then binding URI defaults
                            // to the component URI
                            bindingURI = component.getURI();
                        }
                    } else {
                        // Combine the specified binding URI with the component URI
                        bindingURI = binding.getURI();
                        bindingURI = URI.create(component.getURI() + '/').resolve(bindingURI).toString();
                    }
                   
                    binding.setURI(bindingURI);
                }
                if (componentService.getCallback() != null) {
                    for (Binding binding : componentService.getCallback().getBindings()) {
                        if (binding.getName() == null) {
                            binding.setName(componentService.getName());
                        }
                    }
                }
            }

            // Initialize reference bindings
            for (ComponentReference componentReference : component.getReferences()) {

                // Create default SCA binding
                if (componentReference.getBindings().isEmpty()) {
                    SCABinding scaBinding = createSCABinding();
                    componentReference.getBindings().add(scaBinding);
                }

                // Set binding names
                for (Binding binding : componentReference.getBindings()) {
                    if (binding.getName() == null) {
                        binding.setName(componentReference.getName());
                    }
                }
                if (componentReference.getCallback() != null) {
                    for (Binding binding : componentReference.getCallback().getBindings()) {
                        if (binding.getName() == null) {
                            binding.setName(componentReference.getName());
                        }
                    }
                }
            }
        }
    }

    /**
     * Report a warning.
     *
     * @param problems
     * @param message
     * @param model
     */
    private void warning(String message, Object model) {
        monitor.problem(new ProblemImpl(Severity.WARNING, message, model));
    }

    /**
     * Reconcile component properties and the properties defined by the
     * component type.
     *
     * @param component
     * @param properties
     * @param componentProperties
     * @param problems
     */
    private void reconcileProperties(Component component,
                                     Map<String, Property> properties,
                                     Map<String, ComponentProperty> componentProperties) {

        // Connect component properties to their properties
        for (ComponentProperty componentProperty : component.getProperties()) {
            Property property = properties.get(componentProperty.getName());
            if (property != null) {
                componentProperty.setProperty(property);
            } else {
                warning("Property not found for component property: " + component.getName()
                    + "/"
                    + componentProperty.getName(), component);
            }
        }

        // Create component properties for all properties
        if (component.getImplementation() != null) {
            for (Property property : component.getImplementation().getProperties()) {
                if (!componentProperties.containsKey(property.getName())) {
                    ComponentProperty componentProperty = assemblyFactory.createComponentProperty();
                    componentProperty.setName(property.getName());
                    componentProperty.setMany(property.isMany());
                    componentProperty.setXSDElement(property.getXSDElement());
                    componentProperty.setXSDType(property.getXSDType());
                    componentProperty.setProperty(property);
                    component.getProperties().add(componentProperty);
                }
            }
        }

        // Reconcile component properties and their properties
        for (ComponentProperty componentProperty : component.getProperties()) {
            Property property = componentProperty.getProperty();
            if (property != null) {

                // Check that a component property does not override the
                // mustSupply attribute
                if (!property.isMustSupply() && componentProperty.isMustSupply()) {
                    warning("Component property mustSupply attribute incompatible with property: " + component
                                .getName()
                                + "/"
                                + componentProperty.getName(),
                            component);
                }

                // Default to the mustSupply attribute specified on the property
                if (!componentProperty.isMustSupply())
                    componentProperty.setMustSupply(property.isMustSupply());

                // Default to the value specified on the property
                if (componentProperty.getValue() == null) {
                    componentProperty.setValue(property.getValue());
                }
               
                // Override the property value for the composite
                if(component.getImplementation() instanceof Composite) {
                    property.setValue(componentProperty.getValue());
                }

                // Check that a value is supplied
                if (componentProperty.getValue() == null && property.isMustSupply()) {
                    warning("No value configured on a mustSupply property: " + component.getName()
                        + "/"
                        + componentProperty.getName(), component);
                }

                // Check that a a component property does not override the
                // many attribute
                if (!property.isMany() && componentProperty.isMany()) {
                    warning("Component property many attribute incompatible with property: " + component
                                .getName()
                                + "/"
                                + componentProperty.getName(),
                            component);
                }

                // Default to the many attribute defined on the property
                componentProperty.setMany(property.isMany());

                // Default to the type and element defined on the property
                if (componentProperty.getXSDType() == null) {
                    componentProperty.setXSDType(property.getXSDType());
                }
                if (componentProperty.getXSDElement() == null) {
                    componentProperty.setXSDElement(property.getXSDElement());
                }

                // Check that a type or element are specified
                if (componentProperty.getXSDElement() == null && componentProperty.getXSDType() == null) {
                    warning("No type specified on component property: " + component.getName()
                        + "/"
                        + componentProperty.getName(), component);
                }
            }
        }
    }

    /**
     * Reconcile component references with the references defined on the
     * component type.
     *
     * @param component
     * @param references
     * @param componentReferences
     * @param problems
     */
    private void reconcileReferences(Component component,
                                     Map<String, Reference> references,
                                     Map<String, ComponentReference> componentReferences) {

        // Connect each component reference to the corresponding reference
        for (ComponentReference componentReference : component.getReferences()) {
            Reference reference = references.get(componentReference.getName());
            if (reference != null) {
                componentReference.setReference(reference);
            } else {
                if (!componentReference.getName().startsWith("$self$.")) {
                    warning("Reference not found for component reference: " + component.getName()
                        + "/"
                        + componentReference.getName(), component);
                }
            }
        }

        // Create a component reference for each reference
        if (component.getImplementation() != null) {
            for (Reference reference : component.getImplementation().getReferences()) {
                if (!componentReferences.containsKey(reference.getName())) {
                    ComponentReference componentReference =
                        assemblyFactory.createComponentReference();
                    componentReference.setIsCallback(reference.isCallback());
                    componentReference.setName(reference.getName());
                    componentReference.setReference(reference);
                    component.getReferences().add(componentReference);
                }
            }
        }

        // Reconcile each component reference with its reference
        for (ComponentReference componentReference : component.getReferences()) {
            Reference reference = componentReference.getReference();
            if (reference != null) {
                // Reconcile multiplicity
                if (componentReference.getMultiplicity() != null) {
                    if (!ReferenceUtil.isValidMultiplicityOverride(reference.getMultiplicity(),
                                                                   componentReference
                                                                       .getMultiplicity())) {
                        warning("Component reference multiplicity incompatible with reference multiplicity: " + component
                                    .getName()
                                    + "/"
                                    + componentReference.getName(),
                                component);
                    }
                } else {
                    componentReference.setMultiplicity(reference.getMultiplicity());
                }

                // Reconcile interface
                if (componentReference.getInterfaceContract() != null) {
                    if (!componentReference.getInterfaceContract().equals(reference
                        .getInterfaceContract())) {
                        if (!interfaceContractMapper.isCompatible(reference.getInterfaceContract(),
                                                                  componentReference
                                                                      .getInterfaceContract())) {
                            warning("Component reference interface incompatible with reference interface: " + component
                                        .getName()
                                        + "/"
                                        + componentReference.getName(),
                                    component);
                        }
                    }
                } else {
                    componentReference.setInterfaceContract(reference.getInterfaceContract());
                }

                // Reconcile bindings
                if (componentReference.getBindings().isEmpty()) {
                    componentReference.getBindings().addAll(reference.getBindings());
                }
               
                // Reconcile callback bindings
                if (componentReference.getCallback() == null) {
                    componentReference.setCallback(reference.getCallback());
                    if (componentReference.getCallback() == null) {
                        // Create an empty callback to avoid null check
                        componentReference.setCallback(assemblyFactory.createCallback());
                    }

                } else if (componentReference.getCallback().getBindings().isEmpty() && reference
                    .getCallback() != null) {
                    componentReference.getCallback().getBindings().addAll(reference.getCallback()
                        .getBindings());
                }
               
                // Propagate autowire setting from the component
                if (componentReference.getAutowire() == null) {
                    componentReference.setAutowire(component.getAutowire());
                }

                // Reconcile targets
                if (componentReference.getTargets().isEmpty()) {
                    componentReference.getTargets().addAll(reference.getTargets());
                }
            }
        }
    }

    /**
     * Reconcile component services and services defined on the component type.
     *
     * @param component
     * @param services
     * @param componentServices
     * @param problems
     */
    private void reconcileServices(Component component,
                                   Map<String, Service> services,
                                   Map<String, ComponentService> componentServices) {

        // Connect each component service to the corresponding service
        for (ComponentService componentService : component.getServices()) {
            Service service = services.get(componentService.getName());
            if (service != null) {
                componentService.setService(service);
            } else {
                warning("Service not found for component service: " + component.getName()
                    + "/"
                    + componentService.getName(), component);
            }
        }

        // Create a component service for each service
        if (component.getImplementation() != null) {
            for (Service service : component.getImplementation().getServices()) {
                if (!componentServices.containsKey(service.getName())) {
                    ComponentService componentService = assemblyFactory.createComponentService();
                    componentService.setIsCallback(service.isCallback());
                    String name = service.getName();
                    componentService.setName(name);
                    componentService.setService(service);
                    component.getServices().add(componentService);
                    componentServices.put(name, componentService);
                }
            }
        }

        //Reconcile each component service with its service
        for (ComponentService componentService : component.getServices()) {
            Service service = componentService.getService();
            if (service != null) {
                // Reconcile interface
                if (componentService.getInterfaceContract() != null) {
                    if (!componentService.getInterfaceContract().equals(service
                        .getInterfaceContract())) {
                        if (!interfaceContractMapper.isCompatible(componentService
                            .getInterfaceContract(), service.getInterfaceContract())) {
                            warning("Component service interface incompatible with service interface: " + component
                                        .getName()
                                        + "/"
                                        + componentService.getName(),
                                    component);
                        }
                    }
                } else {
                    componentService.setInterfaceContract(service.getInterfaceContract());
                }

                // Reconcile bindings
                if (componentService.getBindings().isEmpty()) {
                    componentService.getBindings().addAll(service.getBindings());
                }
               
                // Reconcile callback bindings
                if (componentService.getCallback() == null) {
                    componentService.setCallback(service.getCallback());
                    if (componentService.getCallback() == null) {
                        // Create an empty callback to avoid null check
                        componentService.setCallback(assemblyFactory.createCallback());
                    }
                } else if (componentService.getCallback().getBindings().isEmpty() && service
                    .getCallback() != null) {
                    componentService.getCallback().getBindings().addAll(service.getCallback()
                        .getBindings());
                }
            }
        }
    }

    private void indexComponentPropertiesServicesAndReferences(Component component,
                                                               Map<String, ComponentService> componentServices,
                                                               Map<String, ComponentReference> componentReferences,
                                                               Map<String, ComponentProperty> componentProperties) {
        for (ComponentService componentService : component.getServices()) {
            if (componentServices.containsKey(componentService.getName())) {
                warning("Duplicate component service name: " + component.getName()
                    + "/"
                    + componentService.getName(), component);
            } else {
                componentServices.put(componentService.getName(), componentService);
            }
        }
        for (ComponentReference componentReference : component.getReferences()) {
            if (componentReferences.containsKey(componentReference.getName())) {
                warning("Duplicate component reference name: " + component.getName()
                    + "/"
                    + componentReference.getName(), component);
            } else {
                componentReferences.put(componentReference.getName(), componentReference);
            }
        }
        for (ComponentProperty componentProperty : component.getProperties()) {
            if (componentProperties.containsKey(componentProperty.getName())) {
                warning("Duplicate component property name: " + component.getName()
                    + "/"
                    + componentProperty.getName(), component);
            } else {
                componentProperties.put(componentProperty.getName(), componentProperty);
            }
        }

    }

    private void indexImplementationPropertiesServicesAndReferences(Component component,
                                                                    Map<String, Service> services,
                                                                    Map<String, Reference> references,
                                                                    Map<String, Property> properties) {
        // First check that the component has a resolved implementation
        Implementation implementation = component.getImplementation();
        if (implementation == null) {

            // A component must have an implementation
            warning("No implementation for component: " + component.getName(), component);

        } else if (implementation.isUnresolved()) {

            // The implementation must be fully resolved
            warning("Component implementation not found: " + component.getName()
                + " : "
                + implementation.getURI(), component);

        } else {

            // Index properties, services and references, also check for
            // duplicates
            for (Property property : implementation.getProperties()) {
                if (properties.containsKey(property.getName())) {
                    warning("Duplicate property name: " + component.getName()
                        + "/"
                        + property.getName(), component);
                } else {
                    properties.put(property.getName(), property);
                }
            }
            for (Service service : implementation.getServices()) {
                if (services.containsKey(service.getName())) {
                    warning("Duplicate service name: " + component.getName()
                        + "/"
                        + service.getName(), component);
                } else {
                    services.put(service.getName(), service);
                }
            }
            for (Reference reference : implementation.getReferences()) {
                if (references.containsKey(reference.getName())) {
                    warning("Duplicate reference name: " + component.getName()
                        + "/"
                        + reference.getName(), component);
                } else {
                    references.put(reference.getName(), reference);
                }
            }
        }

    }

    /**
     * For all the references with callbacks, create a corresponding callback
     * service.
     *
     * @param component
     */
    private void configureCallbackServices(Component component,
                                           Map<String, ComponentService> componentServices) {
        for (ComponentReference reference : component.getReferences()) {
            if (reference.getInterfaceContract() != null && // can be null in
                                                            // unit tests
            reference.getInterfaceContract().getCallbackInterface() != null) {
                ComponentService service =
                    componentServices.get(reference.getName());
                if (service == null) {
                    service = createCallbackService(component, reference);
                }
                if (reference.getCallback() != null) {
                    if (service.getBindings().isEmpty()) {
                        service.getBindings().addAll(reference.getCallback().getBindings());
                    }
                }
                reference.setCallbackService(service);
            }
        }
    }

    /**
     * Create a callback service for a component reference
     *
     * @param component
     * @param reference
     */
    private ComponentService createCallbackService(Component component, ComponentReference reference) {
        ComponentService componentService = assemblyFactory.createComponentService();
        componentService.setIsCallback(true);
        componentService.setName(reference.getName());
        try {
            InterfaceContract contract =
                (InterfaceContract)reference.getInterfaceContract().clone();
            contract.setInterface(contract.getCallbackInterface());
            contract.setCallbackInterface(null);
            componentService.setInterfaceContract(contract);
        } catch (CloneNotSupportedException e) {
            // will not happen
        }
        Reference implReference = reference.getReference();
        if (implReference != null) {
            Service implService = assemblyFactory.createService();
            implService.setName(implReference.getName());
            try {
                InterfaceContract implContract =
                    (InterfaceContract)implReference.getInterfaceContract().clone();
                implContract.setInterface(implContract.getCallbackInterface());
                implContract.setCallbackInterface(null);
                implService.setInterfaceContract(implContract);
            } catch (CloneNotSupportedException e) {
                // will not happen
            }
            componentService.setService(implService);
        }
        component.getServices().add(componentService);
        return componentService;
    }

    /**
     * For all the services with callbacks, create a corresponding callback
     * reference.
     *
     * @param component
     */
    private void configureCallbackReferences(Component component,
                                             Map<String, ComponentReference> componentReferences) {
        for (ComponentService service : component.getServices()) {
            if (service.getInterfaceContract() != null && // can be null in
                                                            // unit tests
            service.getInterfaceContract().getCallbackInterface() != null) {
                ComponentReference reference =
                    componentReferences.get(service.getName());
                if (reference == null) {
                    reference = createCallbackReference(component, service);
                }
                if (service.getCallback() != null) {
                    if (reference.getBindings().isEmpty()) {
                        reference.getBindings().addAll(service.getCallback().getBindings());
                    }
                }
                service.setCallbackReference(reference);
            }
        }
    }

    /**
     * Create a callback reference for a component service
     *
     * @param component
     * @param service
     */
    private ComponentReference createCallbackReference(Component component, ComponentService service) {
        ComponentReference componentReference = assemblyFactory.createComponentReference();
        componentReference.setIsCallback(true);
        componentReference.setName(service.getName());
        try {
            InterfaceContract contract = (InterfaceContract)service.getInterfaceContract().clone();
            contract.setInterface(contract.getCallbackInterface());
            contract.setCallbackInterface(null);
            componentReference.setInterfaceContract(contract);
        } catch (CloneNotSupportedException e) {
            // will not happen
        }
        Service implService = service.getService();
        if (implService != null) {
            Reference implReference = assemblyFactory.createReference();
            implReference.setName(implService.getName());
            try {
                InterfaceContract implContract =
                    (InterfaceContract)implService.getInterfaceContract().clone();
                implContract.setInterface(implContract.getCallbackInterface());
                implContract.setCallbackInterface(null);
                implReference.setInterfaceContract(implContract);
            } catch (CloneNotSupportedException e) {
                // will not happen
            }
            componentReference.setReference(implReference);
        }
        component.getReferences().add(componentReference);
        return componentReference;
    }

    /**
     * Activate composite services in nested composites.
     *
     * @param composite
     * @param problems
     */
    public void activateCompositeServices(Composite composite) {

        // Process nested composites recursively
        activateNestedCompositeServices(composite);

        // Process top level composite services
        for (Service service : composite.getServices()) {
            CompositeService compositeService = (CompositeService)service;

            // Get the inner most promoted service
            ComponentService promotedService = getPromotedComponentService(compositeService);
            if (promotedService != null) {
                Component promotedComponent = getPromotedComponent(compositeService);

                // Default to use the interface from the promoted service
                if (compositeService.getInterfaceContract() == null && promotedService.getInterfaceContract() != null) {
                    compositeService.setInterfaceContract(promotedService.getInterfaceContract());
                }

                // Create a new component service to represent this composite
                // service on the promoted component
                ComponentService newComponentService = assemblyFactory.createComponentService();
                newComponentService.setName("$promoted$." + compositeService.getName());
                promotedComponent.getServices().add(newComponentService);
                newComponentService.setService(promotedService.getService());
                newComponentService.getBindings().addAll(compositeService.getBindings());
                newComponentService.setInterfaceContract(compositeService.getInterfaceContract());
                if (compositeService.getInterfaceContract() != null && compositeService
                    .getInterfaceContract().getCallbackInterface() != null) {
                    newComponentService.setCallback(assemblyFactory.createCallback());
                    if (compositeService.getCallback() != null) {
                        newComponentService.getCallback().getBindings().addAll(compositeService
                            .getCallback().getBindings());
                    }
                }

                // Change the composite service to now promote the newly
                // created component service directly
                compositeService.setPromotedComponent(promotedComponent);
                compositeService.setPromotedService(newComponentService);
            }
        }
    }

    /**
     * Activate composite services in nested composites.
     *
     * @param composite
     * @param problems
     */
    public void activateNestedCompositeServices(Composite composite) {

        // Process nested composites recursively
        for (Component component : composite.getComponents()) {
            Implementation implementation = component.getImplementation();
            if (implementation instanceof Composite) {

                // First process nested composites
                activateNestedCompositeServices((Composite)implementation);

                // Process the component services declared on components
                // in this composite
                for (ComponentService componentService : component.getServices()) {
                    Service implService = componentService.getService();
                    if (implService != null && implService instanceof CompositeService) {
                        CompositeService compositeService = (CompositeService)implService;

                        // Get the inner most promoted service
                        ComponentService promotedService =
                            getPromotedComponentService(compositeService);
                        if (promotedService != null) {
                            Component promotedComponent = getPromotedComponent(compositeService);

                            // Default to use the interface from the promoted
                            // service
                            if (compositeService.getInterfaceContract() == null) {
                                compositeService.setInterfaceContract(promotedService
                                    .getInterfaceContract());
                            }
                            if (componentService.getInterfaceContract() == null) {
                                componentService.setInterfaceContract(promotedService
                                    .getInterfaceContract());
                            }

                            // Create a new component service to represent this
                            // composite service on the promoted component
                            ComponentService newComponentService =
                                assemblyFactory.createComponentService();
                            newComponentService.setName("$promoted$." + compositeService.getName());
                            promotedComponent.getServices().add(newComponentService);
                            newComponentService.setService(promotedService.getService());
                            newComponentService.getBindings()
                                .addAll(compositeService.getBindings());
                            newComponentService.setInterfaceContract(compositeService
                                .getInterfaceContract());
                            if (compositeService.getInterfaceContract() != null && compositeService
                                .getInterfaceContract().getCallbackInterface() != null) {
                                newComponentService.setCallback(assemblyFactory.createCallback());
                                if (compositeService.getCallback() != null) {
                                    newComponentService.getCallback().getBindings()
                                        .addAll(compositeService.getCallback().getBindings());
                                }
                            }

                            // Change the composite service to now promote the
                            // newly created component service directly
                            compositeService.setPromotedComponent(promotedComponent);
                            compositeService.setPromotedService(newComponentService);
                        }
                    }
                }
            }
        }
    }

    /**
     * @param composite
     */
    private void configureSourcedProperties(Composite composite, List<ComponentProperty> propertySettings) {
        // Resolve properties
        Map<String, Property> compositeProperties = new HashMap<String, Property>();
        ComponentProperty componentProperty = null;
        for (Property p : composite.getProperties()) {
            componentProperty = getComponentPropertyByName(p.getName(), propertySettings);
            if (componentProperty != null) {
                compositeProperties.put(p.getName(), componentProperty);
            } else {
                compositeProperties.put(p.getName(), p);
            }
        }
   
        for (Component component : composite.getComponents()) {
            try {
                PropertyUtil.sourceComponentProperties(compositeProperties, component);
            } catch (Exception e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            Implementation impl = component.getImplementation();
            if (impl instanceof Composite) {
                configureSourcedProperties((Composite)impl, component.getProperties());
            }
        }
    }

    /**
     * Follow a service promotion chain down to the inner most (non composite)
     * component service.
     *
     * @param topCompositeService
     * @return
     */
    static 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;
        }
    }

    /**
     * Follow a service promotion chain down to the inner most (non composite)
     * component.
     *
     * @param compositeService
     * @return
     */
    static Component getPromotedComponent(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 getPromotedComponent((CompositeService)service);

            } else {

                // Found a non-composite service
                return compositeService.getPromotedComponent();
            }
        } else {

            // No promoted service
            return null;
        }
    }

    private ComponentProperty getComponentPropertyByName(String propertyName, List<ComponentProperty> properties) {
        if (properties != null) {
            for (ComponentProperty aProperty : properties) {
                if (aProperty.getName().equals(propertyName)) {
                    return aProperty;
                }
            }
        }
        return null;
    }
   
    private SCABinding createSCABinding() {
        SCABinding scaBinding = scaBindingFactory.createSCABinding();
        IntentAttachPointType bindingType = intentAttachPointTypeFactory.createBindingType();
        bindingType.setName(BINDING_SCA_QNAME);
        bindingType.setUnresolved(true);
        ((PolicySetAttachPoint)scaBinding).setType(bindingType);
       
        return scaBinding;
    }
   

}
TOP

Related Classes of org.apache.tuscany.sca.assembly.builder.impl.CompositeConfigurationBuilderImpl

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.