Source Code Cross Referenced for CheatSheetParser.java in  » IDE-Eclipse » ui » org » eclipse » ui » internal » cheatsheets » data » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » IDE Eclipse » ui » org.eclipse.ui.internal.cheatsheets.data 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*******************************************************************************
0002:         * Copyright (c) 2002, 2007 IBM Corporation and others.
0003:         * All rights reserved. This program and the accompanying materials
0004:         * are made available under the terms of the Eclipse Public License v1.0
0005:         * which accompanies this distribution, and is available at
0006:         * http://www.eclipse.org/legal/epl-v10.html
0007:         *
0008:         * Contributors:
0009:         *     IBM Corporation - initial API and implementation
0010:         *******************************************************************************/package org.eclipse.ui.internal.cheatsheets.data;
0011:
0012:        import java.io.IOException;
0013:        import java.io.InputStream;
0014:        import java.io.StringReader;
0015:        import java.net.URL;
0016:        import java.util.ArrayList;
0017:
0018:        import javax.xml.parsers.DocumentBuilder;
0019:
0020:        import org.eclipse.core.runtime.Assert;
0021:        import org.eclipse.core.runtime.IStatus;
0022:        import org.eclipse.core.runtime.Platform;
0023:        import org.eclipse.core.runtime.Status;
0024:        import org.eclipse.help.internal.UAElement;
0025:        import org.eclipse.help.internal.UAElementFactory;
0026:        import org.eclipse.help.internal.dynamic.DocumentProcessor;
0027:        import org.eclipse.help.internal.dynamic.DocumentReader;
0028:        import org.eclipse.help.internal.dynamic.ExtensionHandler;
0029:        import org.eclipse.help.internal.dynamic.FilterHandler;
0030:        import org.eclipse.help.internal.dynamic.IncludeHandler;
0031:        import org.eclipse.help.internal.dynamic.ProcessorHandler;
0032:        import org.eclipse.osgi.util.NLS;
0033:        import org.eclipse.ui.cheatsheets.AbstractItemExtensionElement;
0034:        import org.eclipse.ui.internal.cheatsheets.CheatSheetEvaluationContext;
0035:        import org.eclipse.ui.internal.cheatsheets.CheatSheetPlugin;
0036:        import org.eclipse.ui.internal.cheatsheets.ICheatSheetResource;
0037:        import org.eclipse.ui.internal.cheatsheets.Messages;
0038:        import org.eclipse.ui.internal.cheatsheets.composite.model.CompositeCheatSheetModel;
0039:        import org.eclipse.ui.internal.cheatsheets.composite.parser.CompositeCheatSheetParser;
0040:        import org.eclipse.ui.internal.cheatsheets.composite.parser.ICompositeCheatsheetTags;
0041:        import org.eclipse.ui.internal.cheatsheets.composite.parser.IStatusContainer;
0042:        import org.eclipse.ui.internal.cheatsheets.registry.CheatSheetItemExtensionElement;
0043:        import org.eclipse.ui.internal.cheatsheets.registry.CheatSheetRegistryReader;
0044:        import org.w3c.dom.Document;
0045:        import org.w3c.dom.NamedNodeMap;
0046:        import org.w3c.dom.Node;
0047:        import org.w3c.dom.NodeList;
0048:        import org.xml.sax.InputSource;
0049:        import org.xml.sax.SAXException;
0050:        import org.xml.sax.SAXParseException;
0051:
0052:        /**
0053:         * Parser for the cheatsheet content files.
0054:         * 
0055:         * Construct an intance of the CheatSheetDomParser.
0056:         * Call <code>parse()</code>.
0057:         * Then get the content items by calling
0058:         * <code>getIntroItem()</code> and <code>getItemsList()</code>.
0059:         * The title of the cheatsheet can be retrieved by calling
0060:         * <code>getTitle()</code>.
0061:         * 
0062:         */
0063:        public class CheatSheetParser implements  IStatusContainer {
0064:
0065:            private static final String TRUE_STRING = "true"; //$NON-NLS-1$
0066:
0067:            private DocumentBuilder documentBuilder;
0068:            private DocumentProcessor processor;
0069:            private ArrayList itemExtensionContainerList;
0070:
0071:            // Cheatsheet kinds that can be parsed
0072:            public static final int COMPOSITE_ONLY = 1;
0073:            public static final int SIMPLE_ONLY = 2;
0074:            public static final int ANY = 3;
0075:
0076:            private IStatus status;
0077:
0078:            private int commandCount;
0079:
0080:            private int actionCount;
0081:
0082:            /**
0083:             * Java constructor comment.
0084:             */
0085:            public CheatSheetParser() {
0086:                super ();
0087:                documentBuilder = CheatSheetPlugin.getPlugin()
0088:                        .getDocumentBuilder();
0089:            }
0090:
0091:            /**
0092:             *  Gets the status of the last call to parse()
0093:             */
0094:            public IStatus getStatus() {
0095:                return status;
0096:            }
0097:
0098:            public void addStatus(int severity, String message,
0099:                    Throwable exception) {
0100:                status = ParserStatusUtility.addStatus(status, severity,
0101:                        message, exception);
0102:            }
0103:
0104:            /**
0105:             * Converts any characters required to escaped by an XML parser to 
0106:             * their escaped counterpart.
0107:             * 
0108:             * Characters			XML escaped counterpart
0109:             * <			->		&lt;
0110:             * >			->		&gt;
0111:             * &			->		&amp;
0112:             * '			->		&apos;
0113:             * "			->		&quot;
0114:             *
0115:             * Tags that will be ignored <b>, </b> and <br/>.
0116:             *
0117:             * @param text the string buffer to have its characters escaped
0118:             * @return string buffer with any of the characters requiring XML escaping escaped
0119:             */
0120:            private StringBuffer escapeXMLCharacters(StringBuffer text) {
0121:                // Set the maximum length of the tags to ignore
0122:                final int MAXIMUM_TAG_LENGTH = 5;
0123:
0124:                // Keep a local variable for the orignal string's length
0125:                int length = text.length();
0126:
0127:                // Create the buffer to store the resulting string
0128:                StringBuffer result = new StringBuffer(length);
0129:
0130:                // Loop for the characters of the original string
0131:                for (int i = 0; i < length; i++) {
0132:                    // Grab the next character and determine how to handle it
0133:                    char c = text.charAt(i);
0134:                    switch (c) {
0135:                    case '<': {
0136:                        // We have a less than, grab the maximum tag length of characters
0137:                        // or the remaining characters which follow and determine if it
0138:                        // is the start of a tag to ignore.
0139:                        String tmp = ICheatSheetResource.EMPTY_STRING;
0140:                        if (i + MAXIMUM_TAG_LENGTH < length)
0141:                            tmp = text.substring(i, i + MAXIMUM_TAG_LENGTH)
0142:                                    .toLowerCase();
0143:                        else {
0144:                            tmp = text.substring(i, length).toLowerCase();
0145:                        }
0146:                        if (tmp.startsWith(IParserTags.BOLD_START_TAG)
0147:                                || tmp.startsWith(IParserTags.BOLD_END_TAG)
0148:                                || tmp.startsWith(IParserTags.BREAK_TAG)) {
0149:                            // We have a tag to ignore so just emit the character
0150:                            result.append(c);
0151:                        } else {
0152:                            // We have detemined that it is just a less than
0153:                            // so emit the XML escaped counterpart
0154:                            result.append(IParserTags.LESS_THAN);
0155:                        }
0156:                        break;
0157:                    }
0158:                    case '>': {
0159:                        // We have a greater than, grab the maximum tag length of characters
0160:                        // or the starting characters which come before and determine if it
0161:                        // is the end of a tag to ignore.
0162:                        String tmp = ICheatSheetResource.EMPTY_STRING;
0163:                        if (i >= MAXIMUM_TAG_LENGTH) {
0164:                            tmp = text.substring(i - MAXIMUM_TAG_LENGTH, i + 1)
0165:                                    .toLowerCase();
0166:                        } else {
0167:                            tmp = text.substring(0, i + 1).toLowerCase();
0168:                        }
0169:                        if (tmp.endsWith(IParserTags.BOLD_START_TAG)
0170:                                || tmp.endsWith(IParserTags.BOLD_END_TAG)
0171:                                || tmp.endsWith(IParserTags.BREAK_TAG)) {
0172:                            // We have a tag to ignore so just emit the character
0173:                            result.append(c);
0174:                        } else {
0175:                            // We have detemined that it is just a greater than
0176:                            // so emit the XML escaped counterpart
0177:                            result.append(IParserTags.GREATER_THAN);
0178:                        }
0179:                        break;
0180:                    }
0181:                    case '&':
0182:                        // We have an ampersand so emit the XML escaped counterpart
0183:                        result.append(IParserTags.AMPERSAND);
0184:                        break;
0185:                    case '\'':
0186:                        // We have an apostrophe so emit the XML escaped counterpart
0187:                        result.append(IParserTags.APOSTROPHE);
0188:                        break;
0189:                    case '"':
0190:                        // We have a quote so emit the XML escaped counterpart
0191:                        result.append(IParserTags.QUOTE);
0192:                        break;
0193:                    case '\t':
0194:                        // We have a tab, replace with a space
0195:                        result.append(' ');
0196:                        break;
0197:                    default:
0198:                        // We have a character that does not require escaping
0199:                        result.append(c);
0200:                        break;
0201:                    }
0202:                }
0203:                return result;
0204:            }
0205:
0206:            private Node findNode(Node startNode, String nodeName) {
0207:                if (startNode == null) {
0208:                    return null;
0209:                }
0210:
0211:                if (startNode.getNodeName().equals(nodeName)) {
0212:                    return startNode;
0213:                }
0214:
0215:                NodeList nodes = startNode.getChildNodes();
0216:                for (int i = 0; i < nodes.getLength(); i++) {
0217:                    Node node = nodes.item(i);
0218:                    if (node.getNodeName().equals(nodeName)) {
0219:                        return node;
0220:                    }
0221:                }
0222:
0223:                return null;
0224:            }
0225:
0226:            private void handleExecutable(IExecutableItem item,
0227:                    Node executableNode, AbstractExecutable executable)
0228:                    throws CheatSheetParserException {
0229:                Assert.isNotNull(item);
0230:                Assert.isNotNull(executableNode);
0231:
0232:                String[] params = null;
0233:
0234:                if (executable instanceof  CheatSheetCommand) {
0235:                    commandCount++;
0236:                }
0237:                if (executable instanceof  Action) {
0238:                    actionCount++;
0239:                }
0240:
0241:                NamedNodeMap attributes = executableNode.getAttributes();
0242:                if (attributes != null) {
0243:                    for (int x = 0; x < attributes.getLength(); x++) {
0244:                        Node attribute = attributes.item(x);
0245:                        String attributeName = attribute.getNodeName();
0246:                        if (attribute == null || attributeName == null)
0247:                            continue;
0248:                        if (attributeName.equals(IParserTags.CONFIRM)) {
0249:                            executable.setConfirm(attribute.getNodeValue()
0250:                                    .equals(TRUE_STRING));
0251:                        } else if (attributeName.equals(IParserTags.WHEN)) {
0252:                            executable.setWhen(attribute.getNodeValue());
0253:                        } else if (attributeName.equals(IParserTags.REQUIRED)) {
0254:                            executable.setRequired(attribute.getNodeValue()
0255:                                    .equals(TRUE_STRING));
0256:                        } else if (attributeName.equals(IParserTags.TRANSLATE)) {
0257:                            // Translation hint, no semantic effect
0258:                        } else if (executable.hasParams()
0259:                                && attributeName.startsWith(IParserTags.PARAM)) {
0260:                            try {
0261:                                if (params == null) {
0262:                                    params = new String[9];
0263:                                }
0264:                                String paramNum = attributeName
0265:                                        .substring(IParserTags.PARAM.length());
0266:                                int num = Integer.parseInt(paramNum) - 1;
0267:
0268:                                if (num > -1 && num < 9) {
0269:                                    params[num] = attribute.getNodeValue();
0270:                                } else {
0271:                                    String message = NLS
0272:                                            .bind(
0273:                                                    Messages.ERROR_PARSING_PARAM_INVALIDRANGE,
0274:                                                    (new Object[] {
0275:                                                            attributeName,
0276:                                                            paramNum }));
0277:                                    addStatus(IStatus.ERROR, message, null);
0278:                                }
0279:                            } catch (NumberFormatException e) {
0280:                                String message = Messages.ERROR_PARSING_PARAM_INVALIDNUMBER;
0281:                                addStatus(IStatus.ERROR, message, e);
0282:                            }
0283:                        } else if (!executable.handleAttribute(attribute)) {
0284:                            String message = NLS.bind(
0285:                                    Messages.WARNING_PARSING_UNKNOWN_ATTRIBUTE,
0286:                                    (new Object[] { attributeName,
0287:                                            executableNode.getNodeName() }));
0288:                            addStatus(IStatus.WARNING, message, null);
0289:                        }
0290:                    }
0291:                    String errorMessage = executable
0292:                            .checkAttributes(executableNode);
0293:                    if (errorMessage != null) {
0294:                        throw new CheatSheetParserException(errorMessage);
0295:                    }
0296:                }
0297:                checkForNoChildren(executableNode);
0298:                executable.setParams(params);
0299:                item.setExecutable(executable);
0300:            }
0301:
0302:            private void checkForNoChildren(Node parentNode) {
0303:                NodeList nodes = parentNode.getChildNodes();
0304:                for (int i = 0; i < nodes.getLength(); i++) {
0305:                    Node node = nodes.item(i);
0306:                    if (node.getNodeType() != Node.TEXT_NODE
0307:                            && node.getNodeType() != Node.COMMENT_NODE) {
0308:                        String message = NLS.bind(
0309:                                Messages.WARNING_PARSING_UNKNOWN_ELEMENT,
0310:                                (new Object[] { node.getNodeName(),
0311:                                        parentNode.getNodeName() }));
0312:                        addStatus(IStatus.WARNING, message, null);
0313:                    }
0314:                }
0315:            }
0316:
0317:            private void handleCheatSheetAttributes(CheatSheet cheatSheet,
0318:                    Node cheatSheetNode) throws CheatSheetParserException {
0319:                Assert.isNotNull(cheatSheet);
0320:                Assert.isNotNull(cheatSheetNode);
0321:                Assert.isTrue(cheatSheetNode.getNodeName().equals(
0322:                        IParserTags.CHEATSHEET));
0323:
0324:                boolean title = false;
0325:
0326:                NamedNodeMap attributes = cheatSheetNode.getAttributes();
0327:                if (attributes != null) {
0328:                    for (int x = 0; x < attributes.getLength(); x++) {
0329:                        Node attribute = attributes.item(x);
0330:                        String attributeName = attribute.getNodeName();
0331:                        if (attribute == null || attributeName == null)
0332:                            continue;
0333:
0334:                        if (attributeName.equals(IParserTags.TITLE)) {
0335:                            title = true;
0336:                            cheatSheet.setTitle(attribute.getNodeValue());
0337:                        } else {
0338:                            String message = NLS.bind(
0339:                                    Messages.WARNING_PARSING_UNKNOWN_ATTRIBUTE,
0340:                                    (new Object[] { attributeName,
0341:                                            cheatSheetNode.getNodeName() }));
0342:                            addStatus(IStatus.WARNING, message, null);
0343:                        }
0344:                    }
0345:                }
0346:
0347:                if (!title) {
0348:                    String message = NLS.bind(Messages.ERROR_PARSING_NO_TITLE,
0349:                            (new Object[] { cheatSheetNode.getNodeName() }));
0350:                    throw new CheatSheetParserException(message);
0351:                }
0352:            }
0353:
0354:            private void handleConditionalSubItem(Item item,
0355:                    Node conditionalSubItemNode)
0356:                    throws CheatSheetParserException {
0357:                Assert.isNotNull(item);
0358:                Assert.isNotNull(conditionalSubItemNode);
0359:                Assert.isTrue(conditionalSubItemNode.getNodeName().equals(
0360:                        IParserTags.CONDITIONALSUBITEM));
0361:
0362:                ConditionalSubItem conditionalSubItem = new ConditionalSubItem();
0363:
0364:                boolean condition = false;
0365:
0366:                // Handle attributes
0367:                NamedNodeMap attributes = conditionalSubItemNode
0368:                        .getAttributes();
0369:                if (attributes != null) {
0370:                    for (int x = 0; x < attributes.getLength(); x++) {
0371:                        Node attribute = attributes.item(x);
0372:                        String attributeName = attribute.getNodeName();
0373:                        if (attribute == null || attributeName == null)
0374:                            continue;
0375:
0376:                        if (attributeName.equals(IParserTags.CONDITION)) {
0377:                            condition = true;
0378:                            conditionalSubItem.setCondition(attribute
0379:                                    .getNodeValue());
0380:                        } else {
0381:                            String message = NLS.bind(
0382:                                    Messages.WARNING_PARSING_UNKNOWN_ATTRIBUTE,
0383:                                    (new Object[] {
0384:                                            attributeName,
0385:                                            conditionalSubItemNode
0386:                                                    .getNodeName() }));
0387:                            addStatus(IStatus.WARNING, message, null);
0388:                        }
0389:                    }
0390:                }
0391:
0392:                if (!condition) {
0393:                    String message = NLS.bind(
0394:                            Messages.ERROR_PARSING_NO_CONDITION,
0395:                            (new Object[] { conditionalSubItemNode
0396:                                    .getNodeName() }));
0397:                    throw new CheatSheetParserException(message);
0398:                }
0399:
0400:                boolean subitem = false;
0401:
0402:                // Handle nodes
0403:                NodeList nodes = conditionalSubItemNode.getChildNodes();
0404:                for (int i = 0; i < nodes.getLength(); i++) {
0405:                    Node node = nodes.item(i);
0406:
0407:                    if (node.getNodeName().equals(IParserTags.SUBITEM)) {
0408:                        subitem = true;
0409:                        handleSubItem(conditionalSubItem, node);
0410:                    } else {
0411:                        if (node.getNodeType() != Node.TEXT_NODE
0412:                                && node.getNodeType() != Node.COMMENT_NODE) {
0413:                            String message = NLS.bind(
0414:                                    Messages.WARNING_PARSING_UNKNOWN_ELEMENT,
0415:                                    (new Object[] {
0416:                                            node.getNodeName(),
0417:                                            conditionalSubItemNode
0418:                                                    .getNodeName() }));
0419:                            addStatus(IStatus.WARNING, message, null);
0420:                        }
0421:                    }
0422:                }
0423:
0424:                if (!subitem) {
0425:                    String message = NLS.bind(
0426:                            Messages.ERROR_PARSING_NO_SUBITEM,
0427:                            (new Object[] { conditionalSubItemNode
0428:                                    .getNodeName() }));
0429:                    throw new CheatSheetParserException(message);
0430:                }
0431:
0432:                item.addSubItem(conditionalSubItem);
0433:            }
0434:
0435:            private void handleDescription(Item item, Node startNode)
0436:                    throws CheatSheetParserException {
0437:                Assert.isNotNull(item);
0438:                Assert.isNotNull(startNode);
0439:
0440:                Node descriptionNode = findNode(startNode,
0441:                        IParserTags.DESCRIPTION);
0442:
0443:                if (descriptionNode != null) {
0444:                    String text = handleMarkedUpText(descriptionNode,
0445:                            startNode, IParserTags.DESCRIPTION);
0446:                    item.setDescription(text);
0447:                } else {
0448:                    Node parentNode = startNode;
0449:                    if (startNode.getNodeName().equals(IParserTags.DESCRIPTION)) {
0450:                        parentNode = startNode.getParentNode();
0451:                    }
0452:                    String message = NLS.bind(
0453:                            Messages.ERROR_PARSING_NO_DESCRIPTION,
0454:                            (new Object[] { parentNode.getNodeName() }));
0455:                    throw new CheatSheetParserException(message);
0456:                }
0457:            }
0458:
0459:            private String handleMarkedUpText(Node nodeContainingText,
0460:                    Node startNode, String nodeName) {
0461:                NodeList nodes = nodeContainingText.getChildNodes();
0462:                StringBuffer text = new StringBuffer();
0463:
0464:                boolean containsMarkup = false;
0465:
0466:                // The documentation for the content file specifies
0467:                // that leading whitespace should be ignored at the
0468:                // beginning of a description or after a <br/>. This 
0469:                // applies also to <onCompletion> elements.
0470:                // See Bug 129208 and Bug 131185
0471:                boolean isLeadingTrimRequired = true;
0472:
0473:                for (int i = 0; i < nodes.getLength(); i++) {
0474:                    Node node = nodes.item(i);
0475:                    if (node.getNodeType() == Node.TEXT_NODE) {
0476:                        String nodeValue = node.getNodeValue();
0477:                        if (isLeadingTrimRequired) {
0478:                            nodeValue = trimLeadingWhitespace(nodeValue);
0479:                        }
0480:                        text.append(nodeValue);
0481:                        isLeadingTrimRequired = false;
0482:                    } else if (node.getNodeType() == Node.ELEMENT_NODE) {
0483:                        // handle <b></b> and <br/>
0484:                        if (node.getNodeName().equals(IParserTags.BOLD)) {
0485:                            containsMarkup = true;
0486:                            text.append(IParserTags.BOLD_START_TAG);
0487:                            text.append(node.getFirstChild().getNodeValue());
0488:                            text.append(IParserTags.BOLD_END_TAG);
0489:                            isLeadingTrimRequired = false;
0490:                        } else if (node.getNodeName().equals(IParserTags.BREAK)) {
0491:                            containsMarkup = true;
0492:                            text.append(IParserTags.BREAK_TAG);
0493:                            isLeadingTrimRequired = true;
0494:                        } else {
0495:                            warnUnknownMarkupElement(startNode, nodeName, node);
0496:                        }
0497:                    }
0498:                }
0499:
0500:                if (containsMarkup) {
0501:                    text = escapeXMLCharacters(text);
0502:                    text.insert(0, IParserTags.FORM_START_TAG);
0503:                    text.append(IParserTags.FORM_END_TAG);
0504:                } else {
0505:                    deTab(text);
0506:                }
0507:
0508:                // Remove the new line, form feed and tab chars
0509:                return text.toString().trim();
0510:            }
0511:
0512:            // Replace any tabs with spaces
0513:
0514:            private void deTab(StringBuffer text) {
0515:                for (int i = 0; i < text.length(); i++) {
0516:                    if (text.charAt(i) == '\t') {
0517:                        text.setCharAt(i, ' ');
0518:                    }
0519:                }
0520:            }
0521:
0522:            private String trimLeadingWhitespace(String nodeValue) {
0523:                int firstNonWhitespaceIndex = 0;
0524:                while (firstNonWhitespaceIndex < nodeValue.length()
0525:                        && Character.isWhitespace(nodeValue
0526:                                .charAt(firstNonWhitespaceIndex))) {
0527:                    firstNonWhitespaceIndex++;
0528:                }
0529:                if (firstNonWhitespaceIndex > 0) {
0530:                    return nodeValue.substring(firstNonWhitespaceIndex,
0531:                            nodeValue.length());
0532:                }
0533:                return nodeValue;
0534:            }
0535:
0536:            /*
0537:             * Write a warning to the log
0538:             */
0539:            private void warnUnknownMarkupElement(Node startNode,
0540:                    String nodeName, Node node) {
0541:                Node parentNode = startNode;
0542:                if (startNode.getNodeName().equals(nodeName)) {
0543:                    parentNode = startNode.getParentNode();
0544:                }
0545:                String message;
0546:                if (IParserTags.DESCRIPTION.equals(nodeName)) {
0547:                    message = NLS
0548:                            .bind(
0549:                                    Messages.WARNING_PARSING_DESCRIPTION_UNKNOWN_ELEMENT,
0550:                                    (new Object[] { parentNode.getNodeName(),
0551:                                            node.getNodeName() }));
0552:                } else {
0553:                    message = NLS
0554:                            .bind(
0555:                                    Messages.WARNING_PARSING_ON_COMPLETION_UNKNOWN_ELEMENT,
0556:                                    (new Object[] { parentNode.getNodeName(),
0557:                                            node.getNodeName() }));
0558:                }
0559:                addStatus(IStatus.WARNING, message, null);
0560:
0561:            }
0562:
0563:            private void handleOnCompletion(Item item, Node onCompletionNode) {
0564:                String text = handleMarkedUpText(onCompletionNode,
0565:                        onCompletionNode, IParserTags.ON_COMPLETION);
0566:                item.setCompletionMessage(text);
0567:            }
0568:
0569:            private void handleIntroNode(CheatSheet cheatSheet, Node introNode)
0570:                    throws CheatSheetParserException {
0571:                Item introItem = new Item();
0572:                introItem.setTitle(Messages.CHEAT_SHEET_INTRO_TITLE);
0573:
0574:                handleIntroAttributes(introItem, introNode);
0575:
0576:                boolean hasDescription = false;
0577:
0578:                NodeList nodes = introNode.getChildNodes();
0579:                for (int i = 0; i < nodes.getLength(); i++) {
0580:                    Node node = nodes.item(i);
0581:
0582:                    if (node.getNodeName().equals(IParserTags.DESCRIPTION)) {
0583:                        if (hasDescription) {
0584:                            String message = NLS
0585:                                    .bind(
0586:                                            Messages.ERROR_PARSING_MULTIPLE_DESCRIPTION,
0587:                                            (new Object[] { introNode
0588:                                                    .getNodeName() }));
0589:                            addStatus(IStatus.ERROR, message, null);
0590:                        } else {
0591:                            hasDescription = true;
0592:                            handleDescription(introItem, node);
0593:                        }
0594:                    } else {
0595:                        if (node.getNodeType() != Node.TEXT_NODE
0596:                                && node.getNodeType() != Node.COMMENT_NODE) {
0597:                            String message = NLS.bind(
0598:                                    Messages.WARNING_PARSING_UNKNOWN_ELEMENT,
0599:                                    (new Object[] { node.getNodeName(),
0600:                                            introNode.getNodeName() }));
0601:                            addStatus(IStatus.WARNING, message, null);
0602:                        }
0603:                    }
0604:                }
0605:
0606:                if (!hasDescription) {
0607:                    String message = NLS.bind(
0608:                            Messages.ERROR_PARSING_NO_DESCRIPTION,
0609:                            (new Object[] { introNode.getNodeName() }));
0610:                    addStatus(IStatus.ERROR, message, null);
0611:                }
0612:
0613:                cheatSheet.setIntroItem(introItem);
0614:            }
0615:
0616:            private void handleIntroAttributes(Item item, Node introNode) {
0617:                Assert.isNotNull(item);
0618:                Assert.isNotNull(introNode);
0619:
0620:                NamedNodeMap attributes = introNode.getAttributes();
0621:                if (attributes != null) {
0622:                    for (int x = 0; x < attributes.getLength(); x++) {
0623:                        Node attribute = attributes.item(x);
0624:                        String attributeName = attribute.getNodeName();
0625:                        if (attribute == null || attributeName == null)
0626:                            continue;
0627:
0628:                        if (attributeName.equals(IParserTags.CONTEXTID)) {
0629:                            item.setContextId(attribute.getNodeValue());
0630:                        } else if (attributeName.equals(IParserTags.HREF)) {
0631:                            item.setHref(attribute.getNodeValue());
0632:                        } else {
0633:                            String message = NLS.bind(
0634:                                    Messages.WARNING_PARSING_UNKNOWN_ATTRIBUTE,
0635:                                    (new Object[] { attributeName,
0636:                                            introNode.getNodeName() }));
0637:                            addStatus(IStatus.WARNING, message, null);
0638:                        }
0639:                    }
0640:                }
0641:            }
0642:
0643:            private Item handleItem(Node itemNode)
0644:                    throws CheatSheetParserException {
0645:                Assert.isNotNull(itemNode);
0646:                Assert.isTrue(itemNode.getNodeName().equals(IParserTags.ITEM));
0647:
0648:                Item item = new Item();
0649:
0650:                handleItemAttributes(item, itemNode);
0651:
0652:                boolean hasDescription = false;
0653:
0654:                NodeList nodes = itemNode.getChildNodes();
0655:
0656:                IncompatibleSiblingChecker checker = new IncompatibleSiblingChecker(
0657:                        this , itemNode);
0658:                for (int i = 0; i < nodes.getLength(); i++) {
0659:                    Node node = nodes.item(i);
0660:                    checker.checkElement(node.getNodeName());
0661:                    if (node.getNodeName().equals(IParserTags.ACTION)) {
0662:                        handleExecutable(item, node, new Action());
0663:                    } else if (node.getNodeName().equals(IParserTags.COMMAND)) {
0664:                        handleExecutable(item, node, new CheatSheetCommand());
0665:                    } else if (node.getNodeName().equals(
0666:                            IParserTags.DESCRIPTION)) {
0667:                        if (hasDescription) {
0668:                            String message = NLS
0669:                                    .bind(
0670:                                            Messages.ERROR_PARSING_MULTIPLE_DESCRIPTION,
0671:                                            (new Object[] { itemNode
0672:                                                    .getNodeName() }));
0673:                            addStatus(IStatus.ERROR, message, null);
0674:                        } else {
0675:                            hasDescription = true;
0676:                            handleDescription(item, node);
0677:                        }
0678:                    } else if (node.getNodeName().equals(
0679:                            IParserTags.ON_COMPLETION)) {
0680:                        handleOnCompletion(item, node);
0681:                    } else if (node.getNodeName().equals(IParserTags.SUBITEM)) {
0682:                        handleSubItem(item, node);
0683:                    } else if (node.getNodeName().equals(
0684:                            IParserTags.CONDITIONALSUBITEM)) {
0685:                        handleConditionalSubItem(item, node);
0686:                    } else if (node.getNodeName().equals(
0687:                            IParserTags.REPEATEDSUBITM)) {
0688:                        handleRepeatedSubItem(item, node);
0689:                    } else if (node.getNodeName().equals(
0690:                            IParserTags.PERFORMWHEN)) {
0691:                        handlePerformWhen(item, node);
0692:                    } else {
0693:                        if (node.getNodeType() != Node.TEXT_NODE
0694:                                && node.getNodeType() != Node.COMMENT_NODE) {
0695:                            String message = NLS.bind(
0696:                                    Messages.WARNING_PARSING_UNKNOWN_ELEMENT,
0697:                                    (new Object[] { node.getNodeName(),
0698:                                            itemNode.getNodeName() }));
0699:                            addStatus(IStatus.WARNING, message, null);
0700:                        }
0701:                    }
0702:                }
0703:
0704:                if (!hasDescription) {
0705:                    String message = NLS.bind(
0706:                            Messages.ERROR_PARSING_NO_DESCRIPTION,
0707:                            (new Object[] { itemNode.getNodeName() }));
0708:                    addStatus(IStatus.ERROR, message, null);
0709:                }
0710:
0711:                return item;
0712:            }
0713:
0714:            private void handleItemAttributes(Item item, Node itemNode)
0715:                    throws CheatSheetParserException {
0716:                Assert.isNotNull(item);
0717:                Assert.isNotNull(itemNode);
0718:
0719:                ArrayList itemExtensionElements = new ArrayList();
0720:
0721:                boolean title = false;
0722:
0723:                NamedNodeMap attributes = itemNode.getAttributes();
0724:                if (attributes != null) {
0725:                    for (int x = 0; x < attributes.getLength(); x++) {
0726:                        Node attribute = attributes.item(x);
0727:                        String attributeName = attribute.getNodeName();
0728:                        if (attribute == null || attributeName == null)
0729:                            continue;
0730:
0731:                        if (attributeName.equals(IParserTags.TITLE)) {
0732:                            title = true;
0733:                            item.setTitle(attribute.getNodeValue());
0734:                        } else if (attributeName.equals(IParserTags.CONTEXTID)) {
0735:                            item.setContextId(attribute.getNodeValue());
0736:                        } else if (attributeName.equals(IParserTags.HREF)) {
0737:                            item.setHref(attribute.getNodeValue());
0738:                        } else if (attributeName.equals(IParserTags.SKIP)) {
0739:                            item.setSkip(attribute.getNodeValue().equals(
0740:                                    TRUE_STRING));
0741:                        } else if (attributeName.equals(IParserTags.DIALOG)) {
0742:                            item.setDialog(attribute.getNodeValue().equals(
0743:                                    TRUE_STRING));
0744:                        } else {
0745:                            AbstractItemExtensionElement[] ie = handleUnknownItemAttribute(
0746:                                    attribute, itemNode);
0747:                            if (ie != null) {
0748:                                itemExtensionElements.add(ie);
0749:                            } else {
0750:                                String message = NLS
0751:                                        .bind(
0752:                                                Messages.WARNING_PARSING_UNKNOWN_ATTRIBUTE,
0753:                                                (new Object[] { attributeName,
0754:                                                        itemNode.getNodeName() }));
0755:                                addStatus(IStatus.WARNING, message, null);
0756:                            }
0757:                        }
0758:                    }
0759:                }
0760:
0761:                if (!title) {
0762:                    String message = NLS.bind(Messages.ERROR_PARSING_NO_TITLE,
0763:                            (new Object[] { itemNode.getNodeName() }));
0764:                    throw new CheatSheetParserException(message);
0765:                }
0766:
0767:                if (itemExtensionElements != null)
0768:                    item.setItemExtensions(itemExtensionElements);
0769:            }
0770:
0771:            private void handlePerformWhen(IPerformWhenItem item,
0772:                    Node performWhenNode) throws CheatSheetParserException {
0773:                Assert.isNotNull(item);
0774:                Assert.isNotNull(performWhenNode);
0775:                Assert.isTrue(performWhenNode.getNodeName().equals(
0776:                        IParserTags.PERFORMWHEN));
0777:
0778:                PerformWhen performWhen = new PerformWhen();
0779:
0780:                boolean condition = false;
0781:
0782:                // Handle attributes
0783:                NamedNodeMap attributes = performWhenNode.getAttributes();
0784:                if (attributes != null) {
0785:                    for (int x = 0; x < attributes.getLength(); x++) {
0786:                        Node attribute = attributes.item(x);
0787:                        String attributeName = attribute.getNodeName();
0788:                        if (attribute == null || attributeName == null)
0789:                            continue;
0790:
0791:                        if (attributeName.equals(IParserTags.CONDITION)) {
0792:                            condition = true;
0793:                            performWhen.setCondition(attribute.getNodeValue());
0794:                        } else {
0795:                            String message = NLS.bind(
0796:                                    Messages.WARNING_PARSING_UNKNOWN_ATTRIBUTE,
0797:                                    (new Object[] { attributeName,
0798:                                            performWhenNode.getNodeName() }));
0799:                            addStatus(IStatus.WARNING, message, null);
0800:                        }
0801:                    }
0802:                }
0803:
0804:                if (!condition) {
0805:                    String message = NLS.bind(
0806:                            Messages.ERROR_PARSING_NO_CONDITION,
0807:                            (new Object[] { performWhenNode.getNodeName() }));
0808:                    throw new CheatSheetParserException(message);
0809:                }
0810:
0811:                boolean exeutable = false;
0812:
0813:                // Handle nodes
0814:                NodeList nodes = performWhenNode.getChildNodes();
0815:                for (int i = 0; i < nodes.getLength(); i++) {
0816:                    Node node = nodes.item(i);
0817:                    if (node.getNodeName().equals(IParserTags.ACTION)) {
0818:                        exeutable = true;
0819:                        handleExecutable(performWhen, node, new Action());
0820:                    } else if (node.getNodeName().equals(IParserTags.COMMAND)) {
0821:                        exeutable = true;
0822:                        handleExecutable(performWhen, node,
0823:                                new CheatSheetCommand());
0824:                    } else {
0825:                        if (node.getNodeType() != Node.TEXT_NODE
0826:                                && node.getNodeType() != Node.COMMENT_NODE) {
0827:                            String message = NLS.bind(
0828:                                    Messages.WARNING_PARSING_UNKNOWN_ELEMENT,
0829:                                    (new Object[] { node.getNodeName(),
0830:                                            performWhenNode.getNodeName() }));
0831:                            addStatus(IStatus.WARNING, message, null);
0832:                        }
0833:                    }
0834:                }
0835:
0836:                if (!exeutable) {
0837:                    String message = NLS.bind(Messages.ERROR_PARSING_NO_ACTION,
0838:                            (new Object[] { performWhenNode.getNodeName() }));
0839:                    throw new CheatSheetParserException(message);
0840:                }
0841:
0842:                item.setPerformWhen(performWhen);
0843:            }
0844:
0845:            private void handleRepeatedSubItem(Item item,
0846:                    Node repeatedSubItemNode) throws CheatSheetParserException {
0847:                Assert.isNotNull(item);
0848:                Assert.isNotNull(repeatedSubItemNode);
0849:                Assert.isTrue(repeatedSubItemNode.getNodeName().equals(
0850:                        IParserTags.REPEATEDSUBITM));
0851:
0852:                RepeatedSubItem repeatedSubItem = new RepeatedSubItem();
0853:
0854:                boolean values = false;
0855:
0856:                // Handle attributes
0857:                NamedNodeMap attributes = repeatedSubItemNode.getAttributes();
0858:                if (attributes != null) {
0859:                    for (int x = 0; x < attributes.getLength(); x++) {
0860:                        Node attribute = attributes.item(x);
0861:                        String attributeName = attribute.getNodeName();
0862:                        if (attribute == null || attributeName == null)
0863:                            continue;
0864:
0865:                        if (attributeName.equals(IParserTags.VALUES)) {
0866:                            values = true;
0867:                            repeatedSubItem.setValues(attribute.getNodeValue());
0868:                        } else {
0869:                            String message = NLS
0870:                                    .bind(
0871:                                            Messages.WARNING_PARSING_UNKNOWN_ATTRIBUTE,
0872:                                            (new Object[] {
0873:                                                    attributeName,
0874:                                                    repeatedSubItemNode
0875:                                                            .getNodeName() }));
0876:                            addStatus(IStatus.WARNING, message, null);
0877:                        }
0878:                    }
0879:                }
0880:
0881:                if (!values) {
0882:                    String message = NLS
0883:                            .bind(Messages.ERROR_PARSING_NO_VALUES,
0884:                                    (new Object[] { repeatedSubItemNode
0885:                                            .getNodeName() }));
0886:                    throw new CheatSheetParserException(message);
0887:                }
0888:
0889:                boolean subitem = false;
0890:
0891:                // Handle nodes
0892:                NodeList nodes = repeatedSubItemNode.getChildNodes();
0893:                for (int i = 0; i < nodes.getLength(); i++) {
0894:                    Node node = nodes.item(i);
0895:
0896:                    if (node.getNodeName().equals(IParserTags.SUBITEM)) {
0897:                        subitem = true;
0898:                        handleSubItem(repeatedSubItem, node);
0899:                    } else {
0900:                        if (node.getNodeType() != Node.TEXT_NODE
0901:                                && node.getNodeType() != Node.COMMENT_NODE) {
0902:                            String message = NLS
0903:                                    .bind(
0904:                                            Messages.WARNING_PARSING_UNKNOWN_ELEMENT,
0905:                                            (new Object[] {
0906:                                                    node.getNodeName(),
0907:                                                    repeatedSubItemNode
0908:                                                            .getNodeName() }));
0909:                            addStatus(IStatus.WARNING, message, null);
0910:                        }
0911:                    }
0912:                }
0913:
0914:                if (!subitem) {
0915:                    String message = NLS
0916:                            .bind(Messages.ERROR_PARSING_NO_SUBITEM,
0917:                                    (new Object[] { repeatedSubItemNode
0918:                                            .getNodeName() }));
0919:                    throw new CheatSheetParserException(message);
0920:                }
0921:
0922:                item.addSubItem(repeatedSubItem);
0923:            }
0924:
0925:            private void handleSubItem(ISubItemItem item, Node subItemNode)
0926:                    throws CheatSheetParserException {
0927:                Assert.isNotNull(item);
0928:                Assert.isNotNull(subItemNode);
0929:                Assert.isTrue(subItemNode.getNodeName().equals(
0930:                        IParserTags.SUBITEM));
0931:
0932:                SubItem subItem = new SubItem();
0933:
0934:                handleSubItemAttributes(subItem, subItemNode);
0935:
0936:                IncompatibleSiblingChecker checker = new IncompatibleSiblingChecker(
0937:                        this , subItemNode);
0938:
0939:                NodeList nodes = subItemNode.getChildNodes();
0940:                for (int i = 0; i < nodes.getLength(); i++) {
0941:                    Node node = nodes.item(i);
0942:                    checker.checkElement(node.getNodeName());
0943:
0944:                    if (node.getNodeName().equals(IParserTags.ACTION)) {
0945:                        handleExecutable(subItem, node, new Action());
0946:                    } else if (node.getNodeName().equals(IParserTags.COMMAND)) {
0947:                        handleExecutable(subItem, node, new CheatSheetCommand());
0948:                    } else if (node.getNodeName().equals(
0949:                            IParserTags.PERFORMWHEN)) {
0950:                        handlePerformWhen(subItem, node);
0951:                    } else {
0952:                        if (node.getNodeType() != Node.TEXT_NODE
0953:                                && node.getNodeType() != Node.COMMENT_NODE) {
0954:                            String message = NLS.bind(
0955:                                    Messages.WARNING_PARSING_UNKNOWN_ELEMENT,
0956:                                    (new Object[] { node.getNodeName(),
0957:                                            subItemNode.getNodeName() }));
0958:                            addStatus(IStatus.WARNING, message, null);
0959:                        }
0960:                    }
0961:                }
0962:                item.addSubItem(subItem);
0963:            }
0964:
0965:            private void handleSubItemAttributes(SubItem subItem,
0966:                    Node subItemNode) throws CheatSheetParserException {
0967:                Assert.isNotNull(subItem);
0968:                Assert.isNotNull(subItemNode);
0969:
0970:                boolean label = false;
0971:
0972:                NamedNodeMap attributes = subItemNode.getAttributes();
0973:                if (attributes != null) {
0974:                    for (int x = 0; x < attributes.getLength(); x++) {
0975:                        Node attribute = attributes.item(x);
0976:                        String attributeName = attribute.getNodeName();
0977:                        if (attribute == null || attributeName == null)
0978:                            continue;
0979:
0980:                        if (attributeName.equals(IParserTags.LABEL)) {
0981:                            label = true;
0982:                            subItem.setLabel(attribute.getNodeValue());
0983:                        } else if (attributeName.equals(IParserTags.SKIP)) {
0984:                            subItem.setSkip(attribute.getNodeValue().equals(
0985:                                    TRUE_STRING));
0986:                        } else if (attributeName.equals(IParserTags.WHEN)) {
0987:                            subItem.setWhen(attribute.getNodeValue());
0988:                        } else {
0989:                            String message = NLS.bind(
0990:                                    Messages.WARNING_PARSING_UNKNOWN_ATTRIBUTE,
0991:                                    (new Object[] { attributeName,
0992:                                            subItemNode.getNodeName() }));
0993:                            addStatus(IStatus.WARNING, message, null);
0994:                        }
0995:                    }
0996:                }
0997:
0998:                if (!label) {
0999:                    String message = NLS.bind(Messages.ERROR_PARSING_NO_LABEL,
1000:                            (new Object[] { subItemNode.getNodeName() }));
1001:                    throw new CheatSheetParserException(message);
1002:                }
1003:            }
1004:
1005:            private AbstractItemExtensionElement[] handleUnknownItemAttribute(
1006:                    Node item, Node node) {
1007:                ArrayList al = new ArrayList();
1008:                if (itemExtensionContainerList == null)
1009:                    return null;
1010:
1011:                for (int i = 0; i < itemExtensionContainerList.size(); i++) {
1012:                    CheatSheetItemExtensionElement itemExtensionElement = (CheatSheetItemExtensionElement) itemExtensionContainerList
1013:                            .get(i);
1014:
1015:                    if (itemExtensionElement.getItemAttribute().equals(
1016:                            item.getNodeName())) {
1017:                        AbstractItemExtensionElement itemElement = itemExtensionElement
1018:                                .createInstance();
1019:                        if (itemElement != null) {
1020:                            itemElement.handleAttribute(item.getNodeValue());
1021:                            al.add(itemElement);
1022:                        }
1023:                    }
1024:                }
1025:
1026:                if (al.size() == 0) {
1027:                    String message = NLS.bind(
1028:                            Messages.WARNING_PARSING_UNKNOWN_ATTRIBUTE,
1029:                            (new Object[] { item.getNodeName(),
1030:                                    node.getNodeName() }));
1031:                    addStatus(IStatus.WARNING, message, null);
1032:                }
1033:                return (AbstractItemExtensionElement[]) al
1034:                        .toArray(new AbstractItemExtensionElement[al.size()]);
1035:            }
1036:
1037:            public ICheatSheet parse(URL url, String pluginId,
1038:                    int cheatSheetKind) {
1039:                return parse(new ParserInput(url, pluginId), cheatSheetKind);
1040:            }
1041:
1042:            public ICheatSheet parse(ParserInput input, int cheatSheetKind) {
1043:                status = Status.OK_STATUS;
1044:                commandCount = 0;
1045:                actionCount = 0;
1046:                if (input == null) {
1047:                    return null;
1048:                }
1049:
1050:                InputStream is = null;
1051:                InputSource inputSource = null;
1052:                String filename = ""; //$NON-NLS-1$
1053:                URL url = input.getUrl();
1054:
1055:                if (input.getXml() != null) {
1056:                    StringReader reader = new StringReader(input.getXml());
1057:                    inputSource = new InputSource(reader);
1058:                } else if (input.getUrl() != null) {
1059:                    try {
1060:                        is = url.openStream();
1061:
1062:                        if (is != null) {
1063:                            inputSource = new InputSource(is);
1064:                        }
1065:                    } catch (Exception e) {
1066:                        String message = NLS.bind(Messages.ERROR_OPENING_FILE,
1067:                                (new Object[] { url.getFile() }));
1068:                        addStatus(IStatus.ERROR, message, e);
1069:                        return null;
1070:                    }
1071:                } else {
1072:                    return null;
1073:                }
1074:
1075:                if (input.getUrl() != null) {
1076:                    filename = url.getFile();
1077:                }
1078:
1079:                Document document;
1080:                try {
1081:                    if (documentBuilder == null) {
1082:                        addStatus(IStatus.ERROR,
1083:                                Messages.ERROR_DOCUMENT_BUILDER_NOT_INIT, null);
1084:                        return null;
1085:                    }
1086:                    document = documentBuilder.parse(inputSource);
1087:                } catch (IOException e) {
1088:                    String message = NLS.bind(
1089:                            Messages.ERROR_OPENING_FILE_IN_PARSER,
1090:                            (new Object[] { filename }));
1091:                    addStatus(IStatus.ERROR, message, e);
1092:                    return null;
1093:                } catch (SAXParseException spe) {
1094:                    String message = NLS.bind(
1095:                            Messages.ERROR_SAX_PARSING_WITH_LOCATION,
1096:                            (new Object[] { filename,
1097:                                    new Integer(spe.getLineNumber()),
1098:                                    new Integer(spe.getColumnNumber()) }));
1099:                    addStatus(IStatus.ERROR, message, spe);
1100:                    return null;
1101:                } catch (SAXException se) {
1102:                    String message = NLS.bind(Messages.ERROR_SAX_PARSING,
1103:                            (new Object[] { filename }));
1104:                    addStatus(IStatus.ERROR, message, se);
1105:                    return null;
1106:                } finally {
1107:                    try {
1108:                        is.close();
1109:                    } catch (Exception e) {
1110:                    }
1111:                }
1112:
1113:                // process dynamic content, normalize paths
1114:                if (processor == null) {
1115:                    DocumentReader reader = new DocumentReader();
1116:                    processor = new DocumentProcessor(new ProcessorHandler[] {
1117:                            new FilterHandler(CheatSheetEvaluationContext
1118:                                    .getContext()), new NormalizeHandler(),
1119:                            new IncludeHandler(reader, Platform.getNL()),
1120:                            new ExtensionHandler(reader, Platform.getNL()) });
1121:                }
1122:                String documentPath = null;
1123:                if (input.getPluginId() != null) {
1124:                    documentPath = '/' + input.getPluginId()
1125:                            + input.getUrl().getPath();
1126:                }
1127:                processor.process(UAElementFactory.newElement(document
1128:                        .getDocumentElement()), documentPath);
1129:
1130:                if (cheatSheetKind == COMPOSITE_ONLY
1131:                        || (cheatSheetKind == ANY && isComposite(document))) {
1132:                    CompositeCheatSheetParser compositeParser = new CompositeCheatSheetParser();
1133:                    CompositeCheatSheetModel result = compositeParser
1134:                            .parseCompositeCheatSheet(document, input.getUrl());
1135:                    status = compositeParser.getStatus();
1136:                    return result;
1137:                }
1138:                try {
1139:                    return parseCheatSheet(document);
1140:                } catch (CheatSheetParserException e) {
1141:                    addStatus(IStatus.ERROR, e.getMessage(), e);
1142:                }
1143:                return null;
1144:            }
1145:
1146:            private boolean isComposite(Document document) {
1147:                if (document != null) {
1148:                    Node rootnode = document.getDocumentElement();
1149:                    // Is the root node compositeCheatsheet?
1150:                    return rootnode.getNodeName().equals(
1151:                            ICompositeCheatsheetTags.COMPOSITE_CHEATSHEET);
1152:                }
1153:                return false;
1154:            }
1155:
1156:            private CheatSheet parseCheatSheet(Document document)
1157:                    throws CheatSheetParserException {
1158:                // If the document passed is null return a null tree and update the status
1159:                if (document != null) {
1160:                    Node rootnode = document.getDocumentElement();
1161:
1162:                    // Is the root node really <cheatsheet>?
1163:                    if (!rootnode.getNodeName().equals(IParserTags.CHEATSHEET)) {
1164:                        throw new CheatSheetParserException(
1165:                                Messages.ERROR_PARSING_CHEATSHEET_ELEMENT);
1166:                    }
1167:
1168:                    // Create the cheat sheet model object
1169:                    CheatSheet cheatSheet = new CheatSheet();
1170:
1171:                    handleCheatSheetAttributes(cheatSheet, rootnode);
1172:
1173:                    boolean hasItem = false;
1174:                    boolean hasIntro = false;
1175:
1176:                    CheatSheetRegistryReader reader = CheatSheetRegistryReader
1177:                            .getInstance();
1178:                    itemExtensionContainerList = reader.readItemExtensions();
1179:
1180:                    NodeList nodes = rootnode.getChildNodes();
1181:                    for (int i = 0; i < nodes.getLength(); i++) {
1182:                        Node node = nodes.item(i);
1183:
1184:                        if (node.getNodeName().equals(IParserTags.ITEM)) {
1185:                            hasItem = true;
1186:                            Item item = handleItem(node);
1187:                            cheatSheet.addItem(item);
1188:                        } else if (node.getNodeName().equals(IParserTags.INTRO)) {
1189:                            if (hasIntro) {
1190:                                addStatus(
1191:                                        IStatus.ERROR,
1192:                                        Messages.ERROR_PARSING_MORE_THAN_ONE_INTRO,
1193:                                        null);
1194:                            } else {
1195:                                hasIntro = true;
1196:                                handleIntroNode(cheatSheet, node);
1197:                            }
1198:                        } else {
1199:                            if (node.getNodeType() != Node.TEXT_NODE
1200:                                    && node.getNodeType() != Node.COMMENT_NODE) {
1201:                                String message = NLS
1202:                                        .bind(
1203:                                                Messages.WARNING_PARSING_UNKNOWN_ELEMENT,
1204:                                                (new Object[] {
1205:                                                        node.getNodeName(),
1206:                                                        rootnode.getNodeName() }));
1207:                                addStatus(IStatus.WARNING, message, null);
1208:                            }
1209:                        }
1210:                    }
1211:
1212:                    if (!hasIntro) {
1213:                        addStatus(IStatus.ERROR,
1214:                                Messages.ERROR_PARSING_NO_INTRO, null);
1215:                    }
1216:                    if (!hasItem) {
1217:                        addStatus(IStatus.ERROR,
1218:                                Messages.ERROR_PARSING_NO_ITEM, null);
1219:                    }
1220:
1221:                    //handleIntro(cheatSheet, document);
1222:
1223:                    //handleItems(cheatSheet, document);
1224:
1225:                    if (status.getSeverity() == IStatus.ERROR) {
1226:                        return null;
1227:                    }
1228:
1229:                    cheatSheet.setContainsCommandOrAction(actionCount != 0
1230:                            || commandCount != 0);
1231:                    return cheatSheet;
1232:                }
1233:                throw new CheatSheetParserException(
1234:                        Messages.ERROR_PARSING_CHEATSHEET_CONTENTS);
1235:            }
1236:
1237:            /*
1238:             * Normalizes composite cheat sheet-relative paths to simple cheat sheets into fully
1239:             * qualified paths, e.g. for the path "tasks/mySimpleCheatSheet.xml" in composite cheat
1240:             * sheet "/my.plugin/cheatsheets/myCompositeCheatSheet.xml", this normalizes to
1241:             * "/my.plugin/cheatsheets/tasks/mySimpleCheatSheet.xml".
1242:             * 
1243:             * This is necessary because with dynamic content we are pulling in tasks from other
1244:             * plug-ins and those tasks have relative paths. It also only applies for cheat sheets
1245:             * located in running plug-ins.
1246:             */
1247:            private class NormalizeHandler extends ProcessorHandler {
1248:
1249:                private static final String ELEMENT_PARAM = "param"; //$NON-NLS-1$
1250:                private static final String ATTRIBUTE_NAME = "name"; //$NON-NLS-1$
1251:                private static final String ATTRIBUTE_VALUE = "value"; //$NON-NLS-1$
1252:                private static final String NAME_PATH = "path"; //$NON-NLS-1$
1253:
1254:                public short handle(UAElement element, String id) {
1255:                    if (id != null
1256:                            && ELEMENT_PARAM.equals(element.getElementName())) {
1257:                        String name = element.getAttribute(ATTRIBUTE_NAME);
1258:                        if (NAME_PATH.equals(name)) {
1259:                            String value = element
1260:                                    .getAttribute(ATTRIBUTE_VALUE);
1261:                            if (value != null) {
1262:                                int index = id.lastIndexOf('/');
1263:                                element.setAttribute(ATTRIBUTE_VALUE, id
1264:                                        .substring(0, index + 1)
1265:                                        + value);
1266:                            }
1267:                        }
1268:                        return HANDLED_CONTINUE;
1269:                    }
1270:                    return UNHANDLED;
1271:                }
1272:            }
1273:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.