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.io.InputStream;
027    import java.io.Reader;
028    import java.math.BigDecimal;
029    import java.net.URI;
030    import java.util.Calendar;
031    import java.util.Date;
032    import java.util.Iterator;
033    import java.util.UUID;
034    import net.jcip.annotations.Immutable;
035    import org.jboss.dna.common.text.TextDecoder;
036    import org.jboss.dna.common.util.CheckArg;
037    import org.jboss.dna.graph.property.Binary;
038    import org.jboss.dna.graph.property.DateTime;
039    import org.jboss.dna.graph.property.IoException;
040    import org.jboss.dna.graph.property.Name;
041    import org.jboss.dna.graph.property.Path;
042    import org.jboss.dna.graph.property.PropertyType;
043    import org.jboss.dna.graph.property.Reference;
044    import org.jboss.dna.graph.property.ValueFactory;
045    import org.jboss.dna.graph.property.ValueFormatException;
046    
047    /**
048     * Abstract {@link ValueFactory}.
049     * 
050     * @author Randall Hauch
051     * @author John Verhaeg
052     * @param <T> the property type
053     */
054    @Immutable
055    public abstract class AbstractValueFactory<T> implements ValueFactory<T> {
056    
057        private final TextDecoder decoder;
058        private final PropertyType propertyType;
059        private final ValueFactory<String> stringValueFactory;
060    
061        protected AbstractValueFactory( PropertyType type,
062                                        TextDecoder decoder,
063                                        ValueFactory<String> stringValueFactory ) {
064            CheckArg.isNotNull(type, "type");
065            this.propertyType = type;
066            this.decoder = decoder != null ? decoder : DEFAULT_DECODER;
067            this.stringValueFactory = stringValueFactory;
068        }
069    
070        /**
071         * @return stringValueFactory
072         */
073        protected ValueFactory<String> getStringValueFactory() {
074            return this.stringValueFactory;
075        }
076    
077        /**
078         * Get the text decoder.
079         * 
080         * @return the decoder
081         */
082        public TextDecoder getDecoder() {
083            return this.decoder;
084        }
085    
086        /**
087         * Utility method to obtain either the supplied decoder (if not null) or this factory's {@link #getDecoder() decoder}.
088         * 
089         * @param decoder the decoder, which may be null if this factory's {@link #getDecoder() is to be used}
090         * @return the decoder; never null
091         */
092        protected TextDecoder getDecoder( TextDecoder decoder ) {
093            return decoder != null ? decoder : this.getDecoder();
094        }
095    
096        /**
097         * {@inheritDoc}
098         */
099        public PropertyType getPropertyType() {
100            return propertyType;
101        }
102    
103        /**
104         * {@inheritDoc}
105         */
106        public T create( Object value ) {
107            if (value == null) return null;
108            if (value instanceof String) return create((String)value);
109            if (value instanceof Integer) return create(((Integer)value).intValue());
110            if (value instanceof Long) return create(((Long)value).longValue());
111            if (value instanceof Double) return create(((Double)value).doubleValue());
112            if (value instanceof Float) return create(((Float)value).floatValue());
113            if (value instanceof Boolean) return create(((Boolean)value).booleanValue());
114            if (value instanceof BigDecimal) return create((BigDecimal)value);
115            if (value instanceof DateTime) return create((DateTime)value);
116            if (value instanceof Calendar) return create((Calendar)value);
117            if (value instanceof Date) return create((Date)value);
118            if (value instanceof Name) return create((Name)value);
119            if (value instanceof Path) return create((Path)value);
120            if (value instanceof Reference) return create((Reference)value);
121            if (value instanceof URI) return create((URI)value);
122            if (value instanceof Binary) return create((Binary)value);
123            if (value instanceof byte[]) return create((byte[])value);
124            if (value instanceof InputStream) return create((InputStream)value, 0);
125            if (value instanceof Reader) return create((Reader)value, 0);
126            return create(value.toString());
127        }
128    
129        protected abstract T[] createEmptyArray( int length );
130    
131        /**
132         * {@inheritDoc}
133         */
134        public T[] create( BigDecimal[] values ) {
135            if (values == null) return null;
136            final int length = values.length;
137            T[] result = createEmptyArray(length);
138            for (int i = 0; i != length; ++i) {
139                result[i] = create(values[i]);
140            }
141            return result;
142        }
143    
144        /**
145         * {@inheritDoc}
146         */
147        public T[] create( boolean[] values ) {
148            if (values == null) return null;
149            final int length = values.length;
150            T[] result = createEmptyArray(length);
151            for (int i = 0; i != length; ++i) {
152                result[i] = create(values[i]);
153            }
154            return result;
155        }
156    
157        /**
158         * {@inheritDoc}
159         */
160        public T[] create( byte[][] values ) {
161            if (values == null) return null;
162            final int length = values.length;
163            T[] result = createEmptyArray(length);
164            for (int i = 0; i != length; ++i) {
165                result[i] = create(values[i]);
166            }
167            return result;
168        }
169    
170        /**
171         * {@inheritDoc}
172         */
173        public T[] create( Calendar[] values ) {
174            if (values == null) return null;
175            final int length = values.length;
176            T[] result = createEmptyArray(length);
177            for (int i = 0; i != length; ++i) {
178                result[i] = create(values[i]);
179            }
180            return result;
181        }
182    
183        /**
184         * {@inheritDoc}
185         */
186        public T[] create( Date[] values ) {
187            if (values == null) return null;
188            final int length = values.length;
189            T[] result = createEmptyArray(length);
190            for (int i = 0; i != length; ++i) {
191                result[i] = create(values[i]);
192            }
193            return result;
194        }
195    
196        /**
197         * {@inheritDoc}
198         * 
199         * @see org.jboss.dna.graph.property.ValueFactory#create(org.jboss.dna.graph.property.DateTime[])
200         */
201        public T[] create( DateTime[] values ) throws ValueFormatException {
202            if (values == null) return null;
203            final int length = values.length;
204            T[] result = createEmptyArray(length);
205            for (int i = 0; i != length; ++i) {
206                result[i] = create(values[i]);
207            }
208            return result;
209        }
210    
211        /**
212         * {@inheritDoc}
213         */
214        public T[] create( double[] values ) {
215            if (values == null) return null;
216            final int length = values.length;
217            T[] result = createEmptyArray(length);
218            for (int i = 0; i != length; ++i) {
219                result[i] = create(values[i]);
220            }
221            return result;
222        }
223    
224        /**
225         * {@inheritDoc}
226         */
227        public T[] create( float[] values ) {
228            if (values == null) return null;
229            final int length = values.length;
230            T[] result = createEmptyArray(length);
231            for (int i = 0; i != length; ++i) {
232                result[i] = create(values[i]);
233            }
234            return result;
235        }
236    
237        /**
238         * {@inheritDoc}
239         */
240        public T[] create( int[] values ) {
241            if (values == null) return null;
242            final int length = values.length;
243            T[] result = createEmptyArray(length);
244            for (int i = 0; i != length; ++i) {
245                result[i] = create(values[i]);
246            }
247            return result;
248        }
249    
250        /**
251         * {@inheritDoc}
252         */
253        public T[] create( long[] values ) {
254            if (values == null) return null;
255            final int length = values.length;
256            T[] result = createEmptyArray(length);
257            for (int i = 0; i != length; ++i) {
258                result[i] = create(values[i]);
259            }
260            return result;
261        }
262    
263        /**
264         * {@inheritDoc}
265         */
266        public T[] create( Name[] values ) {
267            if (values == null) return null;
268            final int length = values.length;
269            T[] result = createEmptyArray(length);
270            for (int i = 0; i != length; ++i) {
271                result[i] = create(values[i]);
272            }
273            return result;
274        }
275    
276        /**
277         * {@inheritDoc}
278         */
279        public T[] create( Object[] values ) {
280            if (values == null) return null;
281            final int length = values.length;
282            T[] result = createEmptyArray(length);
283            for (int i = 0; i != length; ++i) {
284                result[i] = create(values[i]);
285            }
286            return result;
287        }
288    
289        /**
290         * {@inheritDoc}
291         */
292        public T[] create( Path[] values ) {
293            if (values == null) return null;
294            final int length = values.length;
295            T[] result = createEmptyArray(length);
296            for (int i = 0; i != length; ++i) {
297                result[i] = create(values[i]);
298            }
299            return result;
300        }
301    
302        /**
303         * {@inheritDoc}
304         */
305        public T[] create( Reference[] values ) {
306            if (values == null) return null;
307            final int length = values.length;
308            T[] result = createEmptyArray(length);
309            for (int i = 0; i != length; ++i) {
310                result[i] = create(values[i]);
311            }
312            return result;
313        }
314    
315        /**
316         * {@inheritDoc}
317         */
318        public T[] create( String[] values,
319                           TextDecoder decoder ) {
320            if (values == null) return null;
321            final int length = values.length;
322            T[] result = createEmptyArray(length);
323            for (int i = 0; i != length; ++i) {
324                result[i] = create(values[i], decoder);
325            }
326            return result;
327        }
328    
329        /**
330         * {@inheritDoc}
331         */
332        public T[] create( String[] values ) {
333            if (values == null) return null;
334            final int length = values.length;
335            T[] result = createEmptyArray(length);
336            for (int i = 0; i != length; ++i) {
337                result[i] = create(values[i]);
338            }
339            return result;
340        }
341    
342        /**
343         * {@inheritDoc}
344         */
345        public T[] create( URI[] values ) {
346            if (values == null) return null;
347            final int length = values.length;
348            T[] result = createEmptyArray(length);
349            for (int i = 0; i != length; ++i) {
350                result[i] = create(values[i]);
351            }
352            return result;
353        }
354    
355        /**
356         * {@inheritDoc}
357         * 
358         * @see org.jboss.dna.graph.property.ValueFactory#create(java.util.UUID[])
359         */
360        public T[] create( UUID[] values ) {
361            if (values == null) return null;
362            final int length = values.length;
363            T[] result = createEmptyArray(length);
364            for (int i = 0; i != length; ++i) {
365                result[i] = create(values[i]);
366            }
367            return result;
368        }
369    
370        /**
371         * {@inheritDoc}
372         * 
373         * @see org.jboss.dna.graph.property.ValueFactory#create(org.jboss.dna.graph.property.Binary[])
374         */
375        public T[] create( Binary[] values ) throws ValueFormatException, IoException {
376            if (values == null) return null;
377            final int length = values.length;
378            T[] result = createEmptyArray(length);
379            for (int i = 0; i != length; ++i) {
380                result[i] = create(values[i]);
381            }
382            return result;
383        }
384    
385        /**
386         * {@inheritDoc}
387         * 
388         * @see org.jboss.dna.graph.property.ValueFactory#create(java.util.Iterator)
389         */
390        public Iterator<T> create( Iterator<?> values ) throws ValueFormatException, IoException {
391            return new ConvertingIterator<T>(values, this);
392        }
393    
394        /**
395         * {@inheritDoc}
396         * 
397         * @see org.jboss.dna.graph.property.ValueFactory#create(java.lang.Iterable)
398         */
399        public Iterable<T> create( final Iterable<?> valueIterable ) throws ValueFormatException, IoException {
400            return new Iterable<T>() {
401    
402                public Iterator<T> iterator() {
403                    return create(valueIterable.iterator());
404                }
405            };
406        }
407    
408        protected static class ConvertingIterator<ValueType> implements Iterator<ValueType> {
409            private final Iterator<?> delegate;
410            private final ValueFactory<ValueType> factory;
411    
412            protected ConvertingIterator( Iterator<?> delegate,
413                                          ValueFactory<ValueType> factory ) {
414                assert delegate != null;
415                assert factory != null;
416                this.delegate = delegate;
417                this.factory = factory;
418            }
419    
420            /**
421             * {@inheritDoc}
422             * 
423             * @see java.util.Iterator#hasNext()
424             */
425            public boolean hasNext() {
426                return this.delegate.hasNext();
427            }
428    
429            /**
430             * {@inheritDoc}
431             * 
432             * @see java.util.Iterator#next()
433             */
434            public ValueType next() {
435                return factory.create(this.delegate.next());
436            }
437    
438            /**
439             * {@inheritDoc}
440             * 
441             * @see java.util.Iterator#remove()
442             */
443            public void remove() {
444                this.delegate.remove();
445            }
446        }
447    
448    }