View Javadoc

1   /**
2    * Copyright (C) cedarsoft GmbH.
3    *
4    * Licensed under the GNU General Public License version 3 (the "License")
5    * with Classpath Exception; you may not use this file except in compliance
6    * with the License. You may obtain a copy of the License at
7    *
8    *         http://www.cedarsoft.org/gpl3ce
9    *         (GPL 3 with Classpath Exception)
10   *
11   * This code is free software; you can redistribute it and/or modify it
12   * under the terms of the GNU General Public License version 3 only, as
13   * published by the Free Software Foundation. cedarsoft GmbH designates this
14   * particular file as subject to the "Classpath" exception as provided
15   * by cedarsoft GmbH in the LICENSE file that accompanied this code.
16   *
17   * This code is distributed in the hope that it will be useful, but WITHOUT
18   * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
19   * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
20   * version 3 for more details (a copy is included in the LICENSE file that
21   * accompanied this code).
22   *
23   * You should have received a copy of the GNU General Public License version
24   * 3 along with this work; if not, write to the Free Software Foundation,
25   * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
26   *
27   * Please contact cedarsoft GmbH, 72810 Gomaringen, Germany,
28   * or visit www.cedarsoft.com if you need additional information or
29   * have any questions.
30   */
31  
32  package com.cedarsoft.serialization;
33  
34  import com.cedarsoft.version.Version;
35  import com.cedarsoft.version.VersionMismatchException;
36  import com.cedarsoft.version.VersionRange;
37  
38  import javax.annotation.Nonnull;
39  import java.io.ByteArrayOutputStream;
40  import java.io.IOException;
41  
42  /**
43   * Abstract base class for all kinds of serializers.
44   *
45   * @param <T> the type of object this serializer is able to (de)serialize
46   * @param <S> the object to serialize to
47   * @param <D> the object to deserialize from
48   * @param <E> the exception that might be thrown
49   */
50  public abstract class AbstractSerializer<T, S, D, E extends Throwable> implements PluggableSerializer<T, S, D, E> {
51    @Nonnull
52    private final VersionRange formatVersionRange;
53  
54    @Nonnull
55    protected final DelegatesMappings<S, D, E> delegatesMappings;
56  
57    /**
58     * Creates a serializer.
59     *
60     * @param formatVersionRange the version range. The max value is used as format version when written.
61     */
62    protected AbstractSerializer( @Nonnull VersionRange formatVersionRange ) {
63      this.formatVersionRange = formatVersionRange;
64      this.delegatesMappings = new DelegatesMappings<S, D, E>( formatVersionRange );
65    }
66  
67    @Override
68    @Nonnull
69    public Version getFormatVersion() {
70      return formatVersionRange.getMax();
71    }
72  
73    /**
74     * Verifies the format version is supported
75     *
76     * @param formatVersion the format version
77     */
78    protected void verifyVersionReadable( @Nonnull Version formatVersion ) {
79      if ( !isVersionReadable( formatVersion ) ) {
80        throw new VersionMismatchException( getFormatVersionRange(), formatVersion );
81      }
82    }
83  
84    public boolean isVersionReadable( @Nonnull Version formatVersion ) {
85      return getFormatVersionRange().contains( formatVersion );
86    }
87  
88    /**
89     * Verifies whether the format version is writable
90     *
91     * @param formatVersion the format version
92     */
93    protected void verifyVersionWritable( @Nonnull Version formatVersion ) {
94      if ( !isVersionWritable( formatVersion ) ) {
95        throw new VersionMismatchException( getFormatVersion(), formatVersion );
96      }
97    }
98  
99    public boolean isVersionWritable( @Nonnull Version formatVersion ) {
100     return getFormatVersion().equals( formatVersion );
101   }
102 
103   @Override
104   @Nonnull
105   public VersionRange getFormatVersionRange() {
106     return formatVersionRange;
107   }
108 
109   /**
110    * Helper method that serializes to a byte array
111    *
112    * @param object the object
113    * @return the serialized object
114    *
115    * @throws IOException
116    */
117   @Nonnull
118   public byte[] serializeToByteArray( @Nonnull T object ) throws IOException {
119     ByteArrayOutputStream out = new ByteArrayOutputStream();
120     serialize( object, out );
121     return out.toByteArray();
122   }
123 
124   @Nonnull
125   public DelegatesMappings<S, D, E> getDelegatesMappings() {
126     return delegatesMappings;
127   }
128 
129   // Delegate methods to the DelegatesMappings
130 
131   @Nonnull
132   public <T> DelegatesMappings<S, D, E>.FluentFactory<T> add( @Nonnull PluggableSerializer<? super T, S, D, E> pluggableSerializer ) {
133     return delegatesMappings.add( pluggableSerializer );
134   }
135 
136   public <T> void serialize( @Nonnull T object, @Nonnull Class<T> type, @Nonnull S deserializeTo, @Nonnull Version formatVersion ) throws E, IOException {
137     delegatesMappings.serialize( object, type, deserializeTo, formatVersion );
138   }
139 
140   @Nonnull
141   public <T> PluggableSerializer<? super T, S, D, E> getSerializer( @Nonnull Class<T> type ) {
142     return delegatesMappings.getSerializer( type );
143   }
144 
145   @Nonnull
146   public <T> T deserialize( @Nonnull Class<T> type, @Nonnull Version formatVersion, @Nonnull D deserializeFrom ) throws E, IOException {
147     return delegatesMappings.deserialize( type, formatVersion, deserializeFrom );
148   }
149 
150   /**
151    * Helper method that can be used to ensure the right format version for each delegate.
152    *
153    * @param delegate              the delegate
154    * @param expectedFormatVersion the expected format version
155    */
156   protected static void verifyDelegatingSerializerVersion( @Nonnull Serializer<?> delegate, @Nonnull Version expectedFormatVersion ) {
157     Version actualVersion = delegate.getFormatVersion();
158     if ( !actualVersion.equals( expectedFormatVersion ) ) {
159       throw new IllegalArgumentException( "Invalid versions. Expected <" + expectedFormatVersion + "> but was <" + actualVersion + ">" );
160     }
161   }
162 }