All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.tuscany.sca.builder.impl.WireBuilderImpl Maven / Gradle / Ivy

The newest version!
/*
 * 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.builder.impl;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

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.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.Endpoint;
import org.apache.tuscany.sca.assembly.EndpointReference;
import org.apache.tuscany.sca.assembly.Implementation;
import org.apache.tuscany.sca.assembly.Multiplicity;
import org.apache.tuscany.sca.assembly.Reference;
import org.apache.tuscany.sca.assembly.SCABinding;
import org.apache.tuscany.sca.assembly.Wire;
import org.apache.tuscany.sca.assembly.builder.BuilderContext;
import org.apache.tuscany.sca.assembly.builder.CompositeBuilderException;
import org.apache.tuscany.sca.assembly.builder.Messages;
import org.apache.tuscany.sca.core.ExtensionPointRegistry;
import org.apache.tuscany.sca.core.FactoryExtensionPoint;
import org.apache.tuscany.sca.core.UtilityExtensionPoint;
import org.apache.tuscany.sca.interfacedef.InterfaceContractMapper;
import org.apache.tuscany.sca.monitor.Monitor;
import org.apache.tuscany.sca.policy.Intent;
import org.oasisopen.sca.ServiceRuntimeException;

/**
 * Creates endpoint reference models.
 */
public class WireBuilderImpl {

    private AssemblyFactory assemblyFactory;
    private InterfaceContractMapper interfaceContractMapper;

    public WireBuilderImpl(ExtensionPointRegistry registry) {
        UtilityExtensionPoint utilities = registry.getExtensionPoint(UtilityExtensionPoint.class);
        interfaceContractMapper = utilities.getUtility(InterfaceContractMapper.class);

        FactoryExtensionPoint modelFactories = registry.getExtensionPoint(FactoryExtensionPoint.class);
        assemblyFactory = modelFactories.getFactory(AssemblyFactory.class);
    }

    /**
     * Create endpoint references for all component references.
     *
     * @param composite
     */
    public Composite build(Composite composite, BuilderContext context)
        throws CompositeBuilderException {
        Monitor monitor = context.getMonitor();

        // process component references
        processComponentReferences(composite, monitor);
        
        // validate component references
        validateComponentReferences(composite, monitor);
        
        return composite;
    }

    private void processComponentReferences(Composite composite, Monitor monitor) {

        monitor.pushContext("Composite: " + composite.getName().toString());
        try {
            // Index components, services and references
            Map components = new HashMap();
            Map componentServices = new HashMap();
            Map componentReferences = new HashMap();
            indexComponentsServicesAndReferences(composite, components, componentServices, componentReferences);

            // Connect component references as described in wires
            connectWires(composite, componentServices, componentReferences, monitor);

            // create endpoint references for each component's references
            for (Component component : composite.getComponents()) {
                monitor.pushContext("Component: " + component.getName());

                try {

                    // recurse for composite implementations
                    Implementation implementation = component.getImplementation();
                    if (implementation instanceof Composite) {
                        processComponentReferences((Composite)implementation, monitor);
                    }

                    // create endpoint references to represent the component reference
                    for (ComponentReference reference : component.getReferences()) {
                        createReferenceEndpointReferences(composite,
                                                          component,
                                                          reference,
                                                          components,
                                                          componentServices,
                                                          monitor);

                        // fix up links between endpoints and endpoint references that represent callbacks
                        for (ComponentService service : component.getServices()) {
                            if ((service.getInterfaceContract() != null) && (service.getInterfaceContract()
                                .getCallbackInterface() != null)) {
                                if (reference.getName().equals(service.getName())) {
                                    for (Endpoint endpoint : service.getEndpoints()) {
                                        endpoint.getCallbackEndpointReferences().addAll(reference
                                            .getEndpointReferences());
                                    }
                                    break;
                                } // end if
                            } // end if
                        } // end for
                        
                        // push down endpoint references into the leaf component references
                        // in the case where this component reference promotes a reference from
                        // a composite implementation
                        pushDownEndpointReferences(composite,
                                                   component,
                                                   reference,
                                                   monitor);
                        
                    } // end for

                    // Validate that references are wired or promoted, according
                    // to their multiplicity. This validates as we go and catches cases
                    // where a reference has been configured directly incorrectly with its
                    // immediate multiplicity setting. We re-run this validation again later
                    // to catch to more complex cases where reference promotion causes 
                    // multiplicity errors. 
                    validateReferenceMultiplicity(composite, component, monitor);

                } finally {
                    monitor.popContext();
                }
            } // end for

        } finally {
            monitor.popContext();
        }

    } // end method processCompoenntReferences
    
    
    /**
     * The validate stage is separate from the process stage as enpoint references are
     * pushed down the hierarchy. We don't know the full set of endpoint references until
     * all processing is complete. Hence we can't validate as we go
     * 
     * @param composite
     * @param monitor
     */
    private void validateComponentReferences(Composite composite, Monitor monitor) {

        monitor.pushContext("Composite: " + composite.getName().toString());
        try {
            // create endpoint references for each component's references
            for (Component component : composite.getComponents()) {
                monitor.pushContext("Component: " + component.getName());

                try {

                    // recurse for composite implementations
                    Implementation implementation = component.getImplementation();
                    if (implementation instanceof Composite) {
                        validateComponentReferences((Composite)implementation, monitor);
                    }
                    // Validate that references are wired or promoted, according
                    // to their multiplicity   
                    validateReferenceMultiplicity(composite, component, monitor);

                } finally {
                    monitor.popContext();
                }
            }
            
        } finally {
            monitor.popContext();
        }

    }        

