001    /*
002     * JBoss DNA (http://www.jboss.org/dna)
003     * See the COPYRIGHT.txt file distributed with this work for information
004     * regarding copyright ownership.  Some portions may be licensed
005     * to Red Hat, Inc. under one or more contributor license agreements.
006     * See the AUTHORS.txt file in the distribution for a full listing of 
007     * individual contributors. 
008     *
009     * JBoss DNA is free software. Unless otherwise indicated, all code in JBoss DNA
010     * is licensed to you under the terms of the GNU Lesser General Public License as
011     * published by the Free Software Foundation; either version 2.1 of
012     * the License, or (at your option) any later version.
013     *
014     * JBoss DNA is distributed in the hope that it will be useful,
015     * but WITHOUT ANY WARRANTY; without even the implied warranty of
016     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
017     * Lesser General Public License for more details.
018     *
019     * You should have received a copy of the GNU Lesser General Public
020     * License along with this software; if not, write to the Free
021     * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
022     * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
023     */
024    package org.jboss.dna.graph.property.basic;
025    
026    import java.util.Arrays;
027    import java.util.Iterator;
028    import net.jcip.annotations.Immutable;
029    import org.jboss.dna.common.text.TextEncoder;
030    import org.jboss.dna.common.util.CheckArg;
031    import org.jboss.dna.graph.property.Name;
032    import org.jboss.dna.graph.property.NamespaceRegistry;
033    import org.jboss.dna.graph.property.Path;
034    import org.jboss.dna.graph.property.Property;
035    import org.jboss.dna.graph.property.ValueComparators;
036    
037    /**
038     * @author Randall Hauch
039     */
040    @Immutable
041    public abstract class BasicProperty implements Property {
042    
043        private final Name name;
044    
045        /**
046         * @param name
047         */
048        public BasicProperty( Name name ) {
049            this.name = name;
050        }
051    
052        /**
053         * {@inheritDoc}
054         */
055        public Name getName() {
056            return name;
057        }
058    
059        /**
060         * {@inheritDoc}
061         */
062        public Iterator<?> getValues() {
063            return iterator();
064        }
065    
066        /**
067         * {@inheritDoc}
068         */
069        public Object[] getValuesAsArray() {
070            if (size() == 0) return null;
071            Object[] results = new Object[size()];
072            Iterator<?> iter = iterator();
073            int index = 0;
074            while (iter.hasNext()) {
075                Object value = iter.next();
076                results[index++] = value;
077            }
078            return results;
079        }
080    
081        /**
082         * {@inheritDoc}
083         */
084        public int compareTo( Property that ) {
085            if (this == that) return 0;
086            int diff = this.getName().compareTo(that.getName());
087            if (diff != 0) return diff;
088            diff = this.size() - that.size();
089            if (diff != 0) return diff;
090            Iterator<?> thisIter = iterator();
091            Iterator<?> thatIter = that.iterator();
092            while (thisIter.hasNext()) { // && thatIter.hasNext()
093                Object thisValue = thisIter.next();
094                Object thatValue = thatIter.next();
095                diff = ValueComparators.OBJECT_COMPARATOR.compare(thisValue, thatValue);
096                if (diff != 0) return diff;
097            }
098            return 0;
099        }
100    
101        /**
102         * {@inheritDoc}
103         */
104        @Override
105        public int hashCode() {
106            return name.hashCode();
107        }
108    
109        /**
110         * {@inheritDoc}
111         */
112        @Override
113        public boolean equals( Object obj ) {
114            if (this == obj) return true;
115            if (obj instanceof Property) {
116                Property that = (Property)obj;
117                if (!this.getName().equals(that.getName())) return false;
118                if (this.size() != that.size()) return false;
119                Iterator<?> thisIter = iterator();
120                Iterator<?> thatIter = that.iterator();
121                while (thisIter.hasNext()) { // && thatIter.hasNext()
122                    Object thisValue = thisIter.next();
123                    Object thatValue = thatIter.next();
124                    if (ValueComparators.OBJECT_COMPARATOR.compare(thisValue, thatValue) != 0) return false;
125                }
126                return true;
127            }
128            return false;
129        }
130    
131        /**
132         * {@inheritDoc}
133         */
134        public String getString() {
135            return getString(null, null, null);
136        }
137    
138        /**
139         * {@inheritDoc}
140         */
141        public String getString( TextEncoder encoder ) {
142            return getString(null, encoder, null);
143        }
144    
145        /**
146         * {@inheritDoc}
147         */
148        public String getString( NamespaceRegistry namespaceRegistry ) {
149            return getString(namespaceRegistry, null, null);
150        }
151    
152        /**
153         * {@inheritDoc}
154         */
155        public String getString( NamespaceRegistry namespaceRegistry,
156                                 TextEncoder encoder ) {
157            CheckArg.isNotNull(namespaceRegistry, "namespaceRegistry");
158            return getString(namespaceRegistry, encoder, null);
159        }
160    
161        /**
162         * {@inheritDoc}
163         * 
164         * @see org.jboss.dna.graph.property.Path#getString(org.jboss.dna.graph.property.NamespaceRegistry,
165         *      org.jboss.dna.common.text.TextEncoder, org.jboss.dna.common.text.TextEncoder)
166         */
167        public String getString( NamespaceRegistry namespaceRegistry,
168                                 TextEncoder encoder,
169                                 TextEncoder delimiterEncoder ) {
170            StringBuilder sb = new StringBuilder();
171            sb.append(getName().getString(namespaceRegistry, encoder, delimiterEncoder));
172            sb.append(" = ");
173            if (isEmpty()) {
174                sb.append("null");
175            } else {
176                if (isMultiple()) sb.append("[");
177                boolean first = true;
178                for (Object value : this) {
179                    if (first) first = false;
180                    else sb.append(",");
181                    if (value instanceof Path) {
182                        Path path = (Path)value;
183                        sb.append(path.getString(namespaceRegistry, encoder, delimiterEncoder));
184                    } else if (value instanceof Name) {
185                        Name name = (Name)value;
186                        sb.append(name.getString(namespaceRegistry, encoder, delimiterEncoder));
187                    } else {
188                        sb.append(value);
189                    }
190                }
191                if (isMultiple()) sb.append("]");
192            }
193            return sb.toString();
194        }
195    
196        /**
197         * {@inheritDoc}
198         * 
199         * @see java.lang.Object#toString()
200         */
201        @Override
202        public String toString() {
203            StringBuilder sb = new StringBuilder();
204            sb.append(getName());
205            sb.append(" = ");
206            if (isSingle()) {
207                sb.append(getValues().next());
208            } else if (isEmpty()) {
209                sb.append("null");
210            } else {
211                sb.append(Arrays.asList(getValuesAsArray()));
212            }
213            return sb.toString();
214        }
215    }