CHESSIoT_Dev_old-master/org.polarsys.chess.core/src/org/polarsys/chess/core/views/ViewUtils.java
/*
-----------------------------------------------------------------------
--          			CHESS core plugin							 --
--                    Copyright (C) 2016                             --
--                 University of Padova, ITALY                       --
--                                                                   --
-- Authors: Alessandro Zovi          azovi@math.unipd.it             --
--          Laura Baracchi           laura.baracchi@intecs.it        --
--          Stefano Puri             stefano.puri@intecs.it          --
--                                                                   --
-- 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-v20.html                         --
-----------------------------------------------------------------------
*/

package org.polarsys.chess.core.views;

import java.util.ArrayList;

import org.eclipse.emf.common.notify.Notification;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.impl.DynamicEObjectImpl;
import org.eclipse.papyrus.uml.tools.listeners.PapyrusStereotypeListener;
import org.eclipse.uml2.uml.Element;
import org.eclipse.uml2.uml.Model;
import org.eclipse.uml2.uml.Package;
import org.eclipse.uml2.uml.Stereotype;
import org.eclipse.uml2.uml.util.UMLUtil;
import org.polarsys.chess.chessmlprofile.Core.Domain;
import org.polarsys.chess.core.internal.views.InternalViewUtils;
import org.polarsys.chess.core.internal.views.permissions.EntryId;
import org.polarsys.chess.core.internal.views.permissions.PermissionEntry;
import org.polarsys.chess.core.profiles.CHESSProfileManager;
import org.polarsys.chess.core.util.CHESSProjectSupport;
import org.polarsys.chess.core.views.DiagramStatus.DesignView;
 



/**
 * This class contains utility methods to deal with design views.
 */
public class ViewUtils {

	/**
	 * Gets the corresponding design view the model element resides in.
	 * 
	 * This method returns the 'physical' view of an element , hence the owning package
	 * stereotyped with the corresponding design view.
	 * 
	 * @param element  the model element 
	 * @return the Package stereotyped with the corresponding design view
	 */
	public static /*@Nonnull*/Package getView(final EObject element) {
		if (element == null)
			return null;
		Package pkg = null;
		if (element instanceof Package) {
			pkg = (Package) element;
	
			if (InternalViewUtils.hasViewStereotypeApplied(pkg))
				return pkg;
		}
	
		return getView(element.eContainer());
	}

	/**
	 * Checks if the current design view (represented by the DesignView parameter) is the deployment view.
	 *
	 * @param view  the design view, can be null
	 * @return true if it is the deployment view, false otherwise
	 * @deprecated use {@link #isDesignView(DesignView, String)} instead.
	 */
	@Deprecated
	public static boolean isDeploymentView(/*@Nullable*/final DesignView view) {
		return view == null ? false : view.isEnabled(CHESSProfileManager.DEPLOYMENT_VIEW);
	}
	
	/**
	 * Checks if the current design view has the corresponding name.
	 * 
	 * If the name passed does not corresponds to a predefined design view an {@link IllegalArgumentException} is raised.
	 * 
	 * Typical usage:
	 * <code>
	 * //check if the current view is a deployment view
	 * //get the DesignView service
	 * designViewService = ...
	 * isDeploymentView = ViewUtils.isDesignView(designViewService, CHESSProfileManager.DEPLOYMENT_VIEW);
	 * </code>
	 * 
	 * @param view  the design view, can be null
	 * @param name  the name of the design view to check against
	 * @return true if it is the desired view, false otherwise
	 */
	public static boolean isDesignView(/*@Nullable*/final DesignView view, final String name) {
		if (view == null)
			return false;
		if (!CHESSProfileManager.CHESS_VIEWS_LIST.contains(name))
			throw new IllegalArgumentException("Invalid design view name");
		return view.isEnabled(name);
	}
	
	/**
	 * Checks if the {@link Package} passed as a parameter represents an actual design view.
	 * 
	 * @param pkg  the package to check
	 * @param name  the design view name
	 * @return  true if the package represents the desired design view, false otherwise
	 */
	public static boolean isDesignView(final Package pkg, final String name) {
		EList<Stereotype> list = pkg.getAppliedStereotypes();
		for (Stereotype stereotype : list) {
			if (stereotype.getName()
					.equals(name))
				return true;
		}
		return false;
	}

