001: package org.drools.eclipse.editors;
002:
003: import java.util.ArrayList;
004: import java.util.Iterator;
005: import java.util.List;
006: import java.util.regex.Matcher;
007: import java.util.regex.Pattern;
008:
009: import org.drools.eclipse.DroolsEclipsePlugin;
010: import org.drools.eclipse.preferences.IDroolsConstants;
011: import org.eclipse.core.resources.IFile;
012: import org.eclipse.jface.preference.IPreferenceStore;
013: import org.eclipse.jface.text.IDocument;
014: import org.eclipse.jface.text.IRegion;
015: import org.eclipse.jface.text.Position;
016: import org.eclipse.jface.text.reconciler.DirtyRegion;
017: import org.eclipse.jface.text.reconciler.IReconcilingStrategy;
018: import org.eclipse.jface.text.source.Annotation;
019: import org.eclipse.jface.text.source.IAnnotationModel;
020: import org.eclipse.jface.text.source.ISourceViewer;
021: import org.eclipse.jface.util.IPropertyChangeListener;
022: import org.eclipse.jface.util.PropertyChangeEvent;
023: import org.eclipse.swt.widgets.Display;
024:
025: public class DRLReconcilingStrategy implements IReconcilingStrategy {
026:
027: private static final Pattern RULE_PATTERN = Pattern.compile(
028: "\\n\\s*(rule\\s+.*?\\n\\s*end)", Pattern.DOTALL);
029: private static final Pattern TEMPLATE_PATTERN = Pattern.compile(
030: "\\n\\s*(template\\s+.*?\\n\\s*end)", Pattern.DOTALL);
031: private static final Pattern QUERY_PATTERN = Pattern.compile(
032: "\\n\\s*(query\\s+.*?\\n\\s*end)", Pattern.DOTALL);
033: private static final Pattern FUNCTION_PATTERN = Pattern.compile(
034: "\\n\\s*(function\\s+[^\\{]*\\{)", Pattern.DOTALL);
035: private static final Pattern IMPORT_PATTERN = Pattern.compile(
036: "\\n\\s*((\\s*import\\s+[^\\s;]+;?[\\t\\x0B\\f\\r]*\\n)+)",
037: Pattern.DOTALL);
038:
039: private ISourceViewer sourceViewer;
040: private AbstractRuleEditor editor;
041: private IDocument document;
042: private boolean folding;
043:
044: public DRLReconcilingStrategy(ISourceViewer sourceViewer,
045: final AbstractRuleEditor editor) {
046: this .sourceViewer = sourceViewer;
047: this .editor = editor;
048: IPreferenceStore preferenceStore = DroolsEclipsePlugin
049: .getDefault().getPreferenceStore();
050: folding = preferenceStore
051: .getBoolean(IDroolsConstants.EDITOR_FOLDING);
052: preferenceStore
053: .addPropertyChangeListener(new IPropertyChangeListener() {
054: public void propertyChange(PropertyChangeEvent event) {
055: if (IDroolsConstants.EDITOR_FOLDING
056: .equals(event.getProperty())) {
057: folding = ((Boolean) event.getNewValue())
058: .booleanValue();
059: if (folding) {
060: reconcile();
061: } else {
062: Display.getDefault().asyncExec(
063: new Runnable() {
064: public void run() {
065: editor
066: .updateFoldingStructure(new ArrayList());
067: }
068: });
069: }
070: }
071: }
072: });
073: }
074:
075: public void setDocument(IDocument document) {
076: this .document = document;
077: reconcile();
078: }
079:
080: public void reconcile(DirtyRegion dirtyRegion, IRegion region) {
081: reconcile();
082: }
083:
084: public void reconcile(IRegion region) {
085: reconcile();
086: }
087:
088: private void reconcile() {
089: if (document != null) {
090: String s = document.get();
091: if (folding) {
092: calculateFolding(s);
093: }
094:
095: // IFile file = ((IFileEditorInput) input).getFile();
096: // IAnnotationModel annotationModel = sourceViewer.getAnnotationModel();
097: // removeAnnotationsFor(annotationModel);
098: // DroolsBuildMarker[] markers = DroolsBuilder.parseFile(file, s);
099: // for (int i = 0; i < markers.length; i++) {
100: // createAnnotation(file, annotationModel, markers[i].getText(), markers[i].getOffset(), markers[i].getLength());
101: // }
102: }
103: }
104:
105: private static void createAnnotation(IFile file,
106: final IAnnotationModel annotationModel,
107: final String message, final int offset, final int length) {
108: Annotation annotation = new DRLProblemAnnotation(message);
109: Position position = new Position(0, 1);
110: // Position position = new Position(offset, length);
111: annotationModel.addAnnotation(annotation, position);
112: }
113:
114: public static void removeAnnotationsFor(
115: IAnnotationModel annotationModel) {
116: Iterator iterator = annotationModel.getAnnotationIterator();
117: while (iterator.hasNext()) {
118: Annotation annotation = (Annotation) iterator.next();
119: if (annotation instanceof DRLProblemAnnotation) {
120: annotationModel.removeAnnotation(annotation);
121: }
122: }
123: }
124:
125: protected void calculateFolding(String input) {
126: // TODO replace this parsing by getting this input from the parsed rule file
127: final List positions = new ArrayList();
128: Matcher matcher = RULE_PATTERN.matcher(input);
129: while (matcher.find()) {
130: positions.add(new Position(matcher.start(1), matcher.end(1)
131: - matcher.start(1)));
132: }
133: matcher = QUERY_PATTERN.matcher(input);
134: while (matcher.find()) {
135: positions.add(new Position(matcher.start(1), matcher.end(1)
136: - matcher.start(1)));
137: }
138: matcher = TEMPLATE_PATTERN.matcher(input);
139: while (matcher.find()) {
140: positions.add(new Position(matcher.start(1), matcher.end(1)
141: - matcher.start(1)));
142: }
143: matcher = IMPORT_PATTERN.matcher(input);
144: while (matcher.find()) {
145: positions.add(new Position(matcher.start(1), matcher.end(1)
146: - matcher.start(1)));
147: }
148: matcher = FUNCTION_PATTERN.matcher(input);
149: while (matcher.find()) {
150: int start = matcher.start(1);
151: // TODO also take comments, strings etc. in consideration
152: // use JavaPairMatcher or similar
153: int nbOpenBrackets = 1;
154: for (int i = matcher.end(); i < input.length(); i++) {
155: if (input.charAt(i) == '{') {
156: nbOpenBrackets++;
157: } else if (input.charAt(i) == '}') {
158: if (--nbOpenBrackets == 0) {
159: positions
160: .add(new Position(start, i - start + 1));
161: break;
162: }
163: }
164: }
165: }
166: Display.getDefault().asyncExec(new Runnable() {
167: public void run() {
168: editor.updateFoldingStructure(positions);
169: }
170: });
171: }
172: }
|