PageRenderTime 39ms CodeModel.GetById 14ms RepoModel.GetById 0ms app.codeStats 0ms

/src/main/java/org/opentripplanner/kryo/UnmodifiableCollectionsSerializer.java

https://github.com/opentripplanner/OpenTripPlanner
Java | 174 lines | 123 code | 12 blank | 39 comment | 3 complexity | 28672c1456813ae5c1dcfa7f39646a31 MD5 | raw file
  1. /*
  2. * Copyright 2010 Martin Grotzke
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. *
  16. */
  17. package org.opentripplanner.kryo;
  18. import com.esotericsoftware.kryo.Kryo;
  19. import com.esotericsoftware.kryo.Serializer;
  20. import com.esotericsoftware.kryo.io.Input;
  21. import com.esotericsoftware.kryo.io.Output;
  22. import java.util.ArrayList;
  23. import java.util.Arrays;
  24. import java.util.Collection;
  25. import java.util.Collections;
  26. import java.util.HashMap;
  27. import java.util.HashSet;
  28. import java.util.LinkedList;
  29. import java.util.List;
  30. import java.util.Map;
  31. import java.util.Set;
  32. import java.util.SortedMap;
  33. import java.util.SortedSet;
  34. import java.util.TreeMap;
  35. import java.util.TreeSet;
  36. /**
  37. * A kryo {@link Serializer} for unmodifiable {@link Collection}s and {@link Map}s created via
  38. * {@link Collections}.
  39. *
  40. * @author <a href="mailto:martin.grotzke@javakaffee.de">Martin Grotzke</a>
  41. */
  42. public class UnmodifiableCollectionsSerializer extends Serializer<Object> {
  43. /**
  44. * Creates a new {@link UnmodifiableCollectionsSerializer} and registers its serializer for the
  45. * several unmodifiable Collections that can be created via {@link Collections}, including {@link
  46. * Map}s.
  47. *
  48. * @param kryo the {@link Kryo} instance to set the serializer on.
  49. * @see Collections#unmodifiableCollection(Collection)
  50. * @see Collections#unmodifiableList(List)
  51. * @see Collections#unmodifiableSet(Set)
  52. * @see Collections#unmodifiableSortedSet(SortedSet)
  53. * @see Collections#unmodifiableMap(Map)
  54. * @see Collections#unmodifiableSortedMap(SortedMap)
  55. */
  56. public static void registerSerializers(Kryo kryo) {
  57. UnmodifiableCollectionsSerializer serializer = new UnmodifiableCollectionsSerializer();
  58. UnmodifiableCollection.values();
  59. for (UnmodifiableCollection item : UnmodifiableCollection.values()) {
  60. kryo.register(item.type, serializer);
  61. }
  62. }
  63. @Override
  64. public void write(Kryo kryo, Output output, Object object) {
  65. try {
  66. UnmodifiableCollection unmodifiableCollection = UnmodifiableCollection.valueOfType(
  67. object.getClass()
  68. );
  69. // the ordinal could be replaced by s.th. else (e.g. a explicitely managed "id")
  70. output.writeInt(unmodifiableCollection.ordinal(), true);
  71. kryo.writeClassAndObject(output, getValues(object));
  72. } catch (RuntimeException e) {
  73. // Don't eat and wrap RuntimeExceptions because the ObjectBuffer.write...
  74. // handles SerializationException specifically (resizing the buffer)...
  75. throw e;
  76. } catch (Exception e) {
  77. throw new RuntimeException(e);
  78. }
  79. }
  80. @Override
  81. public Object read(Kryo kryo, Input input, Class<?> clazz) {
  82. int ordinal = input.readInt(true);
  83. UnmodifiableCollection unmodifiableCollection = UnmodifiableCollection.values()[ordinal];
  84. Object sourceCollection = kryo.readClassAndObject(input);
  85. return unmodifiableCollection.create(sourceCollection);
  86. }
  87. @Override
  88. public Object copy(Kryo kryo, Object original) {
  89. try {
  90. UnmodifiableCollection unmodifiableCollection = UnmodifiableCollection.valueOfType(
  91. original.getClass()
  92. );
  93. Object sourceCollectionCopy = kryo.copy(getValues(original));
  94. return unmodifiableCollection.create(sourceCollectionCopy);
  95. } catch (RuntimeException e) {
  96. // Don't eat and wrap RuntimeExceptions
  97. throw e;
  98. } catch (Exception e) {
  99. throw new RuntimeException(e);
  100. }
  101. }
  102. private Collection<?> getValues(Object coll) {
  103. return new ArrayList<>((Collection) coll);
  104. }
  105. private enum UnmodifiableCollection {
  106. COLLECTION(Collections.unmodifiableCollection(Arrays.asList("")).getClass()) {
  107. @Override
  108. public Object create(Object sourceCollection) {
  109. return Collections.unmodifiableCollection((Collection<?>) sourceCollection);
  110. }
  111. },
  112. RANDOM_ACCESS_LIST(Collections.unmodifiableList(new ArrayList<Void>()).getClass()) {
  113. @Override
  114. public Object create(Object sourceCollection) {
  115. return Collections.unmodifiableList((List<?>) sourceCollection);
  116. }
  117. },
  118. LIST(Collections.unmodifiableList(new LinkedList<Void>()).getClass()) {
  119. @Override
  120. public Object create(Object sourceCollection) {
  121. return Collections.unmodifiableList((List<?>) sourceCollection);
  122. }
  123. },
  124. SET(Collections.unmodifiableSet(new HashSet<Void>()).getClass()) {
  125. @Override
  126. public Object create(Object sourceCollection) {
  127. return Collections.unmodifiableSet((Set<?>) sourceCollection);
  128. }
  129. },
  130. SORTED_SET(Collections.unmodifiableSortedSet(new TreeSet<Void>()).getClass()) {
  131. @Override
  132. public Object create(Object sourceCollection) {
  133. return Collections.unmodifiableSortedSet((SortedSet<?>) sourceCollection);
  134. }
  135. },
  136. MAP(Collections.unmodifiableMap(new HashMap<Void, Void>()).getClass()) {
  137. @Override
  138. public Object create(Object sourceCollection) {
  139. return Collections.unmodifiableMap((Map<?, ?>) sourceCollection);
  140. }
  141. },
  142. SORTED_MAP(Collections.unmodifiableSortedMap(new TreeMap<Void, Void>()).getClass()) {
  143. @Override
  144. public Object create(Object sourceCollection) {
  145. return Collections.unmodifiableSortedMap((SortedMap<?, ?>) sourceCollection);
  146. }
  147. };
  148. private final Class<?> type;
  149. UnmodifiableCollection(Class<?> type) {
  150. this.type = type;
  151. }
  152. public abstract Object create(Object sourceCollection);
  153. static UnmodifiableCollection valueOfType(Class<?> type) {
  154. for (UnmodifiableCollection item : values()) {
  155. if (item.type.equals(type)) {
  156. return item;
  157. }
  158. }
  159. throw new IllegalArgumentException("The type " + type + " is not supported.");
  160. }
  161. }
  162. }