package org.eclipse.iee.editor.core.container;
import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue;
import org.antlr.v4.runtime.ParserRuleContext;
import org.antlr.v4.runtime.tree.RuleNode;
import org.eclipse.iee.core.document.parser.DocumentStructureConfig;
import org.eclipse.iee.core.document.source.IScope;
import org.eclipse.iee.core.document.source.ISourceGeneratorContext;
import org.eclipse.iee.core.document.source.IVariableType;
import org.eclipse.iee.core.document.writer.IDocumentWriter;
import org.eclipse.iee.editor.core.utils.runtime.file.FileMessager;
import org.eclipse.iee.translator.antlr.java.JavaBaseVisitor;
import org.eclipse.iee.translator.antlr.java.JavaParser.ClassBodyContext;
import org.eclipse.iee.translator.antlr.java.JavaParser.CompilationUnitContext;
import org.eclipse.iee.translator.antlr.translator.JavaTranslator;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.Position;
import org.eclipse.swt.widgets.Display;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.common.base.Throwables;
public class DocumentAccess {
private static final Logger logger = LoggerFactory.getLogger(DocumentAccess.class);
/* Access actions IDs */
static final int WRITE = 0;
static final int RELEASE = 1;
private ContainerManager fContainerManager;
private IDocumentWriter fWriter;
private final class FindByOffset extends JavaBaseVisitor<Boolean> {
private RuleNode node;
private int offset;
private FindByOffset(Container container) {
offset = container.getPosition().getOffset();
}
@Override
public Boolean visitChildren(RuleNode node) {
ParserRuleContext ctx = (ParserRuleContext) node;
if (ctx.getStart().getStartIndex()<= offset && ctx.getStop().getStopIndex() > offset) {
this.node = node;
}
return super.visitChildren(node);
}
public RuleNode getNode() {
return node;
}
}
public class AccessAction {
AccessAction(int actionID, Container container) {
this.actionID = actionID;
this.container = container;
}
public final int actionID;
public final Container container;
};
private Queue<AccessAction> fContainerDocumentAccessQueue = new ConcurrentLinkedQueue<AccessAction>();
DocumentAccess(ContainerManager containerManager) {
fContainerManager = containerManager;
fWriter = containerManager.getWriter();
}
/**
* Adds access action to queue;
*/
void requestAccessAction(int actionID, Container container) {
fContainerDocumentAccessQueue
.add(new AccessAction(actionID, container));
Display.getDefault().asyncExec(new Runnable() {
public void run() {
processNextDocumentAccessRequest();
}
});
}
/**
* This function is called by ContainerManager when document modification is
* allowed.
*/
boolean processNextDocumentAccessRequest() {
logger.debug("processNextDocumentAccessRequest");
AccessAction action;
while ((action = fContainerDocumentAccessQueue.poll()) != null) {
Container container = action.container;
switch (action.actionID) {
case WRITE:
writeContentToTextRegion(container);
break;
case RELEASE:
releaseTextRegion(container);
break;
}
}
return false;
}
/* Format */
/**
* This function is called by ContainerManager which puts Container data to
* Document
*/
public void writeContentToTextRegion(final Container container) {
String payload = getPayload(container);
Position position = container.getPosition();
int from = position.getOffset() + fWriter.getPrologue().length();
int length = position.getLength() - fWriter.getPrologue().length() - fWriter.getEpilogue().length();
try {
if (getDocument().get(from, length).equals(payload)) {
return;
}
getDocument().replace(from, length, payload.toString());
} catch (BadLocationException e) {
logger.error(e.getMessage());
e.printStackTrace();
}
}
public Container createContent(final Container container) {
String payload = getPayload(container);
Position position = container.getPosition();
int from = position.getOffset();
int length = position.getLength();
String text = fWriter.getPrologue() + payload + fWriter.getEpilogue();
try {
if (!getDocument().get(from, length).equals(text)) {
getDocument().replace(from, length, text);
}
return container;
} catch (BadLocationException e) {
throw Throwables.propagate(e);
}
}
private String getPayload(final Container container) {
final ContainerManager containerManager = container.getContainerManager();
CompilationUnitContext ctx = containerManager.getCompilationUnitContext();
FindByOffset visitor = new FindByOffset(container);
ctx.accept(visitor);
final RuleNode node = visitor.getNode();
String payload = fWriter.writeInternalsToString(container.getPadPart(), new ISourceGeneratorContext() {
@Override
public String translateFunction(String function, String id) {
try {
return JavaTranslator.translate(function,
containerManager.getCompilationUnit(),
container.getPosition().getOffset(), container.getContainerID());
} catch (Exception e) {
logger.error("Failed to translate expression " + function, e);
return "";
}
}
@Override
public String getStoragePath() {
return containerManager.getStoragePath() + "/" +
FileMessager.getInstance().getRuntimeDirectoryName();
}
@Override
public boolean isInClassBody() {
return node instanceof ClassBodyContext;
}
@Override
public IVariableType getExpressionType(String expression, IScope scope) {
return JavaTranslator.getType(expression,
containerManager.getCompilationUnit(),
container.getPosition().getOffset(), container.getContainerID());
}
@Override
public IScope getScope() {
return JavaTranslator.getScope(containerManager.getCompilationUnit(),
container.getPosition().getOffset());
}});
return payload;
}
/**
* Removes container's text region from document. This function is called
* from ContainerManager
*/
protected void releaseTextRegion(Container container) {
Position position = container.getPosition();
try {
getDocument().replace(position.getOffset(), position.getLength(),
"");
} catch (BadLocationException e) {
logger.error(e.getMessage());
e.printStackTrace();
}
}
/**
* Parses @param textRegion and returns container's id
*/
String getContainerIDFromTextRegion(String textRegion) {
int from = DocumentStructureConfig.EMBEDDED_REGION_BEGIN.length();
int to = textRegion.indexOf(DocumentStructureConfig.INNER_TEXT_BEGIN);
if (to == -1) {
to = textRegion.indexOf(DocumentStructureConfig.EMBEDDED_REGION_END);
}
try {
return textRegion.substring(from, to);
} catch (IndexOutOfBoundsException e) {
logger.error(e.getMessage());
return null;
}
}
public boolean hasNextDocumentAccessRequest() {
return !fContainerDocumentAccessQueue.isEmpty();
}
private IDocument getDocument() {
return fContainerManager.getDocument();
}
}