/******************************************************************************* * Copyright (c) 2008 Borland Software 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: * Borland Software Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.m2m.internal.qvt.oml.ast.parser; import java.util.HashMap; import java.util.LinkedList; import java.util.List; import java.util.Map; import org.eclipse.emf.ecore.EStructuralFeature; import org.eclipse.m2m.internal.qvt.oml.ast.env.QvtOperationalEnv; import org.eclipse.m2m.internal.qvt.oml.expressions.ContextualProperty; import org.eclipse.m2m.internal.qvt.oml.expressions.Module; import org.eclipse.m2m.internal.qvt.oml.expressions.ModuleImport; import org.eclipse.ocl.util.TypeUtil; import org.eclipse.ocl.utilities.UMLReflection; public class IntermediatePropertyHierarchy { private QvtOperationalEnv fEnv; private Map<String, List<Entry>> fData; public IntermediatePropertyHierarchy(Module module, QvtOperationalEnv env) { if(env == null) { throw new IllegalArgumentException(); } fEnv = env; readHierarchy(module); } public boolean hasHierarchyClashes(ContextualProperty property) { if(fData == null || fData.isEmpty()) { return false; } List<Entry> entryList = fData.get(property.getName()); if(entryList == null) { return false; } for (Entry entry : entryList) { Boolean status = entry.isClashingWith(property); if(Boolean.TRUE.equals(status)) { return true; } } return false; } private Map<String, List<Entry>> getData() { if(fData == null) { fData = new HashMap<String, List<Entry>>(); } return fData; } private void readHierarchy(Module module) { for (ModuleImport moduleImport : module.getModuleImport()) { Module importedModule = moduleImport.getImportedModule(); if(importedModule != null) { readHierarchy(importedModule); } } for (EStructuralFeature nextFeature : module.getEAllStructuralFeatures()) { if(nextFeature instanceof ContextualProperty) { ContextualProperty ctxProp = (ContextualProperty) nextFeature; if(ctxProp.getContext() == null) { continue; } String name = ctxProp.getName(); List<Entry> entryList = getData().get(name); if(entryList == null) { entryList = new LinkedList<Entry>(); getData().put(name, entryList); } boolean joined = false; for (Entry entry : entryList) { if(entry.addIfApplicable(ctxProp)) { joined = true; break; } } if(!joined) { Entry newEntry = new Entry(); entryList.add(newEntry); newEntry.addIfApplicable(ctxProp); } } } } private boolean isPartOfHierarchy(ContextualProperty c1, ContextualProperty c2) { if(c1.getContext() != null && c2.getContext() != null) { int rel = TypeUtil.getRelationship(fEnv, c1.getContext(), c2.getContext()); return (rel & UMLReflection.RELATED_TYPE) != 0; } return false; } private class Entry { private List<ContextualProperty> hierarchy; boolean addIfApplicable(ContextualProperty property) { if(hierarchy == null) { hierarchy = new LinkedList<ContextualProperty>(); hierarchy.add(property); return true; } for (ContextualProperty contextualProperty : hierarchy) { if(property != contextualProperty && isPartOfHierarchy(contextualProperty, property)) { hierarchy.add(property); return false; } } return false; } Boolean isClashingWith(ContextualProperty property) { if(hierarchy == null || hierarchy.isEmpty() || !hierarchy.contains(property)) { return null; } return hierarchy.size() > 1 ? Boolean.TRUE : Boolean.FALSE; } @Override public String toString() { StringBuilder buf = new StringBuilder(); buf.append('['); if(hierarchy != null) { for (ContextualProperty prop : hierarchy) { if(prop.getContext() != null) { buf.append(prop.getContext().getName()); } buf.append(','); } } buf.append(']'); return buf.toString(); } } }