/*
* Copyright 2010 JBoss Inc
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.drools.eclipse.view.rules;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.drools.eclipse.DRLInfo;
import org.drools.eclipse.DroolsEclipsePlugin;
import org.drools.eclipse.ProcessInfo;
import org.drools.eclipse.core.DroolsElement;
import org.drools.eclipse.core.DroolsModelBuilder;
import org.drools.eclipse.core.Function;
import org.drools.eclipse.core.Global;
import org.drools.eclipse.core.Package;
import org.drools.eclipse.core.Process;
import org.drools.eclipse.core.Query;
import org.drools.eclipse.core.Rule;
import org.drools.eclipse.core.RuleSet;
import org.drools.eclipse.core.ui.DroolsContentProvider;
import org.drools.eclipse.core.ui.DroolsLabelProvider;
import org.drools.eclipse.core.ui.DroolsTreeSorter;
import org.drools.eclipse.core.ui.FilterActionGroup;
import org.drools.compiler.lang.descr.FunctionDescr;
import org.drools.compiler.lang.descr.GlobalDescr;
import org.drools.compiler.lang.descr.QueryDescr;
import org.drools.compiler.lang.descr.RuleDescr;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IResourceChangeEvent;
import org.eclipse.core.resources.IResourceChangeListener;
import org.eclipse.core.resources.IResourceDelta;
import org.eclipse.core.resources.IResourceDeltaVisitor;
import org.eclipse.core.resources.IResourceVisitor;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jface.viewers.DoubleClickEvent;
import org.eclipse.jface.viewers.IDoubleClickListener;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.IMemento;
import org.eclipse.ui.IViewSite;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.forms.editor.FormEditor;
import org.eclipse.ui.ide.IDE;
import org.eclipse.ui.part.ViewPart;
import org.eclipse.ui.texteditor.ITextEditor;
public class RulesView extends ViewPart implements IDoubleClickListener, IResourceVisitor, IResourceChangeListener {
private final RuleSet ruleSet = DroolsModelBuilder.createRuleSet();
private Map resourcesMap = new HashMap();
private TreeViewer treeViewer;
public void createPartControl(Composite parent) {
treeViewer = new TreeViewer(parent, SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL);
treeViewer.setContentProvider(new DroolsContentProvider());
treeViewer.setLabelProvider(new DroolsLabelProvider());
treeViewer.setSorter(new DroolsTreeSorter());
treeViewer.addDoubleClickListener(this);
treeViewer.setUseHashlookup(true);
treeViewer.setInput(ruleSet);
FilterActionGroup filterActionGroup = new FilterActionGroup(
treeViewer, "org.drools.eclipse.view.rules.RulesView");
filterActionGroup.fillActionBars(getViewSite().getActionBars());
}
public void init(IViewSite site, IMemento memento) throws PartInitException {
super.init(site, memento);
try {
ResourcesPlugin.getWorkspace().getRoot().accept(this);
} catch (CoreException e) {
DroolsEclipsePlugin.log(e);
}
ResourcesPlugin.getWorkspace().addResourceChangeListener(this);
}
public void dispose() {
ResourcesPlugin.getWorkspace().removeResourceChangeListener(this);
}
public void setFocus() {
treeViewer.getControl().setFocus();
}
public boolean visit(IResource resource) throws CoreException {
return updateResource(resource);
}
private boolean updateResource(IResource resource) {
IProject project = resource.getProject();
if (project != null) {
IJavaProject javaProject = JavaCore.create(project);
if (!javaProject.exists()) {
return false;
}
if (resource instanceof IFile
&& javaProject.isOnClasspath(resource)) {
IFile file = (IFile) resource;
if ("drl".equals(resource.getFileExtension())
|| "dslr".equals(resource.getFileExtension())) {
try {
DRLInfo drlInfo = DroolsEclipsePlugin.getDefault().parseResource(resource, false);
String packageName = drlInfo.getPackageName();
Package pkg = ruleSet.getPackage(packageName);
if (pkg == null) {
pkg = DroolsModelBuilder.addPackage(ruleSet, packageName, 0, 0);
}
if (drlInfo.getBuilderErrors().length > 0 || drlInfo.getPackageDescr() == null) {
return false;
}
// add rules
List rules = drlInfo.getPackageDescr().getRules();
for (Iterator iterator = rules.iterator(); iterator.hasNext();) {
RuleDescr ruleDescr = (RuleDescr) iterator.next();
boolean isQuery = ruleDescr instanceof QueryDescr;
String ruleName = ruleDescr.getName();
if (!isQuery) {
Rule rule = DroolsModelBuilder.addRule(
pkg, ruleName, file, ruleDescr.getStartCharacter(),
ruleDescr.getEndCharacter() - ruleDescr.getStartCharacter() + 1, null);
// create link between resource and created rule nodes
List droolsElements = (List) resourcesMap.get(file);
if (droolsElements == null) {
droolsElements = new ArrayList();
resourcesMap.put(file, droolsElements);
}
droolsElements.add(rule);
} else {
Query query = DroolsModelBuilder.addQuery(
pkg, ruleName, file, ruleDescr.getStartCharacter(),
ruleDescr.getEndCharacter() - ruleDescr.getStartCharacter() + 1);
// create link between resource and created rule nodes
List droolsElements = (List) resourcesMap.get(file);
if (droolsElements == null) {
droolsElements = new ArrayList();
resourcesMap.put(file, droolsElements);
}
droolsElements.add(query);
}
}
// add globals
List globals = drlInfo.getPackageDescr().getGlobals();
for (Iterator iterator = globals.iterator(); iterator.hasNext();) {
GlobalDescr globalDescr = (GlobalDescr) iterator.next();
Global global = DroolsModelBuilder.addGlobal(
pkg, globalDescr.getIdentifier(), file, globalDescr.getStartCharacter(),
globalDescr.getEndCharacter() - globalDescr.getStartCharacter() + 1);
// create link between resource and created rule nodes
List droolsElements = (List) resourcesMap.get(file);
if (droolsElements == null) {
droolsElements = new ArrayList();
resourcesMap.put(file, droolsElements);
}
droolsElements.add(global);
}
// add functions
List functions = drlInfo.getPackageDescr().getFunctions();
for (Iterator iterator = functions.iterator(); iterator.hasNext();) {
FunctionDescr functionDescr = (FunctionDescr) iterator.next();
String functionName = functionDescr.getName();
Function function = DroolsModelBuilder.addFunction(
pkg, functionName, file, functionDescr.getStartCharacter(),
functionDescr.getEndCharacter() - functionDescr.getStartCharacter() + 1);
// create link between resource and created rule nodes
List droolsElements = (List) resourcesMap.get(file);
if (droolsElements == null) {
droolsElements = new ArrayList();
resourcesMap.put(file, droolsElements);
}
droolsElements.add(function);
}
} catch (Throwable t) {
DroolsEclipsePlugin.log(t);
}
return false;
} else if ("rf".equals(resource.getFileExtension())) {
try {
String processString = convertToString(file.getContents());
ProcessInfo processInfo = DroolsEclipsePlugin.getDefault().parseProcess(processString, resource);
if (processInfo != null && processInfo.getProcess() != null) {
String packageName = processInfo.getProcess().getPackageName();
Package pkg = ruleSet.getPackage(packageName);
if (pkg == null) {
pkg = DroolsModelBuilder.addPackage(ruleSet, packageName, 0, 0);
}
Process process = DroolsModelBuilder.addProcess(pkg, processInfo.getProcess().getId(), file);
List droolsElements = (List) resourcesMap.get(file);
if (droolsElements == null) {
droolsElements = new ArrayList();
resourcesMap.put(file, droolsElements);
}
droolsElements.add(process);
}
} catch (Throwable t) {
DroolsEclipsePlugin.log(t);
}
return false;
}
}
}
return true;
}
public void resourceChanged(final IResourceChangeEvent event) {
try {
if (event.getType() == IResourceChangeEvent.POST_CHANGE) {
IResourceDelta delta = event.getDelta();
if (delta != null) {
delta.accept(new IResourceDeltaVisitor() {
public boolean visit(IResourceDelta delta) throws CoreException {
IResource resource = delta.getResource();
removeElementsFromResource(resource);
boolean result = true;
if (delta.getKind() != IResourceDelta.REMOVED) {
result = updateResource(resource);
}
treeViewer.getControl().getDisplay().asyncExec(
new Runnable() {
public void run() {
if (!treeViewer.getControl().isDisposed()) {
treeViewer.refresh();
}
}
}
);
return result;
}
});
}
} else if (event.getType() == IResourceChangeEvent.PRE_DELETE) {
IResource resource = event.getResource();
if (resource != null) {
resource.accept(new IResourceVisitor() {
public boolean visit(IResource resource) throws CoreException {
removeElementsFromResource(resource);
return true;
}
});
}
} else if (event.getType() == IResourceChangeEvent.PRE_CLOSE) {
IResource resource = event.getResource();
if (resource != null) {
resource.accept(new IResourceVisitor() {
public boolean visit(IResource resource) throws CoreException {
removeElementsFromResource(resource);
return true;
}
});
}
}
} catch (Throwable t) {
DroolsEclipsePlugin.log(t);
}
}
private void removeElementsFromResource(IResource resource) {
List droolsElements = (List) resourcesMap.get(resource);
if (droolsElements != null) {
for (Iterator iterator = droolsElements.iterator(); iterator.hasNext();) {
DroolsModelBuilder.removeElement((DroolsElement) iterator.next());
}
resourcesMap.remove(resource);
}
}
public void doubleClick(DoubleClickEvent event) {
ISelection selection = event.getSelection();
if (selection instanceof IStructuredSelection) {
Object selected = ((StructuredSelection) selection).getFirstElement();
if (selected != null && selected instanceof DroolsElement) {
DroolsElement droolsSelected = (DroolsElement) selected;
IFile file = droolsSelected.getFile();
if (file != null) {
try {
IEditorPart editor = IDE.openEditor(getSite().getPage(), file);
if (editor instanceof FormEditor) {
editor = ((FormEditor) editor).getActiveEditor();
}
if (editor instanceof ITextEditor) {
((ITextEditor)editor).selectAndReveal(
droolsSelected.getOffset(), droolsSelected.getLength());
}
} catch (Throwable t) {
DroolsEclipsePlugin.log(t);
}
}
}
}
}
private static String convertToString(final InputStream inputStream) throws IOException {
Reader reader = new InputStreamReader(inputStream);
final StringBuffer text = new StringBuffer();
final char[] buf = new char[1024];
int len = 0;
while ((len = reader.read(buf)) >= 0) {
text.append(buf, 0, len);
}
return text.toString();
}
}