/* * Copyright (C) 2012 Brendan Robert (BLuRry) brendan.robert@gmail.com. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301 USA */ package jace.state; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.Serializable; import java.lang.reflect.InvocationTargetException; import java.util.Arrays; /** * This represents a serializable value of an object * * @author Brendan Robert (BLuRry) brendan.robert@gmail.com * @param <T> */ public class StateValue<T> implements Serializable { public ObjectGraphNode<T> node; public Class<T> type; public T value; public StateValue(ObjectGraphNode<T> node) { this.node = node; this.type = this.node.type; // if (node.name.equals("Z")) { // System.out.println("Z >>>> "+ String.valueOf(node.getCurrentValue())); // System.out.println(String.valueOf(copyObject(node.getCurrentValue()))); // } value = copyObject(this.node.getCurrentValue()); // System.out.print(node.parent != null ? node.parent.name + "." : ""); // System.out.print(node.name); // System.out.print("=="); // System.out.println(value == null ? "NULL" : value.getClass().toString()); } public void mergeValue(StateValue<T> previous) { // Do nothing -- this is here in case it is necessary to implement partial changes } private T copyObject(T currentValue) { if (currentValue == null) return null; if (type.isPrimitive()) { return currentValue; } if (!type.isArray()) { try { return (T) type.getMethod("clone").invoke(currentValue); } catch (NoSuchMethodException | SecurityException | IllegalAccessException | IllegalArgumentException | InvocationTargetException ex) { try { // Use serialization to build a deep copy ByteArrayOutputStream baos = new ByteArrayOutputStream(); ObjectOutputStream oos = new ObjectOutputStream(baos); oos.writeObject(currentValue); ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray()); ObjectInputStream ois = new ObjectInputStream(bais); return (T) ois.readObject(); } catch (IOException | ClassNotFoundException e) { return null; } } } else if (type.isArray()) { // Cross fingers! I hope this works and I don't have to investigate primite types further... if (currentValue instanceof byte[]) { byte[] array = (byte[]) currentValue; return (T) Arrays.copyOf(array, array.length); } else { Object[] array = (Object[]) currentValue; return (T) Arrays.copyOf(array, array.length); } } return currentValue; } }