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