KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > ant > internal > ui > editor > formatter > XmlFormatter


1 /*******************************************************************************
2  * Copyright (c) 2004, 2006 John-Mason P. Shackelford and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  * John-Mason P. Shackelford - initial API and implementation
10  *******************************************************************************/

11 package org.eclipse.ant.internal.ui.editor.formatter;
12
13 import java.util.ArrayList JavaDoc;
14 import java.util.Arrays JavaDoc;
15 import java.util.List JavaDoc;
16
17 import org.eclipse.ant.internal.ui.editor.templates.AntContext;
18 import org.eclipse.ant.internal.ui.editor.text.AntDocumentSetupParticipant;
19 import org.eclipse.ant.internal.ui.editor.text.AntEditorPartitionScanner;
20 import org.eclipse.ant.internal.ui.model.AntElementNode;
21 import org.eclipse.ant.internal.ui.model.AntProjectNode;
22 import org.eclipse.ant.internal.ui.model.IAntModel;
23 import org.eclipse.core.runtime.Assert;
24 import org.eclipse.jface.text.BadLocationException;
25 import org.eclipse.jface.text.BadPositionCategoryException;
26 import org.eclipse.jface.text.DefaultPositionUpdater;
27 import org.eclipse.jface.text.Document;
28 import org.eclipse.jface.text.IDocument;
29 import org.eclipse.jface.text.IRegion;
30 import org.eclipse.jface.text.Position;
31 import org.eclipse.jface.text.Region;
32 import org.eclipse.jface.text.formatter.MultiPassContentFormatter;
33 import org.eclipse.jface.text.templates.TemplateBuffer;
34 import org.eclipse.jface.text.templates.TemplateVariable;
35
36 /**
37  * Utility class for using the ant code formatter in contexts where an IDocument
38  * containing the text to format is not readily available.
39  */