	/**
	 * Checks if is deployment view.
	 *
	 * @param pkg the pkg
	 * @return true, if is deployment view
	 * @deprecated use isDesignView(pkg, CHESSProfileManager.DEPLOYMENT_VIEW)
	 */
	@Deprecated
	public static boolean isDeploymentView(final Package pkg) {
		EList<Stereotype> list = pkg.getAppliedStereotypes();
		for (Stereotype stereotype : list) {
			if (stereotype.getName()
					.equals(CHESSProfileManager.DEPLOYMENT_VIEW))
				return true;
		}
		return false;
	}
	
	/**
	 * Checks if is RT analysis view.
	 *
	 * @param pkg the pkg
	 * @return true, if is RT analysis view
	 * @deprecated use isDesignView(pkg, CHESSProfileManager.RT_ANALYSIS_VIEW)
	 */
	@Deprecated
	public static boolean isRTAnalysisView(Package pkg) {
		EList<Stereotype> list = pkg.getAppliedStereotypes();
		for (Stereotype stereotype : list) {
			if (stereotype.getName()
					.equals(CHESSProfileManager.RT_ANALYSIS_VIEW))
				return true;
		}
		return false;
	}
	
	/**
	 * Checks if is dependability analysis view.
	 *
	 * @param view the view
	 * @return true, if is dependability analysis view
	 * @deprecated use isDesignView(pkg, CHESSProfileManager.DEPENDABILITY_ANALYSIS_VIEW)
	 */
	@Deprecated
	public static boolean isDependabilityAnalysisView(DesignView view) {
		return view == null ? false : view.isEnabled(CHESSProfileManager.DEPENDABILITY_ANALYSIS_VIEW);
	}

	/**
	 * Checks if the current view has write access to (i.e can edit) the element/feature passed.
	 *
	 * @param element  the model element
	 * @param feature  the feature
	 * @param currentView  the DesignView service
	 * @param theDomain the the domain
	 * @return true if the design view can write on the element
	 */
	public static boolean isElementWritable_(EObject element, Object feature,
			DesignView currentView, Domain theDomain) {
		if (currentView != null) {
			ArrayList<EntryId> ids = EntryId.computeEntryIds_(element, feature);
			return checkIdPermission(ids, currentView, PermissionEntry.WRITABLE, theDomain);
		}
		return false;
	}
	
	
	/**
	 * Checks if the given view has write access to (i.e can edit) the element/feature passed.
	 *
	 * @param element  the model element
	 * @param feature  the feature
	 * @param viewName  the view's name
	 * @param currentView the current view
	 * @param theDomain the the domain
	 * @return true if the view can write on the element
	 */
	public static boolean isElementWritable_(EObject element, Object feature,
			String viewName, DesignView currentView, Domain theDomain) {
		if (viewName != null) {
			ArrayList<EntryId> ids = EntryId.computeEntryIds_(element, feature);
			return checkIdPermission(ids, viewName, PermissionEntry.WRITABLE, currentView, theDomain);
		}
		return false;
	}
	
	
	/**
	 * Checks if the current view owns (i.e. can create) the element/feature passed.
	 *
	 * @param element  the element
	 * @param feature  the feature
	 * @param currentView  the DesignView service
	 * @param theDomain the the domain
	 * @return true if the design view owns the element
	 */
	public static boolean isElementInstantiable(EObject element, Object feature,
			DesignView currentView, Domain theDomain) {
		if (currentView != null) {
			ArrayList<EntryId> ids = EntryId.computeEntryIds_(element, feature);
			return checkIdPermission(ids, currentView, PermissionEntry.OWNER, theDomain);
		}
		return false;
	}
	
	
	/**
	 * Checks if the current view can edit a stereotype.
	 *
	 * @param element  the element
	 * @param feature  the feature
	 * @param stereotype  the stereotype
	 * @param currentView  the DesignView service
	 * @param theDomain the the domain
	 * @return true if the view can edit the stereotype
	 */
	public static boolean isStereotypeWritable(EObject element, Object feature, 
			Object stereotype, DesignView currentView, Domain theDomain) {
		if (currentView != null) {
			ArrayList<EntryId> ids = EntryId.computeStereotypeEntryIds(element, feature, stereotype);
			//an element is writable iff all of the permission entry it matches have write rights
			return checkIdPermission(ids, currentView, PermissionEntry.WRITABLE, theDomain);
		}
		return false;
	}