    protected void indexComponentsServicesAndReferences(Composite composite,
                                                        Map components,
                                                        Map componentServices,
                                                        Map componentReferences) {

        for (Component component : composite.getComponents()) {

            // Index components by name
            components.put(component.getName(), component);

            ComponentService nonCallbackService = null;
            int nonCallbackServices = 0;
            for (ComponentService componentService : component.getServices()) {

                // Index component services by component name / service name
                String uri = component.getName() + '/' + componentService.getName();
                componentServices.put(uri, componentService);

                // count how many non-callback services there are
                // if there is only one the component name also acts as the
                // service name
                if (!componentService.isForCallback()) {
                    // Check how many non callback non-promoted services we have
                    if (nonCallbackServices == 0) {
                        nonCallbackService = componentService;
                    }
                    nonCallbackServices++;
                }
            }

            if (nonCallbackServices == 1) {
                // If we have a single non callback service, index it by
                // component name as well
                componentServices.put(component.getName(), nonCallbackService);
            }

            // Index references by component name / reference name
            for (ComponentReference componentReference : component.getReferences()) {
                String uri = component.getName() + '/' + componentReference.getName();
                componentReferences.put(uri, componentReference);
            }
        }
    }

    /**
     * Resolve wires and connect the sources to their targets
     * 
     * @param composite
     * @param componentServices
     * @param componentReferences
     * @param problems
     */
    private void connectWires(Composite composite,
                              Map componentServices,
                              Map componentReferences,
                              Monitor monitor) {

        // For each wire, resolve the source reference, the target service, and
        // add it to the list of targets of the reference
        List wires = composite.getWires();
        for (int i = 0, n = wires.size(); i < n; i++) {
            Wire wire = wires.get(i);

            ComponentReference resolvedReference;
            ComponentService resolvedService;

            // Resolve the source reference
            ComponentReference source = wire.getSource();
            if (source != null && source.isUnresolved()) {
                resolvedReference = componentReferences.get(source.getName());
                if (resolvedReference != null) {
                    wire.setSource(resolvedReference);
                } else {
                    Monitor.warning(monitor, this, Messages.ASSEMBLY_VALIDATION, "WireSourceNotFound", source
                        .getName());
                }
            } else {
                resolvedReference = wire.getSource();
            }

            // Resolve the target service
            ComponentService target = wire.getTarget();
            if (target != null && target.isUnresolved()) {
                resolvedService = componentServices.get(target.getName());
                if (resolvedService != null) {
                    wire.setTarget(target);
                } else {
                    Monitor.warning(monitor, this, Messages.ASSEMBLY_VALIDATION, "WireTargetNotFound", target
                        .getName());
                }
            } else {
                resolvedService = wire.getTarget();
            }

            // Add the target service to the list of targets of the
            // reference
            if (resolvedReference != null && resolvedService != null) {
                // Check that the target component service provides
                // a superset of
                // the component reference interface
                if (resolvedReference.getInterfaceContract() == null || interfaceContractMapper
                    .isCompatibleSubset(resolvedReference.getInterfaceContract(), resolvedService.getInterfaceContract())) {

                    //resolvedReference.getTargets().add(resolvedService);
                    if (wire.isReplace()) {
                        resolvedReference.getTargets().clear();
                    }
                    resolvedReference.getTargets().add(wire.getTarget());
                } else {
                    Monitor.warning(monitor, this, Messages.ASSEMBLY_VALIDATION, "WireIncompatibleInterface", source
                        .getName(), target.getName());
                }
            }
        }

        // Clear the list of wires
        composite.getWires().clear();
    }

