org.modeshape.jcr.value.package-info Maven / Gradle / Ivy
/*
* ModeShape (http://www.modeshape.org)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* Nodes in a graph contain properties, and this package defines the interfaces, classes and exceptions for
* representing and working with properties and their values.
*
* A property consists of a name and a set of values. A property name is represented
* by {@link org.modeshape.jcr.value.Name}, and is defined as a {@link org.modeshape.jcr.value.Name#getLocalName() local name} in a {@link org.modeshape.jcr.value.Name#getNamespaceUri() namespace}.
* Property values can be of any type, although there are specific interfaces for the known types:
*
* - {@link org.modeshape.jcr.value.PropertyType#STRING String} - A value represented with instances of the standard {@link java.lang.String} class.
* - {@link org.modeshape.jcr.value.PropertyType#BINARY Binary} - A value represented with instances of the {@link org.modeshape.jcr.value.BinaryValue} interface.
* - {@link org.modeshape.jcr.value.PropertyType#LONG Long} - A value represented with instances of the standard {@link java.lang.Long} class.
* - {@link org.modeshape.jcr.value.PropertyType#DOUBLE Double} - A value represented with instances of the standard {@link java.lang.Double} class.
* - {@link org.modeshape.jcr.value.PropertyType#DECIMAL Decimal} - A value represented with instances of the standard {@link java.math.BigDecimal} class.
* - {@link org.modeshape.jcr.value.PropertyType#DATE Date} - A value represented with instances of the {@link org.modeshape.jcr.api.value.DateTime} interface.
* This interface hides the mishmash of Java date representations, and is designed to follow the anticipated
*
ZonedDateTime
that is part of JSR-310.
* - {@link org.modeshape.jcr.value.PropertyType#BOOLEAN Boolean} - A value represented with instances of the standard {@link java.lang.Boolean} class.
* - {@link org.modeshape.jcr.value.PropertyType#NAME Name} - A value represented with instances of the {@link org.modeshape.jcr.value.Name} interface.
* - {@link org.modeshape.jcr.value.PropertyType#PATH Path} - A value represented with instances of the {@link org.modeshape.jcr.value.Path} interface.
* - {@link org.modeshape.jcr.value.PropertyType#REFERENCE Reference} - A value represented with instances of the {@link org.modeshape.jcr.value.Reference} interface.
* - {@link org.modeshape.jcr.value.PropertyType#URI URI} - A value represented with instances of the standard {@link java.net.URI} class.
* - {@link org.modeshape.jcr.value.PropertyType#OBJECT Object} - A value represented with instances of any class, although the class
* should in all practicality implement {@link java.io.Serializable}.
*
*
*
* Creating and converting property values
*
* The design of properties and their values was centered around one key principle: when using a property value,
* you often don't care what type the property value actually is, but instead care about converting it to a
* property type that you know how to work with. For example, you may be working with a property that represents
* a date, and you want to work with the value as a {@link org.modeshape.jcr.api.value.DateTime} object, regardless of whether the values
* are actually String, {@link org.modeshape.jcr.api.value.DateTime}, {@link org.modeshape.jcr.value.BinaryValue}, or even {@link java.util.Calendar} or {@link java.util.Date}
* instances. You know its should be a date, so you want to get a value that behaves as a date.
*
*
* This notion of working with a desired type implies the ability to convert from one value type to another.
* And in fact, creating values is really just converting from "other" types into a known type.
* So, we can use the factory design pattern to have a single concept of a component that creates property values
* from a variety of types. But by using generics, we can use a single {@link org.modeshape.jcr.value.ValueFactory factory} interface
* that has the same methods for creating value objects, but make the return type specific to the type we want to create.
*
*
* The {@link org.modeshape.jcr.value.ValueFactory} interface is defined as follows:
*
* public interface ValueFactory<T> {
* T create( String value ) throws ValueFormatException;
* T create( int value ) throws ValueFormatException;
* T create( long value ) throws ValueFormatException;
* T create( double value ) throws ValueFormatException;
* ...
* T create( java.util.Date value ) throws ValueFormatException;
* T create( java.util.Calendar value ) throws ValueFormatException;
* T create( DateTime value ) throws ValueFormatException;
* ...
* T create( java.net.URI value ) throws ValueFormatException;
* T create( Reference value ) throws ValueFormatException;
* T create( Name value ) throws ValueFormatException;
* T create( Path value ) throws ValueFormatException;
* ...
* T create( InputStream value, long approximateLength ) throws ValueFormatException;
* T create( Reader value, long approximateLength ) throws ValueFormatException;
* T create( Binary value ) throws ValueFormatException;
* ...
* T[] create( String[] value ) throws ValueFormatException;
* T[] create( int[] value ) throws ValueFormatException;
* T[] create( long[] value ) throws ValueFormatException;
* T[] create( double[] value ) throws ValueFormatException;
* ...
* }
*
* Notice that all the methods are called create
, and most take a single parameter whose type is
* one of the known types, a primitive, or a number of "other" types frequently encountered. (The create(...)
* methods that take an {@link java.io.InputStream} or {@link java.io.Reader} have a second parameter that specifies
* the length of the data.) Finally, note that almost all of the create
methods have a form that each
* take an array of values and return an array of T
.
*
*
* These methods also all throw a {@link org.modeshape.jcr.value.ValueFormatException}, in case the supplied
* parameter cannot be converted to the desired type. In many cases, there is a conversion (e.g., from the String "123"
* to an integer), but there certainly are cases where no conversion is allowed (e.g., the String "a123" cannot be converted
* to an integer, and a {@link org.modeshape.jcr.value.Name} cannot be converted to a boolean
). All types can be converted
* to a string, and all factories support converting that string back to its original form.
*
*
* The factory for creating {@link org.modeshape.jcr.api.value.DateTime} objects would then be an implementation of ValueFactory<DateTime>
,
* a factory for creating {@link org.modeshape.jcr.value.BinaryValue} objects would be an implementation of ValueFactory<Binary
,
* and so on. In some cases, we'd like to add additional forms of create(...)
for specific values, and
* we can do this by extending a typed {@link org.modeshape.jcr.value.ValueFactory}. For example, the {@link org.modeshape.jcr.value.DateTimeFactory} adds
* more methods for creating {@link org.modeshape.jcr.api.value.DateTime} objects for the current time, current time in UTC, from another time
* and an offset, and from individual field values:
*
* public interface DateTimeFactory extends ValueFactories<DateTime> {
* DateTime create();
* DateTime createUtc();
* DateTime create( DateTime original, long offsetInMillis );
* DateTime create( int year, int monthOfYear, int dayOfMonth,
* int hourOfDay, int minuteOfHour, int secondOfMinute, int millisecondsOfSecond );
* DateTime create( int year, int monthOfYear, int dayOfMonth,
* int hourOfDay, int minuteOfHour, int secondOfMinute, int millisecondsOfSecond,
* int timeZoneOffsetHours );
* DateTime create( int year, int monthOfYear, int dayOfMonth,
* int hourOfDay, int minuteOfHour, int secondOfMinute, int millisecondsOfSecond,
* String timeZoneId );
* }
*
* There are specialized factory interfaces for several other types, including {@link org.modeshape.jcr.value.PathFactory}
* and {@link org.modeshape.jcr.value.NameFactory},
*
*
*
* The {@link org.modeshape.jcr.value.ValueFactories} interface collects all the factories into a single spot:
*
* public interface ValueFactories<T> {
* ValueFactory<String> getStringFactory();
* ValueFactory<Binary> getBinaryFactory();
* ValueFactory<Long> getLongFactory();
* ValueFactory<Double> getDoubleFactory();
* ValueFactory<BigDecimal> getDecimalFactory();
* DateTimeFactory getDateFactory();
* ValueFactory<Boolean> getBooleanFactory();
* NameFactory getNameFactory();
* ValueFactory<Reference> getReferenceFactory();
* PathFactory getPathFactory();
* ValueFactory<URI> getUriFactory();
* UuidFactory getUuidFactory();
* ValueFactory<Object> getObjectFactory();
*
* ValueFactory<?> getValueFactory( PropertyType type );
* ValueFactory<?> getValueFactory( Object prototype );
* }
*
* This allows us to programmatically get the correct factory for a type known at compile time, but also
* to obtain the correct factory given a prototype object or the enumeration literal representing
* the desired type. Thus, the following code compiles:
*
* ValueFactories factories = ...
* DateTime now = factories.getDateFactory.create();
* String stringValue = factories.getStringFactory().create(now);
*
* A {@link org.modeshape.jcr.value.ValueFactories} is provided as part of the {@link org.modeshape.jcr.ExecutionContext}. In this way,
* the environment may use a different implementation of one or more factories.
*
*
* Comparing property values
*
* Because we have a mixture of standard Java types and custom interfaces for property values, we need
* a set of {@link java.util.Comparator} implementations that allow us to compare property values.
* The {@link org.modeshape.jcr.value.ValueComparators} class defines a number of singleton comparators that can be used.
* Plus, the {@link org.modeshape.jcr.value.PropertyType} enumeration has the ability to {@link org.modeshape.jcr.value.PropertyType#getComparator() get the comparator}
* for the specific type (e.g., PropertyType.BINARY.getComparator()
).
*
*
*/
package org.modeshape.jcr.value;