001 /*
002 * Copyright (c) 2007 Mozilla Foundation
003 *
004 * Permission is hereby granted, free of charge, to any person obtaining a
005 * copy of this software and associated documentation files (the "Software"),
006 * to deal in the Software without restriction, including without limitation
007 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
008 * and/or sell copies of the Software, and to permit persons to whom the
009 * Software is furnished to do so, subject to the following conditions:
010 *
011 * The above copyright notice and this permission notice shall be included in
012 * all copies or substantial portions of the Software.
013 *
014 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
015 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
016 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
017 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
018 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
019 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
020 * DEALINGS IN THE SOFTWARE.
021 */
022
023 package org.whattf.checker;
024
025 import java.util.HashMap;
026 import java.util.HashSet;
027 import java.util.LinkedHashMap;
028 import java.util.Map;
029 import java.util.Set;
030
031 import org.xml.sax.Attributes;
032 import org.xml.sax.Locator;
033 import org.xml.sax.SAXException;
034
035 public class UsemapChecker extends Checker {
036
037 private final Map<String, Locator> usemapLocationsById = new LinkedHashMap<String, Locator>();
038
039 private final Set<String> mapIds = new HashSet<String>();
040
041 private Locator locator = null;
042
043 public UsemapChecker() {
044 }
045
046 /**
047 * @see org.whattf.checker.Checker#startElement(java.lang.String, java.lang.String, java.lang.String, org.xml.sax.Attributes)
048 */
049 @Override
050 public void startElement(String uri, String localName, String qName, Attributes atts) throws SAXException {
051 if ("http://www.w3.org/1999/xhtml" == uri) {
052 if ("map" == localName) {
053 String id = atts.getValue("", "id");
054 if (id != null && !"".equals(id)) {
055 mapIds.add(id);
056 }
057 String name = atts.getValue("", "id");
058 if (name != null && !"".equals(name)) {
059 mapIds.add(name);
060 }
061 } else if ("img" == localName || "object" == localName) {
062 String usemap = atts.getValue("", "usemap");
063 if (usemap != null) {
064 int hashIndex = usemap.indexOf('#');
065 if (hashIndex > -1) {
066 // XXX not complaining about bad values here as
067 // the schema takes care of that.
068 if (hashIndex < usemap.length() - 1) {
069 String ref = usemap.substring(hashIndex + 1);
070 usemapLocationsById.put(ref, new LocatorImpl(locator));
071 }
072 }
073 }
074 }
075 }
076 }
077
078 /**
079 * @see org.xml.sax.helpers.XMLFilterImpl#endDocument()
080 */
081 @Override
082 public void endDocument() throws SAXException {
083 for (Map.Entry<String, Locator> entry : usemapLocationsById.entrySet()) {
084 if (!mapIds.contains(entry.getKey())) {
085 err("The hashed ID reference in attribute \u201Cusemap\u201D referred to \u201C" + entry.getKey() + "\u201D, but there is no \u201Cmap\u201D element with that \u201Cid\u201D or \u201Cname\u201D.", entry.getValue());
086 }
087 }
088 usemapLocationsById.clear();
089 mapIds.clear();
090 }
091
092 /**
093 * @see org.xml.sax.helpers.XMLFilterImpl#startDocument()
094 */
095 @Override
096 public void startDocument() throws SAXException {
097 usemapLocationsById.clear();
098 mapIds.clear();
099 }
100
101 /**
102 * @see org.xml.sax.helpers.XMLFilterImpl#setDocumentLocator(org.xml.sax.Locator)
103 */
104 @Override
105 public void setDocumentLocator(Locator locator) {
106 this.locator = locator;
107 }
108
109
110 }