    private void createReferenceEndpointReferences(Composite composite,
                                                   Component component,
                                                   ComponentReference reference,
                                                   Map components,
                                                   Map componentServices,
                                                   Monitor monitor) {

        monitor.pushContext("Reference: " + reference.getName());

        // Get reference targets
        List refTargets = getReferenceTargets(reference);
        if (Boolean.TRUE.equals(reference.getAutowire()) && reference.getTargets().isEmpty()) {

            // Find suitable targets in the current composite for an
            // autowired reference
            Multiplicity multiplicity = reference.getMultiplicity();
            for (Component targetComponent : composite.getComponents()) {

                // Tuscany specific selection of the first autowire reference
                // when there are more than one (ASM_60025)
                if ((multiplicity == Multiplicity.ZERO_ONE || multiplicity == Multiplicity.ONE_ONE) && (reference
                    .getEndpointReferences().size() != 0)) {
                    break;
                }

                // Prevent autowire connecting to self
                if (targetComponent == component)
                    continue;

                for (ComponentService targetComponentService : targetComponent.getServices()) {
                    if (reference.getInterfaceContract() == null || interfaceContractMapper.isCompatibleSubset(reference
                        .getInterfaceContract(), targetComponentService.getInterfaceContract())) {
                        
                        if (intentsMatch(reference.getRequiredIntents(), targetComponentService.getRequiredIntents())) {
                            EndpointReference endpointRef = createEndpointRef(component, reference, false);
                            endpointRef.setTargetEndpoint(createEndpoint(targetComponent, targetComponentService, true));
                            endpointRef.setStatus(EndpointReference.Status.WIRED_TARGET_FOUND_READY_FOR_MATCHING);
                            reference.getEndpointReferences().add(endpointRef);

                            // Stop with the first match for 0..1 and 1..1 references
                            if (multiplicity == Multiplicity.ZERO_ONE || multiplicity == Multiplicity.ONE_ONE) {
                                break;
                            } // end if
                        }

                    } // end if
                } // end for
            } // end for

            if (multiplicity == Multiplicity.ONE_N || multiplicity == Multiplicity.ONE_ONE) {
                if (reference.getEndpointReferences().size() == 0) {
                    Monitor.error(monitor,
                                  this,
                                  Messages.ASSEMBLY_VALIDATION,
                                  "NoComponentReferenceTarget",
                                  reference.getName());
                }
            }

            setSingleAutoWireTarget(reference);

        } else if (!refTargets.isEmpty()) {
            // Check that the component reference does not mix the use of endpoint references
            // specified via the target attribute with the presence of binding elements
            if (bindingsIdentifyTargets(reference)) {
                Monitor.error(monitor,
                              this,
                              Messages.ASSEMBLY_VALIDATION,
                              "ReferenceEndPointMixWithTarget",
                              composite.getName().toString(),
                              component.getName(),
                              reference.getName());
            }

            // Resolve targets specified on the component reference
            for (ComponentService target : refTargets) {

                String targetName = getComponentServiceName(target.getName());
                String bindingName = getBindingName(target.getName());
                ComponentService targetComponentService = componentServices.get(targetName);

                Component targetComponent = getComponentFromTargetName(components, targetName);

                if (targetComponentService != null) {
                    // Check that target component service provides a superset of the component reference interface
                    if (reference.getInterfaceContract() == null || interfaceContractMapper.isCompatibleSubset(reference
                        .getInterfaceContract(), targetComponentService.getInterfaceContract())) {

                        if (bindingName != null) {
                            // the user has selected a binding as part of the target name
                            Binding targetBinding = null;

                            for (Binding tmp : targetComponentService.getBindings()) {
                                if (tmp.getName().equals(bindingName)) {
                                    targetBinding = tmp;
                                    continue;
                                }
                            }

                            if (targetBinding != null) {
                                EndpointReference endpointRef = createEndpointRef(component, reference, false);
                                endpointRef.setTargetEndpoint(createEndpoint(targetComponent,
                                                                             targetComponentService,
                                                                             targetBinding,
                                                                             true));
                                endpointRef.setStatus(EndpointReference.Status.WIRED_TARGET_FOUND_AND_MATCHED);
                                // relying on the registry here to resolve the real endpoint
                                reference.getEndpointReferences().add(endpointRef);

                            } else {
                                EndpointReference endpointRef = createEndpointRef(component, reference, true);
                                endpointRef.setTargetEndpoint(createEndpoint(component, targetName));
                                endpointRef.setStatus(EndpointReference.Status.WIRED_TARGET_NOT_FOUND);
                                reference.getEndpointReferences().add(endpointRef);
                                Monitor.warning(monitor,
                                                this,
                                                Messages.ASSEMBLY_VALIDATION,
                                                "ComponentReferenceTargetNotFound",
                                                composite.getName().toString(),
                                                targetName);
                            }

                        } else {
                            // the user hasn't selected a binding as part of the target name

                            EndpointReference endpointRef = createEndpointRef(component, reference, false);
                            endpointRef
                                .setTargetEndpoint(createEndpoint(targetComponent, targetComponentService, true));
                            endpointRef.setStatus(EndpointReference.Status.WIRED_TARGET_FOUND_READY_FOR_MATCHING);
                            reference.getEndpointReferences().add(endpointRef);
                        }
                    } else {
                        Monitor.error(monitor,
                                      this,
                                      Messages.ASSEMBLY_VALIDATION,
                                      "ReferenceIncompatibleInterface",
                                      composite.getName().toString(),
                                      component.getName() + "." + reference.getName(),
                                      targetName);
                    }
                } else {
                    // add an unresolved endpoint reference with an unresolved endpoint to go with it
                    EndpointReference endpointRef = createEndpointRef(component, reference, true);
                    endpointRef.setTargetEndpoint(createEndpoint(component, targetName));
                    endpointRef.setStatus(EndpointReference.Status.WIRED_TARGET_NOT_FOUND);
                    reference.getEndpointReferences().add(endpointRef);
                    Monitor.warning(monitor,
                                    this,
                                    Messages.ASSEMBLY_VALIDATION,
                                    "ComponentReferenceTargetNotFound",
                                    composite.getName().toString(),
                                    targetName);
                } // end if
            } // end for
        } // end if

        // if no endpoints have found so far the bindings hold the targets.
        if (reference.getEndpointReferences().isEmpty()) {
            for (Binding binding : reference.getBindings()) {

                String uri = binding.getURI();

                // user hasn't put a uri on the binding so it's not a target name and the assumption is that
                // the target is established via configuration of the binding element itself
                if (uri == null) {
                    // Regular forward references are UNWIRED with no endpoint if they have an SCABinding with NO targets
                    // and NO URI set - but Callbacks with an SCABinding are wired and need an endpoint
                    if (!reference.isForCallback() && (binding instanceof SCABinding))
                        continue;

                    // create endpoint reference for manually configured bindings with a resolved endpoint to
                    // signify that this reference is pointing at some unwired endpoint
                    EndpointReference endpointRef = createEndpointRef(component, reference, binding, null, false);
                    if (binding instanceof SCABinding) {
                        // Assume that the system needs to resolve this binding later as
                        // it's the SCA binding
                        endpointRef.setTargetEndpoint(createEndpoint(true));
                        endpointRef.setStatus(EndpointReference.Status.NOT_CONFIGURED);
                    } else {
                        // The user has configured a binding so assume they know what 
                        // they are doing and mark in as already resolved. 
                        endpointRef.setTargetEndpoint(createEndpoint(false));
                        endpointRef.setStatus(EndpointReference.Status.RESOLVED_BINDING);
                    }
                    reference.getEndpointReferences().add(endpointRef);
                    continue;
                } // end if

                // user might have put a local target name in the uri - see if it refers to a target we know about
                // - if it does the reference binding will be matched with a service binding
                // - if it doesn't it is assumed to be an external reference
                if (uri.startsWith("/")) {
                    uri = uri.substring(1);
                }

                String targetName = getComponentServiceName(uri);
                String bindingName = getBindingName(uri);

                // Resolve the target component and service
                ComponentService targetComponentService = componentServices.get(targetName);
                Component targetComponent = getComponentFromTargetName(components, targetName);

                // If the binding URI matches a component in the composite, configure an endpoint reference with
                // this component as the target.
                // If not, the binding URI is assumed to reference an external service
                if (targetComponentService != null) {

                    // Check that the target component service provides
                    // a superset of the component reference interface
                    if (reference.getInterfaceContract() == null || interfaceContractMapper.isCompatibleSubset(reference
                        .getInterfaceContract(), targetComponentService.getInterfaceContract())) {
                        if (bindingName != null) {
                            // the user has selected a binding as part of the target name
                            Binding targetBinding = null;

                            for (Binding tmp : targetComponentService.getBindings()) {
                                if (tmp.getName().equals(bindingName)) {
                                    targetBinding = tmp;
                                    continue;
                                }
                            }

                            if (targetBinding != null) {
                                EndpointReference endpointRef = createEndpointRef(component, reference, false);
                                endpointRef.setTargetEndpoint(createEndpoint(targetComponent,
                                                                             targetComponentService,
                                                                             targetBinding,
                                                                             true));
                                endpointRef.setStatus(EndpointReference.Status.WIRED_TARGET_NOT_FOUND);
                                // relying on the registry here to resolve the real endpoint
                                reference.getEndpointReferences().add(endpointRef);

                            } else {
                                EndpointReference endpointRef = createEndpointRef(component, reference, true);
                                endpointRef.setTargetEndpoint(createEndpoint(component, targetName));
                                endpointRef.setStatus(EndpointReference.Status.WIRED_TARGET_NOT_FOUND);
                                reference.getEndpointReferences().add(endpointRef);
                                Monitor.warning(monitor,
                                                this,
                                                Messages.ASSEMBLY_VALIDATION,
                                                "ComponentReferenceTargetNotFound",
                                                composite.getName().toString(),
                                                targetName);
                            }

                        } else {
                            // create endpoint reference with dummy endpoint which will be replaced when policies
                            // are matched and bindings are configured later
                            EndpointReference endpointRef =
                                createEndpointRef(component, reference, binding, null, false);
                            endpointRef
                                .setTargetEndpoint(createEndpoint(targetComponent, targetComponentService, true));
                            endpointRef.setStatus(EndpointReference.Status.WIRED_TARGET_FOUND_READY_FOR_MATCHING);
                            reference.getEndpointReferences().add(endpointRef);
                        }
                    } else {
                        Monitor.warning(monitor,
                                        this,
                                        Messages.ASSEMBLY_VALIDATION,
                                        "ReferenceIncompatibleInterface",
                                        composite.getName().toString(),
                                        reference.getName(),
                                        uri);
                    }
                } else {
                    // create endpoint reference for manually configured bindings with resolved endpoint
                    // to signify that this reference is pointing at some unwired endpoint. The endpoint
                    // is given the configured binding as a representation of the endpoint configuration. 
                    EndpointReference endpointRef = createEndpointRef(component, reference, binding, null, false);
                    Endpoint endpoint = createEndpoint(false);
                    endpoint.setBinding(binding);
                    endpointRef.setTargetEndpoint(endpoint);
                    endpointRef.setStatus(EndpointReference.Status.RESOLVED_BINDING);
                    reference.getEndpointReferences().add(endpointRef);
                } // end if
            }
        }

        monitor.popContext();

    } // end method
    
