/*
 * 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.List;
import java.util.Set;

import javax.xml.namespace.QName;

import org.apache.tuscany.sca.assembly.Base;
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.Endpoint;
import org.apache.tuscany.sca.assembly.EndpointReference;
import org.apache.tuscany.sca.assembly.Implementation;
import org.apache.tuscany.sca.assembly.builder.BuilderContext;
import org.apache.tuscany.sca.assembly.builder.CompositeBuilder;
import org.apache.tuscany.sca.assembly.builder.CompositeBuilderException;
import org.apache.tuscany.sca.assembly.builder.PolicyBuilder;
import org.apache.tuscany.sca.core.ExtensionPointRegistry;
import org.apache.tuscany.sca.monitor.Monitor;
import org.apache.tuscany.sca.policy.Intent;
import org.apache.tuscany.sca.policy.PolicySet;
import org.apache.tuscany.sca.policy.PolicySubject;
import org.apache.tuscany.sca.policy.util.PolicyHelper;

/**
 * A composite builder that computes policy sets based on attached intents and policy sets.
 * Useful if you want to build the model without making any runtime decisions such as
 * reference/services matching
 *
 * @version $Rev$ $Date$
 */
public class CompositePolicyBuilderImpl extends ComponentPolicyBuilderImpl implements CompositeBuilder {
    private final static QName NOLISTENER_INTENT = new QName(Base.SCA11_NS, "noListener");
    private CompositeBuilder policyAppliesToBuilder = null;
    
    public CompositePolicyBuilderImpl(ExtensionPointRegistry registry) {
        super(registry);
        
        policyAppliesToBuilder = new PolicyAppliesToBuilderImpl(registry);
    }

    public String getID() {
        return "org.apache.tuscany.sca.assembly.builder.CompositePolicyBuilder";
    }

    public Composite build(Composite composite, BuilderContext context) throws CompositeBuilderException {
        computePolicies(composite, context);
        checkPolicies(composite, context);
        buildPolicies(composite, context);
        return composite;
    }

    protected void computePolicies(Composite composite, BuilderContext context) {
        Monitor monitor = context.getMonitor();
        monitor.pushContext("Composite: " + composite.getName().toString());

        try {
            resolveAndCheck(composite, context);

            // compute policies recursively
            for (Component component : composite.getComponents()) {
                monitor.pushContext("Component: " + component.getName());

                //resolve component level
                resolveAndCheck(component, context);
                
                try {
                    Implementation implementation = component.getImplementation();
                    
                    for (ComponentService componentService : component.getServices()) {
                        monitor.pushContext("Service: " + componentService.getName());

                        try {
                            resolveAndCheck(componentService, context);

                            if (componentService.getInterfaceContract() != null) {
                                resolveAndCheck(componentService.getInterfaceContract().getInterface(), context);

                                resolveAndCheck(componentService.getInterfaceContract().getCallbackInterface(), context);

                            }

                            for (Endpoint ep : componentService.getEndpoints()) {
                                if (componentService.getInterfaceContract() != null) {
                                    // Inherit from the component.service.interface
                                    inherit(ep, Intent.Type.interaction, true, componentService.getInterfaceContract().getInterface());
                                }
                                
                                // Inherit from binding
                                inherit(ep, Intent.Type.interaction, true, ep.getBinding());
                                
                                // Inherit from composite/component/service
                                inherit(ep, Intent.Type.interaction, true, ep.getService(), ep.getComponent(), composite );
                                


                                // Replace profile intents with their required intents
                                // Replace unqualified intents if there is a qualified intent in the list
                                // Replace qualifiable intents with the default qualied intent
                                resolveAndNormalize(ep, context);
                                
                                // Replace qualifiable intents with their default qualifier
                                expandDefaultIntents(ep, context);
                                
                                // Remove the intents whose @contraints do not include the current element
                                removeConstrainedIntents(ep, context);
                                
                                // Remove any direct policy sets if an external one has been applied
                                removeDirectPolicySetsIfExternalExists(ep, context);
                                
                                // Validate that noListener is not specified on a service endpoint
                                checkForNoListenerIntent(ep, context);
                                
                                // check that all intents are resolved
                                checkIntentsResolved(ep, context);

                                // check that the resulting endpoint has no mutually exclusive intents
                                checkMutualExclusion(ep, context);
                            }
                        } finally {
                            monitor.popContext();
                        }
                    }

                    for (ComponentReference componentReference : component.getReferences()) {
                        monitor.pushContext("Reference: " + componentReference.getName().toString());

                        try {

                            if (componentReference.getInterfaceContract() != null) {
                                resolveAndCheck(componentReference.getInterfaceContract().getInterface(), context);

                                resolveAndCheck(componentReference.getInterfaceContract().getCallbackInterface(),
                                                context);
                            }

                            for (EndpointReference epr : componentReference.getEndpointReferences()) {

                                // Inherit from the component.reference.interface
                                if (componentReference.getInterfaceContract() != null) {
                                    inherit(epr, Intent.Type.interaction, true, componentReference.getInterfaceContract().getInterface());
                                }
                                
                                // Inherit from binding
                                inherit(epr, Intent.Type.interaction, true, epr.getBinding());

                                // Inherit from composite/component/reference
                                inherit(epr, Intent.Type.interaction, true,  epr.getReference(), epr.getComponent(),  composite);
                                
                              

                                // Replace profile intents with their required intents
                                // Replace unqualified intents if there is a qualified intent in the list
                                // Replace qualifiable intents with the default qualified intent
                                resolveAndNormalize(epr, context);
                                
                                // Replace qualifiable intents with their default qualifier
                                expandDefaultIntents(epr, context);
                                
                                // Remove the intents whose @contraints do not include the current element
                                removeConstrainedIntents(epr, context);
                                
                                removeDirectPolicySetsIfExternalExists(epr, context);
                                
                                // check that all intents are resolved
                                checkIntentsResolved(epr, context);

                                // check that the resulting endpoint reference has no mutually exclusive intents
                                checkMutualExclusion(epr, context);
                            }
                        } finally {
                            monitor.popContext();
                        }
                    }

                    if (implementation instanceof Composite) {
                    	
                    	// POL-4009 componentType attached policySets are ignored when policySets are 
                    	// attached to the using component definition.
                    	if ( !component.getPolicySets().isEmpty() || !composite.getPolicySets().isEmpty() ) {
                    		implementation.getPolicySets().clear();
                    	}
                    		
                        inherit(implementation, Intent.Type.implementation, true, component, composite);                                             
                        computePolicies((Composite)implementation, context);
                        expandDefaultIntents(implementation,context);
                        checkIntentsResolved(implementation,context);
                    } else {
                        resolveAndCheck(implementation, context);
                        if (implementation != null) {
                            inherit(implementation, Intent.Type.implementation, true, component, composite);
                            
                            // Remove the intents whose @contraints do not include the current element
                            removeConstrainedIntents(implementation, context);
                            
                            removeDirectPolicySetsIfExternalExists(implementation, context);
                            
                         // Replace qualifiable intents with their default qualifier
                            expandDefaultIntents(implementation, context);
                            
                            // check that all intents are resolved
                            checkIntentsResolved(implementation, context);
                        }
                    }
                } finally {
                    monitor.popContext();
                }
            }
        } finally {
            monitor.popContext();
        }
    }
    
