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 }