    private boolean intentsMatch(List referenceIntents, List serviceIntents) {
        Set referenceIntentSet = new HashSet(referenceIntents);
        Set serviceIntentSet = new HashSet(serviceIntents);
        return referenceIntentSet.equals(serviceIntentSet);
    }

    /**
     * Reference targets have to be resolved in the context in which they are 
     * defined so they can't be push down the hierarchy during the static build.
     * So we wait until we have calculated the enpoint references before pushing them 
     * down. Muliplicity errors will be caught by the multiplicity validation check that
     * comes next 
     * 
     * @param composite
     * @param component
     * @param reference
     * @param monitor
     */
    private void pushDownEndpointReferences(Composite composite,
                                            Component component,
                                            ComponentReference componentReference,
                                            Monitor monitor) {
        Reference reference = componentReference.getReference();
        
        if (reference instanceof CompositeReference) {
            List leafComponentReferences = getPromotedComponentReferences((CompositeReference)reference);
            
            // for each leaf component reference copy in the endpoint references for this
            // higher level (promoting) reference
            // TODO - the elements are inserted starting at 0 here because the code allows references multiplicity 
            //        validation constraints to be broken if the reference is autowire. At runtime the 
            //        first one is chosen if max multiplicity is 1. We have an OSOA test that assumes that
            //        promoted references overwrite leaf references. This insert gives the same effect in the
            //        autowire case. We need to think about if there is a more correct answer. 
            for (ComponentReference leafRef : leafComponentReferences){
                int insertLocation = 0;
                for (EndpointReference epr : componentReference.getEndpointReferences()){
                    // copy the epr
                    EndpointReference eprCopy = copyHigherReference(epr, leafRef);
                    leafRef.getEndpointReferences().add(insertLocation, eprCopy);
                    insertLocation++;
                }
            }
        }
        
        // TODO - what to do about callbacks in the reference promotion case
    }
    
