package org.ofbiz.plugin.handlers;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import org.eclipse.core.commands.AbstractHandler;
import org.eclipse.core.commands.ExecutionEvent;
import org.eclipse.core.commands.ExecutionException;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IMarker;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.IFileEditorInput;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.handlers.HandlerUtil;
import org.ofbiz.plugin.Plugin;
import org.ofbiz.plugin.model.ControllerHelper;
import org.ofbiz.plugin.model.ScreenHelper;
import org.ofbiz.plugin.model.ServiceHelper;
import org.ofbiz.plugin.ofbiz.Controller;
import org.ofbiz.plugin.ofbiz.Screen;
import org.ofbiz.plugin.parser.Parser;
import org.xmlpull.v1.XmlPullParser;
/**
* Our sample handler extends AbstractHandler, an IHandler base class.
* @see org.eclipse.core.commands.IHandler
* @see org.eclipse.core.commands.AbstractHandler
*/
public class OfbizValidateHandler extends AbstractHandler {
private static final String MARKER_TYPE = "org.ofbiz.plugin.xmlProblem";
/**
* The constructor.
*/
public OfbizValidateHandler() {
}
/**
* the command has been executed, so extract extract the needed information
* from the application context.
*/
public Object execute(ExecutionEvent event) throws ExecutionException {
IWorkbenchWindow window = HandlerUtil.getActiveWorkbenchWindowChecked(event);
IEditorInput editorInput = Plugin.getDefault().getWorkbench().getActiveWorkbenchWindow().getActivePage().getActiveEditor().getSite().getWorkbenchWindow().getActivePage().getActiveEditor().getEditorInput();
if (editorInput instanceof IFileEditorInput) {
IFile file = ((IFileEditorInput) editorInput).getFile();
if (file.getFullPath().toString().endsWith("controller.xml")) {
Controller controller = ControllerHelper.getController(file);
if (controller == null) { //Maybe a parse error for the controller
MessageDialog.openInformation(
window.getShell(),
"Validate current file",
"Not a registered controller.xml file. Maybe the file is never used.");
return null;
}
deleteMarkers(file);
try {
XmlPullParser xpp = Plugin.getDefault().getXmlPullParserPool().getPullParserFromPool();
ControllerXmlParser controllerXmlParser = new ControllerXmlParser(controller);
controllerXmlParser.processDocument(xpp, file);
controllerXmlParser.generateUnusedViews();
} catch (Exception e1) {
}
MessageDialog.openInformation(
window.getShell(),
"Validate current file",
"Validate controller.xml Ok.");
} else {
MessageDialog.openInformation(
window.getShell(),
"Validate current file",
"Current file validation not implemented yet.");
}
}
return null;
}
private void deleteMarkers(IFile file) {
try {
file.deleteMarkers(MARKER_TYPE, false, IResource.DEPTH_ZERO);
} catch (CoreException ce) {
}
}
private class ControllerXmlParser extends Parser {
private Controller controller;
private Set<String> viewReferences = new HashSet<String>();
private Map<String, Integer> viewDeclarations = new HashMap<String, Integer>();
private Map<String, Integer> requestDeclarations = new HashMap<String, Integer>();
public ControllerXmlParser(Controller controller) {
this.controller = controller;
}
@Override
protected void processStartElement(XmlPullParser xpp) {
String name = xpp.getName();
String attributeTypeValue = xpp.getAttributeValue(null, "type");
if (name.equals("view-map")) {
String pageValue = xpp.getAttributeValue(null, "page");
Integer previousDeclaration = viewDeclarations.put(xpp.getAttributeValue(null, "name"), xpp.getLineNumber());
if (previousDeclaration != null) {
addMarker(file, "View map is masked/overriden by another View map", previousDeclaration, IMarker.SEVERITY_WARNING);
addMarker(file, "This View map masks/overrides another View map", xpp.getLineNumber(), IMarker.SEVERITY_WARNING);
}
if (pageValue.equals("component://emerald_admin/widget/voucherstock/Vouche rStockScreens.xml#orionexportresult")) {
System.out.println();
}
if ("screen".equals(attributeTypeValue)) {
Screen screensByComponentName = ScreenHelper.getScreensByComponentName(controller.getComponent().getDirectory().getProject(), pageValue);
if (screensByComponentName == null) {
addMarker(file, "Couldn't find Screen", xpp.getLineNumber(), IMarker.SEVERITY_ERROR);
}
} else if ("ftl".equals(attributeTypeValue)) {
String page = pageValue;
Controller controller = ControllerHelper.getController(file);
IFile findMember;
if (page.contains("component://")) {
findMember = null;
} else if (page.indexOf("/") == 0) {
findMember = null;
} else {
findMember = (IFile) controller.getFile().getParent().getParent().findMember(page);
}
if (findMember == null) {
addMarker(file, "Couldn't find ftl file", xpp.getLineNumber(), IMarker.SEVERITY_ERROR);
}
}
} else if (name.equals("response")) {
String attributeValueValue = xpp.getAttributeValue(null, "value");
if ("view".equals(attributeTypeValue)) {
viewReferences.add(attributeValueValue);
if (ControllerHelper.getHyperlinkForRequestValueView(attributeValueValue, file).size() == 0) {
addMarker(file, "Couldn't find view", xpp.getLineNumber(), IMarker.SEVERITY_ERROR);
}
} else if ("request".equals(attributeTypeValue)) {
if (ControllerHelper.getHyperlinkForRequestValueRequest(attributeValueValue, file).size() == 0) {
addMarker(file, "Couldn't find request", xpp.getLineNumber(), IMarker.SEVERITY_ERROR);
}
}
} else if (name.equals("event")) {
if (attributeTypeValue.equals("service") || attributeTypeValue.equals("service-multi")) {
if (ServiceHelper.findServiceByName(xpp.getAttributeValue(null, "invoke"), controller.getComponent().getDirectory().getProject()).size() == 0) {
addMarker(file, "Couldn't find service", xpp.getLineNumber(), IMarker.SEVERITY_ERROR);
}
}
} else if (name.equals("request-map")) {
Integer previousDeclaration = requestDeclarations.put(xpp.getAttributeValue(null, "uri"), xpp.getLineNumber());
if (previousDeclaration != null) {
addMarker(file, "Request map is masked/overriden by another request", previousDeclaration, IMarker.SEVERITY_WARNING);
addMarker(file, "This request map masks/overrides another request", xpp.getLineNumber(), IMarker.SEVERITY_WARNING);
}
}
}
public void generateUnusedViews() {
for (String viewDeclaration : viewDeclarations.keySet()) {
if (!viewReferences.contains(viewDeclaration)) {
Integer lineNumber = viewDeclarations.get(viewDeclaration);
addMarker(file, "Unused view", lineNumber, IMarker.SEVERITY_WARNING);
}
}
}
}
private void addMarker(IFile file, String message, int lineNumber,
int severity) {
try {
IMarker marker = file.createMarker(MARKER_TYPE);
marker.setAttribute(IMarker.MESSAGE, message);
marker.setAttribute(IMarker.SEVERITY, severity);
if (lineNumber == -1) {
lineNumber = 1;
}
marker.setAttribute(IMarker.LINE_NUMBER, lineNumber);
} catch (CoreException e) {
}
}
}