/**
* <copyright>
*
* Copyright (c) 2007,2010 E.D.Willink 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:
* E.D.Willink - initial API and implementation
*
* </copyright>
*
* $Id: OCLTopLevelEnvironment.java,v 1.2 2010/04/08 06:26:35 ewillink Exp $
*/
package org.eclipse.ocl.examples.parser.ocl.environment;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.eclipse.emf.common.notify.Notifier;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.common.util.WrappedException;
import org.eclipse.emf.ecore.EClassifier;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EPackage;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.xmi.XMIResource;
import org.eclipse.ocl.LookupException;
import org.eclipse.ocl.cst.CSTNode;
import org.eclipse.ocl.cst.OCLDocumentCS;
import org.eclipse.ocl.examples.common.plugin.OCLExamplesCommonPlugin;
import org.eclipse.ocl.examples.common.utils.StringUtils;
import org.eclipse.ocl.examples.modelregistry.environment.AbstractModelResolver;
import org.eclipse.ocl.examples.modelregistry.model.ModelNameAccessor;
import org.eclipse.ocl.examples.modelregistry.model.Registration;
import org.eclipse.ocl.examples.parser.environment.ecore.CSTRootEcoreEnvironment;
import org.eclipse.ocl.parser.OCLAnalyzer;
public class OCLTopLevelEnvironment extends CSTRootEcoreEnvironment<OCLEnvironment<?,?,?>,OCLDocumentCS> implements IOCLEnvironment
{
public static final String PACKAGE_NAME_SEPARATOR = ".";
private Map<String, List<EPackage>> packagePath = null;
public OCLTopLevelEnvironment(OCLFileEnvironment parent, XMIResource astResource, OCLDocumentCS cstNode) {
super(parent, astResource, cstNode);
}
public void addToPackagePath(EList<? extends EObject> contents, String path) {
for (EObject eObject : contents) {
if (eObject instanceof EPackage) {
EPackage ePackage = (EPackage) eObject;
String fullPackageName = path != null ? (path + PACKAGE_NAME_SEPARATOR + ePackage.getName()) : ePackage.getName();
List<EPackage> ePackages = packagePath.get(fullPackageName);
if (ePackages == null) {
ePackages = new ArrayList<EPackage>();
packagePath.put(fullPackageName, ePackages);
}
ePackages.add(ePackage);
addToPackagePath(ePackage.getESubpackages(), fullPackageName);
}
}
}
public OCLEnvironment<?,?,?> createNestedEnvironment(CSTNode cstNode) {
return new OCLEnvironment<IOCLEnvironment,Notifier,CSTNode>(this, null, cstNode);
}
public Map<String, List<EPackage>> getPackagePath() {
if (packagePath == null) {
packagePath = new HashMap<String, List<EPackage>>();
AbstractModelResolver resolver = getFileEnvironment().getResolver();
for (Registration<ModelNameAccessor> registration : resolver.getRegistrations(ModelNameAccessor.NAMESPACE)) {
try {
Resource resource = resolver.getResource(registration);
if (resource != null)
addToPackagePath(resource.getContents(), null);
} catch (IOException e) {
OCLExamplesCommonPlugin.logError("Failed to load " + registration, e);
} catch (WrappedException e) {
OCLExamplesCommonPlugin.logError("Failed to load " + registration, e.exception());
}
}
}
return packagePath;
}
@Override
public void postParse() {
super.postParse();
for (EObject eObject : ast.getContents()) { // Fix up the TypeResolver contributions
if (eObject instanceof EPackage) {
EPackage ePackage = (EPackage) eObject;
if (ePackage.getNsURI() == null)
getFileEnvironment().initializePackageNs(ePackage);
}
}
}
@Override public EClassifier tryLookupClassifier(List<String> names) throws LookupException {
EClassifier eClassifier = super.tryLookupClassifier(names);
if (eClassifier != null)
return eClassifier;
if (names.size() > 1) {
List<String> newNames = names.subList(0, names.size() - 1);
EPackage pkg = tryLookupPackage(newNames);
if (pkg != null) {
String name = names.get(names.size() - 1);
EClassifier result = pkg.getEClassifier(name);
if ((result == null) && OCLAnalyzer.isEscaped(name)) {
// try the unescaped name
result = pkg.getEClassifier(OCLAnalyzer.unescape(name));
}
return result;
}
}
return null;
}
@Override public EPackage tryLookupPackage(List<String> path) throws LookupException {
EPackage ePackage = super.tryLookupPackage(path);
if (ePackage != null)
return ePackage;
String fullPackagePath = StringUtils.splice(path, PACKAGE_NAME_SEPARATOR);
Map<String, List<EPackage>> packagePath = getPackagePath();
List<EPackage> ePackages = packagePath.get(fullPackagePath);
if ((ePackages == null) || (ePackages.size() == 0)) {
// analyzerError(cstNode, "typeName", "Unknown package '" + formatString(fullPackagePath) + "'");
return null;
}
if (ePackages.size() > 1)
throw new LookupException("Ambiguous package '" + formatString(fullPackagePath) + "'");
return ePackages.get(0);
}
}