    /**
     * Follow a reference promotion chain down to the innermost (non composite)
     * component references.
     * 
     * @param compositeReference
     * @return
     */
    private List getPromotedComponentReferences(CompositeReference compositeReference) {
        List componentReferences = new ArrayList();
        collectPromotedComponentReferences(compositeReference, componentReferences);
        return componentReferences;
    }

    /**
     * Follow a reference promotion chain down to the innermost (non composite)
     * component references.
     * 
     * @param compositeReference
     * @param componentReferences
     * @return
     */
    private void collectPromotedComponentReferences(CompositeReference compositeReference,
                                                           List componentReferences) {
        for (ComponentReference componentReference : compositeReference.getPromotedReferences()) {
            Reference reference = componentReference.getReference();
            if (reference instanceof CompositeReference) {

                // Continue to follow the reference promotion chain
                collectPromotedComponentReferences((CompositeReference)reference, componentReferences);

            } else if (reference != null) {

                // Found a non-composite reference
                componentReferences.add(componentReference);
            }
        }
    }
    
    /**
     * Copy a higher level EndpointReference down to a lower level reference which it promotes 
     * @param epRef - the endpoint reference
     * @param promotedReference - the promoted reference
     * @return - a copy of the EndpointReference with data merged from the promoted reference
     */
    private  EndpointReference copyHigherReference(EndpointReference epRef, ComponentReference promotedReference) {
        EndpointReference epRefClone = null;
        try {
            epRefClone = (EndpointReference)epRef.clone();
        } catch (Exception e) {
            throw new ServiceRuntimeException(e);
            // Ignore (we know that EndpointReference2 can be cloned)
        } // end try
        // Copy across details of the inner reference
        // ComponentReference ref = epRefClone.getReference();
        //FIXME
        epRefClone.setReference(promotedReference);
        return epRefClone;
    }   