40 public class XmlFormatter {
41
42     private static final String JavaDoc POS_CATEGORY= "tempAntFormatterCategory"; //$NON-NLS-1$
43

44     /**
45      * Format the text using the ant code formatter.
46      *
47      * @param text
48      * The text to format. Must be a non-null value.
49      * @param prefs
50      * Preferences to use for this format operation. If null, the
51      * preferences currently set in the plug-in's preferences store
52      * are used.
53      * @return The formatted text.
54      */

55     public static String JavaDoc format(String JavaDoc text, FormattingPreferences prefs) {
56         
57       return format(text, prefs, -1);
58     }
59     
60     private static String JavaDoc format(String JavaDoc text, FormattingPreferences prefs, int indent) {
61          Assert.isNotNull(text);
62          
63          FormattingPreferences applyPrefs;
64          if(prefs == null) {
65              applyPrefs = new FormattingPreferences();
66          } else {
67              applyPrefs = prefs;
68          }
69          
70          IDocument doc = new Document();
71          doc.set(text);
72          new AntDocumentSetupParticipant().setup(doc);
73
74          format(applyPrefs, doc, indent);
75
76          return doc.get();
77     }
78
79     private static void format(FormattingPreferences prefs, IDocument doc, int indent) {
80         MultiPassContentFormatter formatter = new MultiPassContentFormatter(
81                 AntDocumentSetupParticipant.ANT_PARTITIONING,
82                 IDocument.DEFAULT_CONTENT_TYPE);
83
84         formatter.setMasterStrategy(new XmlDocumentFormattingStrategy(prefs, indent));
85         formatter.setSlaveStrategy(new XmlElementFormattingStrategy(prefs),
86                 AntEditorPartitionScanner.XML_TAG);
87         formatter.format(doc, new Region(0, doc.getLength()));
88     }
89
90     /**
91      * Format the text using the ant code formatter using the preferences
92      * settings in the plug-in preference store.
93      *
94      * @param text
95      * The text to format. Must be a non-null value.
96      * @return The formatted text.
97      */

98     public static String JavaDoc format(String JavaDoc text) {
99         return format(text,null);
100     }
101     
102     public static void format(TemplateBuffer templateBuffer, AntContext antContext, FormattingPreferences prefs) {
103         String JavaDoc templateString= templateBuffer.getString();
104         IDocument fullDocument= new Document(antContext.getDocument().get());
105         
106         int completionOffset= antContext.getCompletionOffset();
107         try {
108             //trim any starting whitespace
109
IRegion lineRegion= fullDocument.getLineInformationOfOffset(completionOffset);
110             String JavaDoc lineString= fullDocument.get(lineRegion.getOffset(), lineRegion.getLength());
111             lineString= trimBegin(lineString);
112             fullDocument.replace(lineRegion.getOffset(), lineRegion.getLength(), lineString);
113         } catch (BadLocationException e1) {
114             return;
115         }
116         TemplateVariable[] variables= templateBuffer.getVariables();
117         int[] offsets= variablesToOffsets(variables, completionOffset);
118         
119         IDocument origTemplateDoc= new Document(fullDocument.get());
120         try {
121             origTemplateDoc.replace(completionOffset, antContext.getCompletionLength(), templateString);
122         } catch (BadLocationException e) {
123             return; // don't format if the document has changed
124
}
125         
126         IDocument templateDocument= createDocument(origTemplateDoc.get(), createPositions(offsets));
127         
128         String JavaDoc leadingText= getLeadingText(fullDocument, antContext.getAntModel(), completionOffset);
129         String JavaDoc newTemplateString= leadingText + templateString;
130         int indent= XmlDocumentFormatter.computeIndent(leadingText, prefs.getTabWidth());
131         
132         newTemplateString= format(newTemplateString, prefs, indent);
133         
134         try {
135             templateDocument.replace(completionOffset, templateString.length(), newTemplateString);
136         } catch (BadLocationException e) {
137             return;
138         }
139         Position[] positions= null;
140         try {
141             positions= templateDocument.getPositions(POS_CATEGORY);
142         } catch (BadPositionCategoryException e2) {
143         }
144         //offsetsToVariables(offsets, variables, completionOffset);
145
positionsToVariables(positions, variables, completionOffset);
146         templateBuffer.setContent(newTemplateString, variables);
147     }
148     
149     private static void positionsToVariables(Position[] positions, TemplateVariable[] variables, int start) {
150         for (int i= 0; i != variables.length; i++) {
151             TemplateVariable variable= variables[i];
152             
153             int[] offsets= new int[variable.getOffsets().length];
154             for (int j= 0; j != offsets.length; j++) {
155                 offsets[j]= positions[j].getOffset() - start;
156             }
157             
158             variable.setOffsets(offsets);
159         }
160     }
161     private static Document createDocument(String JavaDoc string, Position[] positions) throws IllegalArgumentException JavaDoc {
162         Document doc= new Document(string);
163         try {
164             if (positions != null) {
165                 
166                 doc.addPositionCategory(POS_CATEGORY);
167                 doc.addPositionUpdater(new DefaultPositionUpdater(POS_CATEGORY) {
168                     protected boolean notDeleted() {
169                         if (fOffset < fPosition.offset && (fPosition.offset + fPosition.length < fOffset + fLength)) {
170                             fPosition.offset= fOffset + fLength; // deleted positions: set to end of remove
171
return false;
172                         }
173                         return true;
174                     }
175                 });
176                 for (int i= 0; i < positions.length; i++) {
177                     try {
178                         doc.addPosition(POS_CATEGORY, positions[i]);
179                     } catch (BadLocationException e) {
180                         throw new IllegalArgumentException JavaDoc("Position outside of string. offset: " + positions[i].offset + ", length: " + positions[i].length + ", string size: " + string.length()); //$NON-NLS-1$//$NON-NLS-2$//$NON-NLS-3$
181
}
182                 }
183             }
184         } catch (BadPositionCategoryException cannotHappen) {
185             // can not happen: category is correctly set up
186
}
187         return doc;
188     }
189     
190     public static String JavaDoc trimBegin(String JavaDoc toBeTrimmed) {
191         
192         int i= 0;
193         while ((i != toBeTrimmed.length()) && Character.isWhitespace(toBeTrimmed.charAt(i))) {
194             i++;
195         }
196
197         return toBeTrimmed.substring(i);
198     }
199     
200     private static int[] variablesToOffsets(TemplateVariable[] variables, int start) {
201         List JavaDoc list= new ArrayList JavaDoc();
202         for (int i= 0; i != variables.length; i++) {
203             int[] offsets= variables[i].getOffsets();
204             for (int j= 0; j != offsets.length; j++) {
205                 list.add(new Integer JavaDoc(offsets[j]));
206             }
207         }
208         
209         int[] offsets= new int[list.size()];
210         for (int i= 0; i != offsets.length; i++) {
211             offsets[i]= ((Integer JavaDoc) list.get(i)).intValue() + start;
212         }
213
214         Arrays.sort(offsets);
215
216         return offsets;
217     }
218     
219     /**
220      * Returns the indentation level at the position of code completion.
221      */

222     private static String JavaDoc getLeadingText(IDocument document, IAntModel model, int completionOffset) {
223         AntProjectNode project= model.getProjectNode(false);
224         if (project == null) {
225             return ""; //$NON-NLS-1$
226
}
227         AntElementNode node= project.getNode(completionOffset);// - fAccumulatedChange);
228
if (node == null) {
229             return ""; //$NON-NLS-1$
230
}
231         
232         StringBuffer JavaDoc buf= new StringBuffer JavaDoc();
233         buf.append(XmlDocumentFormatter.getLeadingWhitespace(node.getOffset(), document));
234         buf.append(XmlDocumentFormatter.createIndent());
235         return buf.toString();
236     }
237     
238      private static Position[] createPositions(int[] positions) {
239         Position[] p= null;
240         
241         if (positions != null) {
242             p= new Position[positions.length];
243             for (int i= 0; i < positions.length; i++) {
244                 p[i]= new Position(positions[i], 0);
245             }
246         }
247         return p;
248     }
249 }
250
Popular Tags