/**
* <copyright>
*
* Copyright (c) 2008,2010 Eclipse Modeling Project 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:
* Robert Fuhrer (rfuhrer@watson.ibm.com) - initial API and implementation
* E.D.Willink - abstracted API for common editing framework
*
* </copyright>
*
* $Id: CommonParseController.java,v 1.1 2010/03/11 14:51:20 ewillink Exp $
*/
package org.eclipse.ocl.examples.editor.ui.imp;
/*******************************************************************************
* Copyright (c) 2007 IBM 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:
* Robert Fuhrer (rfuhrer@watson.ibm.com) - initial API and implementation
*******************************************************************************/
import java.io.IOException;
import java.io.StringReader;
import java.util.Iterator;
import java.util.List;
import lpg.runtime.IToken;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.resource.ResourceSet;
import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl;
import org.eclipse.imp.core.ErrorHandler;
import org.eclipse.imp.language.Language;
import org.eclipse.imp.language.ServiceFactory;
import org.eclipse.imp.model.ISourceProject;
import org.eclipse.imp.parser.IMessageHandler;
import org.eclipse.imp.parser.ISourcePositionLocator;
import org.eclipse.imp.services.IAnnotationTypeInfo;
import org.eclipse.imp.services.ILanguageSyntaxProperties;
import org.eclipse.jface.text.IRegion;
import org.eclipse.jface.viewers.ILabelProvider;
import org.eclipse.ocl.examples.common.utils.TracingOption;
import org.eclipse.ocl.examples.editor.ui.ICreationFactory;
import org.eclipse.ocl.examples.editor.ui.OCLExamplesEditorPlugin;
import org.eclipse.ocl.examples.editor.ui.builder.MarkerProblemHandler;
import org.eclipse.ocl.examples.editor.ui.builder.ProblemLimit;
import org.eclipse.ocl.examples.modelregistry.eclipse.EclipseFileHandle;
import org.eclipse.ocl.examples.modelregistry.eclipse.EclipseProjectHandle;
import org.eclipse.ocl.examples.modelregistry.environment.FileHandle;
import org.eclipse.ocl.examples.parser.environment.ICSTFileEnvironment;
import org.eclipse.ocl.lpg.AbstractParser;
import org.eclipse.ocl.lpg.ProblemHandler;
/**
* Base class for an IParseController implementation that encapsulates a simple LPG-based
* scanner and parser. Implements IParseController because methods defined there are
* used here.
*
* @author rfuhrer
*/
public abstract class CommonParseController implements ICommonParseController
{
public static TracingOption parserProgress = new TracingOption(OCLExamplesEditorPlugin.PLUGIN_ID, "parser/progress");
private static int counter = 0;
protected final ICreationFactory creationFactory;
protected final Language fLanguage;
protected ISourceProject fProject;
protected IPath fFilePath;
protected IMessageHandler handler;
private ResourceSet resourceSet;
private ICSTFileEnvironment<?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?> fileEnvironment;
protected CommonParseResult fCurrentAst;
private final CommonAnnotationTypeInfo fSimpleAnnotationTypeInfo = new CommonAnnotationTypeInfo();
private final String id;
private CommonParseHelper parseHelper = null;
public CommonParseController(ICreationFactory creationFactory) {
this.creationFactory = creationFactory;
fLanguage= creationFactory.getLanguage();
id = getClass().getSimpleName() + "-" + ++ counter;
if (parserProgress.isActive())
parserProgress.println(id + " created");
getAnnotationTypeInfo().addProblemMarkerType(creationFactory.getErrorMarkerId());
}
protected ICSTFileEnvironment<?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?> createEnvironment(FileHandle fileHandle) {
if (resourceSet == null) {
resourceSet = createResourceSet();
initializeResourceSet(resourceSet);
}
URI astURI = fileHandle.getURI().appendFileExtension(creationFactory.getXMLExtension());
return creationFactory.createFileEnvironment(fileHandle, resourceSet, astURI);
}
protected ICommonKeyword createKeyword(String text) {
return new CommonKeyword(text);
}
protected CommonParseHelper createParseHelper(AbstractParser parser) {
return new CommonParseHelper(parser);
}
protected CommonParseResult createParsedResult(ICSTFileEnvironment<?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?> fileEnvironment) {
return new CommonParseResult(this, fileEnvironment);
}
protected ProblemHandler createProblemHandler(ICSTFileEnvironment<?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?> environment) {
if (handler instanceof ProblemHandler) {
((ProblemHandler)handler).setParser(environment.getParser());
if (handler instanceof MarkerProblemHandler<?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?>)
((MarkerProblemHandler<?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?>)handler).setProblemLimit(new ProblemLimit(50, 50, 50));
return (ProblemHandler) handler;
}
else {
CommonProblemHandler commonProblemHandler = new CommonProblemHandler(environment.getParser(), handler);
commonProblemHandler.setProblemLimit(new ProblemLimit(50, 50, 50));
return commonProblemHandler;
}
}
protected ResourceSet createResourceSet() {
return new ResourceSetImpl();
}
public IAnnotationTypeInfo getAnnotationTypeInfo() {
return fSimpleAnnotationTypeInfo;
}
public ICreationFactory getCreationFactory() {
return creationFactory;
}
public CommonParseResult getCurrentAst() {
return fCurrentAst;
}
public CommonParseResult getCurrentResult() {
return fCurrentAst;
}
protected FileHandle getFileHandle() {
IProject rawProject = fProject.getRawProject();
EclipseProjectHandle projectHandle = new EclipseProjectHandle(rawProject);
EclipseFileHandle fileHandle = projectHandle.getFileHandle(fFilePath.toString());
return fileHandle;
}
public IMessageHandler getHandler() {
return handler;
}
public List<ICommonKeyword> getKeywords() {
return parseHelper != null ? parseHelper.getKeywords() : null;
}
public ILabelProvider getLabelProvider() {
return ServiceFactory.getInstance().getLabelProvider(fLanguage);
}
public Language getLanguage() {
return fLanguage;
}
@Deprecated // Use getSourcePositionLocator()
public final ISourcePositionLocator getNodeLocator() {
return getSourcePositionLocator();
}
public IPath getPath() {
return fFilePath;
}
public ISourceProject getProject() {
return fProject;
}
public ResourceSet getResourceSet() {
return resourceSet;
}
@Deprecated // use method on ParsedResult
public ISourcePositionLocator getSourcePositionLocator() {
// throw new UnsupportedOperationException(getClass().getSimpleName() + ".getSourcePositionLocator");
if (fCurrentAst == null)
return null;
return fCurrentAst.getSourcePositionLocator();
}
public ILanguageSyntaxProperties getSyntaxProperties() {
return null;
}
@Deprecated // use method on ParsedResult
public Iterator<IToken> getTokenIterator(final IRegion region) {
// throw new UnsupportedOperationException(getClass().getSimpleName() + ".getTokenIterator");
if (fCurrentAst != null)
return fCurrentAst.getTokenIterator(region);
else
return new CommonParseResult.NullTokenIterator();
}
/*
* Defined in the IParseController interface. The implementation here serves
* as a super method to support initialization of lexer and parser in a concrete
* subtype where the concrete lexer and parser types are known.
*
* The handler parameter is required by the IParseController interface and is
* used in a concrete subtype along with a concrete parser type.
*/
public void initialize(IPath filePath, ISourceProject project, IMessageHandler handler) {
this.fProject= project;
this.fFilePath= filePath;
this.handler = handler;
if (parserProgress.isActive())
parserProgress.println(id + " initialized for " + fFilePath.toString());
}
protected void initializeResourceSet(ResourceSet resourceSet) {}
public boolean isCompleteable(int kind) {
switch (getTokenKind(kind)) {
case IDENTIFIER:
case INTEGER:
case KEYWORD:
case REAL:
case STRING:
return true;
}
return false;
}
public boolean isIdentifier(int kind) {
return getTokenKind(kind) == TokenKind.IDENTIFIER;
}
public boolean isKeyword(int kind) {
return parseHelper != null ? parseHelper.isKeyword(kind) : false;
}
public CommonParseResult parse(String contents, IProgressMonitor progressMonitor) {
fCurrentAst = parseWithoutCaching(contents, progressMonitor);
// FIXME my_monitor
return fCurrentAst;
}
// FIXME This is a workaround to Bug 257627
public CommonParseResult parseWithoutCaching(String contents, IProgressMonitor progressMonitor) {
if (parserProgress.isActive())
parserProgress.println(id + " Parse " + fFilePath.toString() + " " + fLanguage + " handler = " + handler.getClass().getName());
if (progressMonitor.isCanceled())
return fCurrentAst;
if (fileEnvironment == null)
fileEnvironment = createEnvironment(getFileHandle());
fileEnvironment.setProblemHandler(createProblemHandler(fileEnvironment));
CommonParseResult newResult = null;
try {
CommonParseResult workingResult = createParsedResult(fileEnvironment);
workingResult.parse(new StringReader(contents), progressMonitor);
newResult = workingResult;
if (parseHelper == null)
parseHelper = createParseHelper(newResult.getParser());
} catch (IOException e) {
ErrorHandler.reportError("Failed to parse language " + getLanguage().getName() + " and input " + getPath() + ":", e);
} catch (CoreException e) {
ErrorHandler.reportError("Failed to parse language " + getLanguage().getName() + " and input " + getPath() + ":", e);
}
return newResult;
}
public void setResourceSet(ResourceSet resourceSet) {
this.resourceSet = resourceSet;
}
}