/******************************************************************************
* 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: CSTFileEnvironment.java,v 1.3 2010/04/08 06:26:23 ewillink Exp $
*/
package org.eclipse.ocl.examples.parser.environment;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.Reader;
import java.util.ArrayList;
import java.util.List;
import lpg.runtime.Monitor;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.emf.common.notify.Adapter;
import org.eclipse.emf.ecore.EPackage;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.resource.ResourceSet;
import org.eclipse.emf.ecore.xmi.XMIResource;
import org.eclipse.ocl.Environment;
import org.eclipse.ocl.TypeResolver;
import org.eclipse.ocl.cst.CSTNode;
import org.eclipse.ocl.examples.common.utils.XMIUtils;
import org.eclipse.ocl.examples.modelregistry.environment.FileHandle;
import org.eclipse.ocl.examples.modelregistry.environment.AbstractModelResolver;
import org.eclipse.ocl.examples.parser.utils.LPGProgressMonitor;
import org.eclipse.ocl.lpg.AbstractParser;
public abstract class CSTFileEnvironment<PK, C, O, P, EL, PM, S, COA, SSA, CT, CLS, E, R extends ICSTRootEnvironment<PK, C, O, P, EL, PM, S, COA, SSA, CT, CLS, E>, V extends ICSTNodeEnvironment<PK, C, O, P, EL, PM, S, COA, SSA, CT, CLS, E>, CST extends CSTNode>
extends CSTEnvironment<PK, C, O, P, EL, PM, S, COA, SSA, CT, CLS, E, V>
implements ICSTFileEnvironment<PK, C, O, P, EL, PM, S, COA, SSA, CT, CLS, E>
{
protected final EPackage.Registry registry;
protected final XMIResource ast;
protected final AbstractModelResolver resolver;
private TypeResolver<C, O, P> typeResolver; // FIXME Duplicated to support reset
// inherited functionality should allow typeResolver to be in CSTRootEnvironment
private CSTFileEnvironment(EPackage.Registry registry, FileHandle file, ResourceSet resourceSet, XMIResource astResource) {
super(null); // Null suppresses inherited createTypeResolver
// super(registry, null); // Null suppresses inherited createTypeResolver
assert (astResource != null);
ast = astResource;
typeResolver = createTypeResolver(ast);
this.registry = registry;
if (file != null) {
resolver = new AbstractModelResolver(file);
resolver.setResourceSet(resourceSet);
}
else
resolver = null;
}
protected CSTFileEnvironment(FileHandle file, ResourceSet resourceSet, XMIResource astResource) {
this(resourceSet.getPackageRegistry(), file, resourceSet, astResource);
}
public abstract ICSTFileAnalyzer<PK, C, O, P, EL, PM, S, COA, SSA, CT, CLS, E, R> createAnalyzer(Monitor monitor);
protected abstract R createRootEnvironment(XMIResource ast, CST cst);
protected abstract TypeResolver<C, O, P> createTypeResolver(Resource resource);
public XMIResource getASTResource() {
return ast;
}
protected abstract String getContentTypeIdentifier();
public FileHandle getFile() {
return getResolver().getHandle();
}
public ICSTFileEnvironment<PK, C, O, P, EL, PM, S, COA, SSA, CT, CLS, E> getFileEnvironment() {
return this;
}
public EPackage.Registry getRegistry() {
return registry;
}
public AbstractModelResolver getResolver() {
return resolver;
}
public ResourceSet getResourceSet() {
return resolver.getResourceSet();
}
public TypeResolver<C, O, P> getTypeResolver() {
return typeResolver;
}
public void initializePackageNs(EPackage ePackage) {
ePackage.setNsPrefix(ePackage.getName());
ePackage.setNsURI(UnresolvedEnvironment.computePackageNs(resolver.getHandle(), ePackage));
}
/**
* Checks whether the specified element has the given name, accounting for
* possibility of underscore-escaped names.
*
* @param name
* a possibly underscore-escaped name of an element
* @param element
* a named element
*
* @return whether the element has this name
* @since 3.0
*/
protected abstract boolean isNamed(E element, String name);
public ICSTRootEnvironment<PK, C, O, P, EL, PM, S, COA, SSA, CT, CLS, E> parse(Reader reader, FileHandle file, IProgressMonitor monitor) throws IOException, CoreException {
Monitor lpgMonitor = new LPGProgressMonitor(monitor);
ICSTFileAnalyzer<PK, C, O, P, EL, PM, S, COA, SSA, CT, CLS, E, R> analyzer = createAnalyzer(lpgMonitor);
if (reader == null)
reader = new InputStreamReader(file.getContents());
else if (!file.exists())
return null;
analyzer.reset(reader, file.getName());
AbstractParser parser = getParser();
if ((monitor != null) && monitor.isCanceled())
return null;
parser.getLexer().lexer(parser.getIPrsStream());
if ((monitor != null) && monitor.isCanceled())
return null;
@SuppressWarnings("unchecked") // Maybe this should be a generic parameter
CST cst = (CST) parser.parser(lpgMonitor, -1);
if (cst == null)
return null;
if ((monitor != null) && monitor.isCanceled())
return null;
R rootEnvironment;
try {
reset();
rootEnvironment = createRootEnvironment(ast, cst);
} catch (ClassCastException e) { // Occurs if cst is not a CST
return null;
}
if (!analyzer.analyze(rootEnvironment))
return null;
if ((monitor != null) && monitor.isCanceled())
return null;
postParse(rootEnvironment);
return rootEnvironment;
}
protected void postParse(R rootEnvironment) {
rootEnvironment.postParse();
XMIUtils.assignLinearIds(ast, "ast");
}
public void reset() {
ast.unload();
typeResolver = createTypeResolver(ast);
List<Adapter> eAdapters = ast.eAdapters();
if (!eAdapters.isEmpty()) {
for (Adapter eAdapter : new ArrayList<Adapter>(eAdapters)) {
if (eAdapter instanceof ICSTEnvironment<?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?>)
eAdapters.remove(eAdapter);
}
}
}
public void setParent(Environment<PK, C, O, P, EL, PM, S, COA, SSA, CT, CLS, E> env) {
throw new UnsupportedOperationException();
}
}