blob: be60eee4925878de0272028e4d7d92af0570f506 [file] [log] [blame]
/*
* Copyright (c) 2012-2014, Paul Merlin. All Rights Reserved.
*
* 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.
*/
package org.qi4j.api.value;
import java.io.OutputStream;
import java.util.HashMap;
import java.util.Map;
import org.qi4j.api.composite.AmbiguousTypeException;
import org.qi4j.functional.Function;
/**
* Use a ValueSerializer to serialize values state.
*
* <p>
* Serialized object must be one of:
* </p>
* <ul>
* <li>a ValueComposite,</li>
* <li>an EntityComposite or EntityReference,</li>
* <li>an Iterable,</li>
* <li>a Map,</li>
* <li>a Plain Value.</li>
* </ul>
* <p>
* Nested plain values, EntityReferences, Iterables, Maps, ValueComposites and EntityComposites are supported.
* EntityComposites and EntityReferences are serialized as their identity string.
* </p>
* <p>
* Plain values can be one of:
* </p>
* <ul>
* <li>String,</li>
* <li>Character or char,</li>
* <li>Boolean or boolean,</li>
* <li>Integer or int,</li>
* <li>Long or long,</li>
* <li>Short or short,</li>
* <li>Byte or byte,</li>
* <li>Float or float,</li>
* <li>Double or double,</li>
* <li>BigInteger,</li>
* <li>BigDecimal,</li>
* <li>Date,</li>
* <li>DateTime (JodaTime),</li>
* <li>LocalDateTime (JodaTime),</li>
* <li>LocalDate (JodaTime).</li>
* </ul>
* <p>
* Values of unknown types and all arrays are considered as {@link java.io.Serializable} and by so are serialized to
* base64 encoded bytes using pure Java serialization. If it happens that the value is not Serializable, a
* ValueSerializationException is thrown.
* </p>
* <p>
* Having type information in the serialized payload allows to keep actual ValueComposite types and by so
* circumvent {@link AmbiguousTypeException} when deserializing.
* </p>
*/
public interface ValueSerializer
{
/**
* Factory method for a serialize function.
*
* @param <T> the parametrized function input type
* @return a serialization function.
*/
<T> Function<T, String> serialize();
/**
* Factory method for a serialize function.
*
* @param <T> the parametrized function input type
* @param includeTypeInfo if type information should be included in the output
* @return a serialization function.
*/
@Deprecated
<T> Function<T, String> serialize( boolean includeTypeInfo );
/**
* Serialize the state of a value with type information.
*
* @param object an Object to serialize
* @return the state
* @throws ValueSerializationException if the Value serialization failed
*/
String serialize( Object object )
throws ValueSerializationException;
/**
* Serialize the state of a value.
*
* @param object an Object to serialize
* @param includeTypeInfo if type information should be included in the output
* @return the state
* @throws ValueSerializationException if the Value serialization failed
*/
@Deprecated
String serialize( Object object, boolean includeTypeInfo )
throws ValueSerializationException;
/**
* Serialize the state of a value with type information.
*
* @param object an Object to serialize
* @param output that will be used as output
* @throws ValueSerializationException if the Value serialization failed
*/
void serialize( Object object, OutputStream output )
throws ValueSerializationException;
/**
* Serialize the state of a value.
*
* @param object an Object to serialize
* @param output that will be used as output
* @param includeTypeInfo if type information should be included in the output
* @throws ValueSerializationException if the Value serialization failed
*/
@Deprecated
void serialize( Object object, OutputStream output, boolean includeTypeInfo )
throws ValueSerializationException;
/**
* Serialization options.
*/
final class Options
{
/**
* Boolean flag to include type information.
* Default to TRUE.
*/
public static final String INCLUDE_TYPE_INFO = "includeTypeInfo";
public static final String MAP_ENTRIES_AS_OBJECTS = "mapentriesasobjects";
private final Map<String, String> options = new HashMap<>();
/**
* Create new default ValueSerializer Options.
*/
public Options()
{
this.options.put( INCLUDE_TYPE_INFO, "true" );
this.options.put( MAP_ENTRIES_AS_OBJECTS, "false" );
}
/**
* Set {@link #INCLUDE_TYPE_INFO} option to TRUE.
* @return This
*/
public Options withTypeInfo()
{
return put( INCLUDE_TYPE_INFO, true );
}
/**
* Set {@link #INCLUDE_TYPE_INFO} option to FALSE.
* @return This
*/
public Options withoutTypeInfo()
{
return put( INCLUDE_TYPE_INFO, false );
}
public Options withMapEntriesAsObjects()
{
return put( MAP_ENTRIES_AS_OBJECTS, true );
}
public Options withMapEntriesAsKeyValuePairs()
{
return put( MAP_ENTRIES_AS_OBJECTS, false );
}
/**
* Get Boolean option value.
* @param option The option
* @return The boolean value of the option, or null if absent
*/
public Boolean getBoolean( String option )
{
String value = options.get( option );
if( value == null )
{
return false;
}
return Boolean.valueOf( value );
}
/**
* Get Integer option value.
* @param option The option
* @return The integer value of the option, or null if absent
*/
public Integer getInteger( String option )
{
if( !options.containsKey( option ) )
{
return null;
}
return Integer.valueOf( options.get( option ) );
}
/**
* Get String option value.
* @param option The option
* @return The string value of the option, or null if absent
*/
public String getString( String option )
{
return options.get( option );
}
/**
* Put an option String value.
* @param option The option
* @param value The value
* @return This Options instance
*/
public Options put( String option, String value )
{
if( value == null )
{
return remove( option );
}
options.put( option, value );
return this;
}
/**
* Put an option boolean value.
* @param option The option
* @param value The value
* @return This Options instance
*/
public Options put( String option, Boolean value )
{
if( value == null )
{
return remove( option );
}
options.put( option, Boolean.toString( value ) );
return this;
}
/**
* Put an option Integer value.
* @param option The option
* @param value The value
* @return This Options instance
*/
public Options put( String option, Integer value )
{
if( value == null )
{
return remove( option );
}
options.put( option, value.toString() );
return this;
}
/**
* Remove an option value.
* @param option The option
* @return This Options instance
*/
public Options remove( String option )
{
options.remove( option );
return this;
}
/**
* Get all defined options as a Map.
* @return All defined options in a new Map
*/
public Map<String, String> toMap()
{
return new HashMap<>( options );
}
}
}