/**
 * File:    AspectManager.java
 * Created: 10.07.2008
 *
 *
/*******************************************************************************
 * Copyright (c) 2008-2009 Open Wide SA <www.openwide.fr>
 *
 * 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:
 *    Marc Dutoo, Open Wide SA 
 *    	- initial API and implementation
 *******************************************************************************/

package org.eclipse.jwt.we.conf.model.aspects;

import java.util.List;

import org.eclipse.emf.ecore.EObject;
import org.eclipse.jwt.we.conf.model.Aspect;
import org.eclipse.jwt.we.conf.model.AspectInstance;
import org.eclipse.jwt.we.conf.model.ConfModel;
import org.eclipse.jwt.we.conf.model.Profile;
import org.eclipse.jwt.we.conf.model.aspects.internal.AspectManagerImpl;
import org.eclipse.jwt.we.conf.model.resource.ConfModelStatus;



/**
 * This class does the aspects management.
 * 
 * It manages conf models. They can be provided in the following ways :
 * <ul>
 * <li>declared using extension point org.eclipse.jwt.we.conf (useful for vendors)</li>
 * <li>discovered under directory conf (useful for power users)</li>
 * <li>embedded in a given workflow model (useful for export)</li>
 * </ul>
 * 
 * These makes it able to tell which aspects are relevant to a given model element
 * (see getAspects()).
 * 
 * From these, it enables the following features :
 * <ul>
 * <li>ModelElementItemProvider can display "new child" commands on a model element
 * for every relevant aspect (thanks to getAspects()) and then create them (thanks
 * to createAspectInstance())</li>
 * <li>TODO XXX can automatically add "default" aspects to a newly created model
 * element(thanks to onCreate())</li>
 * </ul>
 * 
 * Aspect instantiation is handled by its AspectFactory.
 * 
 * TODO :
 * extract itf, refactor, indent
 * model : refactor dependancies and extends between jwt mm and jwt-we-conf mm
 * write sample declared conf
 * implement new specs of Aspects on top of loaded models ; use aspects cache rather than profile ??
 * behaviours : use implemented onCreated / singleton, design a pluggable architecture
 * better ModelElementItemProvider.java using javajetinc or adapter, than merely using in collectNewChildDescriptors @generated NOT
 * merge with Views
 * separate model from we UI
 * improve graphical editor for jwt-we-conf model
 * let custom property editors be specified for aspects (EMF ? see general proposition in bugzilla by mistria)
 * improve generic property property tab, improve facilities for building aspect-specific property tabs
 * write a generic property editor for Property, that handles OK the possible value types
 * 
 * @version $Id: AspectManager.java,v 1.1 2010-05-10 08:27:23 chsaad Exp $
 * @author Marc Dutoo, Open Wide SA
 * @since 0.6
 */
public interface AspectManager {
	
	/**
	 * Singleton
	 */
	AspectManager INSTANCE = AspectManagerImpl.createAspectManager();
	

	/**
	 * Helper
	 * @param element of the conf model or of the decorated model
	 * @return its root element
	 */
	public EObject getModelRoot(Object element);
	/**
	 * TODO impl, cache loaded, manage
	 * rename getEmbeddedConfModel ? getModelConfModel ?
	 * @param modelElement
	 * @return
	 */
	public ConfModel getConfModel(EObject modelElement);
	/**
	 * To be called before getConfModel() to know whether the model
	 * is in error and in this case whether it is patchable, in which
	 * case calling getConfModel() will automatically patch it
	 * @param modelElement
	 * @return MultiStatus with error children if any problem
	 * @author Marc Dutoo, Open Wide SA
	 * @since 0.7.0
	 */
	public ConfModel getConfModel(EObject modelElement, ConfModelStatus cmStatus);
	/**
	 * 
	 * @param modelElement
	 * @return true if it is a ConfModel element (ConfModel, Profile, Aspect...)
	 * and not an element of the aspected model.
	 */
	public boolean isConfModelElement(EObject modelElement);
	
