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