	/**
	 * Checks if the current view can create a stereotype.
	 *
	 * @param element  the element
	 * @param feature  the feature
	 * @param stereotype  the stereotype
	 * @param currentView  the DesignView service
	 * @param theDomain the the domain
	 * @return true if the view can create the stereotype
	 */
	public static boolean isStereotypeInstantiable(EObject element, Object feature, Object stereotype, DesignView currentView, Domain theDomain) {
		if (currentView != null) {
			ArrayList<EntryId> ids = EntryId.computeStereotypeEntryIds(element, feature, stereotype);
			return checkIdPermission(ids, currentView, PermissionEntry.OWNER, theDomain);
		}
		return false;
	}
	
	/**
	 * Check id permission.
	 *
	 * @param ids the ids
	 * @param currentView the current view
	 * @param permission the permission
	 * @param theDomain the the domain
	 * @return true, if successful
	 */
	private static boolean checkIdPermission(ArrayList<EntryId> ids,
			DesignView currentView, byte permission, Domain theDomain) {
		//an element is writable iff all of the permission entry it matches have write rights
		//unless it matches multiple permission with id2<>* (stereotype), in that case it is writable
		//if at least one entry have write rights
		if (ids.isEmpty())
			return true;
		boolean res4Stereo = false;
		for (EntryId entryId : ids) {
			CHESSProjectSupport.printlnToCHESSConsole(entryId.toString());
			boolean perm = InternalViewUtils.checkPermission(currentView, entryId, permission, theDomain);
			if (entryId.getStereotype().equals(EntryId.NONE)){
				if (!perm)
					return false;
			} 
			
			res4Stereo = res4Stereo || perm;
			
		}
		return res4Stereo;
	}
	
	
	/**
	 * Check id permission.
	 *
	 * @param ids the ids
	 * @param viewName the view name
	 * @param permission the permission
	 * @param currentView the current view
	 * @param theDomain the the domain
	 * @return true, if successful
	 */
	private static boolean checkIdPermission(ArrayList<EntryId> ids,
			String viewName, byte permission, DesignView currentView, Domain theDomain) {
		//an element is writable iff all of the permission entry it matches have write rights
		//unless it matches multiple permission with id2<>* (stereotype), in that case it is writable
		//if at least one entry have write rights
		if (ids.isEmpty())
			return true;
		boolean res4Stereo = false;
		for (EntryId entryId : ids) {
			CHESSProjectSupport.printlnToCHESSConsole(entryId.toString());
			boolean perm = InternalViewUtils.checkPermission(viewName, entryId, permission, currentView, theDomain);
			if (entryId.getStereotype().equals(EntryId.NONE)){
				if (!perm)
					return false;
			} 
			
			res4Stereo = res4Stereo || perm;
			
		}
		return res4Stereo;
	}
	

	/**
	 * Checks if is extra functional view.
	 *
	 * @param view the view
	 * @return true, if is extra functional view
	 * @deprecated use isDesignView(pkg, CHESSProfileManager.EXTRAFUNCTIONAL_VIEW)
	 */
	public static boolean isExtraFunctionalView(DesignView view) {
		return view == null ? false : view.isEnabled(CHESSProfileManager.EXTRAFUNCTIONAL_VIEW);
	}

	/**
	 * Checks if is extra functional view.
	 *
	 * @param pkg the pkg
	 * @return true, if is extra functional view
	 * @deprecated use isDesignView(pkg, EXTRAFUNCTIONAL_VIEW)
	 */
	public static boolean isExtraFunctionalView(Package pkg) {
		EList<Stereotype> list = pkg.getAppliedStereotypes();
		for (Stereotype stereotype : list) {
			if (stereotype.getName().equals(
					CHESSProfileManager.EXTRAFUNCTIONAL_VIEW))
				return true;
		}
		return false;
	}

