001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017: package javax.swing.text.html.parser;
018:
019: import java.io.FileNotFoundException;
020: import java.io.FileOutputStream;
021: import java.io.IOException;
022: import java.util.Hashtable;
023: import java.util.Iterator;
024:
025: class DTDUtilities implements DTDConstants {
026: static final String SPLIT_PATTERN = "\\|";
027: static final String REPLACE_PATTERN = " |\\(|\\)";
028:
029: static void putAttribute(final Hashtable atts, final String name,
030: final String value) {
031: if (name.indexOf("|") >= 0) {
032: String[] names = replaceAndSplit(name);
033: for (int i = 0; i < names.length; i++) {
034: putAttribute(atts, names[i], value);
035: }
036: } else {
037: atts.put(name, value);
038: }
039: };
040:
041: static String[] replaceAndSplit(final String s) {
042: return s.replaceAll(REPLACE_PATTERN, "").split(SPLIT_PATTERN);
043: }
044:
045: static void handleElement(final Object obj, final String name,
046: final String descr, final Hashtable attrTable) {
047: //For testing
048: if (obj instanceof Hashtable) {
049: ((Hashtable) obj).put(name, descr);
050: return;
051: }
052: DTD dtd = (DTD) obj;
053: if (name.indexOf("|") >= 0) {
054: String[] names = replaceAndSplit(name);
055: for (int i = 0; i < names.length; i++) {
056: handleElement(dtd, names[i], descr, attrTable);
057: }
058: } else {
059: String[] splDescr = splitElementDescr(descr);
060: boolean oStart = isOmitTag(splDescr[0], true);
061: boolean oEnd = isOmitTag(splDescr[0], false);
062: ContentModel contentModel = createContentModel(dtd,
063: splDescr[1]);
064: String[] exclusions = splitString(splDescr[2]);
065: String[] inclusions = splitString(splDescr[3]);
066: AttributeList atts = createAttributeList(dtd,
067: (String) attrTable.get(name));
068: int type = getType(oEnd, splDescr[1]);
069: dtd.defElement(name, type, oStart, oEnd, contentModel,
070: exclusions, inclusions, atts);
071: }
072: };
073:
074: static int getType(final boolean oEnd, final String descr) {
075: if (descr.startsWith("EMPTY") && oEnd) {
076: return EMPTY;
077: } else if (descr.startsWith("CDATA")) {
078: return CDATA;
079: } else {
080: return MODEL;
081: }
082: }
083:
084: static boolean isOmitTag(final String descr, final boolean isStart) {
085: return descr.charAt(isStart ? 0 : 2) == 'O';
086: }
087:
088: static void handleEntity(final DTD dtd, final String name,
089: final int value) {
090: Entity entity = new Entity(name, (char) value);
091: dtd.entityHash.put(name, entity);
092: dtd.entityHash.put(new Integer(value), entity);
093: }
094:
095: static AttributeList createAttributeList(final DTD dtd,
096: final String spec) {
097: String[] specs = spec.replaceAll("( )+", " ").replaceAll(
098: "( )*\\|( )*", "|").split(" ");
099: AttributeList result = null;
100: String values = "";
101: int modifier = 0;
102: for (int i = specs.length - 3; i >= 0; i -= 3) {
103: modifier = AttributeList.nameToModifier(specs[i + 2]);
104: values = specs[i + 1];
105: values = values.indexOf(")") >= 0 ? values.replaceAll(
106: "\\(|\\)", "") : null;
107: result = dtd.defAttributeList(specs[i + 0], AttributeList
108: .name2type(specs[i + 1]), modifier,
109: modifier == DEFAULT ? specs[i + 2] : null, values,
110: result);
111:
112: }
113: return result;
114: }
115:
116: static String[] splitString(final String s) {
117: return s == null ? null : s.split("\\|");
118: }
119:
120: static boolean isBalanced(final String s) {
121: int count = 0;
122: for (int i = 0; i < s.length(); i++) {
123: char ch = s.charAt(i);
124: if (ch == ')' && count < 0) {
125: count++;
126: } else if (ch == '(') {
127: count--;
128: }
129: }
130: return count == 0;
131: }
132:
133: static ContentModel createContentModel(final DTD dtd,
134: final String descr) {
135: if (descr.startsWith("EMPTY") || descr.startsWith("CDATA")) {
136: return null;
137: }
138: int length = descr.length();
139: if (descr.matches("([a-zA-Z]|[0-9]|#)+")) {
140: return new ContentModel((Element) dtd.elementHash
141: .get(descr));
142: } else if (descr.matches("\\((.)*\\)")
143: && isBalanced(descr.substring(1, length - 1))) {
144: return createContentModel(dtd, descr.substring(1,
145: length - 1));
146: } else if (descr.matches("\\((.)+\\)[+*?]")
147: || descr.matches("([a-zA-Z]|[0-9]|#)+[+|*|?]")) {
148: int index = length - 1;
149: return new ContentModel(descr.charAt(index),
150: createContentModel(dtd, descr.substring(0, index)));
151: } else {
152: int count = 0;
153: char ch = 0;
154: for (int i = descr.length() - 1; i >= 0; i--) {
155: ch = descr.charAt(i);
156: if ("|,&".indexOf(ch) >= 0 && count == 0) {
157: count = i;
158: break;
159: } else if (ch == ')') {
160: count++;
161: } else if (ch == '(') {
162: count--;
163: }
164:
165: }
166: return new ContentModel(ch, createContentModel(dtd, descr
167: .substring(0, count)), createContentModel(dtd,
168: descr.substring(count + 1, length)));
169: }
170: }
171:
172: static String[] splitElementDescr(final String descr) {
173: String tags = descr.substring(0, 3);
174: String allContent = descr.substring(4, descr.length());
175: allContent = allContent.replaceAll("( )+", "");
176: int incIndex = allContent.indexOf("+(");
177: int excIndex = allContent.indexOf("-(");
178: String content = "";
179: String exc = null;
180: String inc = null;
181:
182: if (incIndex >= 0 && excIndex >= 0) {
183: if (incIndex > excIndex) {
184: inc = allContent.substring(incIndex, excIndex);
185: exc = allContent.substring(excIndex, allContent
186: .length());
187: content = allContent.substring(0, incIndex);
188: } else {
189: inc = allContent.substring(excIndex, incIndex);
190: exc = allContent.substring(incIndex, allContent
191: .length());
192: content = allContent.substring(0, excIndex);
193: }
194: } else if (incIndex >= 0) {
195: inc = allContent.substring(incIndex, allContent.length());
196: content = allContent.substring(0, incIndex);
197: } else if (excIndex >= 0) {
198: exc = allContent.substring(excIndex, allContent.length());
199: content = allContent.substring(0, excIndex);
200: } else {
201: content = allContent;
202: }
203: inc = inc == null ? null : inc.substring(2, inc.length() - 1);
204: exc = exc == null ? null : exc.substring(2, exc.length() - 1);
205: return new String[] { tags, content, exc, inc };
206: }
207:
208: static void initDTD(final DTD dtd) {
209: EntitiesHandler.initEntitiesCreation(dtd);
210: ElementsHandler.initAttributes();
211: putAllElementsIntoHash(dtd);
212: ElementsHandler.initElementsCreation(dtd);
213: }
214:
215: static void putAllElementsIntoHash(final DTD dtd) {
216: Iterator iter = ElementsHandler.atts.keySet().iterator();
217: while (iter.hasNext()) {
218: String name = (String) iter.next();
219: dtd.defElement(name, EMPTY, false, false, null, null, null,
220: null);
221: }
222: dtd.defElement("#PCDATA", EMPTY, false, false, null, null,
223: null, null);
224: }
225:
226: public static void createBinaryDTD(final String fileName, DTD dtd) {
227: try {
228: FileOutputStream stream = new FileOutputStream(fileName);
229: Asn1Dtd asn1 = new Asn1Dtd(dtd);
230: byte[] enc = asn1.getEncoded();
231: stream.write(enc);
232: stream.close();
233: } catch (FileNotFoundException e) {
234: e.printStackTrace();
235: } catch (IOException e) {
236: e.printStackTrace();
237: }
238: }
239:
240: public static void createBinaryDTD(final String fileName) {
241: DTD dtd = new DTD("tmp");
242: initDTD(dtd);
243: createBinaryDTD(fileName, dtd);
244: }
245: }
|