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.ArrayList;
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.Base;
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.CompositeReference;
import org.apache.tuscany.sca.assembly.CompositeService;
import org.apache.tuscany.sca.assembly.Implementation;
import org.apache.tuscany.sca.assembly.Multiplicity;
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.Intent;
import org.apache.tuscany.sca.policy.IntentAttachPoint;
import org.apache.tuscany.sca.policy.IntentAttachPointType;
import org.apache.tuscany.sca.policy.PolicySet;
import org.apache.tuscany.sca.policy.PolicySetAttachPoint;
import org.apache.tuscany.sca.policy.QualifiedIntent;

public class CompositeConfigurationBuilderImpl {

    private String CALLBACK_PREFIX = "$callback$.";

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

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

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

    /**
     * Configure components in the composite.
     *
     * @param composite
     * @param uri
     * @param problems
     */
    private void configureComponents(Composite composite, String uri) {
        URI parentURI;
        if (uri != null) {
            parentURI = URI.create(uri + '/');
        } else {
            parentURI = null;
        }

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

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

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

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

        List<Intent> compositeIntents = null;
        List<PolicySet> compositePolicySets = null;
        if (composite instanceof PolicySetAttachPoint) {
            compositeIntents = ((PolicySetAttachPoint)composite).getRequiredIntents();
            compositePolicySets = ((PolicySetAttachPoint)composite).getPolicySets();
        }

        // Initialize service bindings
        for (Service service : composite.getServices()) {
            // Set default binding names and inherit intents and policysets
            // defined at composite level
            addInheritedIntents(compositeIntents, service.getRequiredIntents());
            addInheritedPolicySets(compositePolicySets, service.getPolicySets(), false);
           
            //inherit intents and policies from promoted service
            if ( service instanceof CompositeService ) {
                CompositeService compService = (CompositeService)service;
                addInheritedIntents(compService.getPromotedService().getRequiredIntents(),
                                     service.getRequiredIntents());
                addInheritedPolicySets(compService.getPromotedService().getPolicySets(),
                                     service.getPolicySets(), true);
            }
           

            // Create default SCA binding
            if (service.getBindings().isEmpty()) {
                SCABinding scaBinding = scaBindingFactory.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) {
                   
                    // Binding URI defaults to the binding name
                    bindingURI = String.valueOf(binding.getName());
                } else {
                    bindingURI = binding.getURI();
                }
               
                // Combine with the parent URI
                if (parentURI != null) {
                    bindingURI = parentURI.resolve(bindingURI).toString();
                }
                binding.setURI(bindingURI);
            }
           
            if (service.getCallback() != null) {
                addInheritedIntents(service.getRequiredIntents(),
                                    service.getCallback().getRequiredIntents());
                addInheritedPolicySets(service.getPolicySets(),
                                       service.getCallback().getPolicySets(),
                                       false);
                for (Binding binding : service.getCallback().getBindings()) {
                    if (binding.getName() == null) {
                        binding.setName(service.getName());
                    }
                }
            }
            computeIntents(service.getBindings(), service.getRequiredIntents());
            computePolicySets(service, service.getBindings(), service.getPolicySets());
           
            if ( service.getCallback() != null ) {
                computeIntents(service.getCallback().getBindings(),
                               service.getCallback().getRequiredIntents());
                computePolicySets(service,
                                  service.getCallback().getBindings(),
                                  service.getCallback().getPolicySets());
            }
        }