	/**
	 * Checks if is component view.
	 *
	 * @param view the view
	 * @return true, if is component view
	 * @deprecated use isDesignView(pkg, CHESSProfileManager.COMPONENT_VIEW)
	 */
	public static boolean isComponentView(DesignView view) {
		//return view.isEnabled(CHESSProfileManager.FUNCTIONAL_VIEW);
		return view == null ? false : view.isEnabled(CHESSProfileManager.COMPONENT_VIEW);
	}

	/**
	 * Checks if is component view.
	 *
	 * @param pkg the pkg
	 * @return true, if is component view
	 * @deprecated use isDesignView(pkg, COMPONENT_VIEW)
	 */
	public static boolean isComponentView(Package pkg) {
		if ( pkg != null )
		{
			EList<Stereotype> list = pkg.getAppliedStereotypes();
			for (Stereotype stereotype : list) {
				if (stereotype.getName().equals(CHESSProfileManager.COMPONENT_VIEW/*CHESSProfileManager.FUNCTIONAL_VIEW*/))
					return true;
			}
		}
		return false;
	}

	/**
	 * Checks if is requirement view.
	 *
	 * @param pkg the pkg
	 * @return true, if is requirement view
	 * @deprecated use isDesignView(pkg, REQUIREMENT_VIEW)
	 */
	public static boolean isRequirementView(Package pkg) {
		if ( pkg != null )
		{
			EList<Stereotype> list = pkg.getAppliedStereotypes();
			for (Stereotype stereotype : list) {
				if (stereotype.getName().equals(CHESSProfileManager.REQUIREMENT_VIEW))
					return true;
			}
		}
		return false;
	}

	/**
	 * Checks if is system view.
	 *
	 * @param pkg the pkg
	 * @return true, if is system view
	 * @deprecated use isDesignView(pkg, CHESSProfileManager.SYSTEM_VIEW)
	 */
	public static boolean isSystemView(Package pkg) {
		if ( pkg != null )
		{
			EList<Stereotype> list = pkg.getAppliedStereotypes();
			for (Stereotype stereotype : list) {
				if (stereotype.getName().equals(CHESSProfileManager.SYSTEM_VIEW))
					return true;
			}
		}
		return false;
	}
	
	/**
	 * Checks if is PSM view.
	 *
	 * @param pkg the pkg
	 * @return true, if is PSM view
	 * @deprecated use isDesignView(pkg, CHESSProfileManager.PSM_VIEW)
	 */
	public static boolean isPSMView(Package pkg) {
		if ( pkg != null )
		{
			EList<Stereotype> list = pkg.getAppliedStereotypes();
			for (Stereotype stereotype : list) {
				if (stereotype.getName().equals(CHESSProfileManager.PSM_VIEW))
					return true;
			}
		}
		return false;
	}
	
	/**
	 * Checks if the stereotype of an actual view is modified or removed.
	 *
	 * @param notification the notification
	 * @return true, if is view modified or removed
	 */
	public static boolean isViewModifiedOrRemoved(Notification notification) {
		Object el = notification.getNotifier();
		
		if (notification.getEventType() == PapyrusStereotypeListener.APPLIED_STEREOTYPE 
				|| notification.getEventType() == PapyrusStereotypeListener.UNAPPLIED_STEREOTYPE
				|| notification.getEventType() == PapyrusStereotypeListener.MODIFIED_STEREOTYPE){
			Object st = notification.getNewValue();
			if (el instanceof EObject && st instanceof EObject){
				String viewName = ((EObject) st).eClass().getName();
				return (CHESSProfileManager.CHESS_VIEWS_LIST.contains(viewName));
			}
		}
		if (notification.getEventType() == Notification.REMOVE){
			Object o = notification.getOldValue();
			if (o instanceof EObject){
				return InternalViewUtils.isView((EObject) o);
			}
		}
		if (el instanceof DynamicEObjectImpl) {
			DynamicEObjectImpl d = (DynamicEObjectImpl) el;
			Stereotype stereo = UMLUtil.getStereotype(d);
			return isViewStereotype(stereo);
		}
		if (notification.getEventType() == Notification.SET){
			if (el instanceof EObject)
				return InternalViewUtils.isView((EObject)el);
		}
		
		
		return false;
	}

//	public static boolean isElementWritable(Element element, Package currentView) {
//		Package view = null;
//		if ((view = getView(element.eContainer())) != null
//				&& currentView != null) {
//			Stereotype viewStereotype = getViewStereotypeApplied(view);
//			Stereotype currentViewStereotype = getViewStereotypeApplied(currentView);
//			if (!viewStereotype.equals(currentViewStereotype)) {
//				return false;
//			}
//		}
//		return true;
//	}

