//------------------------------------------------------------------------------
// Copyright (c) 2005, 2006 IBM Corporation and others.
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// which accompanies this distribution, and is available at
// http://www.eclipse.org/legal/epl-v10.html
//
// Contributors:
// IBM Corporation - initial implementation
//------------------------------------------------------------------------------
package org.eclipse.epf.library.configuration;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import org.eclipse.emf.ecore.EStructuralFeature;
import org.eclipse.epf.uma.MethodElement;
import org.eclipse.epf.uma.VariabilityElement;
import org.eclipse.epf.uma.ecore.util.OppositeFeature;

/**
 * realized feature value for a toMany opposite feature
 * 
 * @author Jinhua Xi
 * @since 1.0
 *
 */
public class ToManyOppositeFeatureValue extends ToManyFeatureValue {
	
	/**
	 * @see construct a feature value object for to-many opposite feature
	 * 
	 * @param element
	 * @param feature
	 * @param realizer
	 */
	public ToManyOppositeFeatureValue(MethodElement element, OppositeFeature feature, ElementRealizer realizer) {
		super(element, null, feature, realizer);
	}

	

	/**
	 * @see org.eclipse.epf.library.configuration.ToManyFeatureValue#add(VariabilityElement, Object)
	 */
	public void add(VariabilityElement owner, Object value) {
		
		// work around for opposite feature value that still return a single value instead of a list
		if ( value instanceof MethodElement ) {
			ArrayList v = new ArrayList();
			v.add(value);
			value = v;
		}
		
		if ( !(value instanceof List) ) {	
			return;
		}
			
		OppositeFeature of = (OppositeFeature)feature;
		EStructuralFeature f = of.getTargetFeature();

		for (Iterator it = ((List) value).iterator(); it.hasNext();) {
			MethodElement e = (MethodElement) it.next();

			// Replace does not completely remove
			// outgoing associations
			// if the opposite feature value has replacer in the
			// configuration
			// it's outgoing associations (i.e., this element) will be
			// replaced by the replacing element
			// as a result, the opposite feature value should drop the
			// replaced element
			//
			// for example, R1 -> responsible for A1, R2 responsible for
			// A2
			// if R2 replaces R1, then R2 still responsible for A2
			// but A1 does not have a responsible role (not R2)
			// so for A1's responsible role opposite feature,
			// the value R1 should be dropped instead of realize to R2
			// Jinhua Xi, 10/27/2005
			
			// check the replacer is not enough. If the base element is replaced, 
			// all the contributors to the base should also be considered as replaced.
			// so realize the element, see if it is a replacer
			// Bug 199686 - Replacing roles does not update responsible work product's pages
			VariabilityElement replacer = null;
			if ( e instanceof VariabilityElement ) {
				//replacer = ConfigurationHelper.getReplacer((VariabilityElement) e, realizer.getConfiguration());
				replacer = (VariabilityElement)ConfigurationHelper.getCalculatedElement(e, realizer);
				if ( (replacer == e) || !ConfigurationHelper.isReplacer(replacer) || 
					ConfigurationHelper.contrubuteChain((VariabilityElement) e, (VariabilityElement)replacer)) {					
					replacer = null;
				}
				
			}
			boolean isValueReplaced = (replacer != null);

			boolean keep = !isValueReplaced;
			if ( isValueReplaced && 
					(ConfigurationHelper.isExtendReplacer(replacer) 
					|| ElementRealizer.isExtendReplaceEnabled()) ) {
				// if the value is replaced, but the out going feature is inherited by the replacer
				// then we should keep this value, so we need to calculate the feature value 
				// of the replacer
				if ( f.isMany() ) {
					List items = ConfigurationHelper.calc0nFeatureValue(replacer, f, realizer);
					keep = items.contains(owner);
				} else {
					MethodElement item = ConfigurationHelper.calc01FeatureValue(replacer, f, realizer);
					keep = (item == owner);
				}
			}
			
			// if the value's feature to this element is to-one, 
			// then this value's feature value should be the element,
			// otherwise drop the value
			// for example, 
			// T1 -> R1 (primary performaer)
			// T2 -> R2
			// T2 contributes to T1
			// since T1 already has R1, so R2 is droped
			// so when calculating R2's performing tasks, T1 should not be included
			if ( keep ) {
				MethodElement ve = ConfigurationHelper.getCalculatedElement(e, realizer);
				if ( ve != null ) {
					
					// check if this is a to-one feature, currently only Task->Primary Role and TD -> Primary RD
					EStructuralFeature f1 = ConfigurationHelper.get01Feature(of);
					if ( f1 != null ) {
						MethodElement item = ConfigurationHelper.calc01FeatureValue(ve, f1, realizer);
						
						// if the value element's to-one feature value item is not the current element, 
						// then the element's opposite feature value should not contain this value.
						// say, the value element is a task and the current element is a role,
						// then if the task's primary performer (item above) is not this role (the current element), 
						// then the role's performing tasks (the opposite feature value) 
						// should not contain this task (the value, ve above)
						if ( item != element) {
							keep = false;
						}
					}
				}
			}
			
			
			if ( keep ) {
					
				MethodElement ce = ConfigurationHelper.getCalculatedElement(e, realizer);

				// calculated element can be null if it can't show
				if (ce != null && !values.contains(ce)) {
					values.add(ce);
				}
			}
			
			
			// if the element e has extenders and the extender's feature is the owner element, 
			// then we also need to include the extender
			processExtenders(e, f);
		}	
	}
	
	private void processExtenders(MethodElement e, EStructuralFeature f) {
		if ( !(e instanceof VariabilityElement) ) {
			return;
		}
		
		VariabilityElement ve = (VariabilityElement)e;
		
		List items = ConfigurationHelper.getExtenders( ve, realizer.getConfiguration());
		if ( items.size() > 0 ) {		
			for (Iterator it = items.iterator(); it.hasNext();) {
				MethodElement me = (MethodElement) it.next();
				boolean keep = false;
				if ( f.isMany() ) {
					List vx = ConfigurationHelper.calc0nFeatureValue(me, f, realizer);
					// if the value contains the owner element, then include it
					keep = (vx != null) && vx.contains(super.element);
				} else {
					MethodElement v = ConfigurationHelper.calc01FeatureValue(me, f, realizer);
					
					// if the feature value is the owner element, then this value should be included
					keep = (v == super.element);
				}
				
				if (keep && !super.values.contains(me) ) {
					super.values.add(me);
					processExtenders(me, f);
				}
			}
		}
		
		// if the element is a contributor or replacer, also need to check the extenders of the base element
		if ( ConfigurationHelper.isContributor(ve) || ConfigurationHelper.isReplacer(ve) ) {
			processExtenders(ve.getVariabilityBasedOnElement(), f);
		}
	}
}
