blob: 8a2345184007901993f7eba7830b532d8b4a96d2 [file] [log] [blame]
//------------------------------------------------------------------------------
// 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.validation.constraints;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EReference;
import org.eclipse.emf.ecore.EStructuralFeature;
import org.eclipse.emf.ecore.util.EContentsEList;
import org.eclipse.emf.ecore.util.EcoreUtil;
import org.eclipse.emf.ecore.util.InternalEList;
import org.eclipse.emf.ecore.util.EcoreUtil.ContentTreeIterator;
import org.eclipse.emf.validation.service.AbstractTraversalStrategy;
import org.eclipse.emf.validation.service.ITraversalStrategy;
import org.eclipse.epf.library.edit.util.ModelStructure;
import org.eclipse.epf.library.edit.util.TngUtil;
import org.eclipse.epf.uma.Constraint;
import org.eclipse.epf.uma.ContentElement;
import org.eclipse.epf.uma.ContentPackage;
import org.eclipse.epf.uma.CustomCategory;
import org.eclipse.epf.uma.DiagramElement;
import org.eclipse.epf.uma.MethodConfiguration;
import org.eclipse.epf.uma.MethodElement;
import org.eclipse.epf.uma.MethodLibrary;
import org.eclipse.epf.uma.MethodPackage;
import org.eclipse.epf.uma.MethodPlugin;
import org.eclipse.epf.uma.ProcessComponent;
import org.eclipse.epf.uma.UmaPackage;
import org.eclipse.epf.uma.util.UmaUtil;
/**
* @author Phong Nguyen Le
* @since 1.1
*/
public class LibraryTraversalStrategy extends AbstractTraversalStrategy {
public static final String TRAVERSAL_TYPE = "TRAVERSAL_TYPE"; //$NON-NLS-1$
/**
* Traversal strategy type constant for shadow traversal
*/
public static final int SHADOW = 0;
/**
* Traversal strategy type constant for deep traversal
*/
public static final int DEEP = 1;
public static final ITraversalStrategy deepTraversalStrategy = new LibraryTraversalStrategy(DEEP);
public static class LibraryIterator extends ContentTreeIterator {
private static final long serialVersionUID = -1175428027503440970L;
private int traversalType = DEEP;
protected LibraryIterator(Collection emfObjects) {
super(emfObjects);
}
/**
* @param object
* @param isResolveProxies
*/
public LibraryIterator(Collection eObjects, boolean isResolveProxies, int traversalType, boolean disjoint) {
super(disjoint ? makeTargetsDisjoint(eObjects) : eObjects, isResolveProxies);
this.traversalType = traversalType;
}
@Override
protected Iterator<?> getEObjectChildren(EObject object) {
if(traversalType == DEEP) {
if(!(object instanceof MethodElement)
|| (object instanceof Constraint || object instanceof DiagramElement))
{
return Collections.EMPTY_LIST.iterator();
}
return super.getEObjectChildren(object);
}
if(object instanceof CustomCategory) {
return getEObjectChildren((CustomCategory)object, UmaPackage.Literals.CUSTOM_CATEGORY__CATEGORIZED_ELEMENTS,
UmaPackage.Literals.CUSTOM_CATEGORY);
}
else if (object instanceof ProcessComponent
|| object instanceof MethodConfiguration
|| object instanceof ContentElement
) {
return Collections.EMPTY_LIST.iterator();
}
else if (object instanceof MethodPackage) {
MethodPackage pkg = (MethodPackage) object;
if(TngUtil.isPredefined(pkg) && ModelStructure.CUSTOM_CATEGORY_PACKAGE_NAME.equals(pkg.getName())) {
// this is the content package that contains all the custom categories
// return root custom category as its only child
//
ContentPackage hiddenPkg = UmaUtil.findContentPackage(pkg
.getChildPackages(), ModelStructure.HIDDEN_PACKAGE_NAME);
if (hiddenPkg != null && !hiddenPkg.getContentElements().isEmpty()) {
return hiddenPkg.getContentElements().iterator();
}
else {
return Collections.EMPTY_LIST.iterator();
}
}
else {
return getEObjectChildren(pkg, UmaPackage.Literals.METHOD_PACKAGE__CHILD_PACKAGES, null);
}
}
else if (object instanceof MethodLibrary) {
return getEObjectChildren(
(MethodLibrary) object,
new EStructuralFeature[] {
UmaPackage.Literals.METHOD_LIBRARY__METHOD_PLUGINS,
UmaPackage.Literals.METHOD_LIBRARY__PREDEFINED_CONFIGURATIONS });
}
else if (object instanceof MethodPlugin) {
return getEObjectChildren((EObject) object, UmaPackage.Literals.METHOD_PLUGIN__METHOD_PACKAGES, null);
}
else if (object == this.object) {
return ((Collection)object).iterator();
}
return Collections.EMPTY_LIST.iterator();
}
private Iterator getEObjectChildren(EObject eObject, EStructuralFeature[] features) {
EContentsEList list = new EContentsEList(eObject, features);
return isResolveProxies() ? list.iterator() : list.basicIterator();
}
private Iterator getEObjectChildren(EObject eObject, EReference reference, EClass eClass) {
Iterator iter;
if(reference.isMany()) {
boolean resolve = isResolveProxies();
List list = (List) eObject.eGet(reference, resolve);
iter = !resolve && (list instanceof InternalEList) ? ((InternalEList)list).basicIterator() : list.iterator();
}
else {
Object value = eObject.eGet(reference, isResolveProxies());
iter = value != null ? Collections.singletonList(value).iterator() : Collections.EMPTY_LIST.iterator();
}
if(eClass == null) {
return iter;
}
else {
ArrayList list = new ArrayList();
while(iter.hasNext()) {
Object o = iter.next();
if(eClass.isInstance(o)) {
list.add(o);
}
}
if(list.isEmpty()) {
return Collections.EMPTY_LIST.iterator();
}
else {
return list.iterator();
}
}
}
}
public static int countElements(Collection traversalRoots, int traversalType) {
return countElements(traversalRoots, true, traversalType);
}
private static int countElements(Collection traversalRoots, boolean makeDisjoint, int traversalType) {
int count = 0;
for(Iterator iter = new LibraryIterator(traversalRoots, true, traversalType, makeDisjoint); iter.hasNext(); count++) {
iter.next();
}
return count;
}
private Collection roots;
private boolean contextChanged = true;
private int type = DEEP;
/**
* Initializes me.
*/
public LibraryTraversalStrategy() {
super();
}
public LibraryTraversalStrategy(int traversalType) {
this.type = traversalType;
}
public void startTraversal(
Collection traversalRoots,
IProgressMonitor progressMonitor) {
roots = makeTargetsDisjoint(traversalRoots);
super.startTraversal(traversalRoots, progressMonitor);
}
private Collection getRoots() {
return roots;
}
/* (non-Javadoc)
* Implements the inherited method.
*/
protected int countElements(Collection ignored) {
return countElements(getRoots(), false, type);
}
/* (non-Javadoc)
* Implements the inherited method.
*/
protected Iterator createIterator(Collection ignored) {
return new LibraryIterator(getRoots(), true, type, false) {
private static final long serialVersionUID = -5653134989235663973L;
public Iterator getChildren(Object obj) {
if (obj == getRoots()) {
return new Iterator() {
private final Iterator delegate =
getRoots().iterator();
public boolean hasNext() {
return delegate.hasNext();
}
public Object next() {
// if I'm being asked for my next element, then
// we are stepping to another traversal root
contextChanged = true;
return delegate.next();
}
public void remove() {
delegate.remove();
}};
} else {
return super.getChildren(obj);
}
}
public Object next() {
// this will be set to true again the next time we test hasNext() at
// the traversal root level
contextChanged = false;
return super.next();
}};
}
public boolean isClientContextChanged() {
return contextChanged;
}
public static Set makeTargetsDisjoint(Collection objects) {
Set result = new java.util.HashSet();
// ensure that any contained (descendent) elements of other elements
// that we include are not included, because they will be
// traversed by recursion, anyway
for (Iterator outer = objects.iterator(); outer.hasNext();) {
EObject outerNext = (EObject)outer.next();
for (Iterator inner = result.iterator(); inner.hasNext();) {
EObject innerNext = (EObject)inner.next();
if (EcoreUtil.isAncestor(innerNext, outerNext)) {
outerNext = null; // forget this one
break;
}
}
if (outerNext != null) {
result.add(outerNext);
}
}
return result;
}
}