001: /*
002: * xtc - The eXTensible Compiler
003: * Copyright (C) 2004-2007 Robert Grimm
004: *
005: * This program is free software; you can redistribute it and/or
006: * modify it under the terms of the GNU General Public License
007: * version 2 as published by the Free Software Foundation.
008: *
009: * This program is distributed in the hope that it will be useful,
010: * but WITHOUT ANY WARRANTY; without even the implied warranty of
011: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
012: * GNU General Public License for more details.
013: *
014: * You should have received a copy of the GNU General Public License
015: * along with this program; if not, write to the Free Software
016: * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
017: * USA.
018: */
019: package xtc.tree;
020:
021: import java.io.IOException;
022:
023: import java.util.List;
024:
025: import xtc.util.Pair;
026:
027: /**
028: * A name/value pair.
029: *
030: * @author Robert Grimm
031: * @version $Revision: 1.12 $
032: */
033: public class Attribute extends Node {
034:
035: /** The name. */
036: final String name;
037:
038: /** The value. */
039: final Object value;
040:
041: /**
042: * Create a new attribute with the specified name. The new
043: * attribute's value is <code>null</code>.
044: *
045: * @param name The name.
046: */
047: public Attribute(String name) {
048: this (name, null);
049: }
050:
051: /**
052: * Create a new attribute with the specified name and value.
053: *
054: * @param name The name.
055: * @param value The value.
056: */
057: public Attribute(String name, Object value) {
058: this .name = name;
059: this .value = value;
060: }
061:
062: public boolean hasTraversal() {
063: return true;
064: }
065:
066: public int size() {
067: return null == value ? 1 : 2;
068: }
069:
070: public Object get(int index) {
071: if (0 == index)
072: return name;
073: if ((null != value) && (1 == index))
074: return value;
075: throw new IndexOutOfBoundsException("Index : " + index
076: + ", Size: " + (null == value ? 1 : 2));
077: }
078:
079: public Object set(int index, Object value) {
080: throw new IllegalStateException("Attributes are immutable");
081: }
082:
083: /**
084: * Get the name.
085: *
086: * @return The name.
087: */
088: public String getName() {
089: return name;
090: }
091:
092: /**
093: * Get the value.
094: *
095: * @return The value.
096: */
097: public Object getValue() {
098: return value;
099: }
100:
101: public int hashCode() {
102: return name.hashCode();
103: }
104:
105: public boolean equals(Object o) {
106: if (this == o)
107: return true;
108: if (!(o instanceof Attribute))
109: return false;
110: Attribute other = (Attribute) o;
111: if (!name.equals(other.name))
112: return false;
113: if (null == value)
114: return (null == other.value);
115: return value.equals(other.value);
116: }
117:
118: public void write(Appendable out) throws IOException {
119: out.append(name);
120: if (null != value) {
121: out.append('(');
122: if ((value instanceof List) || (value instanceof Pair)) {
123: boolean first = true;
124: for (Object o : (Iterable<?>) value) {
125: if (first) {
126: first = false;
127: } else {
128: out.append(", ");
129: }
130:
131: if (o instanceof Node) {
132: ((Node) o).write(out);
133: } else {
134: out.append(o.toString());
135: }
136: }
137: } else if (value instanceof Node) {
138: ((Node) value).write(out);
139: } else {
140: out.append(value.toString());
141: }
142: out.append(')');
143: }
144: }
145:
146: /**
147: * Get the attribute with the specified name from the specified list.
148: *
149: * @param name The name.
150: * @param list The list.
151: * @return The corresponding attribute or <code>null</code> if the
152: * list is <code>null</code> or contains no such attribute.
153: */
154: public static Attribute get(String name, List<Attribute> list) {
155: if (null == list)
156: return null;
157: for (Attribute att : list) {
158: if (name.equals(att.name))
159: return att;
160: }
161: return null;
162: }
163:
164: /**
165: * Determine whether the specified lists of attributes are equivalent.
166: *
167: * @param l1 The first list.
168: * @param l2 The second list.
169: * @return <code>true</code> if the two lists are equivalent, that is,
170: * contain the same attributes in some order.
171: */
172: public static boolean areEquivalent(List<Attribute> l1,
173: List<Attribute> l2) {
174: if (null == l1) {
175: return (null == l2) || (0 == l2.size());
176: } else if (null == l2) {
177: return (0 == l1.size());
178: } else {
179: return l1.containsAll(l2) && l2.containsAll(l1);
180: }
181: }
182:
183: }
|