001: /*
002: * Java HTML Tidy - JTidy
003: * HTML parser and pretty printer
004: *
005: * Copyright (c) 1998-2000 World Wide Web Consortium (Massachusetts
006: * Institute of Technology, Institut National de Recherche en
007: * Informatique et en Automatique, Keio University). All Rights
008: * Reserved.
009: *
010: * Contributing Author(s):
011: *
012: * Dave Raggett <dsr@w3.org>
013: * Andy Quick <ac.quick@sympatico.ca> (translation to Java)
014: * Gary L Peskin <garyp@firstech.com> (Java development)
015: * Sami Lempinen <sami@lempinen.net> (release management)
016: * Fabrizio Giustina <fgiust at users.sourceforge.net>
017: *
018: * The contributing author(s) would like to thank all those who
019: * helped with testing, bug fixes, and patience. This wouldn't
020: * have been possible without all of you.
021: *
022: * COPYRIGHT NOTICE:
023: *
024: * This software and documentation is provided "as is," and
025: * the copyright holders and contributing author(s) make no
026: * representations or warranties, express or implied, including
027: * but not limited to, warranties of merchantability or fitness
028: * for any particular purpose or that the use of the software or
029: * documentation will not infringe any third party patents,
030: * copyrights, trademarks or other rights.
031: *
032: * The copyright holders and contributing author(s) will not be
033: * liable for any direct, indirect, special or consequential damages
034: * arising out of any use of the software or documentation, even if
035: * advised of the possibility of such damage.
036: *
037: * Permission is hereby granted to use, copy, modify, and distribute
038: * this source code, or portions hereof, documentation and executables,
039: * for any purpose, without fee, subject to the following restrictions:
040: *
041: * 1. The origin of this source code must not be misrepresented.
042: * 2. Altered versions must be plainly marked as such and must
043: * not be misrepresented as being the original source.
044: * 3. This Copyright notice may not be removed or altered from any
045: * source or altered source distribution.
046: *
047: * The copyright holders and contributing author(s) specifically
048: * permit, without fee, and encourage the use of this source code
049: * as a component for supporting the Hypertext Markup Language in
050: * commercial products. If you use this source code in a product,
051: * acknowledgment is not required but would be appreciated.
052: *
053: */
054: package org.w3c.tidy;
055:
056: import org.w3c.dom.Attr;
057:
058: /**
059: * Attribute/Value linked list node.
060: * @author Dave Raggett <a href="mailto:dsr@w3.org">dsr@w3.org </a>
061: * @author Andy Quick <a href="mailto:ac.quick@sympatico.ca">ac.quick@sympatico.ca </a> (translation to Java)
062: * @author Fabrizio Giustina
063: * @version $Revision: 1.25 $ ($Author: fgiust $)
064: */
065: public class AttVal extends Object implements Cloneable {
066:
067: /**
068: * next AttVal.
069: */
070: protected AttVal next;
071:
072: /**
073: * Attribute definition.
074: */
075: protected Attribute dict;
076:
077: /**
078: * Asp node.
079: */
080: protected Node asp;
081:
082: /**
083: * Php node.
084: */
085: protected Node php;
086:
087: /**
088: * Delimiter (" or ').
089: */
090: protected int delim;
091:
092: /**
093: * Attribute name.
094: */
095: protected String attribute;
096:
097: /**
098: * Attribute value.
099: */
100: protected String value;
101:
102: /**
103: * DOM adapter.
104: */
105: protected Attr adapter;
106:
107: /**
108: * Instantiates a new empty AttVal.
109: */
110: public AttVal() {
111: super ();
112: }
113:
114: /**
115: * Instantiates a new AttVal.
116: * @param next next linked AttVal
117: * @param dict Attribute from dictionary
118: * @param delim delimitator for attribute value
119: * @param attribute attribute name
120: * @param value attribute value
121: */
122: public AttVal(AttVal next, Attribute dict, int delim,
123: String attribute, String value) {
124: this .next = next;
125: this .dict = dict;
126: this .delim = delim;
127: this .attribute = attribute;
128: this .value = value;
129: }
130:
131: /**
132: * Instantiates a new AttVal.
133: * @param next next linked AttVal
134: * @param dict Attribute from dictionary
135: * @param asp contained asp node
136: * @param php contained php node
137: * @param delim delimitator for attribute value
138: * @param attribute attribute name
139: * @param value attribute value
140: */
141: public AttVal(AttVal next, Attribute dict, Node asp, Node php,
142: int delim, String attribute, String value) {
143: this .next = next;
144: this .dict = dict;
145: this .asp = asp;
146: this .php = php;
147: this .delim = delim;
148: this .attribute = attribute;
149: this .value = value;
150: }
151:
152: /**
153: * @see java.lang.Object#clone()
154: */
155: protected Object clone() {
156: AttVal av = null;
157: try {
158: av = (AttVal) super .clone();
159: } catch (CloneNotSupportedException e) {
160: // should never happen
161: }
162:
163: if (this .next != null) {
164: av.next = (AttVal) this .next.clone();
165: }
166: if (this .asp != null) {
167: av.asp = (Node) this .asp.clone();
168: }
169: if (this .php != null) {
170: av.php = (Node) this .php.clone();
171: }
172:
173: return av;
174: }
175:
176: /**
177: * Is this a boolean attribute.
178: * @return <code>true</code> if this is a boolean attribute
179: */
180: public boolean isBoolAttribute() {
181: Attribute attr = this .dict;
182: if (attr != null) {
183: if (attr.getAttrchk() == AttrCheckImpl.BOOL) {
184: return true;
185: }
186: }
187:
188: return false;
189: }
190:
191: /**
192: * Check the attribute value for uppercase letters (only if the value should be lowercase, required for literal
193: * values in xhtml).
194: * @param lexer Lexer
195: * @param node Node which contains this attribute
196: */
197: void checkLowerCaseAttrValue(Lexer lexer, Node node) {
198: if (this .value == null) {
199: return;
200: }
201:
202: String lowercase = this .value.toLowerCase();
203:
204: if (!this .value.equals(lowercase)) {
205: if (lexer.isvoyager) {
206: lexer.report.attrError(lexer, node, this ,
207: Report.ATTR_VALUE_NOT_LCASE);
208: }
209:
210: if (lexer.isvoyager || lexer.configuration.lowerLiterals) {
211: this .value = lowercase;
212: }
213: }
214: }
215:
216: /**
217: * Check attribute name/value and report errors.
218: * @param lexer Lexer
219: * @param node node which contains this attribute
220: * @return Attribute
221: */
222: public Attribute checkAttribute(Lexer lexer, Node node) {
223: TagTable tt = lexer.configuration.tt;
224:
225: Attribute attr = this .dict;
226:
227: // ignore unknown attributes for proprietary elements
228: if (attr != null) {
229:
230: // if attribute looks like <foo/> check XML is ok
231: if (TidyUtils.toBoolean(attr.getVersions() & Dict.VERS_XML)) {
232: if (!(lexer.configuration.xmlTags || lexer.configuration.xmlOut)) {
233: lexer.report.attrError(lexer, node, this ,
234: Report.XML_ATTRIBUTE_VALUE);
235: }
236: }
237: // title first appeared in HTML 4.0 except for a/link
238: else if (attr != AttributeTable.attrTitle
239: || !(node.tag == tt.tagA || node.tag == tt.tagLink)) {
240: lexer.constrainVersion(attr.getVersions());
241: }
242:
243: if (attr.getAttrchk() != null) {
244: attr.getAttrchk().check(lexer, node, this );
245: } else if (TidyUtils.toBoolean(this .dict.getVersions()
246: & Dict.VERS_PROPRIETARY)) {
247: lexer.report.attrError(lexer, node, this ,
248: Report.PROPRIETARY_ATTRIBUTE);
249: }
250:
251: } else if (!lexer.configuration.xmlTags
252: && !(node.tag == null)
253: && this .asp == null
254: && !(node.tag != null && (TidyUtils
255: .toBoolean(node.tag.versions
256: & Dict.VERS_PROPRIETARY)))) {
257: lexer.report.attrError(lexer, node, this ,
258: Report.UNKNOWN_ATTRIBUTE);
259: }
260:
261: return attr;
262: }
263:
264: /**
265: * Return the org.w3c.dom.Attr adapter.
266: * @return org.w3c.dom.Attr adapter
267: */
268: protected org.w3c.dom.Attr getAdapter() {
269: if (this .adapter == null) {
270: this .adapter = new DOMAttrImpl(this );
271: }
272: return this .adapter;
273: }
274:
275: /**
276: * Getter for <code>asp</code>.
277: * @return Returns the asp.
278: */
279: public Node getAsp() {
280: return this .asp;
281: }
282:
283: /**
284: * Setter for <code>asp</code>.
285: * @param asp The asp to set.
286: */
287: public void setAsp(Node asp) {
288: this .asp = asp;
289: }
290:
291: /**
292: * Getter for <code>attribute</code>.
293: * @return Returns the attribute.
294: */
295: public String getAttribute() {
296: return this .attribute;
297: }
298:
299: /**
300: * Setter for <code>attribute</code>.
301: * @param attribute The attribute to set.
302: */
303: public void setAttribute(String attribute) {
304: this .attribute = attribute;
305: }
306:
307: /**
308: * Getter for <code>delim</code>.
309: * @return Returns the delim.
310: */
311: public int getDelim() {
312: return this .delim;
313: }
314:
315: /**
316: * Setter for <code>delim</code>.
317: * @param delim The delim to set.
318: */
319: public void setDelim(int delim) {
320: this .delim = delim;
321: }
322:
323: /**
324: * Getter for <code>dict</code>.
325: * @return Returns the dict.
326: */
327: public Attribute getDict() {
328: return this .dict;
329: }
330:
331: /**
332: * Setter for <code>dict</code>.
333: * @param dict The dict to set.
334: */
335: public void setDict(Attribute dict) {
336: this .dict = dict;
337: }
338:
339: /**
340: * Getter for <code>next</code>.
341: * @return Returns the next.
342: */
343: public AttVal getNext() {
344: return this .next;
345: }
346:
347: /**
348: * Setter for <code>next</code>.
349: * @param next The next to set.
350: */
351: public void setNext(AttVal next) {
352: this .next = next;
353: }
354:
355: /**
356: * Getter for <code>php</code>.
357: * @return Returns the php.
358: */
359: public Node getPhp() {
360: return this .php;
361: }
362:
363: /**
364: * Setter for <code>php</code>.
365: * @param php The php to set.
366: */
367: public void setPhp(Node php) {
368: this .php = php;
369: }
370:
371: /**
372: * Getter for <code>value</code>.
373: * @return Returns the value.
374: */
375: public String getValue() {
376: return this .value;
377: }
378:
379: /**
380: * Setter for <code>value</code>.
381: * @param value The value to set.
382: */
383: public void setValue(String value) {
384: this.value = value;
385: }
386:
387: }
|