View Javadoc

1   package com.cedarsoft.serialization;
2   
3   import com.cedarsoft.version.Version;
4   import com.cedarsoft.version.VersionMismatchException;
5   import com.cedarsoft.version.VersionRange;
6   
7   import javax.annotation.Nonnull;
8   import java.io.IOException;
9   
10  /**
11   * Abstract base class for all kinds of serializers.
12   *
13   * @param <T> the type of object this serializer is able to (de)serialize
14   * @param <S> the object to serialize to
15   * @param <D> the object to deserialize from
16   * @param <E> the exception that might be thrown
17   * @author Johannes Schneider (<a href="mailto:js@cedarsoft.com">js@cedarsoft.com</a>)
18   */
19  public abstract class AbstractSerializer<T, S, D, E extends Throwable, O, I> implements PluggableSerializer<T, S, D, E, O, I> {
20    @Nonnull
21    protected final VersionRange formatVersionRange;
22    @Nonnull
23    protected final DelegatesMappings<S, D, E, O, I> delegatesMappings;
24  
25    /**
26     * Creates a serializer.
27     *
28     * @param formatVersionRange the version range. The max value is used as format version when written.
29     */
30    protected AbstractSerializer( @Nonnull VersionRange formatVersionRange ) {
31      this.formatVersionRange = formatVersionRange;
32      this.delegatesMappings = new DelegatesMappings<S, D, E, O, I>( formatVersionRange );
33    }
34  
35    @Override
36    @Nonnull
37    public Version getFormatVersion() {
38      return formatVersionRange.getMax();
39    }
40  
41    /**
42     * Verifies the format version is supported
43     *
44     * @param formatVersion the format version
45     */
46    protected void verifyVersionReadable( @Nonnull Version formatVersion ) {
47      if ( !isVersionReadable( formatVersion ) ) {
48        throw new VersionMismatchException( getFormatVersionRange(), formatVersion );
49      }
50    }
51  
52    public boolean isVersionReadable( @Nonnull Version formatVersion ) {
53      return getFormatVersionRange().contains( formatVersion );
54    }
55  
56    /**
57     * Verifies whether the format version is writable
58     *
59     * @param formatVersion the format version
60     */
61    protected void verifyVersionWritable( @Nonnull Version formatVersion ) {
62      if ( !isVersionWritable( formatVersion ) ) {
63        throw new VersionMismatchException( getFormatVersion(), formatVersion );
64      }
65    }
66  
67    public boolean isVersionWritable( @Nonnull Version formatVersion ) {
68      return getFormatVersion().equals( formatVersion );
69    }
70  
71    @Override
72    @Nonnull
73    public VersionRange getFormatVersionRange() {
74      return formatVersionRange;
75    }
76  
77    @Nonnull
78    public DelegatesMappings<S, D, E, O, I> getDelegatesMappings() {
79      return delegatesMappings;
80    }
81  
82    @Nonnull
83    public <T> DelegatesMappings<S, D, E, O, I>.FluentFactory<T> add( @Nonnull PluggableSerializer<? super T, S, D, E, O, I> pluggableSerializer ) {
84      return delegatesMappings.add( pluggableSerializer );
85    }
86  
87    public <T> void serialize( @Nonnull T object, @Nonnull Class<T> type, @Nonnull S deserializeTo, @Nonnull Version formatVersion ) throws E, IOException {
88      delegatesMappings.serialize( object, type, deserializeTo, formatVersion );
89    }
90  
91    @Nonnull
92    public <T> PluggableSerializer<? super T, S, D, E, O, I> getSerializer( @Nonnull Class<T> type ) {
93      return delegatesMappings.getSerializer( type );
94    }
95  
96    @Nonnull
97    public <T> T deserialize( @Nonnull Class<T> type, @Nonnull Version formatVersion, @Nonnull D deserializeFrom ) throws E, IOException {
98      return delegatesMappings.deserialize( type, formatVersion, deserializeFrom );
99    }
100 
101   /**
102    * Helper method that can be used to ensure the right format version for each delegate.
103    *
104    * @param delegate              the delegate
105    * @param expectedFormatVersion the expected format version
106    */
107   protected static void verifyDelegatingSerializerVersion( @Nonnull Serializer<?, ?, ?> delegate, @Nonnull Version expectedFormatVersion ) {
108     Version actualVersion = delegate.getFormatVersion();
109     if ( !actualVersion.equals( expectedFormatVersion ) ) {
110       throw new IllegalArgumentException( "Invalid versions. Expected <" + expectedFormatVersion + "> but was <" + actualVersion + ">" );
111     }
112   }
113 }