001/*-------------------------------------------------------------------------+ 002| | 003| Copyright 2005-2011 the ConQAT Project | 004| | 005| Licensed under the Apache License, Version 2.0 (the "License"); | 006| you may not use this file except in compliance with the License. | 007| You may obtain a copy of the License at | 008| | 009| http://www.apache.org/licenses/LICENSE-2.0 | 010| | 011| Unless required by applicable law or agreed to in writing, software | 012| distributed under the License is distributed on an "AS IS" BASIS, | 013| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 014| See the License for the specific language governing permissions and | 015| limitations under the License. | 016+-------------------------------------------------------------------------*/ 017package org.conqat.lib.commons.serialization.utils; 018 019import java.io.IOException; 020import java.util.ArrayList; 021import java.util.HashSet; 022import java.util.List; 023 024import org.conqat.lib.commons.assertion.CCSMAssert; 025import org.conqat.lib.commons.io.SerializationUtils; 026import org.conqat.lib.commons.serialization.SerializedEntityBase; 027import org.conqat.lib.commons.serialization.SerializedEntityPool; 028import org.conqat.lib.commons.serialization.SerializedEntitySerializer; 029import org.conqat.lib.commons.serialization.classes.SerializedClass; 030import org.conqat.lib.commons.serialization.objects.SerializedClassValues; 031import org.conqat.lib.commons.serialization.objects.SerializedObject; 032import org.conqat.lib.commons.serialization.objects.SerializedStringObject; 033 034/** 035 * Utility methods for migrating serialized objects. 036 */ 037public class SerializationMigrationUtils { 038 039 /** Transforms all strings in a (de)serialized string set. */ 040 public static void transformStringsInHashSet(SerializedObject setObject, IStringTransformation transformation, 041 SerializedEntityPool pool) throws IOException { 042 043 SerializedClass setClass = findClassInHierarchy(setObject, HashSet.class); 044 045 SerializedClassValues fieldSets = setObject.getFieldSet(setObject.getPlainClassHierarchy().indexOf(setClass)); 046 047 for (Object data : fieldSets.getPreFieldData()) { 048 if (!(data instanceof Integer)) { 049 continue; 050 } 051 052 SerializedEntityBase containedElement = pool.getEntity((Integer) data, SerializedEntityBase.class); 053 if (containedElement instanceof SerializedStringObject) { 054 SerializedStringObject stringContent = (SerializedStringObject) containedElement; 055 stringContent.setValue(transformation.transform(stringContent.getValue())); 056 } 057 } 058 } 059 060 /** Returns all objects in a (de)serialized {@link ArrayList}. */ 061 @SuppressWarnings("unchecked") 062 public static <T extends SerializedEntityBase> List<T> getObjectsFromArrayList(SerializedObject setObject, 063 SerializedEntityPool pool) throws IOException { 064 065 SerializedClass setClass = findClassInHierarchy(setObject, ArrayList.class); 066 067 SerializedClassValues fieldSets = setObject.getFieldSet(setObject.getPlainClassHierarchy().indexOf(setClass)); 068 List<T> objects = new ArrayList<>(); 069 for (Object data : fieldSets.getPostFieldData()) { 070 if (!(data instanceof Integer)) { 071 continue; 072 } 073 SerializedEntityBase containedElement = pool.getEntity((Integer) data, SerializedEntityBase.class); 074 objects.add((T) containedElement); 075 } 076 return objects; 077 } 078 079 /** 080 * Tries to find a given class in the {@link SerializedObject}'s classHierarchy 081 */ 082 public static SerializedClass findClassInHierarchy(SerializedObject setObject, Class<?> classToFind) 083 throws IOException { 084 for (SerializedClass classObject : setObject.getPlainClassHierarchy()) { 085 if (classToFind.getName().equals(classObject.getName())) { 086 return classObject; 087 } 088 } 089 CCSMAssert.fail("Only works on " + classToFind.getName() + " objects!"); 090 return null; 091 } 092 093 /** 094 * Renames the given entity class, reads it from the pool and returns it. The 095 * given class must be a root entity in the pool. 096 */ 097 @SuppressWarnings("unchecked") 098 public static <T> T serializeRootEntities(SerializedEntityPool entityPool) 099 throws AssertionError, IOException, ClassNotFoundException { 100 List<SerializedEntityBase> rootEntities = entityPool.getRootEntities(); 101 byte[] newValue = SerializedEntitySerializer.serializeToBytes(rootEntities); 102 return (T) SerializationUtils.deserializeFromByteArray(newValue, 103 Thread.currentThread().getContextClassLoader()); 104 } 105 106 /** Interface for transforming strings. */ 107 public interface IStringTransformation { 108 109 /** Transforms a single string. */ 110 String transform(String input); 111 } 112 113 /** Deletes a single field from a class. */ 114 public static void deleteField(SerializedEntityPool pool, String className, String fieldName) throws IOException { 115 SerializedClass migratedClass = pool.findClass(className); 116 if (migratedClass == null) { 117 return; 118 } 119 for (SerializedObject object : pool.getRootEntities(SerializedObject.class)) { 120 if (object.getClassHandle() == migratedClass.getHandle()) { 121 object.removeFieldValue(fieldName); 122 } 123 } 124 migratedClass.removeField(fieldName); 125 } 126 127}