| /* |
| * Copyright (c) 2008, 2009 Borland Software Corporation |
| * |
| * 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: |
| * Artem Tikhomirov (Borland) - initial API and implementation |
| */ |
| package org.eclipse.gmf.internal.codegen.util; |
| |
| import java.util.HashMap; |
| import java.util.List; |
| |
| import org.eclipse.emf.ecore.EAttribute; |
| import org.eclipse.emf.ecore.EClass; |
| import org.eclipse.emf.ecore.EDataType; |
| import org.eclipse.emf.ecore.EObject; |
| import org.eclipse.emf.ecore.EPackage; |
| import org.eclipse.emf.ecore.EStructuralFeature; |
| import org.eclipse.gmf.internal.common.migrate.FilteringCopier; |
| |
| /** |
| * Migrate GMFGen model from year 2006-2007 (as of 2.0 release) to version of |
| * year 2008 (release 2.1) |
| * @author artem |
| */ |
| public /*package-local, but need to be visible from tests*/ class Migrate2008 { |
| private boolean myIsMigrationApplied = false; |
| |
| private final EPackage myMetaPackage; |
| |
| public Migrate2008() { |
| //myMetaPackage = GMFGenPackage.eINSTANCE; |
| myMetaPackage = EPackage.Registry.INSTANCE.getEPackage(ModelVersions.GMFGEN_2_1); |
| } |
| |
| @SuppressWarnings("unchecked") |
| public EObject go(EObject o) { |
| |
| EPackage oldGenModel = o.eClass().getEPackage(); |
| final EStructuralFeature modelElementSelector = ((EClass) oldGenModel.getEClassifier("TypeModelFacet")).getEStructuralFeature("modelElementSelector"); |
| final EStructuralFeature valueExprLanguage = ((EClass) oldGenModel.getEClassifier("ValueExpression")).getEStructuralFeature("language"); |
| final EStructuralFeature gfvsBody = ((EClass) oldGenModel.getEClassifier("GenFeatureValueSpec")).getEStructuralFeature("body"); |
| final EStructuralFeature lcSourceEnd = ((EClass) oldGenModel.getEClassifier("GenLinkConstraints")).getEStructuralFeature("sourceEnd"); |
| final EStructuralFeature lcTargetEnd = ((EClass) oldGenModel.getEClassifier("GenLinkConstraints")).getEStructuralFeature("targetEnd"); |
| final EStructuralFeature auditRule = ((EClass) oldGenModel.getEClassifier("GenAuditRule")).getEStructuralFeature("rule"); |
| final EStructuralFeature metricRule = ((EClass) oldGenModel.getEClassifier("GenMetricRule")).getEStructuralFeature("rule"); |
| final EStructuralFeature providers = ((EClass) oldGenModel.getEClassifier("GenExpressionProviderContainer")).getEStructuralFeature("providers"); |
| final EStructuralFeature ctxSelectorClassName = ((EClass) oldGenModel.getEClassifier("GenAuditRule")).getEStructuralFeature("contextSelectorLocalClassName"); |
| // |
| FilteringCopier cc = new FilteringCopier(myMetaPackage); |
| cc.ignore(modelElementSelector); |
| cc.ignore(valueExprLanguage); |
| cc.ignore(gfvsBody); |
| cc.ignore(lcSourceEnd); |
| cc.ignore(lcTargetEnd); |
| cc.ignore(auditRule); |
| cc.ignore(metricRule); |
| cc.ignore(providers); |
| cc.ignore(ctxSelectorClassName); |
| EObject result = cc.go(o); |
| |
| // |
| HashMap<EObject, EObject> oldValueExpr2New = new HashMap<EObject, EObject>(); |
| assert cc.getIgnoredOwners(providers).size() < 2; |
| EObject providerContainer = cc.getIgnoredOwners(providers).isEmpty() ? null : cc.getIgnoredOwners(providers).get(0); |
| if (providerContainer != null) { |
| EObject newProviderContainer = cc.get(providerContainer); |
| List<EObject> allNewProviders = (List<EObject>) newProviderContainer.eGet(newProviderContainer.eClass().getEStructuralFeature(providers.getName())); |
| for (EObject oldProvider : (List<EObject>) providerContainer.eGet(providers)) { |
| EClass newProviderClass = (EClass) myMetaPackage.getEClassifier(oldProvider.eClass().getName()); |
| EObject newProvider = myMetaPackage.getEFactoryInstance().create(newProviderClass); |
| if ("GenExpressionInterpreter".equals(oldProvider.eClass().getName())) { |
| EStructuralFeature oldLang = oldProvider.eClass().getEStructuralFeature("language"); |
| EStructuralFeature oldClassName = oldProvider.eClass().getEStructuralFeature("className"); |
| newProvider.eSet(newProviderClass.getEStructuralFeature(oldLang.getName()), cc.transformValue((EAttribute) oldLang, oldProvider.eGet(oldLang))); |
| newProvider.eSet(newProviderClass.getEStructuralFeature(oldClassName.getName()), oldProvider.eGet(oldClassName)); |
| } |
| allNewProviders.add(newProvider); |
| EStructuralFeature provBaseExpressions = ((EClass) oldGenModel.getEClassifier("GenExpressionProviderBase")).getEStructuralFeature("expressions"); |
| List<EObject> newProviderExpressions = (List<EObject>) newProvider.eGet(newProvider.eClass().getEStructuralFeature(provBaseExpressions.getName())); |
| for (EObject oldVE : (List<EObject>) oldProvider.eGet(provBaseExpressions)) { |
| EObject newVE; |
| if (oldVE.eClass().getName().equals("GenConstraint")) { |
| newVE = myMetaPackage.getEFactoryInstance().create((EClass) myMetaPackage.getEClassifier("GenConstraint")); |
| } else { |
| // intentionally transform GenFeatureValueSpec into plain ValueExpression |
| newVE = myMetaPackage.getEFactoryInstance().create((EClass) myMetaPackage.getEClassifier("ValueExpression")); |
| } |
| Object bodyValue = oldVE.eGet(oldVE.eClass().getEStructuralFeature("body")); |
| newVE.eSet(newVE.eClass().getEStructuralFeature("body"), bodyValue); |
| oldValueExpr2New.put(oldVE, newVE); |
| newProviderExpressions.add(newVE); |
| } |
| } |
| containment2AssociationCase(cc, modelElementSelector, oldValueExpr2New, allNewProviders); |
| containment2AssociationCase(cc, lcSourceEnd, oldValueExpr2New, allNewProviders); |
| containment2AssociationCase(cc, lcTargetEnd, oldValueExpr2New, allNewProviders); |
| containment2AssociationCase(cc, auditRule, oldValueExpr2New, allNewProviders); |
| containment2AssociationCase(cc, metricRule, oldValueExpr2New, allNewProviders); |
| for (EObject vs : cc.getIgnoredOwners(gfvsBody)) { |
| assert vs.eClass().getName().equals("GenFeatureValueSpec"); |
| myIsMigrationApplied = true; |
| EObject newVS = cc.get(vs); |
| EObject newVE = oldValueExpr2New.get(vs); |
| if (newVE == null) { |
| // isCopy == true, need to match by lang/body |
| newVE = matchCopyVE(vs, allNewProviders); |
| } |
| if (newVE != null) { |
| newVS.eSet(newVS.eClass().getEStructuralFeature("value"), newVE); |
| } |
| } |
| } |
| for (EObject oldRule : cc.getIgnoredOwners(ctxSelectorClassName)) { |
| assert "GenAuditRule".equals(oldRule.eClass().getName()); |
| if (!oldRule.eIsSet(ctxSelectorClassName)) { |
| continue; |
| } |
| EObject root = cc.get(oldRule.eGet(oldRule.eClass().getEStructuralFeature("root"))); |
| assert root != null; |
| myIsMigrationApplied = true; |
| String className = (String) oldRule.eGet(ctxSelectorClassName); |
| EObject context = getOrCreateContext(root, className); |
| EObject target = cc.get(oldRule.eGet(oldRule.eClass().getEStructuralFeature("target"))); |
| if (target != null) { |
| target.eSet(((EClass) myMetaPackage.getEClassifier("GenAuditable")).getEStructuralFeature("contextSelector"), context); |
| } |
| } |
| return result; |
| } |
| |
| @SuppressWarnings("unchecked") |
| private static EObject matchCopyVE(EObject oldVE, List<EObject> allProviders) { |
| final EStructuralFeature langFeature = oldVE.eClass().getEStructuralFeature("language"); |
| final EStructuralFeature bodyFeature = oldVE.eClass().getEStructuralFeature("body"); |
| if (langFeature == null || bodyFeature == null) { |
| return null; |
| } |
| final Object langValue = oldVE.eClass().getEPackage().getEFactoryInstance().convertToString((EDataType) langFeature.getEType(), oldVE.eGet(langFeature)); |
| final Object bodyValue = oldVE.eGet(bodyFeature); |
| if (bodyValue != null) { |
| for (EObject p : allProviders) { |
| EStructuralFeature provLangFeat = p.eClass().getEStructuralFeature("language"); |
| // java provider has no language feature, hence hardcoded "java" value |
| Object providerLang = provLangFeat == null ? "java" : p.eClass().getEPackage().getEFactoryInstance().convertToString((EDataType) provLangFeat.getEType(), p.eGet(provLangFeat)); |
| if (providerLang != null && providerLang.equals(langValue)) { |
| for (EObject ve : (List<EObject>) p.eGet(p.eClass().getEStructuralFeature("expressions"))) { |
| EStructuralFeature veBodyFeature = ve.eClass().getEStructuralFeature("body"); |
| if (veBodyFeature != null /* just in case */&& bodyValue.equals(ve.eGet(veBodyFeature))) { |
| return ve; |
| } |
| } |
| } |
| } |
| } // body == null, no much sense to match... |
| return null; |
| } |
| |
| private void containment2AssociationCase(FilteringCopier cc, EStructuralFeature oldFeature, HashMap<EObject, EObject> old2newVE, List<EObject> allProviders) { |
| for (EObject o : cc.getIgnoredOwners(oldFeature)) { |
| EObject n = cc.get(o); |
| Object oldVE = o.eGet(oldFeature); |
| if (oldVE == null) { |
| continue; //nothing to do. |
| } |
| myIsMigrationApplied = true; |
| EObject newVE = old2newVE.get(oldVE); |
| if (newVE == null) { |
| // isCopy == true, need to match by lang/body |
| if (oldVE instanceof EObject) { |
| newVE = matchCopyVE((EObject) oldVE, allProviders); |
| } |
| } |
| if (newVE != null) { |
| n.eSet(n.eClass().getEStructuralFeature(oldFeature.getName()), newVE); |
| } |
| } |
| } |
| |
| @SuppressWarnings("unchecked") |
| private static EObject getOrCreateContext(EObject root, String className) { |
| assert root != null && "GenAuditRoot".equals(root.eClass().getName()); |
| EPackage metaPackage = root.eClass().getEPackage(); |
| EClass class_genAuditContext = (EClass) metaPackage.getEClassifier("GenAuditContext"); |
| EStructuralFeature feature_genAuditContext_className = class_genAuditContext.getEStructuralFeature("className"); |
| EStructuralFeature feature_genAuditContext_id = class_genAuditContext.getEStructuralFeature("id"); |
| EStructuralFeature feature_genAuditRoot_clientContexts = root.eClass().getEStructuralFeature("clientContexts"); |
| EObject context = null; |
| for (EObject next : (List<EObject>) root.eGet(feature_genAuditRoot_clientContexts)) { |
| String explicit = (String) next.eGet(feature_genAuditContext_className); |
| if (className == explicit || (className != null && className.equals(explicit)) || (explicit == null && className.equals(next.eGet(feature_genAuditContext_id)))) { |
| context = next; |
| break; |
| } |
| } |
| if (context == null) { |
| context = metaPackage.getEFactoryInstance().create(class_genAuditContext); |
| String id = generateUnique(root, className == null ? "" : className); |
| context.eSet(feature_genAuditContext_id, id); |
| if (!id.equals(className)) { |
| context.eSet(feature_genAuditContext_className, className); |
| } |
| ((List<EObject>) root.eGet(feature_genAuditRoot_clientContexts)).add(context); |
| } |
| return context; |
| } |
| |
| @SuppressWarnings("unchecked") |
| private static String generateUnique(EObject root, String defaultId) { |
| assert root != null && "GenAuditRoot".equals(root.eClass().getName()); |
| String id = defaultId; |
| int i = 0; |
| boolean haveSuchId = false; |
| EStructuralFeature feature_genAuditRoot_clientContexts = root.eClass().getEStructuralFeature("clientContexts"); |
| do { |
| haveSuchId = false; |
| for (EObject next : (List<EObject>) root.eGet(feature_genAuditRoot_clientContexts)) { |
| EStructuralFeature feature_genAuditContext_id = next.eClass().getEStructuralFeature("id"); |
| if (id.equals(next.eGet(feature_genAuditContext_id))) { |
| haveSuchId = true; |
| id = defaultId + (++i); |
| break; |
| } |
| } |
| } while (haveSuchId); |
| return id; |
| } |
| |
| public boolean wasMigrationApplied() { |
| return myIsMigrationApplied; |
| } |
| } |