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.math.BigDecimal;
027    import java.net.URI;
028    import java.util.HashMap;
029    import java.util.Map;
030    import net.jcip.annotations.Immutable;
031    import org.jboss.dna.common.text.TextDecoder;
032    import org.jboss.dna.common.text.TextEncoder;
033    import org.jboss.dna.common.util.CheckArg;
034    import org.jboss.dna.graph.property.BinaryFactory;
035    import org.jboss.dna.graph.property.DateTimeFactory;
036    import org.jboss.dna.graph.property.NameFactory;
037    import org.jboss.dna.graph.property.NamespaceRegistry;
038    import org.jboss.dna.graph.property.PathFactory;
039    import org.jboss.dna.graph.property.PropertyType;
040    import org.jboss.dna.graph.property.Reference;
041    import org.jboss.dna.graph.property.UuidFactory;
042    import org.jboss.dna.graph.property.ValueFactory;
043    
044    /**
045     * The standard set of {@link ValueFactory value factories}.
046     * 
047     * @author Randall Hauch
048     */
049    @Immutable
050    public class StandardValueFactories extends AbstractValueFactories {
051    
052        // This class is implemented with separate members for each factory so that the typical usage is optimized.
053        private final ValueFactory<String> stringFactory;
054        private final BinaryFactory binaryFactory;
055        private final ValueFactory<Boolean> booleanFactory;
056        private final DateTimeFactory dateFactory;
057        private final ValueFactory<BigDecimal> decimalFactory;
058        private final ValueFactory<Double> doubleFactory;
059        private final ValueFactory<Long> longFactory;
060        private final NameFactory nameFactory;
061        private final PathFactory pathFactory;
062        private final ValueFactory<Reference> referenceFactory;
063        private final ValueFactory<URI> uriFactory;
064        private final UuidFactory uuidFactory;
065        private final ValueFactory<Object> objectFactory;
066    
067        private final NamespaceRegistry namespaceRegistry;
068        private final TextDecoder decoder;
069        private final TextEncoder encoder;
070    
071        /**
072         * Create a standard set of value factories, using the {@link ValueFactory#DEFAULT_DECODER default decoder}.
073         * 
074         * @param namespaceRegistry the namespace registry
075         * @throws IllegalArgumentException if the namespace registry is null
076         */
077        public StandardValueFactories( NamespaceRegistry namespaceRegistry ) {
078            this(namespaceRegistry, null, null);
079        }
080    
081        /**
082         * Create a standard set of value factories, using the supplied encoder/decoder.
083         * 
084         * @param namespaceRegistry the namespace registry
085         * @param decoder the decoder that should be used; if null, the {@link ValueFactory#DEFAULT_DECODER default decoder} is used.
086         * @param encoder the encoder that should be used; if null, the {@link ValueFactory#DEFAULT_ENCODER default encoder} is used.
087         * @param extraFactories any extra factories that should be used; any factory will override the standard factories based upon
088         *        the {@link ValueFactory#getPropertyType() factory's property type}.
089         * @throws IllegalArgumentException if the namespace registry is null
090         */
091        public StandardValueFactories( NamespaceRegistry namespaceRegistry,
092                                       TextDecoder decoder,
093                                       TextEncoder encoder,
094                                       ValueFactory<?>... extraFactories ) {
095            CheckArg.isNotNull(namespaceRegistry, "namespaceRegistry");
096            this.namespaceRegistry = namespaceRegistry;
097            this.decoder = decoder != null ? decoder : ValueFactory.DEFAULT_DECODER;
098            this.encoder = encoder != null ? encoder : ValueFactory.DEFAULT_ENCODER;
099            Map<PropertyType, ValueFactory<?>> factories = new HashMap<PropertyType, ValueFactory<?>>();
100    
101            // Put the extra factories into the map first ...
102            for (ValueFactory<?> factory : extraFactories) {
103                if (factory == null) continue;
104                factories.put(factory.getPropertyType(), factory);
105            }
106    
107            // Now assign the members, using the factories in the map or (if null) the supplied default ...
108            this.stringFactory = getFactory(factories, new StringValueFactory(this.namespaceRegistry, this.decoder, this.encoder));
109    
110            // The binary factory should NOT use the string factory that converts namespaces to prefixes ...
111            StringValueFactory stringFactoryWithoutNamespaces = new StringValueFactory(this.decoder, this.encoder);
112            this.binaryFactory = (BinaryFactory)getFactory(factories, new InMemoryBinaryValueFactory(this.decoder,
113                                                                                                     stringFactoryWithoutNamespaces));
114            this.booleanFactory = getFactory(factories, new BooleanValueFactory(this.decoder, this.stringFactory));
115            this.dateFactory = (DateTimeFactory)getFactory(factories, new JodaDateTimeValueFactory(this.decoder, this.stringFactory));
116            this.decimalFactory = getFactory(factories, new DecimalValueFactory(this.decoder, this.stringFactory));
117            this.doubleFactory = getFactory(factories, new DoubleValueFactory(this.decoder, this.stringFactory));
118            this.longFactory = getFactory(factories, new LongValueFactory(this.decoder, this.stringFactory));
119            this.nameFactory = (NameFactory)getFactory(factories, new NameValueFactory(this.namespaceRegistry, this.decoder,
120                                                                                       this.stringFactory));
121            this.pathFactory = (PathFactory)getFactory(factories, new PathValueFactory(this.decoder, this.stringFactory,
122                                                                                       this.nameFactory));
123            this.referenceFactory = getFactory(factories, new UuidReferenceValueFactory(this.decoder, this.stringFactory));
124            this.uuidFactory = (UuidFactory)getFactory(factories, new UuidValueFactory(this.decoder, this.stringFactory));
125            this.uriFactory = getFactory(factories, new UriValueFactory(this.namespaceRegistry, this.decoder, this.stringFactory));
126            this.objectFactory = getFactory(factories, new ObjectValueFactory(this.decoder, this.stringFactory, this.binaryFactory));
127        }
128    
129        @SuppressWarnings( "unchecked" )
130        private static <T> ValueFactory<T> getFactory( Map<PropertyType, ValueFactory<?>> factories,
131                                                       ValueFactory<T> defaultFactory ) {
132            PropertyType type = defaultFactory.getPropertyType();
133            ValueFactory<?> factory = factories.get(type);
134            if (factory == null) {
135                factory = defaultFactory;
136                factories.put(type, factory);
137            }
138            return (ValueFactory<T>)factory;
139        }
140    
141        /**
142         * @return decoder
143         */
144        public TextDecoder getTextDecoder() {
145            return this.decoder;
146        }
147    
148        /**
149         * @return namespaceRegistry
150         */
151        public NamespaceRegistry getNamespaceRegistry() {
152            return this.namespaceRegistry;
153        }
154    
155        /**
156         * {@inheritDoc}
157         */
158        public BinaryFactory getBinaryFactory() {
159            return this.binaryFactory;
160        }
161    
162        /**
163         * {@inheritDoc}
164         */
165        public ValueFactory<Boolean> getBooleanFactory() {
166            return this.booleanFactory;
167        }
168    
169        /**
170         * {@inheritDoc}
171         */
172        public DateTimeFactory getDateFactory() {
173            return this.dateFactory;
174        }
175    
176        /**
177         * {@inheritDoc}
178         */
179        public ValueFactory<BigDecimal> getDecimalFactory() {
180            return this.decimalFactory;
181        }
182    
183        /**
184         * {@inheritDoc}
185         */
186        public ValueFactory<Double> getDoubleFactory() {
187            return this.doubleFactory;
188        }
189    
190        /**
191         * {@inheritDoc}
192         */
193        public ValueFactory<Long> getLongFactory() {
194            return this.longFactory;
195        }
196    
197        /**
198         * {@inheritDoc}
199         */
200        public NameFactory getNameFactory() {
201            return this.nameFactory;
202        }
203    
204        /**
205         * {@inheritDoc}
206         */
207        public PathFactory getPathFactory() {
208            return this.pathFactory;
209        }
210    
211        /**
212         * {@inheritDoc}
213         */
214        public ValueFactory<Reference> getReferenceFactory() {
215            return this.referenceFactory;
216        }
217    
218        /**
219         * {@inheritDoc}
220         */
221        public ValueFactory<String> getStringFactory() {
222            return this.stringFactory;
223        }
224    
225        /**
226         * {@inheritDoc}
227         */
228        public ValueFactory<URI> getUriFactory() {
229            return this.uriFactory;
230        }
231    
232        /**
233         * {@inheritDoc}
234         * 
235         * @see org.jboss.dna.graph.property.ValueFactories#getUuidFactory()
236         */
237        public UuidFactory getUuidFactory() {
238            return this.uuidFactory;
239        }
240    
241        /**
242         * {@inheritDoc}
243         */
244        public ValueFactory<Object> getObjectFactory() {
245            return this.objectFactory;
246        }
247    
248    }