/****************************************************************************** * 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 API and implementation ****************************************************************************/ package org.eclipse.gmf.runtime.emf.type.core.internal.descriptors; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IConfigurationElement; import org.eclipse.emf.ecore.EClass; import org.eclipse.emf.ecore.EClassifier; import org.eclipse.emf.ecore.EPackage; import org.eclipse.emf.ecore.EReference; import org.eclipse.emf.ecore.EStructuralFeature; import org.eclipse.gmf.runtime.common.core.util.Log; import org.eclipse.gmf.runtime.common.core.util.StringStatics; import org.eclipse.gmf.runtime.emf.type.core.IContainerDescriptor; import org.eclipse.gmf.runtime.emf.type.core.IElementMatcher; import org.eclipse.gmf.runtime.emf.type.core.internal.EMFTypePlugin; import org.eclipse.gmf.runtime.emf.type.core.internal.EMFTypePluginStatusCodes; import org.eclipse.gmf.runtime.emf.type.core.internal.impl.XMLExpressionMatcher; import org.eclipse.gmf.runtime.emf.type.core.internal.l10n.EMFTypeCoreMessages; /** * Descriptor for a model element container. * * @author ldamus */ class ContainerDescriptor implements IContainerDescriptor { /** * The matcher class name. May be <code>null</code>. */ private String matcherClassName; /** * The container element matcher. May be <code>null</code>. */ private IElementMatcher matcher; /** * The container matcher configuration element. */ private IConfigurationElement matcherConfig; /** * The containment features. May be <code>null</code>. */ private EReference[] containmentFeatures; /** * The containment feature names. */ private List featureNames = new ArrayList(); /** * The metamodel descriptor. */ private final MetamodelDescriptor metamodelDescriptor; /** * Constructs a new container descriptor from the configuration element. * * @param config * the configuration element * @throws CoreException * when the configuration element does not contain the required * elements and attributes */ public ContainerDescriptor(IConfigurationElement config, MetamodelDescriptor metamodelDescriptor, String id) throws CoreException { this.metamodelDescriptor = metamodelDescriptor; // CONTAINMENT FEATURES IConfigurationElement[] featureConfigs = config .getChildren(ElementTypeXmlConfig.E_ECONTAINMENT_FEATURE); if (featureConfigs.length > 0 && metamodelDescriptor == null) { // Containment features can only be specified if a metamodel is // specified. throw EMFTypePluginStatusCodes .getInitException( id, EMFTypeCoreMessages .bind( EMFTypeCoreMessages.element_reason_no_econtainmentfeature_metamodel_WARN_, featureConfigs[0]), null); } for (int i = 0; i < featureConfigs.length; i++) { IConfigurationElement nextFeatureConfig = featureConfigs[i]; String qname = nextFeatureConfig .getAttribute(ElementTypeXmlConfig.A_QNAME); if (qname == null) { throw EMFTypePluginStatusCodes .getInitException( id, EMFTypeCoreMessages.element_reason_no_econtainmentfeature_qname_WARN_, null); } featureNames.add(qname); } // XML MATCHER EXPRESSION IConfigurationElement[] enablementConfigs = config .getChildren(ElementTypeXmlConfig.E_ENABLEMENT); if (enablementConfigs.length > 0) { matcher = new XMLExpressionMatcher(enablementConfigs[0], id); } // MATCHER CLASS if (matcher == null) { IConfigurationElement[] matcherConfigs = config .getChildren(ElementTypeXmlConfig.E_MATCHER); if (matcherConfigs.length > 0) { matcherClassName = matcherConfigs[0] .getAttribute(ElementTypeXmlConfig.A_CLASS); if (matcherClassName == null) { throw EMFTypePluginStatusCodes .getInitException( id, EMFTypeCoreMessages.element_reason_matcher_no_class_WARN_, null); } matcherConfig = matcherConfigs[0]; } } } /* * (non-Javadoc) * * @see org.eclipse.gmf.runtime.emf.type.core.IContainerDescriptor#getMatcher() */ public IElementMatcher getMatcher() { if (matcher == null && matcherClassName != null && matcherConfig != null) { try { matcher = (IElementMatcher) matcherConfig .createExecutableExtension(ElementTypeXmlConfig.A_CLASS); } catch (CoreException e) { Log .error( EMFTypePlugin.getPlugin(), EMFTypePluginStatusCodes.MATCHER_CLASS_NOT_FOUND, EMFTypeCoreMessages .bind( EMFTypeCoreMessages.matcher_class_not_found_ERROR_, matcherClassName), e); // Don't recompute the matcher class if it has failed once. matcherClassName = null; } } return matcher; } /* * (non-Javadoc) * * @see org.eclipse.gmf.runtime.emf.type.core.IContainerDescriptor#getContainmentFeatures() */ public EReference[] getContainmentFeatures() { if (containmentFeatures == null && !featureNames.isEmpty()) { List references = new ArrayList(); if (metamodelDescriptor != null) { for (Iterator i = featureNames.iterator(); i.hasNext();) { String nextFeatureName = (String) i.next(); EPackage ePackage = metamodelDescriptor.getEPackage(); int featureIndex = nextFeatureName .lastIndexOf(StringStatics.PERIOD); String classifierName = nextFeatureName.substring(0, featureIndex); EClassifier classifier = ePackage .getEClassifier(classifierName); if ((featureIndex < nextFeatureName.length() - 1) && classifier instanceof EClass) { String featureName = nextFeatureName .substring(featureIndex + 1); EStructuralFeature feature = ((EClass) classifier) .getEStructuralFeature(featureName); if (feature instanceof EReference) { references.add(feature); } else { Log .error( EMFTypePlugin.getPlugin(), EMFTypePluginStatusCodes.CONTAINMENT_FEATURE_NOT_REFERENCE_FEATURE, EMFTypeCoreMessages .bind( EMFTypeCoreMessages.eContainmentFeature_not_reference_feature_ERROR_, nextFeatureName), null); } } else { Log .error( EMFTypePlugin.getPlugin(), EMFTypePluginStatusCodes.CONTAINMENT_FEATURE_NO_SUCH_FEATURE, EMFTypeCoreMessages .bind( EMFTypeCoreMessages.eContainmentFeature_no_such_feature_ERROR_, nextFeatureName), null); } } } containmentFeatures = (EReference[]) references .toArray(new EReference[] {}); } return containmentFeatures; } }