blob: 54975b9b83d1c7565ffa1bcb88f9b339ae97b0dd [file] [log] [blame]
/******************************************************************************
* 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;
}
}