/*
* Copyright (c) 2006 Borland Software 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:
* Michael Golubev (Borland) - initial API and implementation
*/
package org.eclipse.uml2.diagram.parser;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import org.eclipse.core.commands.ExecutionException;
import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.emf.common.notify.Notification;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EStructuralFeature;
import org.eclipse.emf.transaction.TransactionalEditingDomain;
import org.eclipse.emf.transaction.util.TransactionUtil;
import org.eclipse.gmf.runtime.common.core.command.CommandResult;
import org.eclipse.gmf.runtime.common.core.command.ICommand;
import org.eclipse.gmf.runtime.common.core.command.UnexecutableCommand;
import org.eclipse.gmf.runtime.common.ui.services.parser.IParser;
import org.eclipse.gmf.runtime.common.ui.services.parser.IParserEditStatus;
import org.eclipse.gmf.runtime.common.ui.services.parser.ParserEditStatus;
import org.eclipse.gmf.runtime.diagram.ui.editparts.DiagramEditPart;
import org.eclipse.gmf.runtime.diagram.ui.editparts.IGraphicalEditPart;
import org.eclipse.gmf.runtime.emf.commands.core.command.AbstractTransactionalCommand;
import org.eclipse.gmf.runtime.emf.commands.core.command.CompositeTransactionalCommand;
import org.eclipse.jface.text.contentassist.IContentAssistProcessor;
import org.eclipse.uml2.diagram.parser.lookup.LookupResolver;
import org.eclipse.uml2.diagram.parser.lookup.LookupResolverImpl;
import org.eclipse.uml2.diagram.parser.lookup.LookupSuite;
import org.eclipse.uml2.internal.diagram.parser.MDTDiagramParserPlugin;
public class ParserAdapter implements IParser {
private static final String NOT_AN_OBJECT = "Unknown";
private final ExternalParserBase myDelegate;
private final EObject myTester;
private final ApplyStrategy myApplier;
private final ExternalToString myView;
private final ExternalToString myEdit;
private final static MessageFormatEscaper ourMessageFormatEscaper = new MessageFormatEscaper();
public ParserAdapter(ExternalParserBase delegate, ApplyStrategy applier) {
this(delegate, applier, ExternalToString.NOT_IMPLEMENTED);
}
public ParserAdapter(ExternalParserBase delegate, ApplyStrategy applier, ExternalToString viewAndEdit) {
this(delegate, applier, viewAndEdit, viewAndEdit);
}
public ParserAdapter(ExternalParserBase delegate, ApplyStrategy applier, ExternalToString view, ExternalToString edit) {
myDelegate = delegate;
myApplier = applier;
myView = view;
myEdit = edit;
myTester = myDelegate.createSubjectPrototype();
}
public IContentAssistProcessor getCompletionProcessor(IAdaptable element) {
return null;
}
public String getEditString(IAdaptable element, int flags) {
return getToString(element, flags, myEdit);
}
public String getPrintString(IAdaptable element, int flags) {
return getToString(element, flags, myView);
}
public final boolean isAffectingEvent(Object event, int flags) {
return isAffectingEvent(event);
}
protected boolean isAffectingEvent(Object event) {
if (event instanceof Notification) {
Object feature = ((Notification) event).getFeature();
return (feature instanceof EStructuralFeature) && myView.isAffectingFeature((EStructuralFeature) feature);
}
return false;
}
public IParserEditStatus isValidEditString(IAdaptable adapter, String editString) {
EObject modelObject = (EObject) adapter.getAdapter(EObject.class);
if (modelObject == null) {
return new ParserEditStatus(MDTDiagramParserPlugin.getPluginID(), IParserEditStatus.UNEDITABLE, "Can not find context object");
}
LookupSuite oldLookup = myDelegate.getLookupSuite();
try {
myDelegate.setLookupSuite(LookupSuite.NULL_SUITE);
myDelegate.parse(myTester, editString, modelObject);
return ParserEditStatus.EDITABLE_STATUS;
} catch (ExternalParserException e) {
//CellEditor uses MessageFormat to format the message
//we need to escape '{', '}', '\' to prevent failure while formatting an error
String message = e.getMessage();
if (message == null) {
message = "";
}
message = ourMessageFormatEscaper.getEscaped(message);
return new ParserEditStatus(MDTDiagramParserPlugin.getPluginID(), IParserEditStatus.UNEDITABLE, "Invalid input: " + message);
} finally {
myDelegate.setLookupSuite(oldLookup);
}
}
public ICommand getParseCommand(IAdaptable adapter, String newString, int flags) {
final EObject modelObject = (EObject) adapter.getAdapter(EObject.class);
if (modelObject == null) {
return UnexecutableCommand.INSTANCE;
}
TransactionalEditingDomain editingDomain = TransactionUtil.getEditingDomain(modelObject);
if (editingDomain == null) {
return UnexecutableCommand.INSTANCE;
}
IGraphicalEditPart diagramEditPart = (DiagramEditPart) adapter.getAdapter(DiagramEditPart.class);
LookupResolver resolver = LookupResolver.NULL;
if (diagramEditPart != null) {
resolver = new LookupResolverImpl(diagramEditPart);
}
myDelegate.setLookupResolver(resolver);
final EObject parsed;
try {
parsed = myDelegate.parseNewObject(modelObject, newString);
} catch (ExternalParserException e) {
//strange
//e.printStackTrace();
return UnexecutableCommand.INSTANCE;
} finally {
myDelegate.setLookupResolver(null);
}
List commandList = new LinkedList();
if (resolver.canResolve()) {
AbstractTransactionalCommand resolveCommand = resolver.getResolveCommand();
AbstractTransactionalCommand computeAndApplyCommand = new AbstractTransactionalCommand(editingDomain, "", null) {
@Override
protected CommandResult doExecuteWithResult(IProgressMonitor monitor, IAdaptable info) throws ExecutionException {
for (Iterator applyCommands = myApplier.apply(modelObject, parsed).iterator(); applyCommands.hasNext();) {
ICommand next = (ICommand) applyCommands.next();
next.execute(monitor, info);
}
return CommandResult.newOKCommandResult();
}
};
commandList.add(resolveCommand);
commandList.add(computeAndApplyCommand);
} else {
commandList.addAll(myApplier.apply(modelObject, parsed));
}
return new CompositeTransactionalCommand(editingDomain, getCommandLabel(commandList), commandList);
}
protected final ExternalToString getViewToString() {
return myView;
}
private String getToString(IAdaptable element, int flags, ExternalToString toString) {
EObject modelObject = (EObject) element.getAdapter(EObject.class);
return isValidElement(modelObject) ? toString.getToString(modelObject, flags) : NOT_AN_OBJECT;
}
private String getCommandLabel(List/*1.5 <ICommand>*/commandList) {
return "-not-implemented-";
}
protected final boolean isValidElement(Object object) {
return object != null && myDelegate.getSubjectClass().isInstance(object);
}
private static class MessageFormatEscaper {
private final char S_QUOTE = '\'';
public String getEscaped(String input) {
if (!input.contains("'")) {
return "'" + input + "'";
}
StringBuffer result = new StringBuffer(input.length() + 5);
result.append(S_QUOTE);
for (int i = 0; i < input.length(); i++) {
char next = result.charAt(i);
if (next == S_QUOTE) {
result.append(S_QUOTE);
}
result.append(next);
}
result.append(S_QUOTE);
return result.toString();
}
}
}