Source Code Cross Referenced for DTDParser.java in  » IDE-Netbeans » html » org » netbeans » editor » ext » html » dtd » 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 Netbeans » html » org.netbeans.editor.ext.html.dtd 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
0003:         *
0004:         * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
0005:         *
0006:         * The contents of this file are subject to the terms of either the GNU
0007:         * General Public License Version 2 only ("GPL") or the Common
0008:         * Development and Distribution License("CDDL") (collectively, the
0009:         * "License"). You may not use this file except in compliance with the
0010:         * License. You can obtain a copy of the License at
0011:         * http://www.netbeans.org/cddl-gplv2.html
0012:         * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
0013:         * specific language governing permissions and limitations under the
0014:         * License.  When distributing the software, include this License Header
0015:         * Notice in each file and include the License file at
0016:         * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
0017:         * particular file as subject to the "Classpath" exception as provided
0018:         * by Sun in the GPL Version 2 section of the License file that
0019:         * accompanied this code. If applicable, add the following below the
0020:         * License Header, with the fields enclosed by brackets [] replaced by
0021:         * your own identifying information:
0022:         * "Portions Copyrighted [year] [name of copyright owner]"
0023:         *
0024:         * Contributor(s):
0025:         *
0026:         * The Original Software is NetBeans. The Initial Developer of the Original
0027:         * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
0028:         * Microsystems, Inc. All Rights Reserved.
0029:         *
0030:         * If you wish your version of this file to be governed by only the CDDL
0031:         * or only the GPL Version 2, indicate your decision by adding
0032:         * "[Contributor] elects to include this software in this distribution
0033:         * under the [CDDL or GPL Version 2] license." If you do not indicate a
0034:         * single choice of license, a recipient has the option to distribute
0035:         * your version of this file under either the CDDL, the GPL Version 2 or
0036:         * to extend the choice of license to its licensees as provided above.
0037:         * However, if you add GPL Version 2 code and therefore, elected the GPL
0038:         * Version 2 license, then the option applies only if the new code is
0039:         * made subject to such option by the copyright holder.
0040:         */
0041:        package org.netbeans.editor.ext.html.dtd;
0042:
0043:        import java.io.Reader;
0044:        import java.io.PushbackReader;
0045:        import java.io.IOException;
0046:        import java.util.*;
0047:
0048:        import org.netbeans.editor.ext.html.WeakHashSet;
0049:
0050:        /**
0051:         * !!! Includes !!!! String->DTD.Element
0052:         * @author  Petr Nejedly
0053:         * @version 0.2
0054:         */
0055:        class DTDParser extends Object {
0056:
0057:            // The provider used to provide the Readers for this DTD.
0058:            private ReaderProvider provider = null;
0059:
0060:            // Asks for Reader for given DTD.
0061:            private Reader getReader(String identifier, String fileName) {
0062:                if (provider == null)
0063:                    return null;
0064:                return provider.getReaderForIdentifier(identifier, fileName);
0065:            }
0066:
0067:            /** Weak set for holding already created strings, to not create more
0068:             * instances of the same string */
0069:            private WeakHashSet stringCache = new WeakHashSet(131, 0.75f);
0070:
0071:            /** Weak set of attributes - helps sharing common attributes */
0072:            private WeakHashSet attributes = new WeakHashSet(23, 0.75f);
0073:
0074:            /** Weak set of models */
0075:            private WeakHashSet models = new WeakHashSet(131, 0.75f);
0076:
0077:            /** Weak set of Contents */
0078:            private WeakHashSet contents = new WeakHashSet(131, 0.75f);
0079:
0080:            /** Temporal storage of all ContentLeafs that needs to get their 
0081:             * elements filled in at the end of parsing
0082:             */
0083:            Set leafs = new HashSet(131, 0.75f);
0084:
0085:            /** Map of all character references.
0086:             * Mapping is String name -> DTD.CharRef instance */
0087:            private SortedMap charRefs = new TreeMap();
0088:
0089:            /** Map holding partially completed instances of Element.
0090:             * Mapping is String name -> DTD.Element instance */
0091:            private SortedMap elementMap = new TreeMap();
0092:
0093:            /** Map holding entities during creation of DTD.
0094:             * Mapping is String name -> String content.
0095:             * This map should not be used for direct put(..), because entities
0096:             * are defined by first declaration and can not be overriden.
0097:             */
0098:            private Map entityMap = new HashMap();
0099:
0100:            public DTD createDTD(ReaderProvider provider, String identifier,
0101:                    String fileName) throws WrongDTDException {
0102:                this .provider = provider;
0103:
0104:                Reader reader = getReader(identifier, fileName);
0105:                if (reader == null)
0106:                    throw new WrongDTDException(
0107:                            "Can't open Reader for public identifier "
0108:                                    + identifier); // NOI18N
0109:                try {
0110:                    parseDTD(new PushbackReader(reader, 1024 * 128));
0111:                } catch (IOException e) {
0112:                    throw new WrongDTDException("IOException during parsing: "
0113:                            + e.getMessage()); // NOI18N
0114:                }
0115:
0116:                // fixup includes and excludes of all elements
0117:                for (Iterator it = elementMap.values().iterator(); it.hasNext();) {
0118:                    DTD.Element elem = (DTD.Element) it.next();
0119:                    ContentModelImpl cm = (ContentModelImpl) elem
0120:                            .getContentModel();
0121:
0122:                    Set newIncs = new HashSet();
0123:                    for (Iterator incIter = cm.included.iterator(); incIter
0124:                            .hasNext();) {
0125:                        Object oldElem;
0126:                        Object subElem = oldElem = incIter.next();
0127:                        if (subElem instanceof  String) {
0128:                            subElem = elementMap.get(((String) subElem)
0129:                                    .toUpperCase());
0130:                        }
0131:                        if (subElem == null) {
0132:                            throw new WrongDTDException("'" + oldElem
0133:                                    + "' element referenced from "
0134:                                    + elem.getName()
0135:                                    + " not found throughout the DTD."); // NOI18N
0136:                        }
0137:                        newIncs.add(subElem);
0138:                    }
0139:                    cm.included = newIncs;
0140:
0141:                    Set newExcs = new HashSet();
0142:                    for (Iterator excIter = cm.excluded.iterator(); excIter
0143:                            .hasNext();) {
0144:                        Object oldElem;
0145:                        Object subElem = oldElem = excIter.next();
0146:                        if (subElem instanceof  String) {
0147:                            subElem = elementMap.get(((String) subElem)
0148:                                    .toUpperCase());
0149:                        }
0150:                        if (subElem == null) {
0151:                            throw new WrongDTDException("'" + oldElem
0152:                                    + "' element referenced from "
0153:                                    + elem.getName()
0154:                                    + " not found throughout the DTD."); // NOI18N
0155:                        }
0156:                        newExcs.add(subElem);
0157:                    }
0158:                    cm.excluded = newExcs;
0159:                    cm.hashcode = cm.content.hashCode() + 2
0160:                            * cm.included.hashCode() + 3
0161:                            * cm.excluded.hashCode();
0162:                }
0163:
0164:                // fixup content leafs
0165:                for (Iterator it = leafs.iterator(); it.hasNext();) {
0166:                    ContentLeafImpl leaf = (ContentLeafImpl) it.next();
0167:                    leaf.elem = (DTD.Element) elementMap.get(leaf.elemName);
0168:                }
0169:
0170:                return new DTDImpl(identifier, elementMap, charRefs);
0171:            }
0172:
0173:            /** Method for adding new entities to their map. Obeys the rule that
0174:             * entity, once defined, can not be overriden */
0175:            void addEntity(String name, String content) {
0176:                if (entityMap.get(name) == null)
0177:                    entityMap.put(name, content);
0178:            }
0179:
0180:            /** Method for adding new entities to their map. Obeys the rule that
0181:             * entity, once defined, can not be overriden */
0182:            void addPublicEntity(String name, String identifier, String file)
0183:                    throws WrongDTDException {
0184:                if (entityMap.get(name) == null) {
0185:
0186:                    StringBuffer sb = new StringBuffer();
0187:                    char[] buffer = new char[16384];
0188:                    Reader r = getReader(identifier, file);
0189:                    try {
0190:                        int len;
0191:                        while ((len = r.read(buffer)) >= 0) {
0192:                            sb.append(buffer, 0, len);
0193:                        }
0194:                    } catch (IOException e) {
0195:                        throw new WrongDTDException(
0196:                                "Error reading included public entity " + name
0197:                                        + " - " + e.getMessage()); // NOI18N
0198:                    }
0199:
0200:                    entityMap.put(name, sb.toString());
0201:                }
0202:            }
0203:
0204:            DTD.Value createValue(String name) {
0205:                return new ValueImpl((String) stringCache.put(name));
0206:            }
0207:
0208:            /** Creates new or lookups old ContentModel with given properites */
0209:            DTD.ContentModel createContentModel(DTD.Content content,
0210:                    Set included, Set excluded) {
0211:
0212:                DTD.ContentModel cm = new ContentModelImpl(content, included,
0213:                        excluded);
0214:                return (DTD.ContentModel) models.put(cm);
0215:            }
0216:
0217:            /** Creates new or lookups old ContentLeaf with given properites */
0218:            DTD.Content createContentLeaf(String name) {
0219:                DTD.Content c = new ContentLeafImpl(name);
0220:                c = (DTD.Content) contents.put(c);
0221:                leafs.add(c); // remember for final fixup
0222:                return c;
0223:            }
0224:
0225:            /** Creates new or lookups old ContentNode with given properites */
0226:            DTD.Content createContentNode(char type, DTD.Content subContent) {
0227:                return (DTD.Content) contents.put(new UnaryContentNodeImpl(
0228:                        type, subContent));
0229:            }
0230:
0231:            /** Creates new or lookups old ContentNode with given properites */
0232:            DTD.Content createContentNode(char type, DTD.Content[] subContent) {
0233:                return (DTD.Content) contents.put(new MultiContentNodeImpl(
0234:                        type, subContent));
0235:            }
0236:
0237:            DTD.Element createElement(String name, DTD.ContentModel cm,
0238:                    boolean optStart, boolean optEnd) {
0239:                DTD.Element retVal = new ElementImpl(name, cm, optStart,
0240:                        optEnd, new TreeMap());
0241:                return retVal;
0242:            }
0243:
0244:            /** Creates new or lookups old attribute with given properites */
0245:            DTD.Attribute createAttribute(String name, int type,
0246:                    String baseType, String typeHelper, String defaultMode,
0247:                    SortedMap values) {
0248:                DTD.Attribute attr = new AttributeImpl(name, type,
0249:                        (String) stringCache.put(baseType),
0250:                        (String) stringCache.put(typeHelper),
0251:                        (String) stringCache.put(defaultMode), values);
0252:                return (DTD.Attribute) attributes.put(attr);
0253:            }
0254:
0255:            /** Adds given instance of DTD.Attribute to Element named elemName */
0256:            void addAttrToElement(String elemName, DTD.Attribute attr)
0257:                    throws WrongDTDException {
0258:                ElementImpl elem = (ElementImpl) elementMap.get(elemName
0259:                        .toUpperCase());
0260:                if (elem == null)
0261:                    throw new WrongDTDException(
0262:                            "Attribute definition for unknown Element \""
0263:                                    + elemName + "\"."); // NOI18N
0264:                elem.addAttribute(attr);
0265:            }
0266:
0267:            void createAddCharRef(String name, char value) {
0268:                DTD.CharRef ref = new CharRefImpl(name, value);
0269:                charRefs.put(name, ref);
0270:            }
0271:
0272:            private boolean isNameChar(char c) {
0273:                return Character.isLetterOrDigit(c) || c == '_' || c == '-'
0274:                        || c == '.' || c == ':';
0275:            }
0276:
0277:            /*----------------------------------------------------------------------------*/
0278:            /*----------------------------- Parsing routines ---------------------------- */
0279:            /*----------------------------------------------------------------------------*/
0280:            private static final int DTD_INIT = 0;
0281:            private static final int DTD_LT = 1; // after '<'
0282:            private static final int DTD_EXC = 2; // after "<!"
0283:            private static final int DTD_MINUS = 3; // after "<!-"
0284:            private static final int DTD_ACOMMENT = 4; // after comment was parsed, awaiting '>'
0285:
0286:            private void parseDTD(PushbackReader in) throws IOException,
0287:                    WrongDTDException {
0288:                int state = DTD_INIT;
0289:                for (;;) {
0290:                    int i = in.read();
0291:                    if (i == -1) {
0292:                        break;
0293:                    }
0294:                    switch (state) {
0295:                    case DTD_INIT:
0296:                        switch (i) {
0297:                        case '<':
0298:                            state = DTD_LT;
0299:                            break;
0300:                        case '%':
0301:                            parseEntityReference(in);
0302:                            break; // Stay in DTD_INIT
0303:                        }
0304:                        break;
0305:
0306:                    case DTD_LT:
0307:                        if (i != '!')
0308:                            throw new WrongDTDException("Unexpected char '"
0309:                                    + (char) i + "' after '<'"); // NOI18N
0310:                        state = DTD_EXC;
0311:                        break;
0312:
0313:                    case DTD_EXC:
0314:                        switch (i) {
0315:                        case '-':
0316:                            state = DTD_MINUS;
0317:                            break;
0318:                        case '[':
0319:                            parseOptional(in);
0320:                            state = DTD_INIT;
0321:                            break;
0322:                        default:
0323:                            in.unread(i);
0324:                            parseMarkup(in);
0325:                            state = DTD_INIT;
0326:                            break;
0327:                        }
0328:                        break;
0329:
0330:                    case DTD_MINUS:
0331:                        if (i != '-')
0332:                            throw new WrongDTDException("Unexpected char '"
0333:                                    + (char) i + "' after \"<!-\""); // NOI18N
0334:                        parseComment(in);
0335:                        state = DTD_ACOMMENT;
0336:                        break;
0337:
0338:                    case DTD_ACOMMENT:
0339:                        if (i != '>')
0340:                            throw new WrongDTDException("Unexpected char '"
0341:                                    + (char) i + "' after comment"); // NOI18N
0342:                        state = DTD_INIT;
0343:                        break;
0344:
0345:                    }
0346:                }
0347:                if (state != DTD_INIT)
0348:                    throw new WrongDTDException("Premature end of DTD"); // NOI18N
0349:            }
0350:
0351:            /** Parser that reads the markup type after <!. Recognizes ENTITY, ELEMENT
0352:             * and ATTLIST markup and forwards their processing to proper parser.
0353:             * It gets the control just after starting "<!" and releases after eating
0354:             * final '>' */
0355:            private void parseMarkup(PushbackReader in) throws IOException,
0356:                    WrongDTDException {
0357:                StringBuffer sb = new StringBuffer();
0358:                for (;;) {
0359:                    int i = in.read();
0360:                    if (i == -1)
0361:                        throw new WrongDTDException("Premature end of DTD"); // NOI18N EOF
0362:                    if (i == ' ')
0363:                        break;
0364:                    sb.append((char) i); // next char of name
0365:                }
0366:
0367:                String markup = sb.toString();
0368:
0369:                if ("ENTITY".equals(markup)) { // NOI18N
0370:                    parseEntityDefinition(in);
0371:                } else if ("ELEMENT".equals(markup)) { // NOI18N
0372:                    parseElement(in);
0373:                } else if ("ATTLIST".equals(markup)) { // NOI18N
0374:                    parseAttlist(in);
0375:                } else
0376:                    throw new WrongDTDException("Wrong DTD markup <!" + markup); // NOI18N
0377:            }
0378:
0379:            private static final int PED_INIT = 0;
0380:            private static final int PED_PERCENT = 1;
0381:            private static final int PED_CHAR = 2;
0382:            private static final int PED_NAME = 3;
0383:            private static final int PED_ANAME = 4;
0384:            private static final int PED_VAL = 5;
0385:            private static final int PED_TYPE = 6;
0386:            private static final int PED_AVAL = 7;
0387:            private static final int PED_AVAL_M = 8;
0388:            private static final int PED_ATYPE = 9;
0389:            private static final int PED_ID = 10;
0390:            private static final int PED_AID = 11;
0391:            private static final int PED_FILE = 12;
0392:            private static final int PED_AFILE = 13;
0393:            private static final int PED_AFILE_M = 14;
0394:            private static final int PED_ACHAR = 15;
0395:            private static final int PED_CH_TYPE = 16;
0396:            private static final int PED_CH_ATYPE = 17;
0397:            private static final int PED_CH_QUOT = 18;
0398:
0399:            /* TODO: Parsing fo character references */
0400:            private void parseEntityDefinition(PushbackReader in)
0401:                    throws IOException, WrongDTDException {
0402:                int state = PED_INIT;
0403:                StringBuffer name = new StringBuffer();
0404:                StringBuffer value = new StringBuffer();
0405:                StringBuffer type = new StringBuffer();
0406:                StringBuffer identifier = new StringBuffer();
0407:
0408:                for (;;) {
0409:                    int i = in.read();
0410:                    if (i == -1)
0411:                        throw new WrongDTDException("Premature end of DTD"); // NOI18N EOF
0412:                    switch (state) {
0413:                    case PED_INIT:
0414:                        if (Character.isWhitespace((char) i))
0415:                            break;
0416:                        if (i == '%')
0417:                            state = PED_PERCENT;
0418:                        else {
0419:                            name.append((char) i);
0420:                            state = PED_CHAR;
0421:                        }
0422:                        break;
0423:
0424:                    case PED_PERCENT:
0425:                        if (Character.isWhitespace((char) i))
0426:                            break;
0427:                        name.append((char) i);
0428:                        state = PED_NAME;
0429:                        break;
0430:
0431:                    case PED_NAME:
0432:                        if (Character.isWhitespace((char) i)) {
0433:                            state = PED_ANAME;
0434:                        } else {
0435:                            name.append((char) i);
0436:                        }
0437:                        break;
0438:
0439:                    case PED_ANAME:
0440:                        if (Character.isWhitespace((char) i))
0441:                            break;
0442:                        if (i == '"')
0443:                            state = PED_VAL;
0444:                        else {
0445:                            in.unread(i);
0446:                            state = PED_TYPE;
0447:                        }
0448:                        break;
0449:
0450:                    case PED_VAL:
0451:                        if (i == '"') {
0452:                            addEntity(name.toString(), value.toString());
0453:                            state = PED_AVAL;
0454:                        } else {
0455:                            value.append((char) i);
0456:                        }
0457:                        break;
0458:
0459:                    case PED_AVAL:
0460:                        if (i == '>') {
0461:                            return;
0462:                        }
0463:                        if (i == '-')
0464:                            state = PED_AVAL_M;
0465:                        break;
0466:
0467:                    case PED_AVAL_M:
0468:                        if (i == '-')
0469:                            parseComment(in);
0470:                        state = PED_AVAL;
0471:                        break;
0472:
0473:                    case PED_TYPE:
0474:                        if (Character.isWhitespace((char) i)) {
0475:                            if (type.toString().equals("PUBLIC")) { // NOI18N
0476:                                state = PED_ATYPE;
0477:                            } else {
0478:                                throw new WrongDTDException(
0479:                                        "Unexpected entity type \"" + type
0480:                                                + "\"."); // NOI18N
0481:                            }
0482:                        } else {
0483:                            type.append((char) i);
0484:                        }
0485:                        break;
0486:
0487:                    case PED_ATYPE:
0488:                        if (Character.isWhitespace((char) i))
0489:                            break;
0490:                        if (i == '"') {
0491:                            state = PED_ID;
0492:                            break;
0493:                        }
0494:                        throw new WrongDTDException("Unexpected char '"
0495:                                + (char) i + "' in PUBLIC entity."); // NOI18N
0496:
0497:                    case PED_ID:
0498:                        if (i == '"') {
0499:                            state = PED_AID;
0500:                        } else {
0501:                            identifier.append((char) i);
0502:                        }
0503:                        break;
0504:
0505:                    case PED_AID:
0506:                        if (Character.isWhitespace((char) i))
0507:                            break;
0508:                        if (i == '"') {
0509:                            state = PED_FILE;
0510:                            break;
0511:                        }
0512:                        if (i == '>') {
0513:                            addPublicEntity(name.toString(), identifier
0514:                                    .toString(), null);
0515:                            return;
0516:                        }
0517:                        throw new WrongDTDException("Unexpected char '"
0518:                                + (char) i + "' in PUBLIC entity."); // NOI18N
0519:
0520:                    case PED_FILE:
0521:                        if (i == '"') {
0522:                            state = PED_AFILE;
0523:                        } else {
0524:                            value.append((char) i);
0525:                        }
0526:                        break;
0527:
0528:                    case PED_AFILE:
0529:                        if (Character.isWhitespace((char) i))
0530:                            break;
0531:                        if (i == '-') {
0532:                            state = PED_AFILE_M;
0533:                            break;
0534:                        }
0535:                        if (i == '>') {
0536:                            addPublicEntity(name.toString(), identifier
0537:                                    .toString(), value.toString());
0538:                            return;
0539:                        }
0540:                        throw new WrongDTDException("Unexpected char '"
0541:                                + (char) i + "' in PUBLIC entity."); // NOI18N
0542:
0543:                    case PED_AFILE_M:
0544:                        if (i == '-') {
0545:                            parseComment(in);
0546:                            state = PED_FILE;
0547:                            break;
0548:                        }
0549:                        throw new WrongDTDException("Unexpected sequence \"-"
0550:                                + (char) i + "\" in in PUBLIC entity."); // NOI18N
0551:
0552:                    case PED_CHAR:
0553:                        if (Character.isWhitespace((char) i)) {
0554:                            state = PED_ACHAR;
0555:                        } else {
0556:                            name.append((char) i);
0557:                        }
0558:                        break;
0559:
0560:                    case PED_ACHAR:
0561:                        if (Character.isWhitespace((char) i))
0562:                            break;
0563:                        else {
0564:                            type.append((char) i);
0565:                            state = PED_CH_TYPE;
0566:                        }
0567:                        break;
0568:
0569:                    case PED_CH_TYPE:
0570:                        if (Character.isWhitespace((char) i)) {
0571:                            if (type.toString().equals("CDATA")) { // NOI18N
0572:                                state = PED_ATYPE;
0573:                                state = PED_CH_ATYPE;
0574:                            } else {
0575:                                throw new WrongDTDException(
0576:                                        "Unexpected entity type \"" + type
0577:                                                + "\"."); // NOI18N
0578:                            }
0579:                        } else {
0580:                            type.append((char) i);
0581:                        }
0582:                        break;
0583:
0584:                    case PED_CH_ATYPE:
0585:                        if (Character.isWhitespace((char) i))
0586:                            break;
0587:                        else if (i == '"') {
0588:                            state = PED_CH_QUOT;
0589:                        } else {
0590:                            throw new WrongDTDException("Unexpected char '"
0591:                                    + (char) i + "' in entity."); // NOI18N
0592:                        }
0593:                        break;
0594:
0595:                    case PED_CH_QUOT:
0596:                        if (i == '"') {
0597:                            value.delete(0, 2);
0598:                            value.deleteCharAt(value.length() - 1);
0599:                            int code = Integer.parseInt(value.toString());
0600:                            createAddCharRef(name.toString(), (char) code);
0601:                            state = PED_AVAL;
0602:                        } else {
0603:                            value.append((char) i);
0604:                        }
0605:                    }
0606:
0607:                }
0608:            }
0609:
0610:            private static final int GR_INIT = 0;
0611:            private static final int GR_NAME = 1;
0612:            private static final int GR_ANAME = 2;
0613:
0614:            /** Parse group of names separated by '|' character and optional spaces
0615:             * @return List of Strings containing names */
0616:            private List parseGroup(PushbackReader in) throws IOException,
0617:                    WrongDTDException {
0618:                int state = GR_INIT;
0619:                StringBuffer name = new StringBuffer();
0620:                List list = new ArrayList();
0621:
0622:                for (;;) {
0623:                    int i = in.read();
0624:                    if (i == -1)
0625:                        throw new WrongDTDException("Premature end of DTD"); // NOI18N EOF
0626:                    switch (state) {
0627:                    case GR_INIT:
0628:                        if (Character.isWhitespace((char) i))
0629:                            break;
0630:                        if (i == '%') {
0631:                            parseEntityReference(in);
0632:                        } else {
0633:                            name.append((char) i);
0634:                            state = GR_NAME;
0635:                        }
0636:                        break;
0637:
0638:                    case GR_NAME:
0639:                        if (isNameChar((char) i)) {
0640:                            name.append((char) i);
0641:                            break;
0642:                        }
0643:                        switch (i) {
0644:                        case ')':
0645:                            list.add(name.toString());
0646:                            return list;
0647:                        case '|':
0648:                            list.add(name.toString());
0649:                            name.setLength(0);
0650:                            state = GR_INIT;
0651:                            break;
0652:                        default:
0653:                            if (Character.isWhitespace((char) i)) {
0654:                                list.add(name.toString());
0655:                                name.setLength(0);
0656:                                state = GR_ANAME;
0657:                                break;
0658:                            } else {
0659:                                throw new WrongDTDException("Unexpected char '"
0660:                                        + (char) i + "' in group definition."); // NOI18N
0661:                            }
0662:                        }
0663:                        break;
0664:
0665:                    case GR_ANAME:
0666:                        if (Character.isWhitespace((char) i))
0667:                            break;
0668:                        switch (i) {
0669:                        case ')':
0670:                            return list;
0671:                        case '|':
0672:                            state = GR_INIT;
0673:                            break;
0674:                        default:
0675:                            throw new WrongDTDException("Unexpected char '"
0676:                                    + (char) i + "' in group definition."); // NOI18N
0677:                        }
0678:                        break;
0679:                    }
0680:                }
0681:
0682:            }
0683:
0684:            private static final int EL_INIT = 0;
0685:            private static final int EL_NAME = 1;
0686:            private static final int EL_ANAME = 2;
0687:            private static final int EL_ASTART = 3;
0688:            private static final int EL_ACONTENT = 4;
0689:            private static final int EL_PLUS = 5;
0690:            private static final int EL_MINUS = 6;
0691:
0692:            /** parse the whole element(s) definition including content model.
0693:             * Create corresponding instances of DTD.Element filled with proper
0694:             * informations. Make the same content models and their contents shared
0695:             * across the DTD */
0696:            private void parseElement(PushbackReader in) throws IOException,
0697:                    WrongDTDException {
0698:                int state = EL_INIT;
0699:                StringBuffer name = new StringBuffer();
0700:                List list = null;
0701:                boolean optStart = false;
0702:                boolean optEnd = false;
0703:                DTD.Content content = null;
0704:                Set inSet = new HashSet();
0705:                Set exSet = new HashSet();
0706:
0707:                for (;;) {
0708:                    int i = in.read();
0709:                    if (i == -1)
0710:                        break;
0711:                    switch (state) {
0712:                    case EL_INIT:
0713:                        if (Character.isWhitespace((char) i))
0714:                            break;
0715:                        switch (i) {
0716:                        case '(':
0717:                            list = parseGroup(in);
0718:                            state = EL_ANAME;
0719:                            break;
0720:                        case '%':
0721:                            parseEntityReference(in);
0722:                            break; // Stay in EL_INIT
0723:                        default:
0724:                            name.append((char) i);
0725:                            state = EL_NAME;
0726:                            break;
0727:                        }
0728:                        break;
0729:
0730:                    case EL_NAME:
0731:                        if (Character.isWhitespace((char) i)) {
0732:                            state = EL_ANAME;
0733:                            list = new ArrayList();
0734:                            list.add(name.toString());
0735:                        } else {
0736:                            name.append((char) i);
0737:                        }
0738:                        break;
0739:
0740:                    case EL_ANAME:
0741:                        if (Character.isWhitespace((char) i))
0742:                            break;
0743:                        switch (i) {
0744:                        case 'O':
0745:                            optStart = true; // fall fhrough
0746:                        case '-':
0747:                            state = EL_ASTART;
0748:                            break;
0749:                        default:
0750:                            throw new WrongDTDException("Unexpected char '"
0751:                                    + (char) i
0752:                                    + "' in ELEMENT optStart definition."); // NOI18N
0753:                        }
0754:                        break;
0755:
0756:                    case EL_ASTART:
0757:                        if (Character.isWhitespace((char) i))
0758:                            break;
0759:                        switch (i) {
0760:                        case 'O':
0761:                            optEnd = true; // fall fhrough
0762:                        case '-':
0763:                            content = parseContent(in);
0764:                            state = EL_ACONTENT;
0765:                            break;
0766:                        default:
0767:                            throw new WrongDTDException("Unexpected char '"
0768:                                    + (char) i
0769:                                    + "' in ELEMENT optEnd definition."); // NOI18N
0770:                        }
0771:                        break;
0772:
0773:                    case EL_ACONTENT:
0774:                        if (Character.isWhitespace((char) i))
0775:                            break;
0776:                        switch (i) {
0777:                        case '+':
0778:                            state = EL_PLUS;
0779:                            break;
0780:                        case '-':
0781:                            state = EL_MINUS;
0782:                            break;
0783:                        case '>':
0784:                            DTD.ContentModel cm = createContentModel(content,
0785:                                    inSet, exSet);
0786:                            for (Iterator iter = list.iterator(); iter
0787:                                    .hasNext();) {
0788:                                String key = ((String) iter.next())
0789:                                        .toUpperCase();
0790:                                elementMap.put(key, createElement(key, cm,
0791:                                        optStart, optEnd));
0792:                            }
0793:                            return;
0794:                        default:
0795:                            throw new WrongDTDException("Unexpected char '"
0796:                                    + (char) i + "' in ELEMENT definition."); // NOI18N
0797:                        }
0798:                        break;
0799:
0800:                    case EL_PLUS:
0801:                        if (i == '(') {
0802:                            state = EL_ACONTENT;
0803:                            inSet.addAll(parseGroup(in));
0804:                        } else {
0805:                            throw new WrongDTDException("Unexpected char '"
0806:                                    + (char) i + "' in ELEMENT definition."); // NOI18N
0807:                        }
0808:                        break;
0809:
0810:                    case EL_MINUS:
0811:                        switch (i) {
0812:                        case '(':
0813:                            state = EL_ACONTENT;
0814:                            List l = parseGroup(in);
0815:                            exSet.addAll(l);
0816:                            break;
0817:                        case '-':
0818:                            state = EL_ACONTENT;
0819:                            parseComment(in);
0820:                            break;
0821:                        default:
0822:                            throw new WrongDTDException("Unexpected char '"
0823:                                    + (char) i + "' in ELEMENT definition."); // NOI18N
0824:                        }
0825:                        break;
0826:                    }
0827:                }
0828:
0829:                //XXX
0830:            }
0831:
0832:            private static final int CO_INIT = 0;
0833:            private static final int CO_NAME = 1;
0834:            private static final int CO_AMODEL = 2;
0835:            private static final int CO_AND = 3;
0836:            private static final int CO_OR = 4;
0837:            private static final int CO_SEQ = 5;
0838:            private static final int CO_AGROUP = 6;
0839:
0840:            /** This automata would parse content model definitions and return them
0841:             * as a Content instance of root of generated CM tree */
0842:            private DTD.Content parseContent(PushbackReader in)
0843:                    throws IOException, WrongDTDException {
0844:                int state = EL_INIT;
0845:                StringBuffer name = new StringBuffer();
0846:                ArrayList list = null;
0847:                DTD.Content content = null;
0848:
0849:                for (;;) {
0850:                    int i = in.read();
0851:                    if (i == -1)
0852:                        break;
0853:                    switch (state) {
0854:                    case CO_INIT:
0855:                        if (Character.isWhitespace((char) i))
0856:                            break;
0857:                        switch (i) {
0858:                        case '%':
0859:                            parseEntityReference(in);
0860:                            break; // Stay in CO_INIT
0861:                        case '(':
0862:                            content = parseContent(in);
0863:                            state = CO_AMODEL;
0864:                            break;
0865:                        default:
0866:                            name.append((char) i);
0867:                            state = CO_NAME;
0868:                            break;
0869:                        }
0870:                        break;
0871:
0872:                    case CO_NAME:
0873:                        if (isNameChar((char) i)) {
0874:                            name.append((char) i);
0875:                        } else {
0876:                            switch (i) {
0877:                            case '?':
0878:                            case '+':
0879:                            case '*':
0880:                                DTD.Content leaf = createContentLeaf(name
0881:                                        .toString());
0882:                                return createContentNode((char) i, leaf);
0883:
0884:                            default:
0885:                                in.unread(i);
0886:                                return createContentLeaf(name.toString());
0887:                            }
0888:                        }
0889:                        break;
0890:
0891:                    case CO_AMODEL:
0892:                        if (Character.isWhitespace((char) i))
0893:                            break;
0894:                        switch (i) {
0895:                        case '&':
0896:                            list = new ArrayList();
0897:                            list.add(content);
0898:                            list.add(parseContent(in));
0899:                            state = CO_AND;
0900:                            break;
0901:                        case '|':
0902:                            list = new ArrayList();
0903:                            list.add(content);
0904:                            list.add(parseContent(in));
0905:                            state = CO_OR;
0906:                            break;
0907:                        case ',':
0908:                            list = new ArrayList();
0909:                            list.add(content);
0910:                            list.add(parseContent(in));
0911:                            state = CO_SEQ;
0912:                            break;
0913:                        case ')':
0914:                            state = CO_AGROUP;
0915:                            break;
0916:                        default:
0917:                            throw new WrongDTDException("Unexpected char '"
0918:                                    + (char) i
0919:                                    + "' in ELEMENT optEnd definition."); // NOI18N
0920:                        }
0921:                        break;
0922:
0923:                    case CO_AND:
0924:                        if (Character.isWhitespace((char) i))
0925:                            break;
0926:                        switch (i) {
0927:                        case '&':
0928:                            list.add(parseContent(in));
0929:                            break;
0930:                        case ')':
0931:                            content = createContentNode('&',
0932:                                    (DTD.Content[]) list
0933:                                            .toArray(new DTD.Content[0]));
0934:                            state = CO_AGROUP;
0935:                            break;
0936:                        default:
0937:                            throw new WrongDTDException("Unexpected char '"
0938:                                    + (char) i
0939:                                    + "' in ContentModel definition."); // NOI18N
0940:                        }
0941:                        break;
0942:
0943:                    case CO_OR:
0944:                        if (Character.isWhitespace((char) i))
0945:                            break;
0946:                        switch (i) {
0947:                        case '|':
0948:                            list.add(parseContent(in));
0949:                            break;
0950:                        case ')':
0951:                            content = createContentNode('|',
0952:                                    (DTD.Content[]) list
0953:                                            .toArray(new DTD.Content[0]));
0954:                            state = CO_AGROUP;
0955:                            break;
0956:                        default:
0957:                            throw new WrongDTDException("Unexpected char '"
0958:                                    + (char) i
0959:                                    + "' in ContentModel definition."); // NOI18N
0960:                        }
0961:                        break;
0962:
0963:                    case CO_SEQ:
0964:                        if (Character.isWhitespace((char) i))
0965:                            break;
0966:                        switch (i) {
0967:                        case ',':
0968:                            list.add(parseContent(in));
0969:                            break;
0970:                        case ')':
0971:                            content = createContentNode(',',
0972:                                    (DTD.Content[]) list
0973:                                            .toArray(new DTD.Content[0]));
0974:                            state = CO_AGROUP;
0975:                            break;
0976:                        default:
0977:                            throw new WrongDTDException("Unexpected char '"
0978:                                    + (char) i
0979:                                    + "' in ContentModel definition."); // NOI18N
0980:                        }
0981:                        break;
0982:
0983:                    case CO_AGROUP:
0984:                        if (Character.isWhitespace((char) i))
0985:                            return content;
0986:                        switch (i) {
0987:                        case '?':
0988:                        case '+':
0989:                        case '*':
0990:                            return createContentNode((char) i, content);
0991:                        default:
0992:                            in.unread(i);
0993:                            return content;
0994:                        }
0995:                    }
0996:                }
0997:
0998:                throw new WrongDTDException("Premature end of DTD"); // NOI18N EOF
0999:
1000:            }
1001:
1002:            private static final int ATT_INIT = 0;
1003:            private static final int ATT_NAME = 1;
1004:            private static final int ATT_ANAME = 2;
1005:            private static final int ATT_ANAME_M = 3;
1006:            private static final int ATT_VAR = 4;
1007:            private static final int ATT_AVAR = 5;
1008:            private static final int ATT_TYPE = 6;
1009:            private static final int ATT_ATYPE = 7;
1010:            private static final int ATT_MODE = 8;
1011:
1012:            private void parseAttlist(PushbackReader in) throws IOException,
1013:                    WrongDTDException {
1014:                int state = ATT_INIT;
1015:                StringBuffer name = new StringBuffer();
1016:                List list = null; // List of tag names for which are these attribs
1017:                StringBuffer attr = new StringBuffer(); // name of attribute
1018:                List values = null; // (list of possible values
1019:                StringBuffer type = new StringBuffer(); // OR the type of attribute )
1020:                String typeHelper = null; // AND name of entity
1021:                StringBuffer mode = new StringBuffer(); // default mode of this attrib
1022:                for (;;) {
1023:                    int i = in.read();
1024:                    if (i == -1)
1025:                        break;
1026:                    switch (state) {
1027:                    case ATT_INIT:
1028:                        if (Character.isWhitespace((char) i))
1029:                            break;
1030:                        switch (i) {
1031:                        case '%':
1032:                            parseEntityReference(in);
1033:                            break; // Stay in ATT_INIT
1034:                        case '(':
1035:                            list = parseGroup(in);
1036:                            state = ATT_ANAME;
1037:                            break;
1038:                        default:
1039:                            name.append((char) i);
1040:                            state = ATT_NAME;
1041:                            break;
1042:                        }
1043:                        break;
1044:
1045:                    case ATT_NAME:
1046:                        if (Character.isWhitespace((char) i)) {
1047:                            list = new ArrayList();
1048:                            list.add(name.toString());
1049:                            state = ATT_ANAME;
1050:                            break;
1051:                        }
1052:                        name.append((char) i);
1053:                        break;
1054:
1055:                    case ATT_ANAME:
1056:                        if (Character.isWhitespace((char) i))
1057:                            break;
1058:                        switch (i) {
1059:                        case '%':
1060:                            parseEntityReference(in);
1061:                            break; // Stay in ATT_ANAME
1062:                        case '-':
1063:                            state = ATT_ANAME_M;
1064:                            break;
1065:                        case '>':
1066:                            return;
1067:                        default:
1068:                            attr.append((char) i);
1069:                            state = ATT_VAR;
1070:                            break;
1071:                        }
1072:                        break;
1073:
1074:                    case ATT_ANAME_M:
1075:                        if (i == '-') {
1076:                            parseComment(in); // skip the comment
1077:                            state = ATT_ANAME;
1078:                        } else {
1079:                            throw new WrongDTDException("Unexpected char '"
1080:                                    + (char) i + "' in ATTLIST definition."); // NOI18N
1081:                        }
1082:                        break;
1083:
1084:                    case ATT_VAR:
1085:                        if (Character.isWhitespace((char) i)) {
1086:                            state = ATT_AVAR;
1087:                            break;
1088:                        }
1089:                        attr.append((char) i);
1090:                        break;
1091:
1092:                    case ATT_AVAR:
1093:                        if (Character.isWhitespace((char) i))
1094:                            break;
1095:                        switch (i) {
1096:                        case '%':
1097:                            typeHelper = parseEntityReference(in);
1098:                            break; // Stay in ATT_AVAR
1099:                        case '(':
1100:                            values = parseGroup(in);
1101:                            state = ATT_ATYPE;
1102:                            break;
1103:                        default:
1104:                            type.append((char) i);
1105:                            state = ATT_TYPE;
1106:                            break;
1107:                        }
1108:                        break;
1109:
1110:                    case ATT_TYPE:
1111:                        if (Character.isWhitespace((char) i)) {
1112:                            state = ATT_ATYPE;
1113:                            break;
1114:                        }
1115:                        type.append((char) i);
1116:                        break;
1117:
1118:                    case ATT_ATYPE:
1119:                        if (Character.isWhitespace((char) i))
1120:                            break;
1121:                        switch (i) {
1122:                        case '%':
1123:                            parseEntityReference(in);
1124:                            break; // Stay in ATT_ATYPE
1125:                        default:
1126:                            mode.append((char) i);
1127:                            state = ATT_MODE;
1128:                            break;
1129:                        }
1130:                        break;
1131:
1132:                    case ATT_MODE:
1133:                        if (Character.isWhitespace((char) i)) {
1134:                            // Create attr and add it to all tags
1135:                            DTD.Attribute a = null;
1136:
1137:                            if (values == null) { // HOTSPOT for internation of strings!!!
1138:                                a = createAttribute(attr.toString(),
1139:                                        DTD.Attribute.TYPE_BASE, type
1140:                                                .toString(), typeHelper, mode
1141:                                                .toString(), null);
1142:                            } else if (values.size() == 1) {
1143:                                a = createAttribute(attr.toString(),
1144:                                        DTD.Attribute.TYPE_BOOLEAN, null,
1145:                                        typeHelper, mode.toString(), null);
1146:                            } else {
1147:                                SortedMap vals = new TreeMap();
1148:                                for (Iterator iter = values.iterator(); iter
1149:                                        .hasNext();) {
1150:                                    String valName = ((String) iter.next())
1151:                                            .toLowerCase();
1152:                                    vals.put(valName, createValue(valName));
1153:                                }
1154:                                a = createAttribute(attr.toString(),
1155:                                        DTD.Attribute.TYPE_SET, null,
1156:                                        typeHelper, mode.toString(), vals);
1157:                            }
1158:                            for (Iterator iter = list.iterator(); iter
1159:                                    .hasNext();) {
1160:                                addAttrToElement((String) iter.next(), a);
1161:                            }
1162:
1163:                            typeHelper = null;
1164:                            attr.setLength(0);
1165:                            type.setLength(0);
1166:                            mode.setLength(0);
1167:                            values = null;
1168:
1169:                            state = ATT_ANAME;
1170:                            break;
1171:                        }
1172:                        mode.append((char) i);
1173:                        break;
1174:                    }
1175:                }
1176:            }
1177:
1178:            private static final int OPT_INIT = 0;
1179:            private static final int OPT_PROCESS = 1;
1180:            private static final int OPT_APROCESS = 2;
1181:            private static final int OPT_CONTENT = 3;
1182:            private static final int OPT_BRAC1 = 4;
1183:            private static final int OPT_BRAC2 = 5;
1184:
1185:            /** Parser that takes care of conditional inclusion/exclusion of part
1186:             * of DTD. Gets the control just after "<![" */
1187:            private void parseOptional(PushbackReader in) throws IOException,
1188:                    WrongDTDException {
1189:                int state = OPT_INIT;
1190:                StringBuffer process = new StringBuffer();
1191:                StringBuffer content = new StringBuffer();
1192:                boolean ignore = false;
1193:
1194:                for (;;) {
1195:                    int i = in.read();
1196:                    if (i == -1)
1197:                        break; // EOF
1198:                    switch (state) {
1199:                    case OPT_INIT:
1200:                        if (Character.isWhitespace((char) i))
1201:                            break;
1202:                        if (i == '%') {
1203:                            parseEntityReference(in);
1204:                            break;
1205:                        }
1206:                        process.append((char) i);
1207:                        state = OPT_PROCESS;
1208:                        break;
1209:
1210:                    case OPT_PROCESS:
1211:                        if (Character.isWhitespace((char) i)) {
1212:                            String s = process.toString();
1213:                            if ("IGNORE".equals(s))
1214:                                ignore = true; // NOI18N
1215:                            else if (!"INCLUDE".equals(s))
1216:                                throw new WrongDTDException(
1217:                                        "Unexpected processing instruction "
1218:                                                + s); // NOI18N
1219:                            state = OPT_APROCESS;
1220:                        } else {
1221:                            process.append((char) i);
1222:                        }
1223:                        break;
1224:
1225:                    case OPT_APROCESS:
1226:                        if (Character.isWhitespace((char) i))
1227:                            break;
1228:                        if (i == '[')
1229:                            state = OPT_CONTENT;
1230:                        else
1231:                            throw new WrongDTDException("Unexpected char '"
1232:                                    + (char) i + "' in processing instruction."); // NOI18N
1233:                        break;
1234:
1235:                    case OPT_CONTENT:
1236:                        if (i == ']')
1237:                            state = OPT_BRAC1;
1238:                        else
1239:                            content.append((char) i);
1240:                        break;
1241:
1242:                    case OPT_BRAC1:
1243:                        if (i == ']')
1244:                            state = OPT_BRAC2;
1245:                        else {
1246:                            content.append(']').append((char) i);
1247:                            state = OPT_CONTENT;
1248:                        }
1249:                        break;
1250:
1251:                    case OPT_BRAC2:
1252:                        if (Character.isWhitespace((char) i))
1253:                            break;
1254:                        if (i == '>') {
1255:                            if (!ignore)
1256:                                in.unread(content.toString().toCharArray());
1257:                            return;
1258:                        }
1259:                        throw new WrongDTDException("Unexpected char '"
1260:                                + (char) i + "' in processing instruction."); // NOI18N
1261:                    }
1262:                }
1263:
1264:            }
1265:
1266:            private static final int COMM_TEXT = 0; // anywhere in text
1267:            private static final int COMM_DASH = 1; // after '-'
1268:
1269:            /** Parser that eats everything until two consecutive dashes (inclusive) */
1270:            private void parseComment(PushbackReader in) throws IOException,
1271:                    WrongDTDException {
1272:                int state = COMM_TEXT;
1273:                for (;;) {
1274:                    int i = in.read();
1275:                    if (i == -1)
1276:                        break; // EOF
1277:                    switch (state) {
1278:                    case COMM_TEXT:
1279:                        if (i == '-')
1280:                            state = COMM_DASH;
1281:                        break;
1282:                    case COMM_DASH:
1283:                        if (i == '-')
1284:                            return; // finished eating comment
1285:                        state = COMM_TEXT;
1286:                        break;
1287:                    }
1288:                }
1289:                throw new WrongDTDException("Premature end of DTD"); // NOI18N
1290:            }
1291:
1292:            /** Parser that reads the name of entity reference and replace it with
1293:             * the content of that entity (using the pushback capability of input).
1294:             * It gets the control just after starting '%'
1295:             * @returns the name of reference which was replaced. */
1296:            private String parseEntityReference(PushbackReader in)
1297:                    throws IOException, WrongDTDException {
1298:                StringBuffer sb = new StringBuffer();
1299:                for (;;) {
1300:                    int i = in.read();
1301:                    if (i == -1)
1302:                        break; // EOF
1303:                    if (isNameChar((char) i)) {
1304:                        sb.append((char) i); // next char of name
1305:                    } else {
1306:                        String entValue = (String) entityMap.get(sb.toString()); //get the entity content
1307:                        if (entValue == null)
1308:                            throw new WrongDTDException("No such entity: \""
1309:                                    + sb + "\""); // NOI18N
1310:
1311:                        if (i != ';')
1312:                            in.unread(i);
1313:                        in.unread(entValue.toCharArray()); // push it back to stream
1314:                        return sb.toString();
1315:                    }
1316:                }
1317:                throw new WrongDTDException("Premature end of DTD"); // NOI18N
1318:            }
1319:
1320:            public static class WrongDTDException extends Exception {
1321:                public WrongDTDException(String reason) {
1322:                    super (reason);
1323:                }
1324:            }
1325:
1326:            /*----------------------------------------------------------------------------*/
1327:            /*---------- Implementation of classes this factory uses as results ----------*/
1328:            /*----------------------------------------------------------------------------*/
1329:
1330:            /** Implementation of the DTD which this DTDcreator works as factory for. */
1331:            private static class DTDImpl implements  DTD {
1332:                private String id;
1333:                private SortedMap elements;
1334:                private SortedMap charRefs;
1335:
1336:                DTDImpl(String identifier, SortedMap elements,
1337:                        SortedMap charRefs) {
1338:                    this .id = identifier;
1339:                    this .elements = elements;
1340:                    this .charRefs = charRefs;
1341:                }
1342:
1343:                /** Identify this instance of DTD */
1344:                public String getIdentifier() {
1345:                    return id;
1346:                }
1347:
1348:                /** Get List of all Elements whose names starts with given prefix  */
1349:                public List getElementList(String prefix) {
1350:                    List l = new ArrayList();
1351:                    prefix = prefix == null ? "" : prefix.toUpperCase();
1352:                    Iterator i = elements.tailMap(prefix).entrySet().iterator();
1353:
1354:                    while (i.hasNext()) {
1355:                        Map.Entry entry = (Map.Entry) i.next();
1356:                        if (((String) entry.getKey()).startsWith(prefix)) {
1357:                            l.add(entry.getValue());
1358:                        } else { // we're getting data from SortedSet, so when any
1359:                            break; // entry fails, all remaining entry would fail.
1360:                        }
1361:                    }
1362:
1363:                    return l;
1364:                }
1365:
1366:                /** Get the Element of given name. */
1367:                public DTD.Element getElement(String name) {
1368:                    return (DTD.Element) elements.get(name);
1369:                }
1370:
1371:                /** Get List of all CharRefs whose aliases starts with given prefix. */
1372:                public List getCharRefList(String prefix) {
1373:                    List l = new ArrayList();
1374:                    Iterator i = charRefs.tailMap(prefix).entrySet().iterator();
1375:
1376:                    while (i.hasNext()) {
1377:                        Map.Entry entry = (Map.Entry) i.next();
1378:                        if (((String) entry.getKey()).startsWith(prefix)) {
1379:                            l.add(entry.getValue());
1380:                        } else { // we're getting data from SortedSet, so when any
1381:                            break; // entry fails, all remaining entry would fail.
1382:                        }
1383:                    }
1384:
1385:                    return l;
1386:                }
1387:
1388:                /** Get the CharRef of given name */
1389:                public DTD.CharRef getCharRef(String name) {
1390:                    return (DTD.CharRef) charRefs.get(name);
1391:                }
1392:
1393:                public String toString() {
1394:                    return super .toString() + "[id=" + id + ", elements="
1395:                            + elements + ",charRefs=" + charRefs + "]"; // NOI18N
1396:                }
1397:            }
1398:
1399:            /** Implementation of Element used by this DTDcreator. */
1400:            private static class ElementImpl implements  DTD.Element {
1401:
1402:                private String name;
1403:                private DTD.ContentModel model;
1404:                private boolean optStart;
1405:                private boolean optEnd;
1406:                private SortedMap attributes; //these are sorted just by name
1407:                private DTD dtd;
1408:
1409:                ElementImpl(String name, DTD.ContentModel model,
1410:                        boolean optStart, boolean optEnd, SortedMap attributes) {
1411:                    this .name = name;
1412:                    this .model = model;
1413:                    this .optStart = optStart;
1414:                    this .optEnd = optEnd;
1415:                    this .attributes = attributes;
1416:                }
1417:
1418:                /** Get the name of this Element */
1419:                public String getName() {
1420:                    return name;
1421:                }
1422:
1423:                /** Shorthand to resolving if content model of this Element is EMPTY */
1424:                public boolean isEmpty() {
1425:                    if (optEnd && model.getContent() instanceof  DTD.ContentLeaf)
1426:                        return true;
1427:                    //&& ((DTD.ContentLeaf)model.getContent()).getName().equals( "EMPTY" ) ) return true; 
1428:                    return false;
1429:                }
1430:
1431:                /** Tells if this Element has optional Start Tag. */
1432:                public boolean hasOptionalStart() {
1433:                    return optStart;
1434:                }
1435:
1436:                /** Tells if this Element has optional End Tag. */
1437:                public boolean hasOptionalEnd() {
1438:                    return optEnd;
1439:                }
1440:
1441:                /** Get the List of Attributes of this Element, which starts with
1442:                 * given <CODE>prefix</CODE>. */
1443:                public List getAttributeList(String prefix) {
1444:                    TreeSet set = new TreeSet(new Comparator() {
1445:                        public int compare(Object o1, Object o2) {
1446:                            if (isRequired(o1) && !isRequired(o2))
1447:                                return -1;
1448:                            if (!isRequired(o1) && isRequired(o2))
1449:                                return 1;
1450:                            return ((DTD.Attribute) o1).getName().compareTo(
1451:                                    ((DTD.Attribute) o2).getName());
1452:                        }
1453:
1454:                        private final boolean isRequired(Object o) {
1455:                            return ((DTD.Attribute) o).getDefaultMode().equals(
1456:                                    DTD.Attribute.MODE_REQUIRED);
1457:                        }
1458:                    });
1459:                    prefix = prefix.toLowerCase();
1460:                    Iterator i = attributes.tailMap(prefix).entrySet()
1461:                            .iterator();
1462:
1463:                    while (i.hasNext()) {
1464:                        Map.Entry entry = (Map.Entry) i.next();
1465:                        if (((String) entry.getKey()).startsWith(prefix)) {
1466:                            set.add(entry.getValue());
1467:                        } else { // we're getting data from SortedSet, so when any
1468:                            break; // entry fails, all remaining entry would fail.
1469:                        }
1470:                    }
1471:                    return new ArrayList(set);
1472:                }
1473:
1474:                /** Get the Attribute of given name. */
1475:                public DTD.Attribute getAttribute(String name) {
1476:                    return (DTD.Attribute) attributes.get(name);
1477:                }
1478:
1479:                void addAttribute(DTD.Attribute attr) {
1480:                    attributes.put(attr.getName(), attr);
1481:                }
1482:
1483:                /** Get the content model of this Element */
1484:                public DTD.ContentModel getContentModel() {
1485:                    return model;
1486:                }
1487:
1488:                public String toString() {
1489:                    return super .toString() + "[" + name
1490:                            + (optStart ? " O" : " -")
1491:                            + (optEnd ? " O " : " - ") + model + " attribs="
1492:                            + attributes + "]"; // NOI18 // NOI18N
1493:                }
1494:            }
1495:
1496:            /** */
1497:            public static class AttributeImpl implements  DTD.Attribute {
1498:
1499:                private String name;
1500:                private int type;
1501:                private String baseType;
1502:                private String typeHelper;
1503:                private String defaultMode;
1504:                private SortedMap values;
1505:                private int hashcode;
1506:
1507:                public AttributeImpl(String name, int type, String baseType,
1508:                        String typeHelper, String defaultMode, SortedMap values) {
1509:                    this .name = name;
1510:                    this .type = type;
1511:                    this .baseType = baseType;
1512:                    this .typeHelper = typeHelper;
1513:                    this .defaultMode = defaultMode;
1514:                    this .values = values;
1515:                    hashcode = name.hashCode() * (type + 1)
1516:                            * (baseType == null ? 1 : baseType.hashCode())
1517:                            + (typeHelper == null ? 1 : typeHelper.hashCode())
1518:                            + defaultMode.hashCode()
1519:                            + (values == null ? 1 : values.hashCode());
1520:                }
1521:
1522:                /** @return name of this attribute */
1523:                public String getName() {
1524:                    return name;
1525:                }
1526:
1527:                /** @return type of this attribute */
1528:                public int getType() {
1529:                    return type;
1530:                }
1531:
1532:                public String getBaseType() {
1533:                    return baseType;
1534:                }
1535:
1536:                /** The last entity name through which was this Attribute's type defined. */
1537:                public String getTypeHelper() {
1538:                    return typeHelper;
1539:                }
1540:
1541:                /** This method is used to obtain default value information. */
1542:                public String getDefaultMode() {
1543:                    return defaultMode;
1544:                }
1545:
1546:                /** Shorthand for determining if defaultMode is "#REQUIRED" */
1547:                public boolean isRequired() {
1548:                    return defaultMode.equals(MODE_REQUIRED);
1549:                }
1550:
1551:                /** The way how to obtain possible values for TYPE_SET Attributes
1552:                 * @param prefix required prefix, or <CODE>null</CODE>, if all
1553:                 *   possible values are required.
1554:                 * @return List of Values starting with prefix, from this attribute
1555:                 * if it is of TYPE_SET. For other types, it doesn't make a sense
1556:                 * and returns null.
1557:                 */
1558:                public List getValueList(String prefix) {
1559:                    if (type != TYPE_SET)
1560:                        return null;
1561:
1562:                    if (prefix == null)
1563:                        prefix = "";
1564:                    else
1565:                        prefix = prefix.toLowerCase();
1566:
1567:                    List retVal = new ArrayList();
1568:                    Iterator i = values.tailMap(prefix).entrySet().iterator();
1569:
1570:                    while (i.hasNext()) {
1571:                        Map.Entry entry = (Map.Entry) i.next();
1572:                        if (((String) entry.getKey()).startsWith(prefix)) {
1573:                            retVal.add(entry.getValue());
1574:                        } else { // we're getting data from SortedSet, so when any
1575:                            break; // entry fails, all remaining entry would fail.
1576:                        }
1577:                    }
1578:                    return retVal;
1579:                }
1580:
1581:                /** Get the value of given name. */
1582:                public DTD.Value getValue(String name) {
1583:                    return (DTD.Value) values.get(name);
1584:                }
1585:
1586:                public String toString() {
1587:                    if (type == TYPE_SET) {
1588:                        return name + " " + values + "[" + typeHelper + "] "
1589:                                + defaultMode; // NOI18 // NOI18N
1590:                    } else if (type == TYPE_BOOLEAN) {
1591:                        return name + " (" + name + ")[" + typeHelper + "] "
1592:                                + defaultMode; // NOI18 // NOI18N
1593:                    } else {
1594:                        return name + " " + baseType + "[" + typeHelper + "] "
1595:                                + defaultMode; // NOI18 // NOI18N
1596:                    }
1597:                }
1598:
1599:                public int hashCode() {
1600:                    return hashcode;
1601:                }
1602:
1603:                public boolean equals(Object obj) {
1604:                    if (!(obj instanceof  AttributeImpl))
1605:                        return false;
1606:                    AttributeImpl a = (AttributeImpl) obj;
1607:                    return (hashcode == a.hashcode
1608:                            && name.equals(a.name)
1609:                            && type == a.type
1610:                            && (baseType == a.baseType || baseType != null
1611:                                    && baseType.equals(a.baseType))
1612:                            && (typeHelper == a.typeHelper || typeHelper != null
1613:                                    && typeHelper.equals(a.typeHelper))
1614:                            && defaultMode.equals(a.defaultMode) && (values == a.values || values != null
1615:                            && values.equals(a.values)));
1616:                }
1617:            }
1618:
1619:            private static class ValueImpl implements  DTD.Value {
1620:                String name;
1621:
1622:                ValueImpl(String name) {
1623:                    this .name = name;
1624:                }
1625:
1626:                public String getName() {
1627:                    return name;
1628:                }
1629:
1630:                public boolean equals(Object obj) {
1631:                    if (!(obj instanceof  ValueImpl))
1632:                        return false;
1633:                    return name.equals(((ValueImpl) obj).name);
1634:                }
1635:
1636:                public int hashCode() {
1637:                    return name.hashCode();
1638:                }
1639:
1640:                public String toString() {
1641:                    return name;
1642:                }
1643:            }
1644:
1645:            private static class CharRefImpl implements  DTD.CharRef {
1646:                private String name;
1647:                private char value;
1648:
1649:                CharRefImpl(String name, char value) {
1650:                    this .name = name;
1651:                    this .value = value;
1652:                }
1653:
1654:                /** @return alias to this CharRef */
1655:                public String getName() {
1656:                    return name;
1657:                }
1658:
1659:                /** @return the character this alias is for */
1660:                public char getValue() {
1661:                    return value;
1662:                }
1663:
1664:                public String toString() {
1665:                    return name + "->'" + value + "'(&#" + (int) value + ";)"; // NOI18N
1666:                }
1667:
1668:                public boolean equals(Object obj) {
1669:                    if (!(obj instanceof  CharRefImpl))
1670:                        return false;
1671:                    return name.equals(((CharRefImpl) obj).name)
1672:                            && value == ((CharRefImpl) obj).value;
1673:                }
1674:
1675:                public int hashCode() {
1676:                    return name.hashCode() * value;
1677:                }
1678:            }
1679:
1680:            /** The implementation of ContentModel. It is immutable */
1681:            private static class ContentModelImpl implements  DTD.ContentModel {
1682:                int hashcode;
1683:                DTD.Content content;
1684:                Set included;
1685:                Set excluded;
1686:
1687:                public ContentModelImpl(DTD.Content content, Set included,
1688:                        Set excluded) {
1689:                    this .content = content;
1690:                    this .included = included;
1691:                    this .excluded = excluded;
1692:                    hashcode = content.hashCode() + 2 * included.hashCode() + 3
1693:                            * excluded.hashCode();
1694:                }
1695:
1696:                /** @return the Content tree part of this model */
1697:                public DTD.Content getContent() {
1698:                    return content;
1699:                }
1700:
1701:                /** @return Set of Element names which are recursively included. */
1702:                public Set getIncludes() {
1703:                    return included;
1704:                }
1705:
1706:                /** @return Set of Element names which are recursively excluded. */
1707:                public Set getExcludes() {
1708:                    return excluded;
1709:                }
1710:
1711:                public String toString() {
1712:                    StringBuffer sb = new StringBuffer(content.toString());
1713:
1714:                    if (!included.isEmpty()) {
1715:                        sb.append(" +("); // NOI18N
1716:                        Iterator i = included.iterator();
1717:                        for (;;) {
1718:                            sb.append(((DTD.Element) i.next()).getName());
1719:                            if (i.hasNext())
1720:                                sb.append("|"); // NOI18N
1721:                            else
1722:                                break;
1723:                        }
1724:                        sb.append(")"); // NOI18N
1725:                    }
1726:
1727:                    if (!excluded.isEmpty()) {
1728:                        sb.append(" -("); // NOI18N
1729:                        Iterator i = excluded.iterator();
1730:                        for (;;) {
1731:                            sb.append(((DTD.Element) i.next()).getName());
1732:                            if (i.hasNext())
1733:                                sb.append("|"); // NOI18N
1734:                            else
1735:                                break;
1736:                        }
1737:                        sb.append(")"); // NOI18N
1738:                    }
1739:
1740:                    return sb.toString();
1741:                }
1742:
1743:                public boolean equals(Object obj) {
1744:                    if (!(obj instanceof  ContentModelImpl))
1745:                        return false;
1746:                    ContentModelImpl cmi = (ContentModelImpl) obj;
1747:                    return content.equals(cmi.content)
1748:                            && included.equals(cmi.included)
1749:                            && excluded.equals(cmi.excluded);
1750:                }
1751:
1752:                public int hashCode() {
1753:                    return hashcode;
1754:                }
1755:
1756:            }
1757:
1758:            /** ContentLeaf is leaf of content tree, matches just one Element name (String)*/
1759:            static class ContentLeafImpl implements  DTD.ContentLeaf {
1760:                String elemName;
1761:                DTD.Element elem;
1762:
1763:                public ContentLeafImpl(String name) {
1764:                    this .elemName = name;
1765:                }
1766:
1767:                /** get the name of leaf Element */
1768:                public String getName() {
1769:                    return elemName;
1770:                }
1771:
1772:                public DTD.Element getElement() {
1773:                    return elem;
1774:                }
1775:
1776:                public boolean equals(Object obj) {
1777:                    if (!(obj instanceof  ContentLeafImpl))
1778:                        return false;
1779:                    return elemName.equals(((ContentLeafImpl) obj).elemName);
1780:                }
1781:
1782:                public int hashCode() {
1783:                    return elemName.hashCode();
1784:                }
1785:
1786:                public String toString() {
1787:                    return elemName;
1788:                }
1789:
1790:                /** ContentLeaf can't be discarded as it hac no operation associated */
1791:                public boolean isDiscardable() {
1792:                    return false;
1793:                }
1794:
1795:                /** ContentLeaf is either reduced to EMPTY_CONTENT or doesn't
1796:                 * match at all */
1797:                public DTD.Content reduce(String elementName) {
1798:                    if (elemName.equals(elementName))
1799:                        return EMPTY_CONTENT;
1800:                    return null;
1801:                }
1802:
1803:                public Set getPossibleElements() {
1804:                    Set s = new HashSet();
1805:                    s.add(elem);
1806:                    return s;
1807:                }
1808:            }
1809:
1810:            /** ContentNode is node of content tree */
1811:            private static class UnaryContentNodeImpl implements 
1812:                    DTD.ContentNode {
1813:                int hashcode;
1814:                char type;
1815:                DTD.Content content;
1816:
1817:                /* Constructor for unary ContentNodes */
1818:                public UnaryContentNodeImpl(char type, DTD.Content content) {
1819:                    // sanity check:
1820:                    if (type != '*' && type != '?' && type != '+') {
1821:                        throw new IllegalArgumentException(
1822:                                "Unknown unary content type '" + type + "'"); // NOI18N
1823:                    }
1824:
1825:                    this .type = type;
1826:                    this .content = content;
1827:                    hashcode = type + content.hashCode();
1828:                }
1829:
1830:                /** This is node, always return false */
1831:                public boolean isLeaf() {
1832:                    return false;
1833:                }
1834:
1835:                /** Get the operator for this node */
1836:                public char getType() {
1837:                    return type;
1838:                }
1839:
1840:                /** Get the content of this node */
1841:                public DTD.Content[] getContent() {
1842:                    return new DTD.Content[] { content };
1843:                }
1844:
1845:                public boolean equals(Object obj) {
1846:                    if (!(obj instanceof  UnaryContentNodeImpl))
1847:                        return false;
1848:                    return type == ((UnaryContentNodeImpl) obj).type
1849:                            && content
1850:                                    .equals(((UnaryContentNodeImpl) obj).content);
1851:                }
1852:
1853:                public int hashCode() {
1854:                    return hashcode;
1855:                }
1856:
1857:                public String toString() {
1858:                    return content.toString() + type;
1859:                }
1860:
1861:                public boolean isDiscardable() {
1862:                    if (type == '*' || type == '?')
1863:                        return true;
1864:                    // The only remaining type, don't check: if( type == '+' )
1865:                    return content.isDiscardable();
1866:                }
1867:
1868:                public DTD.Content reduce(String elementName) {
1869:                    DTD.Content sub = content.reduce(elementName);
1870:                    if (sub == null)
1871:                        return null;
1872:                    if (sub == EMPTY_CONTENT) {
1873:                        if (type == '?')
1874:                            return EMPTY_CONTENT;
1875:                        if (type == '*')
1876:                            return this ;
1877:                        // '+' is the last one: if( type == '+' )
1878:                        // we fullfilled the '+' rule, remainder is '*'
1879:                        return new UnaryContentNodeImpl('*', content);
1880:                    }
1881:                    if (type == '?')
1882:                        return sub;
1883:                    DTD.Content second = (type == '*') ? this 
1884:                            : new UnaryContentNodeImpl('*', content);
1885:                    return new MultiContentNodeImpl(',', new DTD.Content[] {
1886:                            sub, second });
1887:                }
1888:
1889:                public Set getPossibleElements() {
1890:                    return content.getPossibleElements();
1891:                }
1892:
1893:            }
1894:
1895:            /** ContentNodeImpl is n-ary node of content tree */
1896:            private static class MultiContentNodeImpl implements 
1897:                    DTD.ContentNode {
1898:                int hashcode;
1899:                char type;
1900:                DTD.Content[] content;
1901:
1902:                /* Constructor for n-ary ContentNodes */
1903:                public MultiContentNodeImpl(char type, DTD.Content[] content) {
1904:                    // sanity check:
1905:                    if (type != '|' && type != '&' && type != ',') {
1906:                        throw new IllegalArgumentException(
1907:                                "Unknown n-ary content type '" + type + "'"); // NOI18N
1908:                    }
1909:
1910:                    this .type = type;
1911:                    this .content = content;
1912:                    hashcode = type;
1913:                    for (int i = 0; i < content.length; i++) {
1914:                        hashcode += content[i].hashCode();
1915:                    }
1916:                }
1917:
1918:                /** This is node, always return false */
1919:                public boolean isLeaf() {
1920:                    return false;
1921:                }
1922:
1923:                /** Get the operator for this node */
1924:                public char getType() {
1925:                    return type;
1926:                }
1927:
1928:                /** Get the content of this node */
1929:                public DTD.Content[] getContent() {
1930:                    return content;
1931:                }
1932:
1933:                public boolean equals(Object obj) {
1934:                    if (!(obj instanceof  MultiContentNodeImpl))
1935:                        return false;
1936:                    return type == ((MultiContentNodeImpl) obj).type
1937:                            && Arrays.equals(content,
1938:                                    ((MultiContentNodeImpl) obj).content);
1939:                }
1940:
1941:                public String toString() {
1942:                    StringBuffer sb = new StringBuffer("("); // NOI18N
1943:                    for (int i = 0; i < content.length; i++) {
1944:                        sb.append(content[i].toString());
1945:                        if (i + 1 < content.length)
1946:                            sb.append(type);
1947:                    }
1948:                    sb.append(')');
1949:                    return sb.toString();
1950:                }
1951:
1952:                public int hashCode() {
1953:                    return hashcode;
1954:                }
1955:
1956:                public boolean isDiscardable() {
1957:                    if (type == '&' || type == ',') {
1958:                        for (int i = 0; i < content.length; i++) {
1959:                            if (!content[i].isDiscardable())
1960:                                return false;
1961:                        }
1962:                        return true;
1963:                    }
1964:                    // The only remaining type, don't check: if( type == '|' )
1965:                    for (int i = 0; i < content.length; i++) {
1966:                        if (content[i].isDiscardable())
1967:                            return true;
1968:                    }
1969:                    return false;
1970:                }
1971:
1972:                public DTD.Content reduce(String elementName) {
1973:
1974:                    if (type == '|') {
1975:                        for (int index = 0; index < content.length; index++) {
1976:                            DTD.Content sub = content[index]
1977:                                    .reduce(elementName);
1978:                            if (sub != null)
1979:                                return sub;
1980:                        }
1981:                        return null;
1982:                    } else if (type == ',') {
1983:                        // everything before index doesn't match and is discardable
1984:                        int index = 0;
1985:
1986:                        while (index < content.length) {
1987:                            DTD.Content sub = content[index]
1988:                                    .reduce(elementName);
1989:                            // element of sequence still don't match and isn't discardable:
1990:                            if (sub == null && !content[index].isDiscardable())
1991:                                return null;
1992:
1993:                            // Element matches fully:
1994:                            if (sub == EMPTY_CONTENT) {
1995:                                int newLen = content.length - index - 1;
1996:                                if (newLen > 1) { // resulting sequence contains 2+ elements
1997:                                    DTD.Content[] newSub = new DTD.Content[newLen];
1998:                                    System.arraycopy(content, index + 1,
1999:                                            newSub, 0, newLen);
2000:                                    return new MultiContentNodeImpl(',', newSub);
2001:                                } else { // resulting sequence is one-item only
2002:                                    return content[index + 1];
2003:                                }
2004:                            }
2005:
2006:                            // Element matches and is modified
2007:                            if (sub != null) {
2008:                                int newLen = content.length - index;
2009:                                if (newLen > 1) { // resulting sequence contains 2+ elements
2010:                                    DTD.Content[] newSub = new DTD.Content[newLen];
2011:                                    System.arraycopy(content, index + 1,
2012:                                            newSub, 1, newLen - 1);
2013:                                    newSub[0] = sub;
2014:                                    return new MultiContentNodeImpl(',', newSub);
2015:                                } else { // resulting sequence is one modified item only
2016:                                    return sub;
2017:                                }
2018:                            }
2019:                            index++; //discard the first element and try again
2020:                        }
2021:
2022:                        return null; // Doesn't match at all                
2023:                    } else { // only '&' remains: if( type == '&' ) {
2024:                        for (int index = 0; index < content.length; index++) {
2025:                            DTD.Content sub = content[index]
2026:                                    .reduce(elementName);
2027:                            if (sub == EMPTY_CONTENT) {
2028:                                int newLen = content.length - 1;
2029:                                if (newLen > 1) {
2030:                                    DTD.Content[] newSub = new DTD.Content[newLen];
2031:                                    System.arraycopy(content, 0, newSub, 0,
2032:                                            index);
2033:                                    if (index < newSub.length) {
2034:                                        System.arraycopy(content, index + 1,
2035:                                                newSub, index, newLen - index);
2036:                                    }
2037:                                    return new MultiContentNodeImpl('&', newSub);
2038:                                } else {
2039:                                    return content[1 - index];
2040:                                }
2041:                            }
2042:                            if (sub != null) {
2043:                                DTD.Content right;
2044:                                if (content.length > 1) {
2045:                                    int newLen = content.length - 1;
2046:                                    DTD.Content[] newSub = new DTD.Content[newLen];
2047:                                    System.arraycopy(content, 0, newSub, 0,
2048:                                            index);
2049:                                    if (index < newSub.length) {
2050:                                        System.arraycopy(content, index + 1,
2051:                                                newSub, index, newLen - index);
2052:                                    }
2053:                                    right = new MultiContentNodeImpl('&',
2054:                                            newSub);
2055:                                } else {
2056:                                    right = content[1 - index];
2057:                                }
2058:                                return new MultiContentNodeImpl(',',
2059:                                        new DTD.Content[] { sub, right });
2060:                            }
2061:                        }
2062:                        return null;
2063:
2064:                    }
2065:                }
2066:
2067:                public Set getPossibleElements() {
2068:                    Set retVal = new HashSet(11);
2069:
2070:                    if (type == '|' || type == '&') {
2071:                        for (int index = 0; index < content.length; index++)
2072:                            retVal.addAll(content[index].getPossibleElements());
2073:
2074:                    } else { // only ',' remains if( type == ',' ) {}
2075:                        int index = 0;
2076:                        while (index < content.length) {
2077:                            retVal.addAll(content[index].getPossibleElements());
2078:                            if (!content[index].isDiscardable())
2079:                                break;
2080:                            index++;
2081:                        }
2082:                    }
2083:                    return retVal;
2084:                }
2085:            }
2086:
2087:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.