KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > ui > internal > cheatsheets > composite > parser > CompositeCheatSheetParser


1 /*******************************************************************************
2  * Copyright (c) 2005, 2006 IBM Corporation 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  * IBM Corporation - initial API and implementation
10  *******************************************************************************/

11
12 package org.eclipse.ui.internal.cheatsheets.composite.parser;
13
14 import java.io.IOException JavaDoc;
15 import java.io.InputStream JavaDoc;
16 import java.net.URL JavaDoc;
17
18 import javax.xml.parsers.DocumentBuilder JavaDoc;
19 import javax.xml.parsers.DocumentBuilderFactory JavaDoc;
20
21 import org.eclipse.core.runtime.IStatus;
22 import org.eclipse.core.runtime.Status;
23 import org.eclipse.osgi.util.NLS;
24 import org.eclipse.ui.internal.cheatsheets.Messages;
25 import org.eclipse.ui.internal.cheatsheets.composite.model.AbstractTask;
26 import org.eclipse.ui.internal.cheatsheets.composite.model.CompositeCheatSheetModel;
27 import org.eclipse.ui.internal.cheatsheets.composite.model.EditableTask;
28 import org.eclipse.ui.internal.cheatsheets.composite.model.TaskGroup;
29 import org.eclipse.ui.internal.cheatsheets.data.CheatSheetParserException;
30 import org.eclipse.ui.internal.cheatsheets.data.IParserTags;
31 import org.eclipse.ui.internal.cheatsheets.data.ParserStatusUtility;
32 import org.w3c.dom.Document JavaDoc;
33 import org.w3c.dom.NamedNodeMap JavaDoc;
34 import org.w3c.dom.Node JavaDoc;
35 import org.w3c.dom.NodeList JavaDoc;
36 import org.xml.sax.InputSource JavaDoc;
37 import org.xml.sax.SAXException JavaDoc;
38 import org.xml.sax.SAXParseException JavaDoc;
39
40 public class CompositeCheatSheetParser implements IStatusContainer {
41     
42     private DocumentBuilder JavaDoc documentBuilder;
43     
44     private IStatus status;
45     
46     private int nextTaskId = 0;
47     
48     
49     /**
50      * Gets the status of the last call to parseGuide
51      */

52     
53     public IStatus getStatus() {
54         return status;
55     }
56     
57     /**
58      * Returns the DocumentBuilder to be used by composite cheat sheets.
59      */

60     public DocumentBuilder JavaDoc getDocumentBuilder() {
61         if(documentBuilder == null) {
62             try {
63                 documentBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
64             } catch (Exception JavaDoc e) {
65                 addStatus(IStatus.ERROR, Messages.ERROR_CREATING_DOCUMENT_BUILDER, e);
66             }
67         }
68         return documentBuilder;
69     }
70         
71     public void addStatus(int severity, String JavaDoc message, Throwable JavaDoc exception) {
72         status = ParserStatusUtility.addStatus(status, severity, message, exception);
73     }
74     
75     /**
76      * Parse a composite cheat sheet from a url. The parser status will be set as a result
77      * of this operation, if the status is IStatus.ERROR the parser returns null
78      * @param url The url of the input
79      * @return A valid composite cheat sheet or null if there was an error
80      */

81     public CompositeCheatSheetModel parseGuide(URL JavaDoc url) {
82         status = Status.OK_STATUS;
83         if(url == null) {
84             String JavaDoc message = NLS.bind(Messages.ERROR_OPENING_FILE, (new Object JavaDoc[] {""})); //$NON-NLS-1$
85
addStatus(IStatus.ERROR, message, null);
86             return null;
87         }
88
89         InputStream JavaDoc is = null;
90
91         try {
92             is = url.openStream();
93
94             if (is == null) {
95                 String JavaDoc message = NLS.bind(Messages.ERROR_OPENING_FILE, (new Object JavaDoc[] {url.getFile()}));
96                 addStatus(IStatus.ERROR, message, null);
97                 return null;
98             }
99         } catch (Exception JavaDoc e) {
100             String JavaDoc message = NLS.bind(Messages.ERROR_OPENING_FILE, (new Object JavaDoc[] {url.getFile()}));
101             addStatus(IStatus.ERROR, message, e);
102             return null;
103         }
104         
105         Document JavaDoc document;
106         String JavaDoc filename = url.getFile();
107         try {
108             InputSource JavaDoc inputSource = new InputSource JavaDoc(is);
109             document = getDocumentBuilder().parse(inputSource);
110         } catch (IOException JavaDoc e) {
111             String JavaDoc message = NLS.bind(Messages.ERROR_OPENING_FILE_IN_PARSER, (new Object JavaDoc[] {filename}));
112             addStatus(IStatus.ERROR, message, e);
113             return null;
114         } catch (SAXParseException JavaDoc spe) {
115             String JavaDoc message = NLS.bind(Messages.ERROR_SAX_PARSING_WITH_LOCATION, (new Object JavaDoc[] {filename, new Integer JavaDoc(spe.getLineNumber()), new Integer JavaDoc(spe.getColumnNumber())}));
116             addStatus(IStatus.ERROR, message, spe);
117             return null;
118         } catch (SAXException JavaDoc se) {
119             String JavaDoc message = NLS.bind(Messages.ERROR_SAX_PARSING, (new Object JavaDoc[] {filename}));
120             addStatus(IStatus.ERROR, message, se);
121             return null;
122         } finally {
123             try {
124                 is.close();
125             } catch (Exception JavaDoc e) {
126             }
127         }
128         
129         CompositeCheatSheetModel result = parseCompositeCheatSheet(document, url);
130         return result;
131     }
132
133     /**
134      * Parse a composite cheatsheet. The parser status will be set as a result
135      * of this operation, if the status is IStatus.ERROR the parser returns null
136      * @param url The url of the input. This is only used so the model can record
137      * its input location
138      * @param document the document to be parse
139      * @return A valid composite cheat sheet or null if there was an error
140      * @return
141      */

142     public CompositeCheatSheetModel parseCompositeCheatSheet(Document JavaDoc document, URL JavaDoc url) {
143         status = Status.OK_STATUS;
144         try {
145             // If the document passed is null return a null tree and update the status
146
if (document != null) {
147                 Node JavaDoc rootnode = document.getDocumentElement();
148                 
149                 // Is the root node correct?
150
if( !rootnode.getNodeName().equals(ICompositeCheatsheetTags.COMPOSITE_CHEATSHEET )) {
151                     String JavaDoc message = NLS.bind(Messages.ERROR_PARSING_ROOT_NODE_TYPE, (
152                             new Object JavaDoc[] {ICompositeCheatsheetTags.COMPOSITE_CHEATSHEET}));
153                     throw new CheatSheetParserException(message);
154                 }
155                 
156                 String JavaDoc name = ""; //$NON-NLS-1$
157
boolean nameFound = false;
158                 String JavaDoc explorerId = ICompositeCheatsheetTags.TREE;
159                 
160                 NamedNodeMap JavaDoc attributes = rootnode.getAttributes();
161                 if (attributes != null) {
162                     for (int x = 0; x < attributes.getLength(); x++) {
163                         Node JavaDoc attribute = attributes.item(x);
164                         String JavaDoc attributeName = attribute.getNodeName();
165                         if ( attributeName != null && attributeName.equals(ICompositeCheatsheetTags.NAME)) {
166                             nameFound = true;
167                             name= attribute.getNodeValue();
168                         }
169                         if (attributeName.equals(ICompositeCheatsheetTags.EXPLORER)) {
170                             explorerId= attribute.getNodeValue();
171                         }
172                     }
173                 }
174                 CompositeCheatSheetModel compositeCS = new CompositeCheatSheetModel(name, name, explorerId);
175                 
176                 parseCompositeCheatSheetChildren(rootnode, compositeCS);
177                 
178                 compositeCS.getDependencies().resolveDependencies(this);
179                 
180                 if (compositeCS.getRootTask() == null) {
181                     addStatus(IStatus.ERROR, Messages.ERROR_PARSING_NO_ROOT, null);
182                 }
183                 if (!nameFound) {
184                     addStatus(IStatus.ERROR, Messages.ERROR_PARSING_CCS_NO_NAME, null);
185                 }
186                 if (status.getSeverity() != IStatus.ERROR) {
187                     compositeCS.setContentUrl(url);
188                     return compositeCS;
189                 }
190             }
191             return null;
192         } catch(CheatSheetParserException e) {
193             addStatus(IStatus.ERROR, e.getMessage(), null);
194             return null;
195         }
196     }
197
198     private void parseCompositeCheatSheetChildren(Node JavaDoc compositeCSNode, CompositeCheatSheetModel model) {
199         nextTaskId = 0;
200         NodeList JavaDoc childNodes = compositeCSNode.getChildNodes();
201         for (int index = 0; index < childNodes.getLength(); index++) {
202             Node JavaDoc nextNode = childNodes.item(index);
203             if (isAbstractTask(nextNode.getNodeName()) ) {
204                 AbstractTask task = parseAbstractTask(nextNode, model);
205                 if (model.getRootTask() == null ) {
206                     model.setRootTask(task);
207                     parseTaskChildren(nextNode, task, model);
208                 } else {
209                     addStatus(IStatus.ERROR, Messages.ERROR_PARSING_MULTIPLE_ROOT, null);
210                 }
211             }
212         }
213     }
214
215     public static boolean isAbstractTask(String JavaDoc nodeName) {
216         return nodeName == ICompositeCheatsheetTags.TASK ||
217             nodeName == ICompositeCheatsheetTags.TASK_GROUP;
218     }
219     
220     private void parseTaskChildren(Node JavaDoc parentNode, AbstractTask parentTask, CompositeCheatSheetModel model) {
221         NodeList JavaDoc childNodes = parentNode.getChildNodes();
222         ITaskParseStrategy strategy = parentTask.getParserStrategy();
223         strategy.init();
224         for (int index = 0; index < childNodes.getLength(); index++) {
225             Node JavaDoc childNode = childNodes.item(index);
226             if (childNode.getNodeType() == Node.ELEMENT_NODE) {
227                 String JavaDoc nodeName = childNode.getNodeName();
228                 if (nodeName == IParserTags.PARAM) {
229                     addParameter(parentTask, childNode.getAttributes());
230                 } else if (nodeName == IParserTags.INTRO) {
231                     parentTask.setDescription(MarkupParser.parseAndTrimTextMarkup(childNode));
232                 } else if (nodeName == ICompositeCheatsheetTags.ON_COMPLETION) {
233                     parentTask.setCompletionMessage(MarkupParser.parseAndTrimTextMarkup(childNode));
234                 } else if (nodeName == ICompositeCheatsheetTags.DEPENDS_ON) {
235                     parseDependency(childNode, parentTask, model);
236                 } else if (CompositeCheatSheetParser.isAbstractTask(nodeName)) {
237                     if (parentTask instanceof TaskGroup) {
238                         AbstractTask task = parseAbstractTask(childNode, model);
239                         ((TaskGroup)parentTask).addSubtask(task);
240                         parseTaskChildren(childNode, task, model);
241                     }
242                 } else {
243                     if (!strategy.parseElementNode(childNode, parentNode, parentTask, this)) {
244                         String JavaDoc message = NLS
245                         .bind(
246                                 Messages.WARNING_PARSING_UNKNOWN_ELEMENT,
247                                 (new Object JavaDoc[] { nodeName,
248                                         parentNode.getNodeName() }));
249                         addStatus(IStatus.WARNING, message, null);
250                     }
251                 }
252             }
253         }
254         // Check for missing attributes and add dependencies if this was a sequence
255
strategy.parsingComplete(parentTask, this);
256     }
257
258     private void parseDependency(Node JavaDoc taskNode, AbstractTask task, CompositeCheatSheetModel model) {
259         NamedNodeMap JavaDoc attributes = taskNode.getAttributes();
260         if (attributes != null) {
261              Node JavaDoc taskAttribute = attributes.getNamedItem(ICompositeCheatsheetTags.TASK);
262              if (taskAttribute != null) {
263                  String JavaDoc requiredTaskId = taskAttribute.getNodeValue();
264                  model.getDependencies().addDependency(task, requiredTaskId);
265              } else {
266                  addStatus(IStatus.ERROR, Messages.ERROR_PARSING_NO_ID, null);
267              }
268         }
269     }
270
271     private void addParameter(AbstractTask parentTask, NamedNodeMap JavaDoc attributes) {
272         String JavaDoc name = null;
273         String JavaDoc value = null;
274
275         if (attributes != null) {
276             for (int x = 0; x < attributes.getLength(); x++) {
277                 Node JavaDoc attribute = attributes.item(x);
278                 String JavaDoc attributeName = attribute.getNodeName();
279                 if (attribute == null || attributeName == null)
280                     continue;
281                 if (attributeName.equals(ICompositeCheatsheetTags.NAME)) {
282                     name = attribute.getNodeValue();
283                 }
284                 if (attributeName.equals(ICompositeCheatsheetTags.VALUE)) {
285                     value= attribute.getNodeValue();
286                 }
287             }
288         }
289         if (name == null) {
290             addStatus(IStatus.WARNING, Messages.ERROR_PARSING_NO_NAME, null);
291             return;
292         } else if (value == null) {
293             addStatus(IStatus.WARNING, Messages.ERROR_PARSING_NO_VALUE, null);
294             return;
295         } else {
296             parentTask.getParameters().put(name, value);
297         }
298         
299     }
300
301     private AbstractTask parseAbstractTask(Node JavaDoc taskNode, CompositeCheatSheetModel model) {
302         AbstractTask task;
303         NamedNodeMap JavaDoc attributes = taskNode.getAttributes();
304         String JavaDoc kind = null;
305         String JavaDoc name = null;
306         String JavaDoc id = null;
307         boolean skippable = false;
308         if (attributes != null) {
309             for (int x = 0; x < attributes.getLength(); x++) {
310                 Node JavaDoc attribute = attributes.item(x);
311                 String JavaDoc attributeName = attribute.getNodeName();
312                 if (attribute == null || attributeName == null)
313                     continue;
314                 if (attributeName.equals(ICompositeCheatsheetTags.KIND)) {
315                     kind = attribute.getNodeValue();
316                 }
317                 if (attributeName.equals(ICompositeCheatsheetTags.NAME)) {
318                     name= attribute.getNodeValue();
319                 }
320                 if (attributeName.equals(IParserTags.ID)) {
321                     id = attribute.getNodeValue();
322                 }
323                 if (attributeName.equals(IParserTags.SKIP)) {
324                     skippable = "true".equalsIgnoreCase(attribute.getNodeValue()); //$NON-NLS-1$
325
}
326             }
327         }
328
329         String JavaDoc nodeName = taskNode.getNodeName();
330         if (id == null) {
331             id = autoGenerateId();
332         }
333         if (name == null) {
334             String JavaDoc message = NLS.bind(Messages.ERROR_PARSING_TASK_NO_NAME, (new Object JavaDoc[] {nodeName}));
335             addStatus(IStatus.ERROR, message, null);
336         }
337         task = createTask(nodeName, model, kind, id, name);
338         task.setSkippable(skippable);
339
340         if (model.getDependencies().getTask(id) != null) {
341             String JavaDoc message = NLS.bind(Messages.ERROR_PARSING_DUPLICATE_TASK_ID, (new Object JavaDoc[] {id, }));
342             addStatus(IStatus.ERROR, message, null);
343         } else {
344             model.getDependencies().saveId(task);
345         }
346
347         return task;
348     }
349
350     private AbstractTask createTask(String JavaDoc nodeKind, CompositeCheatSheetModel model, String JavaDoc kind, String JavaDoc id, String JavaDoc name) {
351         AbstractTask task;
352         if (ICompositeCheatsheetTags.TASK_GROUP.equals(nodeKind)) {
353             task = new TaskGroup(model, id, name, kind);
354         } else {
355             task = new EditableTask(model, id, name, kind);
356         }
357         task.setCompletionMessage(Messages.COMPLETED_TASK);
358         return task;
359     }
360     
361     private String JavaDoc autoGenerateId() {
362         return "TaskId_" + nextTaskId++; //$NON-NLS-1$
363
}
364
365 }
366
Popular Tags