package org.andork.spec.json; import java.util.HashMap; import java.util.Map; import org.andork.model.HasChangeSupport; import org.andork.spec.json.JsonSpec.Attribute; import org.andork.spec.json.JsonSpec.Format; import org.andork.util.Java7; import com.google.gson.JsonObject; /** * A type-safe property set that can be converted to JSON via {@link #toJson()} and converted from JSON via {@link JsonSpec#fromJson(JsonObject)}.<br> * <br> * * @param <S> * the type of the {@link JsonSpec} for this {@code SpecObject}. * * @author james.a.edwards */ @SuppressWarnings( "serial" ) public final class JsonSpecObject<S extends JsonSpec<S>> extends JsonSpecElement implements HasChangeSupport { private final S spec; private final Map<Attribute<?>, Object> attributes = new HashMap<Attribute<?>, Object>( ); /** * Creates a {@code SpecObject} with the given spec. * * @param spec * the {@link JsonSpec} for this SpecObject. */ private JsonSpecObject( S spec ) { this.spec = spec; } public static <S extends JsonSpec<S>> JsonSpecObject<S> newInstance( S spec ) { return new JsonSpecObject<S>( spec ); } /** * @return the {@link JsonSpec} of this SpecObject. */ public S getSpec( ) { return spec; } /** * Gets the value of an attribute.<br> * <br> * To see the list of attributes this SpecObject has, use {@link JsonSpec#getAttributes() getSpec().getAttributes()}. * * @param Attribute * the attribute to get the value of. * @return the value of the attribute (may be {@code null}). */ public <T> T get( Attribute<T> Attribute ) { return ( T ) attributes.get( Attribute ); } public <T> T set( Attribute<T> attribute , T newValue ) { T oldValue = ( T ) attributes.get( attribute ); if( oldValue instanceof JsonSpecElement ) { ( ( JsonSpecElement ) oldValue ).changeSupport( ).removePropertyChangeListener( propagator ); } attributes.put( attribute , newValue ); if( newValue instanceof JsonSpecElement ) { ( ( JsonSpecElement ) newValue ).changeSupport( ).addPropertyChangeListener( propagator ); } if( !Java7.Objects.equals( oldValue , newValue ) ) { changeSupport.firePropertyChange( this , attribute , oldValue , newValue ); } return oldValue; } public boolean has( Attribute<?> attribute ) { return attributes.containsKey( attribute ); } public JsonObject toJson( ) { JsonObject result = new JsonObject( ); for( Map.Entry<Attribute<?>, Object> entry : attributes.entrySet( ) ) { result.add( entry.getKey( ).getName( ) , ( ( Format ) entry.getKey( ).getFormat( ) ).format( entry.getValue( ) ) ); } return result; } public String toString( ) { return toJson( ).toString( ); } }