    private void checkForNoListenerIntent(Endpoint ep, BuilderContext context) {
		PolicyHelper helper = new PolicyHelper();
		if ( helper.getIntent(ep, NOLISTENER_INTENT) != null ) {
			  error(context.getMonitor(), 
                      "NoListenerIntentSpecifiedOnService", 
                      this,
                      ep.toString());
		} 				
		
	}

	private void removeDirectPolicySetsIfExternalExists(PolicySubject subject,
			BuilderContext context) {
    	boolean foundExternalPolicySet = false;
		for (PolicySet ps : subject.getPolicySets() ) {
			if ( ps.getAttachTo() != null ) 
				foundExternalPolicySet = true;
		}
		
		if ( foundExternalPolicySet ) {
			List<PolicySet> copy = new ArrayList<PolicySet>(subject.getPolicySets());
			for ( PolicySet ps : copy ) {
				if ( ps.getAttachTo() == null ) {
					subject.getPolicySets().remove(ps);
				}
			}
		}
		
	} 

	/**
     * This is mainly about removing policies that don't "applyTo" the element where
     * they have ended up after all the attachment and inheritance processing
     * 
     * @param composite
     * @param context
     */
    protected void checkPolicies(Composite composite, BuilderContext context) throws CompositeBuilderException{
        policyAppliesToBuilder.build(composite, context);
    }

    protected void buildPolicies(Composite composite, BuilderContext context) {

        // build policies recursively
        for (Component component : composite.getComponents()) {
            Implementation implementation = component.getImplementation();
            if (implementation instanceof Composite) {
                buildPolicies((Composite)implementation, context);
            }
        }

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

            for (ComponentService componentService : component.getServices()) {
                for (Endpoint ep : componentService.getEndpoints()) {
                    Set<QName> policyNames = getPolicyNames(ep);
                    
                    // check that only one policy language is present in the endpoint's policy sets
                    if (policyNames.size() > 1){
                        error(context.getMonitor(), 
                              "MultiplePolicyLanguagesInEP", 
                              this,
                              ep.toString(), 
                              policyNames.toString());
                    } else {
                        for (QName policyType : policyNames) {
                            PolicyBuilder builder = builders.getPolicyBuilder(policyType);
                            if (builder != null) {
                                builder.build(ep, context);
                            }
                        }
                    }
                }
            }

            for (ComponentReference componentReference : component.getReferences()) {
                for (EndpointReference epr : componentReference.getEndpointReferences()) {
                    Set<QName> policyNames = getPolicyNames(epr);
                    
                    // check that only one policy language is present in the endpoint references's policy sets
                    if (policyNames.size() > 1){
                        error(context.getMonitor(),  
                              "MultiplePolicyLanguagesInEPR",
                              this,
                              epr.toString(), 
                              policyNames.toString());
                    } else {                    
                        for (QName policyType : policyNames) {
                            PolicyBuilder builder = builders.getPolicyBuilder(policyType);
                            if (builder != null) {
                                builder.build(epr, context);
                            }
                        }
                    }
                }
            }

            Implementation implementation = component.getImplementation();
            if (implementation != null) {
                Set<QName> policyNames = getPolicyNames(implementation);
                
                // check that only one policy language is present in the implementations's policy sets
                if (policyNames.size() > 1){
                    error(context.getMonitor(), 
                          "MultiplePolicyLanguagesInImplementation", 
                          this,
                          component.toString(), 
                          policyNames.toString());
                } else {
                    for (QName policyType : policyNames) {
                        PolicyBuilder builder = builders.getPolicyBuilder(policyType);
                        if (builder != null) {
                            builder.build(component, implementation, context);
                        }
                    }
                }
            }
        }
    }
}