	/**
	 * Returns all aspects configured for the given model element,
	 * according to the merged conf model.
	 * Cached impl.
	 * @param modelElement
	 * @return
	 */
	public List<Aspect> getAspects(EObject modelElement);
	/**
	 * Returns the profiles that are activated for the model
	 * of the given element.
	 * @param model if null, returns all installed profiles
	 * @return installed profiles referenced by the modelElement's model's embedded conf's profiles
	 */
	public List<Profile> getActivatedProfiles(EObject modelElement);

	/**
	 * Returns whether this model's conf & Aspects features should be based on
	 * his embedded conf (useful when designing aspects) rather than on
	 * JWT's installed conf (normal behaviour).
	 * TODO make it confble in model and why not globally
	 * @param model
	 * @return 
	 */
	public boolean useEmbeddedConf(EObject modelElement);

	/**
	 * Finds and returns the corresponding Aspect
	 * @param aspectInstance used for knowing activated conf and aspectId
	 * @return the Aspect definition that has the given id
	 */
	public Aspect getAspect(AspectInstance aspectInstance);
	/**
	 * Finds and returns the corresponding Aspect
	 * TODO still used ??
	 * @param modelElement required in order to know the activated profiles
	 * @param aspectId
	 * @return the Aspect definition that has the given id
	 * @obsolete
	 */
	public Aspect getAspect(EObject modelElement, String aspectId);
	
    /**
     * ? copy required when long winded manipulations since comes from a loaded model
	 * TODO versions
     * @param model
     * @return
     */
	public List<Profile> getMissingInstalledProfiles(EObject modelElement);

	/**
	 * Activates the given installed profile on the given model, including
	 * updating the model according to aspect behaviour.
	 * If the given model has a conf without the given profile,
	 * copies and adds the given profile to the given model's conf,
	 * then triggers "onCreated" aspect behaviour on all impacted elements.
	 * of the model.
	 * @param modelRoot
	 * @param profile
	 */
	public void activateProfile(EObject modelElement, Profile installedProfile);
	/**
	 * Activates the given installed profile on the given model, including
	 * updating the model according to aspect behaviour.
	 * If the given model has a conf without the given profile,
	 * copies and adds the given profile to the given model's conf,
	 * then if executeBehaviours is true,
	 * triggers "onCreated" aspect behaviour on all impacted elements
	 * of the model.
	 * @param modelRoot
	 * @param profile
	 * @param executeBehaviours
	 */
	public void activateProfile(EObject modelElement, Profile profile, boolean executeBehaviours);
	/**
	 * Removes the given profile from the given model's conf if any,
	 * and removes the corresponding aspect instances from the model
	 * @param modelElement
	 * @param installedProfile
	 */
	public void disableProfile(EObject modelElement, Profile installedProfile);
	/**
	 * Removes the given profile from the given model's conf if any,
	 * and if removeAspectInstances is true,
	 * removes the corresponding aspect instances from the model
	 * @param modelElement
	 * @param installedProfile
	 * @param removeAspectInstances
	 */
	public void disableProfile(EObject modelElement, Profile profile, boolean removeAspectInstances);
	
	/**
	 * Finds and returns the corresponding Aspect
	 * @param aspectInstance used for knowing activated conf and aspectId
	 * @return the Aspect definition that has the given id
	 */
	public List<AspectInstance> getAspectInstances(EObject modelElement);

	/**
	 * Returns the corresponding aspect instance of the given model element if any
	 * @param modelElement
	 * @param aspect
	 */
	public AspectInstance getAspectInstance(EObject modelElement, Aspect aspect);

	/**
	 * Creates a new instance of the given aspect on the given model element if any
	 * @param modelElement
	 * @param aspect
	 */
	public AspectInstance createAndAddAspectInstance(Aspect aspect, EObject modelElement);
	
}
