4bfbac7b7cf584a52406b361fa8f676d7e37d74f
[phpeclipse.git] / net.sourceforge.phpeclipse.ui / src / net / sourceforge / phpeclipse / xml / ui / internal / text / XMLReconcileStep.java
1 /*
2  * Copyright (c) 2003-2004 Christopher Lenz and others.
3  * All rights reserved. This program and the accompanying materials 
4  * are made available under the terms of the Common Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/cpl-v10.html
7  * 
8  * Contributors:
9  *     Christopher Lenz - initial API and implementation
10  * 
11  * $Id: XMLReconcileStep.java,v 1.2 2006-10-21 23:14:13 pombredanne Exp $
12  */
13
14 package net.sourceforge.phpeclipse.xml.ui.internal.text;
15
16 import java.util.ArrayList;
17 import java.util.Collections;
18 import java.util.List;
19
20 import net.sourceforge.phpeclipse.xml.core.model.IXMLDocument;
21 import net.sourceforge.phpeclipse.xml.core.parser.IProblem;
22 import net.sourceforge.phpeclipse.xml.core.parser.IProblemCollector;
23 import net.sourceforge.phpeclipse.xml.ui.internal.editor.XMLDocumentProvider;
24
25 import org.eclipse.core.resources.IFile;
26 import org.eclipse.jface.text.IRegion;
27 import org.eclipse.jface.text.Position;
28 import org.eclipse.jface.text.reconciler.AbstractReconcileStep;
29 import org.eclipse.jface.text.reconciler.DirtyRegion;
30 import org.eclipse.jface.text.reconciler.IReconcilableModel;
31 import org.eclipse.jface.text.reconciler.IReconcileResult;
32 import org.eclipse.jface.text.reconciler.IReconcileStep;
33 import org.eclipse.jface.text.source.Annotation;
34 import org.eclipse.ui.IEditorInput;
35 import org.eclipse.ui.IFileEditorInput;
36 import org.eclipse.ui.texteditor.IDocumentProvider;
37 import org.eclipse.ui.texteditor.ITextEditor;
38
39 /**
40  * Implementation of a reconcile step for building the XML parse tree on changes
41  * to the editor content.
42  */
43 public class XMLReconcileStep extends AbstractReconcileStep {
44
45         // Inner Classes -----------------------------------------------------------
46
47         /**
48          * Adapts an <code>IXMLDocument</code> to the
49          * <code>IReconcilableModel</code> interface.
50          */
51         private class XMLDocumentAdapter implements IReconcilableModel {
52                 private IXMLDocument document;
53
54                 public XMLDocumentAdapter(IXMLDocument document) {
55                         this.document = document;
56                 }
57
58                 public IXMLDocument getDocument() {
59                         return document;
60                 }
61
62         }
63
64         /**
65          * Implementation of the problem collector interface for creating problem
66          * annotations when there are problems parsing the style sheet.
67          */
68         private class ProblemCollector implements IProblemCollector {
69                 /**
70                  * The list of problems added to this collector.
71                  */
72                 private List collectedProblems = new ArrayList();
73
74                 /**
75                  * @see IProblemCollector#addProblem(IProblem)
76                  */
77                 public void addProblem(IProblem problem) {
78                         collectedProblems.add(problem);
79                 }
80
81                 /**
82                  * Returns the list of problems collected while the CSS source has been
83                  * parsed, in the order they were reported. The list returned is
84                  * immutable.
85                  * 
86                  * @return the list of collected problems (of type {@link IProblem})
87                  */
88                 public List getProblems() {
89                         return Collections.unmodifiableList(collectedProblems);
90                 }
91         }
92
93         /**
94          * Adapter that adapts an {@link IProblem} to an {@link Annotation}.
95          */
96         private class ProblemAdapter extends AnnotationAdapter {
97                 private IProblem problem;
98
99                 private Position position;
100
101                 public ProblemAdapter(IProblem problem) {
102                         this.problem = problem;
103                 }
104
105                 public Position getPosition() {
106                         if (position == null) {
107                                 position = createPositionFromProblem();
108                         }
109
110                         return position;
111                 }
112
113                 public Annotation createAnnotation() {
114                         int start = problem.getSourceStart();
115                         if (start < 0) {
116                                 return null;
117                         }
118
119                         int length = problem.getSourceEnd() - start + 1;
120                         if (length < 0) {
121                                 return null;
122                         }
123
124                         String type;
125                         if (problem.isWarning()) {
126                                 type = XMLAnnotation.TYPE_ERROR;
127                         } else if (problem.isError()) {
128                                 type = XMLAnnotation.TYPE_WARNING;
129                         } else {
130                                 type = XMLAnnotation.TYPE_INFO;
131                         }
132
133                         return new XMLAnnotation(type, false, problem.getMessage());
134                 }
135
136                 private Position createPositionFromProblem() {
137                         int start = problem.getSourceStart();
138                         if (start < 0) {
139                                 return null;
140                         }
141
142                         int length = problem.getSourceEnd() - problem.getSourceStart() + 1;
143                         if (length < 0) {
144                                 return null;
145                         }
146
147                         return new Position(start, length);
148                 }
149
150         }
151
152         // Instance Variables ------------------------------------------------------
153
154         private ITextEditor editor;
155
156         private XMLDocumentAdapter xmlDocumentAdapter;
157
158         // Constructors ------------------------------------------------------------
159
160         /**
161          * Default constructor.
162          */
163         public XMLReconcileStep(ITextEditor editor) {
164                 this.editor = editor;
165
166                 xmlDocumentAdapter = new XMLDocumentAdapter(getXMLDocument());
167         }
168
169         /**
170          * Constructor.
171          * 
172          * @param step
173          *            the step to add to the pipe
174          * @param editor
175          *            the associated text editor
176          */
177         public XMLReconcileStep(IReconcileStep step, ITextEditor editor) {
178                 super(step);
179
180                 this.editor = editor;
181
182                 xmlDocumentAdapter = new XMLDocumentAdapter(getXMLDocument());
183         }
184
185         // AbstractReconcileStep Implementation ------------------------------------
186
187         /*
188          * @see AbstractReconcileStep#reconcileModel(DirtyRegion, IRegion)
189          */
190         protected IReconcileResult[] reconcileModel(DirtyRegion dirtyRegion,
191                         IRegion subRegion) {
192                 IXMLDocument model = xmlDocumentAdapter.getDocument();
193
194                 IEditorInput editorInput = null;
195                 IFile file = null;
196                 if (editor != null) {
197                         editorInput = editor.getEditorInput();
198                 }
199
200                 if (editorInput instanceof IFileEditorInput)
201                         file = ((IFileEditorInput) editorInput).getFile();
202                 ProblemCollector problemCollector = new ProblemCollector();
203                 model.reconcile(problemCollector, file);
204
205                 List problems = problemCollector.getProblems();
206                 IReconcileResult[] retVal = new IReconcileResult[problems.size()];
207                 for (int i = 0; i < problems.size(); i++) {
208                         IProblem problem = (IProblem) problems.get(i);
209                         retVal[i] = new ProblemAdapter(problem);
210                 }
211
212                 return retVal;
213         }
214
215         /*
216          * @see AbstractReconcileStep#getModel()
217          */
218         public IReconcilableModel getModel() {
219                 return xmlDocumentAdapter;
220         }
221
222         // Private Methods Implementation ------------------------------------------
223
224         /**
225          * Retrieve the style sheet associated with the editor input.
226          */
227         private IXMLDocument getXMLDocument() {
228                 IDocumentProvider documentProvider = editor.getDocumentProvider();
229                 if (documentProvider instanceof XMLDocumentProvider) {
230                         XMLDocumentProvider xmlDocumentProvider = (XMLDocumentProvider) documentProvider;
231                         return xmlDocumentProvider.getModel(editor.getEditorInput());
232                 }
233
234                 return null;
235         }
236 }