	/**
	 * Checks if the stereotype passed as a parameter represents a design view.
	 * 
	 * @param stereotype  the stereotype
	 * @return true if the stereotype represents a design view
	 */
	public static boolean isViewStereotype(Stereotype stereotype) {
		if (CHESSProfileManager.CHESS_VIEWS_LIST.contains(stereotype.getName()))
			return true;
		return false;
	}

	/**
	 * Checks if the current design view is a virtual view.
	 *
	 * @param currentView  the DesignView service
	 * @return true if the current design view is a virtual view
	 */
	public static boolean isConcurrentView(DesignView currentView) {
		if (currentView == null)
			return false;
		for (String view : CHESSProfileManager.CONCURRENT_VIEWS) {
			if (currentView.isEnabled(view))
				return true;
		}
		return false;
	}
	
	/**
	 * 
	 * Checks if the virtual design view is enabled.
	 * 
	 * @param currentView  the DesignView service
	 * @param view  the name of the virtual design view to check
	 * @return true if it is enabled
	 */
	public static boolean isOnView(DesignView currentView, String view) {
		if (currentView == null)
			return false;
		
		for(String v : CHESSProfileManager.CONCURRENT_VIEWS_ASSOCIATION.get(view)){
			if (currentView.isEnabled(v))
				return true;
		}
		return false;
	}
	
	/**
	 * Returns the package representing the RTAnalysisView.
	 *
	 * @param theModel  the model
	 * @return the package representing the RTAnalysisView
	 */
	public static Package getCHESSRtAnalysisPackage(Model theModel) {
		for (Element p : theModel.allOwnedElements()) {
			if (p instanceof Package)
				if (isRTAnalysisView((Package)p))
					return (Package) p;
		}
		return (Package)theModel;
	}
	
	/**
	 * Returns the package representing the DeploymentView.
	 *
	 * @param theModel  the model
	 * @return the package representing the RTAnalysisView
	 */
	public static Package getCHESSDeploymentPackage(Model theModel) {
		for (Element p : theModel.allOwnedElements()) {
			if (p instanceof Package)
				if (isDeploymentView((Package)p))
					return (Package) p;
		}
		return (Package)theModel;
	}
	
	/**
	 * Returns the package representing the PSMView.
	 *
	 * @param theModel  the model
	 * @return the package representing the RTAnalysisView
	 */
	public static Package getCHESSPSMPackage(Model theModel) {
		for (Element p : theModel.allOwnedElements()) {
			if (p instanceof Package)
				if (isPSMView((Package)p))
					return (Package) p;
		}
		return (Package)theModel;
	}

	/**
	 * Checks if the current view has virtual views activated.
	 * For example if the COMPONENT_VIEW has also the EXTRAFUNCTIONAL_VIEW activated on top of it
	 * then this method returns true.
	 * 
	 * @param currentView  the DesignView service
	 * @return  true if there are virtual view activated.
	 */
	public static boolean hasConcurrentViews(DesignView currentView) {
		for(String v : CHESSProfileManager.CONCURRENT_VIEWS_ASSOCIATION.keySet()){
			if(currentView.isEnabled(v))
				return true;
		}
		return false;
	}
	
	/**
	 * Checks if a design view can have virtual views.
	 * 
	 * @param viewName  the name of the view
	 * @return  true if this view can have virtual views.
	 */
	public static boolean hasConcurrentViews(String viewName) {
		return CHESSProfileManager.CONCURRENT_VIEWS_ASSOCIATION.keySet().contains(viewName);
	}
	
	/**
	 * Returns the name of the current actual view.
	 * 
	 * @param currentView  the DesignView service
	 * @return the name of the current actual view.
	 */
	public static String getBaseViewName(DesignView currentView) {
		return currentView.getName();
	}	
}
