View Javadoc

1   /*
2    * ModeShape (http://www.modeshape.org)
3    * See the COPYRIGHT.txt file distributed with this work for information
4    * regarding copyright ownership.  Some portions may be licensed
5    * to Red Hat, Inc. under one or more contributor license agreements.
6    * See the AUTHORS.txt file in the distribution for a full listing of 
7    * individual contributors. 
8    *
9    * ModeShape is free software. Unless otherwise indicated, all code in ModeShape
10   * is licensed to you under the terms of the GNU Lesser General Public License as
11   * published by the Free Software Foundation; either version 2.1 of
12   * the License, or (at your option) any later version.
13   *
14   * ModeShape is distributed in the hope that it will be useful,
15   * but WITHOUT ANY WARRANTY; without even the implied warranty of
16   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17   * Lesser General Public License for more details.
18   *
19   * You should have received a copy of the GNU Lesser General Public
20   * License along with this software; if not, write to the Free
21   * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
22   * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
23   */
24  package org.modeshape.graph.property.basic;
25  
26  import java.math.BigDecimal;
27  import java.net.URI;
28  import java.util.HashMap;
29  import java.util.Map;
30  import net.jcip.annotations.Immutable;
31  import org.modeshape.common.text.TextDecoder;
32  import org.modeshape.common.text.TextEncoder;
33  import org.modeshape.common.util.CheckArg;
34  import org.modeshape.graph.property.BinaryFactory;
35  import org.modeshape.graph.property.DateTimeFactory;
36  import org.modeshape.graph.property.NameFactory;
37  import org.modeshape.graph.property.NamespaceRegistry;
38  import org.modeshape.graph.property.PathFactory;
39  import org.modeshape.graph.property.PropertyType;
40  import org.modeshape.graph.property.Reference;
41  import org.modeshape.graph.property.UuidFactory;
42  import org.modeshape.graph.property.ValueFactory;
43  import org.modeshape.graph.property.ValueTypeSystem;
44  import org.modeshape.graph.query.model.TypeSystem;
45  
46  /**
47   * The standard set of {@link ValueFactory value factories}.
48   */
49  @Immutable
50  public class StandardValueFactories extends AbstractValueFactories {
51  
52      // This class is implemented with separate members for each factory so that the typical usage is optimized.
53      private final ValueFactory<String> stringFactory;
54      private final BinaryFactory binaryFactory;
55      private final ValueFactory<Boolean> booleanFactory;
56      private final DateTimeFactory dateFactory;
57      private final ValueFactory<BigDecimal> decimalFactory;
58      private final ValueFactory<Double> doubleFactory;
59      private final ValueFactory<Long> longFactory;
60      private final NameFactory nameFactory;
61      private final PathFactory pathFactory;
62      private final ValueFactory<Reference> referenceFactory;
63      private final ValueFactory<URI> uriFactory;
64      private final UuidFactory uuidFactory;
65      private final ValueFactory<Object> objectFactory;
66  
67      private final NamespaceRegistry namespaceRegistry;
68  
69      private final TypeSystem typeSystem;
70  
71      /**
72       * Create a standard set of value factories, using the {@link ValueFactory#DEFAULT_DECODER default decoder}.
73       * 
74       * @param namespaceRegistry the namespace registry
75       * @throws IllegalArgumentException if the namespace registry is null
76       */
77      public StandardValueFactories( NamespaceRegistry namespaceRegistry ) {
78          this(namespaceRegistry, null, null);
79      }
80  
81      /**
82       * Create a standard set of value factories, using the supplied encoder/decoder.
83       * 
84       * @param namespaceRegistry the namespace registry
85       * @param decoder the decoder that should be used; if null, the {@link ValueFactory#DEFAULT_DECODER default decoder} is used.
86       * @param encoder the encoder that should be used; if null, the {@link ValueFactory#DEFAULT_ENCODER default encoder} is used.
87       * @param extraFactories any extra factories that should be used; any factory will override the standard factories based upon
88       *        the {@link ValueFactory#getPropertyType() factory's property type}.
89       * @throws IllegalArgumentException if the namespace registry is null
90       */
91      public StandardValueFactories( NamespaceRegistry namespaceRegistry,
92                                     TextDecoder decoder,
93                                     TextEncoder encoder,
94                                     ValueFactory<?>... extraFactories ) {
95          CheckArg.isNotNull(namespaceRegistry, "namespaceRegistry");
96          this.namespaceRegistry = namespaceRegistry;
97          decoder = decoder != null ? decoder : ValueFactory.DEFAULT_DECODER;
98          encoder = encoder != null ? encoder : ValueFactory.DEFAULT_ENCODER;
99          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, decoder, encoder));
109 
110         // The binary factory should NOT use the string factory that converts namespaces to prefixes ...
111         StringValueFactory stringFactoryWithoutNamespaces = new StringValueFactory(decoder, encoder);
112         this.binaryFactory = (BinaryFactory)getFactory(factories, new InMemoryBinaryValueFactory(decoder,
113                                                                                                  stringFactoryWithoutNamespaces));
114         this.booleanFactory = getFactory(factories, new BooleanValueFactory(decoder, this.stringFactory));
115         this.dateFactory = (DateTimeFactory)getFactory(factories, new JodaDateTimeValueFactory(decoder, this.stringFactory));
116         this.decimalFactory = getFactory(factories, new DecimalValueFactory(decoder, this.stringFactory));
117         this.doubleFactory = getFactory(factories, new DoubleValueFactory(decoder, this.stringFactory));
118         this.longFactory = getFactory(factories, new LongValueFactory(decoder, this.stringFactory));
119         this.nameFactory = (NameFactory)getFactory(factories, new NameValueFactory(this.namespaceRegistry, decoder,
120                                                                                    this.stringFactory));
121         this.pathFactory = (PathFactory)getFactory(factories, new PathValueFactory(decoder, this.stringFactory, this.nameFactory));
122         this.referenceFactory = getFactory(factories, new ReferenceValueFactory(decoder, this.stringFactory));
123         this.uuidFactory = (UuidFactory)getFactory(factories, new UuidValueFactory(decoder, this.stringFactory));
124         this.uriFactory = getFactory(factories, new UriValueFactory(this.namespaceRegistry, decoder, this.stringFactory));
125         this.objectFactory = getFactory(factories, new ObjectValueFactory(decoder, this.stringFactory, this.binaryFactory));
126 
127         this.typeSystem = new ValueTypeSystem(this);
128     }
129 
130     @SuppressWarnings( "unchecked" )
131     private static <T> ValueFactory<T> getFactory( Map<PropertyType, ValueFactory<?>> factories,
132                                                    ValueFactory<T> defaultFactory ) {
133         PropertyType type = defaultFactory.getPropertyType();
134         ValueFactory<?> factory = factories.get(type);
135         if (factory == null) {
136             factory = defaultFactory;
137             factories.put(type, factory);
138         }
139         return (ValueFactory<T>)factory;
140     }
141 
142     /**
143      * {@inheritDoc}
144      * 
145      * @see org.modeshape.graph.property.ValueFactories#getTypeSystem()
146      */
147     public TypeSystem getTypeSystem() {
148         return typeSystem;
149     }
150 
151     /**
152      * @return namespaceRegistry
153      */
154     public NamespaceRegistry getNamespaceRegistry() {
155         return this.namespaceRegistry;
156     }
157 
158     /**
159      * {@inheritDoc}
160      */
161     public BinaryFactory getBinaryFactory() {
162         return this.binaryFactory;
163     }
164 
165     /**
166      * {@inheritDoc}
167      */
168     public ValueFactory<Boolean> getBooleanFactory() {
169         return this.booleanFactory;
170     }
171 
172     /**
173      * {@inheritDoc}
174      */
175     public DateTimeFactory getDateFactory() {
176         return this.dateFactory;
177     }
178 
179     /**
180      * {@inheritDoc}
181      */
182     public ValueFactory<BigDecimal> getDecimalFactory() {
183         return this.decimalFactory;
184     }
185 
186     /**
187      * {@inheritDoc}
188      */
189     public ValueFactory<Double> getDoubleFactory() {
190         return this.doubleFactory;
191     }
192 
193     /**
194      * {@inheritDoc}
195      */
196     public ValueFactory<Long> getLongFactory() {
197         return this.longFactory;
198     }
199 
200     /**
201      * {@inheritDoc}
202      */
203     public NameFactory getNameFactory() {
204         return this.nameFactory;
205     }
206 
207     /**
208      * {@inheritDoc}
209      */
210     public PathFactory getPathFactory() {
211         return this.pathFactory;
212     }
213 
214     /**
215      * {@inheritDoc}
216      */
217     public ValueFactory<Reference> getReferenceFactory() {
218         return this.referenceFactory;
219     }
220 
221     /**
222      * {@inheritDoc}
223      */
224     public ValueFactory<String> getStringFactory() {
225         return this.stringFactory;
226     }
227 
228     /**
229      * {@inheritDoc}
230      */
231     public ValueFactory<URI> getUriFactory() {
232         return this.uriFactory;
233     }
234 
235     /**
236      * {@inheritDoc}
237      * 
238      * @see org.modeshape.graph.property.ValueFactories#getUuidFactory()
239      */
240     public UuidFactory getUuidFactory() {
241         return this.uuidFactory;
242     }
243 
244     /**
245      * {@inheritDoc}
246      */
247     public ValueFactory<Object> getObjectFactory() {
248         return this.objectFactory;
249     }
250 
251 }