1 package com.thaiopensource.relaxng.impl; 2 3 import com.thaiopensource.validate.Validator; 4 import com.thaiopensource.xml.util.StringSplitter; 5 import com.thaiopensource.xml.util.Name; 6 import org.relaxng.datatype.Datatype; 7 import org.xml.sax.Attributes ; 8 import org.xml.sax.ErrorHandler ; 9 import org.xml.sax.Locator ; 10 import org.xml.sax.SAXException ; 11 import org.xml.sax.SAXParseException ; 12 import org.xml.sax.ContentHandler ; 13 import org.xml.sax.DTDHandler ; 14 import org.xml.sax.helpers.LocatorImpl ; 15 16 import java.util.Enumeration ; 17 import java.util.Hashtable ; 18 import java.util.Vector ; 19 20 public class IdSoundnessChecker implements Validator, ContentHandler { 21 private final IdTypeMap idTypeMap; 22 private final ErrorHandler eh; 23 private Locator locator; 24 private final Hashtable table = new Hashtable (); 25 26 private static class Entry { 27 Locator idLoc; 28 Vector idrefLocs; 29 boolean hadId; 30 } 31 32 public IdSoundnessChecker(IdTypeMap idTypeMap, ErrorHandler eh) { 33 this.idTypeMap = idTypeMap; 34 this.eh = eh; 35 } 36 37 public void reset() { 38 table.clear(); 39 locator = null; 40 } 41 42 public ContentHandler getContentHandler() { 43 return this; 44 } 45 46 public DTDHandler getDTDHandler() { 47 return null; 48 } 49 50 public void setDocumentLocator(Locator locator) { 51 this.locator = locator; 52 } 53 54 public void startDocument() throws SAXException { 55 } 56 57 void setComplete() { 58 } 59 60 public void endDocument() throws SAXException { 61 for (Enumeration e = table.keys(); e.hasMoreElements();) { 62 String token = (String )e.nextElement(); 63 Entry entry = (Entry)table.get(token); 64 if (!entry.hadId) { 65 for (Enumeration f = entry.idrefLocs.elements(); f.hasMoreElements();) 66 error("missing_id", token, (Locator )f.nextElement()); 67 } 68 } 69 setComplete(); 70 } 71 72 public void startPrefixMapping(String s, String s1) throws SAXException { 73 } 74 75 public void endPrefixMapping(String s) throws SAXException { 76 } 77 78 public void startElement(String namespaceUri, String localName, String qName, Attributes attributes) 79 throws SAXException { 80 Name elementName = new Name(namespaceUri, localName); 81 int len = attributes.getLength(); 82 for (int i = 0; i < len; i++) { 83 Name attributeName = new Name(attributes.getURI(i), attributes.getLocalName(i)); 84 int idType = idTypeMap.getIdType(elementName, attributeName); 85 if (idType != Datatype.ID_TYPE_NULL) { 86 String [] tokens = StringSplitter.split(attributes.getValue(i)); 87 switch (idType) { 88 case Datatype.ID_TYPE_ID: 89 if (tokens.length == 1) 90 id(tokens[0]); 91 else if (tokens.length == 0) 92 error("id_no_tokens"); 93 else 94 error("id_multiple_tokens"); 95 break; 96 case Datatype.ID_TYPE_IDREF: 97 if (tokens.length == 1) 98 idref(tokens[0]); 99 else if (tokens.length == 0) 100 error("idref_no_tokens"); 101 else 102 error("idref_multiple_tokens"); 103 break; 104 case Datatype.ID_TYPE_IDREFS: 105 if (tokens.length > 0) { 106 for (int j = 0; j < tokens.length; j++) 107 idref(tokens[j]); 108 } 109 else 110 error("idrefs_no_tokens"); 111 break; 112 } 113 } 114 } 115 } 116 117 private void id(String token) throws SAXException { 118 Entry entry = (Entry)table.get(token); 119 if (entry == null) { 120 entry = new Entry(); 121 table.put(token, entry); 122 } 123 else if (entry.hadId) { 124 error("duplicate_id", token); 125 error("first_id", token, entry.idLoc); 126 return; 127 } 128 entry.idLoc = new LocatorImpl (locator); 129 entry.hadId = true; 130 } 131 132 private void idref(String token) { 133 Entry entry = (Entry)table.get(token); 134 if (entry == null) { 135 entry = new Entry(); 136 table.put(token, entry); 137 } 138 if (entry.hadId) 139 return; 140 if (entry.idrefLocs == null) 141 entry.idrefLocs = new Vector (); 142 entry.idrefLocs.addElement(new LocatorImpl (locator)); 143 } 144 145 public void endElement(String s, String s1, String s2) throws SAXException { 146 } 147 148 public void characters(char[] chars, int i, int i1) throws SAXException { 149 } 150 151 public void ignorableWhitespace(char[] chars, int i, int i1) throws SAXException { 152 } 153 154 public void processingInstruction(String s, String s1) throws SAXException { 155 } 156 157 public void skippedEntity(String s) throws SAXException { 158 } 159 160 public void notationDecl(String name, 161 String publicId, 162 String systemId) 163 throws SAXException { 164 } 165 166 public void unparsedEntityDecl(String name, 167 String publicId, 168 String systemId, 169 String notationName) 170 throws SAXException { 171 } 172 173 private void error(String key) throws SAXException { 174 eh.error(new SAXParseException (SchemaBuilderImpl.localizer.message(key), locator)); 175 } 176 177 private void error(String key, String arg) throws SAXException { 178 eh.error(new SAXParseException (SchemaBuilderImpl.localizer.message(key, arg), locator)); 179 } 180 181 private void error(String key, String arg, Locator loc) throws SAXException { 182 eh.error(new SAXParseException (SchemaBuilderImpl.localizer.message(key, arg), 183 loc)); 184 } 185 } 186 | Popular Tags |