package net.enilink.komma.edit.properties;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import net.enilink.komma.common.adapter.IAdapterFactory;
import net.enilink.komma.common.command.CommandResult;
import net.enilink.komma.common.command.ICommand;
import net.enilink.komma.common.command.SimpleCommand;
import net.enilink.komma.core.IEntity;
import net.enilink.komma.core.IEntityManager;
import net.enilink.komma.core.IReference;
import net.enilink.komma.core.IStatement;
import net.enilink.komma.core.IValue;
import net.enilink.komma.core.Statement;
import net.enilink.komma.core.URI;
import net.enilink.komma.edit.assist.IContentProposal;
import net.enilink.komma.edit.assist.IContentProposalProvider;
import net.enilink.komma.edit.assist.ParboiledProposalProvider;
import net.enilink.komma.edit.assist.ReflectiveSemanticProposals;
import net.enilink.komma.edit.properties.ResourceFinder.Match;
import net.enilink.komma.edit.properties.ResourceFinder.Options;
import net.enilink.komma.edit.provider.IItemLabelProvider;
import net.enilink.komma.parser.manchester.IManchesterActions;
import net.enilink.komma.parser.manchester.ManchesterSyntaxParser;
import net.enilink.komma.parser.sparql.tree.BNode;
import net.enilink.komma.parser.sparql.tree.BooleanLiteral;
import net.enilink.komma.parser.sparql.tree.DoubleLiteral;
import net.enilink.komma.parser.sparql.tree.GenericLiteral;
import net.enilink.komma.parser.sparql.tree.IntegerLiteral;
import net.enilink.komma.parser.sparql.tree.IriRef;
import net.enilink.komma.parser.sparql.tree.Literal;
import net.enilink.komma.parser.sparql.tree.QName;
import net.enilink.komma.parser.sparql.tree.visitor.TreeWalker;
import org.eclipse.core.commands.ExecutionException;
import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.core.runtime.IProgressMonitor;
import org.parboiled.Parboiled;
import org.parboiled.errors.ErrorUtils;
import org.parboiled.parserunners.ReportingParseRunner;
import org.parboiled.support.ParsingResult;
public class ManchesterEditingSupport extends ResourceEditingSupport {
class ManchesterActions implements IManchesterActions {
@Override
public boolean createStmt(Object subject, Object predicate,
Object object) {
return true;
}
}
class ManchesterProposals extends ReflectiveSemanticProposals {
IEntityManager em;
IEntity subject;
public ManchesterProposals(IEntityManager em, IEntity subject) {
this.em = em;
this.subject = subject;
}
public IContentProposal[] IriRef(ParsingResult<?> result, int index,
String prefix) {
StringBuilder text = new StringBuilder();
for (int l = 1; l <= result.inputBuffer.getLineCount(); l++) {
text.append(result.inputBuffer.extractLine(l));
}
int insertPos = index - prefix.length();
List<IContentProposal> proposals = new ArrayList<IContentProposal>();
int limit = 20;
Options options = subject == null ? Options.create(em, null,
prefix, limit) : Options.create(subject, prefix, limit);
for (Match match : new ResourceFinder().findAnyResources(options)) {
String label = getLabel(match.resource);
String origText = text.substring(insertPos, index);
// insert proposal text
text.replace(insertPos, index, label);
// create proposal
proposals.add(new ResourceProposal(text.toString(), insertPos
+ label.length(), match.resource).setUseAsValue(text
.length() == label.length()));
// restore original text
text.replace(insertPos, insertPos + label.length(), origText);
}
return proposals.toArray(new IContentProposal[proposals.size()]);
}
};
public ManchesterEditingSupport(IAdapterFactory adapterFactory) {
super(adapterFactory);
}
protected CommandResult addStatements(final IEntityManager em,
final Object subject, final List<Object[]> stmts) {
Map<BNode, IReference> bNodes = new HashMap<BNode, IReference>();
List<IStatement> realStmts = new ArrayList<IStatement>();
for (Object[] stmt : stmts) {
Object s = stmt[0], p = stmt[1], o = stmt[2];
realStmts
.add(new Statement((IReference) toValue(em, s, bNodes),
(IReference) toValue(em, p, bNodes), toValue(em, o,
bNodes)));
}
em.add(realStmts);
return CommandResult.newOKCommandResult(toValue(em, subject, bNodes));
}
protected IValue toValue(final IEntityManager em, Object value,
final Map<BNode, IReference> bNodes) {
if (value instanceof BNode) {
IReference reference = bNodes.get(value);
if (reference == null) {
bNodes.put((BNode) value, reference = em.create());
}
return reference;
} else if (value instanceof IriRef || value instanceof QName) {
return toURI(em, value);
} else if (value instanceof Literal) {
final IValue[] result = new IValue[1];
((Literal) value).accept(new TreeWalker<Void>() {
@Override
public Boolean integerLiteral(IntegerLiteral numericLiteral,
Void data) {
result[0] = em.toValue(numericLiteral.getValue());
return false;
}
@Override
public Boolean booleanLiteral(BooleanLiteral booleanLiteral,
Void data) {
result[0] = em.toValue(booleanLiteral.getValue());
return false;
}
@Override
public Boolean doubleLiteral(DoubleLiteral doubleLiteral,
Void data) {
result[0] = em.toValue(doubleLiteral.getValue());
return false;
}
@Override
public Boolean genericLiteral(GenericLiteral genericLiteral,
Void data) {
result[0] = em.createLiteral(
genericLiteral.getLabel(),
(URI) toValue(em, genericLiteral.getDatatype(),
bNodes), genericLiteral.getLanguage());
return false;
}
}, null);
return (IValue) result[0];
}
return (IReference) value;
}
@Override
public IProposalSupport getProposalSupport(Object element) {
final IEntity subject = getSubject(element);
if (subject == null) {
return null;
}
final IItemLabelProvider resourceLabelProvider = super
.getProposalSupport(element).getLabelProvider();
final ManchesterSyntaxParser parser = Parboiled.createParser(
ManchesterSyntaxParser.class, new ManchesterActions());
return new IProposalSupport() {
@Override
public IContentProposalProvider getProposalProvider() {
return new ParboiledProposalProvider(parser.Description(),
new ManchesterProposals(subject.getEntityManager(),
subject));
}
@Override
public char[] getAutoActivationCharacters() {
return null;
}
@Override
public IItemLabelProvider getLabelProvider() {
return new IItemLabelProvider() {
@Override
public String getText(Object object) {
if (object instanceof ResourceProposal) {
return resourceLabelProvider.getText(object);
}
return ((IContentProposal) object).getLabel();
}
@Override
public Object getImage(Object object) {
if (object instanceof ResourceProposal) {
return resourceLabelProvider.getImage(object);
}
return null;
}
};
}
};
}
@Override
public ICommand convertEditorValue(final Object editorValue,
final IEntityManager entityManager, Object element) {
return new SimpleCommand() {
@Override
protected CommandResult doExecuteWithResult(
IProgressMonitor progressMonitor, IAdaptable info)
throws ExecutionException {
final List<Object[]> newStmts = new ArrayList<Object[]>();
ParsingResult<Object> result = new ReportingParseRunner<Object>(
Parboiled.createParser(ManchesterSyntaxParser.class,
new ManchesterActions() {
@Override
public boolean createStmt(Object subject,
Object predicate, Object object) {
newStmts.add(new Object[] { subject,
predicate, object });
return true;
}
}).Description()).run((String) editorValue);
if (result.matched && result.resultValue != null) {
return addStatements(entityManager, result.resultValue,
newStmts);
} else {
return CommandResult.newErrorCommandResult(ErrorUtils
.printParseErrors(result.parseErrors));
}
}
};
}
}