    private void validateReferenceMultiplicity(Composite composite, Component component, Monitor monitor) {
        for (ComponentReference componentReference : component.getReferences()) {
            if (!validateMultiplicity(componentReference.getMultiplicity(),
                                      componentReference.getEndpointReferences())) {
                if (componentReference.getEndpointReferences().isEmpty()) {

                    // No error if the reference is promoted out of the current composite
                    boolean promoted = false;
                    for (Reference reference : composite.getReferences()) {
                        CompositeReference compositeReference = (CompositeReference)reference;
                        if (compositeReference.getPromotedReferences().contains(componentReference)) {
                            promoted = true;
                            break;
                        }
                    }
                    if (!promoted && !componentReference.isForCallback() && !componentReference.isWiredByImpl()) {
                        Monitor.error(monitor,
                                      this,
                                      Messages.ASSEMBLY_VALIDATION,
                                      "ReferenceWithoutTargets",
                                      composite.getName().toString(),
                                      componentReference.getName());
                    }
                } else {
                    // no error if reference is autowire and more targets
                    // than multiplicity have been found 
                    if (Boolean.TRUE.equals(componentReference.getAutowire())) {
                        break;
                    }

                    Monitor.error(monitor,
                                  this,
                                  Messages.ASSEMBLY_VALIDATION,
                                  "TooManyReferenceTargets",
                                  componentReference.getName());
                }
            }
        }

    }
    
