/******************************************************************************* * Copyright (c) 2008, 2010 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.HashSet; import java.util.IdentityHashMap; import java.util.Map; import java.util.Set; import org.eclipse.emf.common.notify.Adapter; import org.eclipse.emf.ecore.EClass; import org.eclipse.emf.ecore.EFactory; import org.eclipse.emf.ecore.EObject; import org.eclipse.emf.ecore.EStructuralFeature; import org.eclipse.emf.ecore.util.EcoreUtil; import org.eclipse.m2m.internal.qvt.oml.ast.env.QvtOperationalEvaluationEnv; import org.eclipse.m2m.internal.qvt.oml.ast.env.QvtOperationalStdLibrary; import org.eclipse.m2m.internal.qvt.oml.cst.adapters.AbstractGenericAdapter; 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; /** * @author sboyko * */ public class IntermediatePropertyModelAdapter extends AbstractGenericAdapter<IntermediatePropertyModelAdapter> { private IntermediatePropertyModelAdapter() { } public boolean isAdapterForType(Object type) { return type == IntermediatePropertyModelAdapter.class; } @Override public boolean equals(Object obj) { return obj instanceof IntermediatePropertyModelAdapter; } @Override public int hashCode() { return IntermediatePropertyModelAdapter.class.hashCode(); } public static ShadowEntry getPropertyHolder(EObject moduleInstance, ContextualProperty property, Object ownerInstance) { IntermediatePropertyModelAdapter adapter = (IntermediatePropertyModelAdapter) EcoreUtil.getAdapter(moduleInstance.eAdapters(), IntermediatePropertyModelAdapter.class); if (adapter == null) { adapter = new IntermediatePropertyModelAdapter(); moduleInstance.eAdapters().add(adapter); } return adapter.getPropertyHolder(property, ownerInstance); } private ShadowEntry getPropertyHolder(ContextualProperty property, Object ownerInstance) { ShadowEntry runtimeShadow = myProp2HolderMap.get(property); if(runtimeShadow == null) { runtimeShadow = new ShadowEntry(myPropShadowHelper.createShadowProperty(property)); myProp2HolderMap.put(property, runtimeShadow); } return runtimeShadow; } private static Object getInitialValue(EStructuralFeature feature, QvtOperationalEvaluationEnv evalEnv) { //return myInitExpression.accept(evalVisitor); return EvaluationUtil.createInitialValue(feature.getEType(), QvtOperationalStdLibrary.INSTANCE.getOCLStdLib(), evalEnv); } private final Map<ContextualProperty, ShadowEntry> myProp2HolderMap = new IdentityHashMap<ContextualProperty, ShadowEntry>(2); private final RuntimePropertyShadowHelper myPropShadowHelper = new RuntimePropertyShadowHelper(); public static class ShadowEntry { private EStructuralFeature myFeature; private Map<Object, EObject> myOwner2ShadowMap = new IdentityHashMap<Object, EObject>(); private ShadowEntry(EStructuralFeature runtimeFeature) { assert runtimeFeature != null; myFeature = runtimeFeature; } public EStructuralFeature getProperty() { return myFeature; } public EObject getPropertyRuntimeOwner(Object shadowedInstance, QvtOperationalEvaluationEnv evalEnv) { EObject owner = myOwner2ShadowMap.get(shadowedInstance); if (owner == null) { EClass ownerClass = myFeature.getEContainingClass(); EFactory eFactory = ownerClass.getEPackage().getEFactoryInstance(); owner = eFactory.create(ownerClass); myOwner2ShadowMap.put(shadowedInstance, owner); Object initialValue = getInitialValue(myFeature, evalEnv); if (initialValue != null) { owner.eSet(myFeature, initialValue); } } return owner; } } /* https://bugs.eclipse.org/bugs/show_bug.cgi?id=279251 */ public static void cleanup(Module module) { cleanup(module, new HashSet<Module>()); } private static void cleanup(Module module, Set<Module> processed) { Adapter adapter = EcoreUtil.getExistingAdapter(module, IntermediatePropertyModelAdapter.class); if(adapter != null) { module.eAdapters().remove(adapter); } processed.add(module); for(ModuleImport nextImport : module.getModuleImport()) { Module importedModule = nextImport.getImportedModule(); if(!processed.contains(importedModule)) { cleanup(importedModule, processed); } } } }