1 11 12 package org.eclipse.ui.internal.cheatsheets.composite.parser; 13 14 import java.io.IOException ; 15 import java.io.InputStream ; 16 import java.net.URL ; 17 18 import javax.xml.parsers.DocumentBuilder ; 19 import javax.xml.parsers.DocumentBuilderFactory ; 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 ; 33 import org.w3c.dom.NamedNodeMap ; 34 import org.w3c.dom.Node ; 35 import org.w3c.dom.NodeList ; 36 import org.xml.sax.InputSource ; 37 import org.xml.sax.SAXException ; 38 import org.xml.sax.SAXParseException ; 39 40 public class CompositeCheatSheetParser implements IStatusContainer { 41 42 private DocumentBuilder documentBuilder; 43 44 private IStatus status; 45 46 private int nextTaskId = 0; 47 48 49 52 53 public IStatus getStatus() { 54 return status; 55 } 56 57 60 public DocumentBuilder getDocumentBuilder() { 61 if(documentBuilder == null) { 62 try { 63 documentBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder(); 64 } catch (Exception 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 message, Throwable exception) { 72 status = ParserStatusUtility.addStatus(status, severity, message, exception); 73 } 74 75 81 public CompositeCheatSheetModel parseGuide(URL url) { 82 status = Status.OK_STATUS; 83 if(url == null) { 84 String message = NLS.bind(Messages.ERROR_OPENING_FILE, (new Object [] {""})); addStatus(IStatus.ERROR, message, null); 86 return null; 87 } 88 89 InputStream is = null; 90 91 try { 92 is = url.openStream(); 93 94 if (is == null) { 95 String message = NLS.bind(Messages.ERROR_OPENING_FILE, (new Object [] {url.getFile()})); 96 addStatus(IStatus.ERROR, message, null); 97 return null; 98 } 99 } catch (Exception e) { 100 String message = NLS.bind(Messages.ERROR_OPENING_FILE, (new Object [] {url.getFile()})); 101 addStatus(IStatus.ERROR, message, e); 102 return null; 103 } 104 105 Document document; 106 String filename = url.getFile(); 107 try { 108 InputSource inputSource = new InputSource (is); 109 document = getDocumentBuilder().parse(inputSource); 110 } catch (IOException e) { 111 String message = NLS.bind(Messages.ERROR_OPENING_FILE_IN_PARSER, (new Object [] {filename})); 112 addStatus(IStatus.ERROR, message, e); 113 return null; 114 } catch (SAXParseException spe) { 115 String message = NLS.bind(Messages.ERROR_SAX_PARSING_WITH_LOCATION, (new Object [] {filename, new Integer (spe.getLineNumber()), new Integer (spe.getColumnNumber())})); 116 addStatus(IStatus.ERROR, message, spe); 117 return null; 118 } catch (SAXException se) { 119 String message = NLS.bind(Messages.ERROR_SAX_PARSING, (new Object [] {filename})); 120 addStatus(IStatus.ERROR, message, se); 121 return null; 122 } finally { 123 try { 124 is.close(); 125 } catch (Exception e) { 126 } 127 } 128 129 CompositeCheatSheetModel result = parseCompositeCheatSheet(document, url); 130 return result; 131 } 132 133 142 public CompositeCheatSheetModel parseCompositeCheatSheet(Document document, URL url) { 143 status = Status.OK_STATUS; 144 try { 145 if (document != null) { 147 Node rootnode = document.getDocumentElement(); 148 149 if( !rootnode.getNodeName().equals(ICompositeCheatsheetTags.COMPOSITE_CHEATSHEET )) { 151 String message = NLS.bind(Messages.ERROR_PARSING_ROOT_NODE_TYPE, ( 152 new Object [] {ICompositeCheatsheetTags.COMPOSITE_CHEATSHEET})); 153 throw new CheatSheetParserException(message); 154 } 155 156 String name = ""; boolean nameFound = false; 158 String explorerId = ICompositeCheatsheetTags.TREE; 159 160 NamedNodeMap attributes = rootnode.getAttributes(); 161 if (attributes != null) { 162 for (int x = 0; x < attributes.getLength(); x++) { 163 Node attribute = attributes.item(x); 164 String 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 compositeCSNode, CompositeCheatSheetModel model) { 199 nextTaskId = 0; 200 NodeList childNodes = compositeCSNode.getChildNodes(); 201 for (int index = 0; index < childNodes.getLength(); index++) { 202 Node 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 nodeName) { 216 return nodeName == ICompositeCheatsheetTags.TASK || 217 nodeName == ICompositeCheatsheetTags.TASK_GROUP; 218 } 219 220 private void parseTaskChildren(Node parentNode, AbstractTask parentTask, CompositeCheatSheetModel model) { 221 NodeList childNodes = parentNode.getChildNodes(); 222 ITaskParseStrategy strategy = parentTask.getParserStrategy(); 223 strategy.init(); 224 for (int index = 0; index < childNodes.getLength(); index++) { 225 Node childNode = childNodes.item(index); 226 if (childNode.getNodeType() == Node.ELEMENT_NODE) { 227 String 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 message = NLS 245 .bind( 246 Messages.WARNING_PARSING_UNKNOWN_ELEMENT, 247 (new Object [] { nodeName, 248 parentNode.getNodeName() })); 249 addStatus(IStatus.WARNING, message, null); 250 } 251 } 252 } 253 } 254 strategy.parsingComplete(parentTask, this); 256 } 257 258 private void parseDependency(Node taskNode, AbstractTask task, CompositeCheatSheetModel model) { 259 NamedNodeMap attributes = taskNode.getAttributes(); 260 if (attributes != null) { 261 Node taskAttribute = attributes.getNamedItem(ICompositeCheatsheetTags.TASK); 262 if (taskAttribute != null) { 263 String 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 attributes) { 272 String name = null; 273 String value = null; 274 275 if (attributes != null) { 276 for (int x = 0; x < attributes.getLength(); x++) { 277 Node attribute = attributes.item(x); 278 String 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 taskNode, CompositeCheatSheetModel model) { 302 AbstractTask task; 303 NamedNodeMap attributes = taskNode.getAttributes(); 304 String kind = null; 305 String name = null; 306 String id = null; 307 boolean skippable = false; 308 if (attributes != null) { 309 for (int x = 0; x < attributes.getLength(); x++) { 310 Node attribute = attributes.item(x); 311 String 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()); } 326 } 327 } 328 329 String nodeName = taskNode.getNodeName(); 330 if (id == null) { 331 id = autoGenerateId(); 332 } 333 if (name == null) { 334 String message = NLS.bind(Messages.ERROR_PARSING_TASK_NO_NAME, (new Object [] {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 message = NLS.bind(Messages.ERROR_PARSING_DUPLICATE_TASK_ID, (new Object [] {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 nodeKind, CompositeCheatSheetModel model, String kind, String id, String 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 autoGenerateId() { 362 return "TaskId_" + nextTaskId++; } 364 365 } 366 | Popular Tags |