        // Initialize reference bindings
        for (Reference reference : composite.getReferences()) {
            addInheritedIntents(compositeIntents, reference.getRequiredIntents());
            addInheritedPolicySets(compositePolicySets, reference.getPolicySets(), false);

            //inherit intents and policies from promoted service
            if ( reference instanceof CompositeReference ) {
                CompositeReference compReference = (CompositeReference)reference;
                for ( Reference promotedReference : compReference.getPromotedReferences() ) {
                    addInheritedIntents(promotedReference.getRequiredIntents(),
                                         reference.getRequiredIntents());
               
                    addInheritedPolicySets(promotedReference.getPolicySets(),
                                         reference.getPolicySets(), true);
                }
            }
           
            // Create default SCA binding
            if (reference.getBindings().isEmpty()) {
                SCABinding scaBinding = scaBindingFactory.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());
                    }
                }
            }
           
            computeIntents(reference.getBindings(), reference.getRequiredIntents());
            computePolicySets(reference, reference.getBindings(), reference.getPolicySets());
           
            if ( reference.getCallback() != null ) {
                computeIntents(reference.getCallback().getBindings(),
                               reference.getCallback().getRequiredIntents());
                computePolicySets(reference,
                                  reference.getCallback().getBindings(),
                                  reference.getCallback().getPolicySets());
            }
        }

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

            // 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 (composite.isAutowire()) {
                component.setAutowire(true);
            }

            // Inherit intents defined at the composite level
            addInheritedIntents(compositeIntents, component.getRequiredIntents());
           
            // Inherit policysets defined at the composite level
            addInheritedPolicySets(compositePolicySets, component.getPolicySets(), false);

            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 = scaBindingFactory.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) {
                            // Binding URI defaults component URI / binding name
                            bindingURI = String.valueOf(binding.getName());
                            bindingURI = componentURI.resolve(bindingURI).toString();
                        } else {
                            // If there's only one service then binding URI defaults
                            // to the component URI
                            bindingURI = componentURI.toString();
                        }
                    } else {
                        // Combine the specified binding URI with the component URI
                        bindingURI = binding.getURI();
                        bindingURI = componentURI.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 = scaBindingFactory.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(CALLBACK_PREFIX + 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());
                }

                // 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()) {
            // inherit intents and policysets from component
            addInheritedIntents(component.getRequiredIntents(), componentReference.getRequiredIntents());
            addInheritedPolicySets(component.getPolicySets(), componentReference.getPolicySets(), false);

            Reference reference = componentReference.getReference();
            if (reference != null) {
                // reconcile intents and policysets
                addInheritedIntents(reference.getRequiredIntents(), componentReference.getRequiredIntents());
                addInheritedPolicySets(reference.getPolicySets(), componentReference.getPolicySets(), true);

                // 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 (component.isAutowire()) {
                    componentReference.setAutowire(true);
                }

                // Reconcile targets
                if (componentReference.getTargets().isEmpty()) {
                    componentReference.getTargets().addAll(reference.getTargets());
                }
            }
           
            //compute intents and policyset for each binding
            computeIntents(componentReference.getBindings(),
                           componentReference.getRequiredIntents());
            computePolicySets(componentReference,
                              componentReference.getBindings(),
                              componentReference.getPolicySets());
           
            if ( componentReference.getCallback() != null ) {
                //compute intents and policyset for each callback binding
                computeIntents(componentReference.getCallback().getBindings(),
                               componentReference.getRequiredIntents());
                computePolicySets(componentReference,
                                  componentReference.getCallback().getBindings(),
                                  componentReference.getPolicySets());
               

            }
           
        }
    }

    /**
     * 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()) {
            // inherit intents and policysets from component
            addInheritedIntents(component.getRequiredIntents(), componentService.getRequiredIntents());
            addInheritedPolicySets(component.getPolicySets(), componentService.getPolicySets(), false);

            Service service = componentService.getService();
            if (service != null) {
                // reconcile intents and policysets
                addInheritedIntents(service.getRequiredIntents(), componentService.getRequiredIntents());
                addInheritedPolicySets(service.getPolicySets(),
                                       componentService.getPolicySets(),
                                       true);
                // 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());
                }
            }
            //compute intents and policyset for each binding
            computeIntents(componentService.getBindings(),
                           componentService.getRequiredIntents());
            computePolicySets(componentService,
                              componentService.getBindings(),
                              componentService.getPolicySets());
           
            if ( componentService.getCallback() != null ) {
                //compute intents and policyset for each binding
                computeIntents(componentService.getCallback().getBindings(),
                               componentService.getRequiredIntents());
                computePolicySets(componentService,
                                  componentService.getCallback().getBindings(),
                                  componentService.getPolicySets());
            }
        }
    }

    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(CALLBACK_PREFIX + reference.getName());
                if (service == null) {
                    service = createCallbackService(component, reference);
                }
                if (reference.getCallback() != null) {
                    if (service.getBindings().isEmpty()) {
                        service.getBindings().addAll(reference.getCallback().getBindings());
                    }
                    if (service.getPolicySets().isEmpty()) {
                        service.getPolicySets().addAll(reference.getCallback().getPolicySets());
                    }
                    if (service.getRequiredIntents().isEmpty()) {
                        service.getRequiredIntents().addAll(reference.getCallback()
                            .getRequiredIntents());
                    }
                }
                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(CALLBACK_PREFIX + 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(CALLBACK_PREFIX + 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(CALLBACK_PREFIX + service.getName());
                if (reference == null) {
                    reference = createCallbackReference(component, service);
                }
                if (service.getCallback() != null) {
                    if (reference.getBindings().isEmpty()) {
                        reference.getBindings().addAll(service.getCallback().getBindings());
                    }
                    if (reference.getPolicySets().isEmpty()) {
                        reference.getPolicySets().addAll(service.getCallback().getPolicySets());
                    }
                    if (reference.getRequiredIntents().isEmpty()) {
                        reference.getRequiredIntents().addAll(service.getCallback()
                            .getRequiredIntents());
                    }
                }
                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(CALLBACK_PREFIX + 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(CALLBACK_PREFIX + 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;
    }

    /**
     * Create a self-reference for a component service
     *
     * @param component
     * @param service
     */
    private ComponentReference createSelfReference(Component component, ComponentService service) {
        ComponentReference componentReference = assemblyFactory.createComponentReference();
        componentReference.setName("$self$." + service.getName());
        componentReference.getBindings().addAll(service.getBindings());
        componentReference.setCallback(service.getCallback());
        ComponentService componentService = assemblyFactory.createComponentService();
        componentService.setName(component.getName() + '/' + service.getName());
        componentService.setUnresolved(true);
        componentReference.getTargets().add(componentService);
        componentReference.getPolicySets().addAll(service.getPolicySets());
        componentReference.getRequiredIntents().addAll(service.getRequiredIntents());

        // FIXME: What interface contract should be used?
        InterfaceContract interfaceContract = service.getInterfaceContract();
        Service componentTypeService = service.getService();
        if (componentTypeService != null && componentTypeService.getInterfaceContract() != null) {
            interfaceContract = componentTypeService.getInterfaceContract();
        }
        componentReference.setInterfaceContract(interfaceContract);
        componentReference.setMultiplicity(Multiplicity.ONE_ONE);
        component.getReferences().add(componentReference);
        return componentReference;
    }

    /**
     * For all the services, create a corresponding self-reference.
     *
     * @param component
     */
    private void createSelfReferences(Component component) {
        for (ComponentService service : component.getServices()) {
            if (!service.isCallback()) {
                createSelfReference(component, service);
            }
        }
    }

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

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

                // First process nested composites
                activateCompositeServices((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());
                                }
                            }

                            // Create a self-reference for the promoted service
                            ComponentReference selfReference =
                                createSelfReference(promotedComponent, newComponentService);
                            Binding binding =
                                BindingUtil.resolveBindings(selfReference,
                                                            promotedComponent,
                                                            newComponentService);
                            selfReference.getBindings().clear();
                            selfReference.getBindings().add(binding);
                            selfReference.getTargets().clear();

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

        // Process composite services declared in this composite
        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);
            }
        }
    }

    /**
     * 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;
        }
    }

    /**
     * Follow a service promotion chain down to the inner most (non composite)
     * component.
     *
     * @param compositeService
     * @return
     */
    private 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 void computeIntents(List<Binding> bindings, List<Intent> inheritedIntents) {
        boolean found = false;

        for (Binding binding : bindings) {
            if (binding instanceof IntentAttachPoint) {
                IntentAttachPoint policiedBinding = (IntentAttachPoint)binding;
                IntentAttachPointType bindingType = policiedBinding.getType();

                // validate intents specified for the binding
                for (Intent intent : policiedBinding.getRequiredIntents()) {
                    for (QName constrained : intent.getConstrains()) {
                        if (bindingType.getName().getNamespaceURI().equals(constrained
                            .getNamespaceURI()) && bindingType.getName().getLocalPart()
                            .startsWith(constrained.getLocalPart())) {
                            found = true;
                            break;
                        }
                    }

                    if (!found) {
                        warning("Policy Intent '" + intent.getName()
                            + "' does not constrain binding type  "
                            + bindingType, binding);
                    }
                }

                for (Intent intent : inheritedIntents) {
                    for (QName constrained : intent.getConstrains()) {
                        if (bindingType.getName().getNamespaceURI().equals(constrained
                            .getNamespaceURI()) && bindingType.getName().getLocalPart()
                            .startsWith(constrained.getLocalPart())) {
                            policiedBinding.getRequiredIntents().add(intent);
                            break;
                        }
                    }
                }
               
                Map<QName, Intent> intentsTable = new HashMap<QName, Intent>();
                //remove duplicates
                for ( Intent intent : policiedBinding.getRequiredIntents() ) {
                    intentsTable.put(intent.getName(), intent);
                }
               
                //if qualified form of intent exists remove the unqualified form
                for ( Intent intent : intentsTable.values() ) {
                    if ( intent instanceof QualifiedIntent ) {
                        QualifiedIntent qualifiedIntent = (QualifiedIntent)intent;
                        if ( intentsTable.get(qualifiedIntent.getQualifiableIntent().getName()) != null ) {
                            intentsTable.remove(qualifiedIntent.getQualifiableIntent().getName());
                        }
                    }
                }
                policiedBinding.getRequiredIntents().clear();
                policiedBinding.getRequiredIntents().addAll(intentsTable.values());
            }
        }
    }

    private void computePolicySets(Base parent,
                                   List<Binding> bindings,
                                   List<PolicySet> inheritedPolicySets) {
        String appliesTo = null;
        HashMap<QName, PolicySet> policySetTable = new HashMap<QName, PolicySet>();
       
        for (Binding binding : bindings) {
            if (binding instanceof PolicySetAttachPoint) {
                PolicySetAttachPoint policiedBinding = (PolicySetAttachPoint)binding;
                IntentAttachPointType bindingType = policiedBinding.getType();

                //validate policysets specified for the binding
                for (PolicySet policySet : policiedBinding.getPolicySets()) {
                    appliesTo = policySet.getAppliesTo();

                    if (!isPolicySetApplicable(parent, appliesTo, bindingType)) {
                        warning("Policy Set '" + policySet.getName()
                            + "' does not apply to binding type  "
                            + bindingType, binding);

                    }
                }
               
                for (PolicySet policySet : inheritedPolicySets) {
                    appliesTo = policySet.getAppliesTo();
                    if (isPolicySetApplicable(parent, appliesTo, bindingType)) {
                        policiedBinding.getPolicySets().add(policySet);
                    }
                }
               
                //get rid of duplicate entries
                for ( PolicySet policySet : policiedBinding.getPolicySets() ) {
                    policySetTable.put(policySet.getName(), policySet);
                }
                policiedBinding.getPolicySets().clear();
                policiedBinding.getPolicySets().addAll(policySetTable.values());
            }
        }
    }

    private boolean isPolicySetApplicable(Base parent,
                                          String xpath,
                                          IntentAttachPointType bindingType) {
        //create a xml node out of the parent object.. i.e. write the parent object as scdl fragment
        //invoke PropertyUtil.evaluate(null, node, xpath)
        //verify the result Node's QName against the bindingType's name
       
        if (parent instanceof ComponentReference) {
        } else if (parent instanceof ComponentReference) {
        } else if (parent instanceof Component) {
        } else if (parent instanceof CompositeService) {
        } else if (parent instanceof CompositeReference) {

        }
        return true;
    }

    private void addInheritedIntents(List<Intent> sourceList, List<Intent> targetList) {
        if (sourceList != null) {
            targetList.addAll(sourceList);
        }
    }
   
    private  void addInheritedPolicySets(List<PolicySet> sourceList, List<PolicySet> targetList, boolean checkOverrides) {
        //check overrides is true when policysets are to be copied from componentType to component level
        if ( checkOverrides ) {
            //aggregate all the provided intents present in the target
            List<Intent> targetProvidedIntents = new ArrayList<Intent>();
            for ( PolicySet policySet : targetList ) {
                targetProvidedIntents.addAll(policySet.getProvidedIntents());
            }
           
            //for every policy set in the source check if it provides one of the intents that is
            //already provided by the policysets in the destination and do not copy them.
            for ( PolicySet policySet : sourceList ) {
                for ( Intent sourceProvidedIntent : policySet.getProvidedIntents() ) {
                    if ( !targetProvidedIntents.contains(sourceProvidedIntent) ) {
                        targetList.add(policySet);
                    }
                }
            }
        } else {
            targetList.addAll(sourceList);
        }
    }
}
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.