*** empty log message ***
[phpeclipse.git] / net.sourceforge.phpeclipse.xml.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.1 2004-09-02 18:28:03 jsurfer 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                 private Position position;
99
100                 public ProblemAdapter(IProblem problem)  {
101                         this.problem = problem;
102                 }
103
104                 public Position getPosition()  {
105                         if (position == null) {
106                                 position = createPositionFromProblem();
107                         }
108
109                         return position;
110                 }
111
112                 public Annotation createAnnotation() {
113                         int start = problem.getSourceStart();
114                         if (start < 0) {
115                                 return null;
116                         }
117
118                         int length = problem.getSourceEnd() - start + 1;
119                         if (length < 0) {
120                                 return null;
121                         }
122
123                         String type;
124                         if (problem.isWarning()) {
125                                 type = XMLAnnotation.TYPE_ERROR;
126                         } else if (problem.isError()) {
127                                 type = XMLAnnotation.TYPE_WARNING;
128                         } else {
129                                 type = XMLAnnotation.TYPE_INFO;
130                         }
131
132                         return new XMLAnnotation(type, false, problem.getMessage());
133                 }
134
135                 private Position createPositionFromProblem() {
136                         int start = problem.getSourceStart();
137                         if (start < 0) {
138                                 return null;
139                         }
140
141                         int length = problem.getSourceEnd() - problem.getSourceStart() + 1;
142                         if (length < 0) {
143                                 return null;
144                         }
145
146                         return new Position(start, length);
147                 }
148
149         }
150
151         // Instance Variables ------------------------------------------------------
152
153         private ITextEditor editor;
154
155         private XMLDocumentAdapter xmlDocumentAdapter;
156
157         // Constructors ------------------------------------------------------------
158
159         /**
160          * Default constructor.
161          */
162         public XMLReconcileStep(ITextEditor editor) {
163                 this.editor = editor;
164
165                 xmlDocumentAdapter = new XMLDocumentAdapter(getXMLDocument());
166         }
167
168         /**
169          * Constructor.
170          * 
171          * @param step the step to add to the pipe
172          * @param editor the associated text editor
173          */
174         public XMLReconcileStep(IReconcileStep step, ITextEditor editor) {
175                 super(step);
176
177                 this.editor = editor;
178
179                 xmlDocumentAdapter = new XMLDocumentAdapter(getXMLDocument());
180         }
181
182         // AbstractReconcileStep Implementation ------------------------------------
183
184         /*
185          * @see AbstractReconcileStep#reconcileModel(DirtyRegion, IRegion)
186          */
187         protected IReconcileResult[] reconcileModel(
188                 DirtyRegion dirtyRegion, IRegion subRegion
189         ) {
190                 IXMLDocument model = xmlDocumentAdapter.getDocument();
191
192                 
193                 IEditorInput editorInput = null;
194                 IFile file = null;
195             if (editor != null) {
196               editorInput = editor.getEditorInput();
197             }
198
199             if (editorInput instanceof IFileEditorInput)
200               file = ((IFileEditorInput) editorInput).getFile();
201             ProblemCollector problemCollector = new ProblemCollector();
202                 model.reconcile(problemCollector, file);
203
204                 List problems = problemCollector.getProblems();
205                 IReconcileResult[] retVal = new IReconcileResult[problems.size()];
206                 for (int i = 0; i < problems.size(); i++) {
207                         IProblem problem = (IProblem) problems.get(i);
208                         retVal[i] = new ProblemAdapter(problem);
209                 }
210
211                 return retVal;
212         }
213
214         /*
215          * @see AbstractReconcileStep#getModel()
216          */
217         public IReconcilableModel getModel() {
218                 return xmlDocumentAdapter;
219         }
220
221         // Private Methods Implementation ------------------------------------------
222
223         /**
224          * Retrieve the style sheet associated with the editor input.
225          */
226         private IXMLDocument getXMLDocument() {
227                 IDocumentProvider documentProvider = editor.getDocumentProvider();
228                 if (documentProvider instanceof XMLDocumentProvider) {
229                         XMLDocumentProvider xmlDocumentProvider =
230                                         (XMLDocumentProvider) documentProvider;
231                         return xmlDocumentProvider.getModel(editor.getEditorInput());
232                 }
233
234                 return null;
235         }
236 }