private void selectForwardEndpoint()

in modules/core/src/main/java/org/apache/tuscany/sca/core/runtime/impl/EndpointReferenceBinderImpl.java [420:550]


    private void selectForwardEndpoint(EndpointReference endpointReference, List<Endpoint> endpoints, Audit matchAudit, BuilderContext builderContext, boolean runtime) {    
             
        Endpoint matchedEndpoint = null;
        
        if (endpointReference.getReference().getName().startsWith("$self$.")){
            // just select the first one and don't do any policy matching
            if (endpointReference.getTargetEndpoint() != null && !endpointReference.getTargetEndpoint().isUnresolved()) {
                matchedEndpoint = endpointReference.getTargetEndpoint();
            } else {
                matchedEndpoint = endpoints.get(0);
            }
        } else {
            // find the endpoints that match this endpoint reference
            List<Endpoint> matchedEndpoints = new ArrayList<Endpoint>();
            
            for (Endpoint endpoint : endpoints){
                if (haveMatchingPolicy(endpointReference, endpoint, matchAudit, builderContext) &&
                    haveMatchingInterfaceContracts(endpointReference, endpoint, matchAudit)){
                    matchedEndpoints.add(endpoint);
                }
            }
            
            // TUSCANY-4005 - raise an error if a reference target that only specifies the
            //                component name matches more than one component service
            if (endpointReference.getTargetEndpoint().getService() == null &&
                endpointReference.getTargetEndpoint().getBinding() == null &&
                matchedEndpoints.size() > 1   ) {
                
                String serviceName = null;
                for (Endpoint endpoint : matchedEndpoints){
                    // ignore service names called "default" as these indicate dynamic services
                    // created for the likes of implementation.python
                    if (serviceName == null &&
                        !endpoint.getService().getName().equals("default")){
                        serviceName = endpoint.getService().getName();
                    }
                    
                    if (serviceName != null &&
                        !endpoint.getService().getName().equals("default") &&
                        !endpoint.getService().getName().equals(serviceName)){
                        if (runtime){
                            Monitor.error(monitor, 
                                          this, 
                                          "endpoint-validation-messages", 
                                          "TooManyTargetServices", 
                                          endpointReference.toString(),
                                          endpointReference.getTargetEndpoint().toString(),
                                          matchAudit);
                            throw new ServiceRuntimeException("Unable to bind " + 
                                                              monitor.getLastProblem().toString());
                        } else {
                            Monitor.warning(monitor, 
                                            this, 
                                            "endpoint-validation-messages", 
                                            "TooManyTargetServices", 
                                            endpointReference.toString(),
                                            endpointReference.getTargetEndpoint().toString());
                            return;
                        }
                    }
                }
            }
            
            // TUSCANY-3941 check for the case where the user has provided a 
            //              binding.sca at the reference and make sure we pick
            //              a binding.sca at the service regardless of how many
            //              other bindings are provided
            if (endpointReference.getBinding() != null &&
                endpointReference.getBinding() instanceof SCABinding ){
                for (Endpoint endpoint : matchedEndpoints){
                    if (endpoint.getBinding() instanceof SCABinding){
                        matchedEndpoint = endpoint;
                        break;
                    }
                }
            } 
            
            // TUSCANY-4069 if no binding specified on reference then use service binding.sca if that exists 
            if (endpointReference.getBinding() == null && Boolean.TRUE.equals(endpointReference.getReference()
                .getAutowire())) {
                for (Endpoint endpoint : matchedEndpoints) {
                    if (endpoint.getBinding() instanceof SCABinding) {
                        matchedEndpoint = endpoint;
                        break;
                    }
                }
            }

            if (matchedEndpoint == null) {
                // just take the first matched endpoint from the list
                if (matchedEndpoints.size() > 0){
                    matchedEndpoint = matchedEndpoints.get(0);
                }
            }
        }
        
        if (matchedEndpoint == null){
            return;
        } else {
            endpointReference.setTargetEndpoint(matchedEndpoint);
            Binding binding = matchedEndpoint.getBinding();
            try {
                endpointReference.setBinding((Binding)binding.clone());
            } catch (CloneNotSupportedException e) {
                // shouldn't happen
                throw new RuntimeException(e);
            }
            // TUSCANY-3873 - add policy from the service
            //                we don't care about intents at this stage
            endpointReference.getPolicySets().addAll(matchedEndpoint.getPolicySets());
            
            // TODO - we need to re-run the appliesTo processing here but there is some question about what 
            //        appliesTo means. It's also difficult to get to the PolicyAppliesToBuilder from here and
            //        need a new EntensionInterface to support access. So for now I'm just cheating and looking to 
            //        see if the XPath expression contains the binding type as a string while we discuss appliesTo
            List<PolicySet> psToRemove = new ArrayList<PolicySet>();
            
            for (PolicySet ps : endpointReference.getPolicySets() ) {
                if (!ps.getAppliesTo().contains(endpointReference.getBinding().getType().getLocalPart())){
                    psToRemove.add(ps);
                }
            }
            
            endpointReference.getPolicySets().removeAll(psToRemove);
            
            build(endpointReference);
            endpointReference.setStatus(EndpointReference.Status.WIRED_TARGET_FOUND_AND_MATCHED);
            endpointReference.setUnresolved(false);
        }
        
    }