    private boolean validateMultiplicity(Multiplicity multiplicity, List endpointReferences) {

        // In some tests multiplicity is not set
        if (multiplicity == null) {
            return true;
        }

        // Count targets
        int count = endpointReferences.size();

        switch (multiplicity) {
            case ZERO_N:
                break;
            case ZERO_ONE:
                if (count > 1) {
                    return false;
                }
                break;
            case ONE_ONE:
                if (count != 1) {
                    return false;
                }
                break;
            case ONE_N:
                if (count < 1) {
                    return false;
                }
                break;
        }
        return true;
    }    

    /**
     * Evaluates whether the bindings attached to a reference identify one or more target services.
     * @param reference - the reference
     * @return true if the bindings identify a target, false otherwise
     */
    private boolean bindingsIdentifyTargets(ComponentReference reference) {
        for (Binding binding : reference.getBindings()) {
            //  getReferenceTargets(ComponentReference reference) {
        List theTargets = reference.getTargets();
        if (theTargets.isEmpty()) {
            // Component reference list of targets is empty, try the implementation reference
            if (reference.getReference() != null) {
                theTargets = reference.getReference().getTargets();
            } // end if
        } // end if
        return theTargets;
    } // end method getReferenceTargets

    /**
     * Target names can take the form 
     *   component/service/binding
     * This extracts the component/service part
     * 
     * @param targetName
     * @return String the component/service name
     */
    private String getComponentServiceName(String targetName) {
        String[] parts = targetName.split("/");

        if (parts.length > 1) {
            return parts[0] + "/" + parts[1];
        } else {
            return parts[0];
        }
    }

    /**
     * Target names can take the form 
     *   component/service/binding
     * This extracts the binding part and returns
     * it. If there is no binding part it returns null
     * 
     * @param targetName
     * @return String the binding name or null if there is no binding name
     */
    private String getBindingName(String targetName) {
        String[] parts = targetName.split("/");

        if (parts.length == 3) {
            return parts[2];
        } else {
            return null;
        }
    }

    /**
     * Helper method that finds the Component given a target name
     * @param components
     * @param targetName
     * @return the component
     */
    private Component getComponentFromTargetName(Map components, String targetName) {
        Component theComponent;
        int s = targetName.indexOf('/');
        if (s == -1) {
            theComponent = components.get(targetName);
        } else {
            theComponent = components.get(targetName.substring(0, s));
        }
        return theComponent;
    } // end method getComponentFromTargetName

    /**
     * Helper method to create an Endpoint Reference
     * @param component
     * @param reference
     * @param binding
     * @param endpoint
     * @param unresolved
     * @return the endpoint reference
     */
    private EndpointReference createEndpointRef(Component component,
                                                ComponentReference reference,
                                                Binding binding,
                                                Endpoint endpoint,
                                                boolean unresolved) {
        EndpointReference endpointRef = createEndpointRef(component, reference, unresolved);
        endpointRef.setBinding(binding);
        endpointRef.setTargetEndpoint(endpoint);
        return endpointRef;
    } // end method

    /**
     * Helper method to create an Endpoint Reference
     * @param component
     * @param reference
     * @param unresolved
     * @return the endpoint reference
     */
    private EndpointReference createEndpointRef(Component component, ComponentReference reference, boolean unresolved) {
        EndpointReference endpointRef = assemblyFactory.createEndpointReference();
        endpointRef.setComponent(component);
        endpointRef.setReference(reference);
        endpointRef.setUnresolved(unresolved);
        return endpointRef;
    } // end method createEndpointRef

    /**
     * Helper method to create an endpoint
     * @param component
     * @param service
     * @param unresolved
     * @return the endpoint
     */
    private Endpoint createEndpoint(Component component, ComponentService service, boolean unresolved) {
        Endpoint endpoint = createEndpoint(unresolved);
        endpoint.setComponent(component);
        endpoint.setService(service);
        endpoint.setUnresolved(unresolved);
        return endpoint;
    } // end method createEndpoint

    /**
     * Helper method to create an endpoint
     * @param component
     * @param service
     * @param binding
     * @param unresolved
     * @return the endpoint
     */
    private Endpoint createEndpoint(Component component, ComponentService service, Binding binding, boolean unresolved) {
        Endpoint endpoint = createEndpoint(unresolved);
        endpoint.setComponent(component);
        endpoint.setService(service);
        endpoint.setBinding(binding);
        endpoint.setUnresolved(unresolved);
        return endpoint;
    } // end method createEndpoint    

    /**
     * Helper method to create an Endpoint
     * @param unresolved
     * @return the endpoint
     */
    private Endpoint createEndpoint(boolean unresolved) {
        Endpoint endpoint = assemblyFactory.createEndpoint();
        endpoint.setUnresolved(unresolved);
        return endpoint;
    } // end method createEndpoint

    /**
     * Helper method to create an Endpoint
     *
     * @param component The component that owns the reference
     * @param targetName It can be one of the following formats
     * 
    *
  • componentName *
  • componentName/serviceName *
  • componentName/serviceName/bindingName *
* @return the endpoint */ private Endpoint createEndpoint(Component component, String targetName) { String[] parts = targetName.split("/"); if (parts.length < 1 || parts.length > 3) { throw new IllegalArgumentException("Invalid target URI: " + targetName); } // Find the parent uri String uri = component.getURI(); int index = uri.lastIndexOf('/'); if (index == -1) { uri = ""; } else { uri = uri.substring(0, index); } if (parts.length >= 1) { // Append the target component name if (uri.length() == 0) { uri = parts[0]; } else { uri = uri + "/" + parts[0]; } } if (parts.length == 3) { // #service-binding(serviceName/bindingName) uri = uri + "#service-binding(" + parts[1] + "/" + parts[2] + ")"; } else if (parts.length == 2) { // #service(serviceName) uri = uri + "#service(" + parts[1] + ")"; } Endpoint endpoint = assemblyFactory.createEndpoint(); endpoint.setUnresolved(true); endpoint.setURI(uri); return endpoint; } // end method createEndpoint /** * ASM_5021: where a of a has @autowire=true * and where the has a child element which * declares a single target service, the reference is wired only to * the single service identified by the element */ private void setSingleAutoWireTarget(ComponentReference reference) { if (reference.getEndpointReferences().size() > 1 && reference.getBindings() != null && reference.getBindings().size() == 1) { String uri = reference.getBindings().get(0).getURI(); if (uri != null) { if (uri.indexOf('/') > -1) { // TODO: must be a way to avoid this fiddling int i = uri.indexOf('/'); String c = uri.substring(0, i); String s = uri.substring(i + 1); uri = c + "#service(" + s + ")"; } for (EndpointReference er : reference.getEndpointReferences()) { if (er.getTargetEndpoint() != null && uri.equals(er.getTargetEndpoint().getURI())) { reference.getEndpointReferences().clear(); reference.getEndpointReferences().add(er); return; } } } } } } // end class




© 2015 - 2025 Weber Informatics LLC | Privacy Policy