/******************************************************************************* * Copyright (c) 2009 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.evaluator; import java.util.HashMap; import java.util.Map; import org.eclipse.emf.ecore.EOperation; import org.eclipse.m2m.internal.qvt.oml.expressions.ImperativeOperation; import org.eclipse.m2m.internal.qvt.oml.expressions.ImportKind; import org.eclipse.m2m.internal.qvt.oml.expressions.Module; import org.eclipse.m2m.internal.qvt.oml.expressions.ModuleImport; class OperationOverrideMap { private Map<ImperativeOperation, ImperativeOperation> fMapping; OperationOverrideMap() { super(); } public ImperativeOperation getOverridingOperation(ImperativeOperation overridden) { if(overridden == null) { throw new IllegalArgumentException(); } return fMapping == null ? null : fMapping.get(overridden); } static Map<Module, OperationOverrideMap> create(Module mainModule) { HashMap<Module, OperationOverrideMap> module2OverrideMap = new HashMap<Module, OperationOverrideMap>(3); buildModuleOverrideMap(mainModule, module2OverrideMap); for (ModuleImport moduleImport : mainModule.getModuleImport()) { if(moduleImport.getKind() == ImportKind.EXTENSION) { Module importedModule = moduleImport.getImportedModule(); inherit(mainModule, importedModule, module2OverrideMap); } } module2OverrideMap.get(mainModule); return module2OverrideMap; } private static void buildModuleOverrideMap(Module module, Map<Module, OperationOverrideMap> modules2OverrideMap) { for (EOperation operation : module.getEOperations()) { if(operation instanceof ImperativeOperation) { ImperativeOperation overriding = (ImperativeOperation) operation; ImperativeOperation overridden = overriding.getOverridden(); if(overridden != null) { pushUpOperation(overriding, overridden, modules2OverrideMap); } } } for (ModuleImport moduleImport : module.getModuleImport()) { if(moduleImport.getKind() == ImportKind.EXTENSION) { Module importedModule = moduleImport.getImportedModule(); buildModuleOverrideMap(importedModule, modules2OverrideMap); } } } private static void inherit(Module extending, Module extended, Map<Module, OperationOverrideMap> modules2OverrideMap) { for (ModuleImport moduleImport : extended.getModuleImport()) { if(moduleImport.getKind() == ImportKind.EXTENSION) { inherit(extended, moduleImport.getImportedModule(), modules2OverrideMap); } } OperationOverrideMap extendedMap = modules2OverrideMap.get(extended); if(extendedMap != null) { OperationOverrideMap extendingMap = modules2OverrideMap.get(extending); if(extendingMap == null) { modules2OverrideMap.put(extending, extendingMap = new OperationOverrideMap()); } extendingMap.merge(extendedMap); } } private static void pushUpOperation(ImperativeOperation overriding, ImperativeOperation overriden, Map<Module, OperationOverrideMap> tableMap) { Module extendedModule = (Module)overriden.getEContainingClass(); OperationOverrideMap nextTable = tableMap.get(extendedModule); if(nextTable == null) { nextTable = new OperationOverrideMap(); tableMap.put(extendedModule, nextTable); } ImperativeOperation existingOverride = nextTable.getOverridingOperation(overriden); if(existingOverride != null) { return; } nextTable.add(overriden, overriding); if(overriden.getOverridden() != null) { pushUpOperation(overriding, overriden.getOverridden(), tableMap); } } private void merge(OperationOverrideMap mergedMap) { if(fMapping == null) { fMapping = new HashMap<ImperativeOperation, ImperativeOperation>(); } if(mergedMap != null) { fMapping.putAll(mergedMap.fMapping); } } private void add(ImperativeOperation overriden, ImperativeOperation overriding) { if(fMapping == null) { fMapping = new HashMap<ImperativeOperation, ImperativeOperation>(); } fMapping.put(overriden, overriding); } }