package com.liferay.ide.velocity.vaulttec.ui.editor;
import java.io.IOException;
import java.io.Reader;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.List;
import org.apache.velocity.runtime.RuntimeInstance;
import org.apache.velocity.runtime.parser.ParseException;
import org.apache.velocity.runtime.parser.Token;
import org.apache.velocity.runtime.parser.node.SimpleNode;
import org.eclipse.core.resources.IMarker;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IRegion;
import org.eclipse.jface.text.reconciler.DirtyRegion;
import org.eclipse.jface.text.reconciler.IReconcilingStrategy;
import org.eclipse.jface.text.reconciler.IReconcilingStrategyExtension;
import org.eclipse.swt.widgets.Display;
import org.eclipse.ui.IFileEditorInput;
import org.htmlparser.Node;
import org.htmlparser.Parser;
import org.htmlparser.Tag;
import org.htmlparser.util.NodeIterator;
import org.htmlparser.util.ParserException;
import com.liferay.ide.velocity.editor.VelocityEditor;
import com.liferay.ide.velocity.editor.VelocityFoldingStructureProvider;
import com.liferay.ide.velocity.vaulttec.ui.VelocityPlugin;
import com.liferay.ide.velocity.vaulttec.ui.editor.parser.NodeVisitor;
import com.liferay.ide.velocity.vaulttec.ui.model.ITreeNode;
import com.liferay.ide.velocity.vaulttec.ui.model.ITreeVisitor;
import com.liferay.ide.velocity.vaulttec.ui.model.Template;
/**
* Reconciler strategy which parses the whole editor's content (a Velocity
* template) on a document change.
*/
public class VelocityReconcilingStrategy implements IReconcilingStrategy,
IReconcilingStrategyExtension
{
private VelocityEditor fEditor;
private Template fTemplate;
private Template fLastTemplate;
private String fError;
private IDocument fDocument;
private VelocityFoldingStructureProvider fFoldingStructureProvider;
public VelocityReconcilingStrategy(VelocityEditor anEditor)
{
fEditor = anEditor;
fFoldingStructureProvider = new VelocityFoldingStructureProvider(fEditor);
}
/**
* DOCUMENT ME!
*
* @param aDocument
* DOCUMENT ME!
*/
public void setDocument(IDocument aDocument)
{
fDocument = aDocument;
fFoldingStructureProvider.setDocument(fDocument);
parse();
}
/**
* DOCUMENT ME!
*
* @param aDirtyRegion
* DOCUMENT ME!
* @param aRegion
* DOCUMENT ME!
*/
public void reconcile(DirtyRegion aDirtyRegion, IRegion aRegion)
{
parse();
}
/**
* DOCUMENT ME!
*
* @param aPartition
* DOCUMENT ME!
*/
public void reconcile(IRegion aPartition)
{
parse();
}
private List htmlTags = null;
private void parse()
{
String name = fEditor.getEditorInput().getName();
Reader reader = new StringReader(fEditor.getDocument().get());
Template template = null;
try
{
parseHtml();
if (fEditor.getEditorInput() instanceof IFileEditorInput)
((IFileEditorInput) fEditor.getEditorInput()).getFile().deleteMarkers(
IMarker.PROBLEM, true, IResource.DEPTH_INFINITE);
RuntimeInstance runtime = VelocityEditorEnvironment.getParser();
SimpleNode root = runtime.parse(reader, name);
// Create tree model
NodeVisitor visitor = new NodeVisitor(name);
root.jjtAccept(visitor, null);
template = visitor.getTemplate();
fError = "";
}
catch (ParseException e)
{
if (!name.matches(".*?\\.jsp.*"))
{
if (e.getMessage() != null)
{
fError = e.getMessage();
Token token = e.currentToken;
if (token != null)
{
fEditor.addProblemMarker(e.getMessage(), token.next.beginLine,
IMarker.SEVERITY_ERROR);
}
}
else
{
fError = "";
}
}
}
catch (Exception e)
{
fError = "";
VelocityPlugin.log(e);
}
finally
{
try
{
reader.close();
}
catch (IOException e)
{
VelocityPlugin.log(e);
}
}
// Replace saved template with the new parsed one
synchronized (this)
{
if (template != null)
{
fTemplate = template;
// Save last successful parse tree
fLastTemplate = template;
}
else
{
fTemplate = null;
}
}
// Update outline view and display error message in status line
Display.getDefault().syncExec(new Runnable()
{
public void run()
{
fEditor.updateOutlinePage();
fEditor.displayErrorMessage(fError);
}
});
reconcile();
}
private class HtmlNode implements ITreeNode
{
private Tag arg0 = null;
/**
*
*/
public HtmlNode(Tag arg0)
{
this.arg0 = arg0;
}
public String getName()
{
return null;
}
public Object getParent()
{
return null;
}
public boolean hasChildren()
{
return false;
}
public Object[] getChildren()
{
return NO_CHILDREN;
}
public String getUniqueID()
{
return arg0.toString();
}
public int getStartLine()
{
return arg0.getStartingLineNumber() + 1;
}
public int getEndLine()
{
int nr = arg0.getStartingLineNumber() + 1;
int nrE = nr;
Tag endTag = arg0.getEndTag();
if (endTag != null)
{
nrE = endTag.getEndingLineNumber();
int offset = endTag.getStartPosition() - endTag.getEndPosition();
if (offset == 0)
fEditor.addProblemMarker(endTag.getTagName().toLowerCase()
+ " is not correctly closed proposed line for closing is line "
+ nrE, nr, IMarker.SEVERITY_WARNING);
}
return nrE;
}
public boolean accept(ITreeVisitor aVisitor)
{
// TODO Auto-generated method stub
return false;
}
}
private class VHtmlNodeVisitor extends org.htmlparser.visitors.NodeVisitor
{
public void visitTag(final Tag arg0)
{
htmlTags.add(new HtmlNode(arg0));
}
}
/**
* @throws ParserException
*/
private void parseHtml() throws ParserException
{
htmlTags = new ArrayList();
Parser parser = new Parser();
parser.setInputHTML(fDocument.get());
for (NodeIterator e = parser.elements(); e.hasMoreNodes();)
{
Node node = e.nextNode();
VHtmlNodeVisitor htmlNodeVisitor = new VHtmlNodeVisitor();
node.accept(htmlNodeVisitor);
}
}
/**
* Returns root elements of current parse tree.
*/
public Object[] getRootElements()
{
return ((fTemplate != null) ? fTemplate.getChildren()
: ITreeNode.NO_CHILDREN);
}
/**
* Returns root node of current parse tree.
*/
public ITreeNode getRootNode()
{
return fTemplate;
}
/**
* Returns last successful parse tree.
*/
public ITreeNode getLastRootNode()
{
return fLastTemplate;
}
/*
* (non-Javadoc)
*
* @seeorg.eclipse.jface.text.reconciler.IReconcilingStrategyExtension#
* initialReconcile()
*/
public void initialReconcile()
{
reconcile();
}
private void reconcile()
{
if (fTemplate != null && htmlTags != null)
htmlTags.add(fTemplate);
if (htmlTags != null)
{
fFoldingStructureProvider.updateFoldingRegions(htmlTags.toArray());// TODO
}
}
/**
*
*/
/*
* (non-Javadoc)
*
* @seeorg.eclipse.jface.text.reconciler.IReconcilingStrategyExtension#
* setProgressMonitor(org.eclipse.core.runtime.IProgressMonitor)
*/
public void setProgressMonitor(IProgressMonitor monitor)
{
// TODO Auto-generated method stub
}
}