From 90af571f76a63aa2afb80a2d436174886102fa97 Mon Sep 17 00:00:00 2001 From: Paul Speed Date: Wed, 9 Mar 2016 00:59:21 -0500 Subject: [PATCH] Added a test/demo showing how to use the cloner with various examples of the kinds of classes it can work with. --- .../main/java/jme3test/app/TestCloner.java | 368 ++++++++++++++++++ 1 file changed, 368 insertions(+) create mode 100644 jme3-examples/src/main/java/jme3test/app/TestCloner.java diff --git a/jme3-examples/src/main/java/jme3test/app/TestCloner.java b/jme3-examples/src/main/java/jme3test/app/TestCloner.java new file mode 100644 index 000000000..fa193f4b6 --- /dev/null +++ b/jme3-examples/src/main/java/jme3test/app/TestCloner.java @@ -0,0 +1,368 @@ +/* + * Copyright (c) 2016 jMonkeyEngine + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * * Neither the name of 'jMonkeyEngine' nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package jme3test.app; + +import java.util.*; + +import com.jme3.util.clone.*; + +/** + * + * + * @author Paul Speed + */ +public class TestCloner { + + public static void main( String... args ) { + + System.out.println("Clone test:"); + + Cloner cloner = new Cloner(); + + RegularObject ro = new RegularObject(42); + System.out.println("Regular Object:" + ro); + RegularObject roCloneLegacy = ro.clone(); + System.out.println("Regular Object Clone:" + roCloneLegacy); + RegularObject roClone = cloner.clone(ro); + System.out.println("cloner: Regular Object Clone:" + roClone); + + System.out.println("------------------------------------"); + System.out.println(); + + cloner = new Cloner(); + RegularSubclass rsc = new RegularSubclass(69, "test"); + System.out.println("Regular subclass:" + rsc); + RegularSubclass rscCloneLegacy = (RegularSubclass)rsc.clone(); + System.out.println("Regular subclass Clone:" + rscCloneLegacy); + RegularSubclass rscClone = cloner.clone(rsc); + System.out.println("cloner: Regular subclass Clone:" + rscClone); + + System.out.println("------------------------------------"); + System.out.println(); + + cloner = new Cloner(); + Parent parent = new Parent("Foo", 34); + System.out.println("Parent:" + parent); + Parent parentCloneLegacy = parent.clone(); + System.out.println("Parent Clone:" + parentCloneLegacy); + Parent parentClone = cloner.clone(parent); + System.out.println("cloner: Parent Clone:" + parentClone); + + System.out.println("------------------------------------"); + System.out.println(); + + cloner = new Cloner(); + GraphNode root = new GraphNode("root"); + GraphNode child1 = root.addLink("child1"); + GraphNode child2 = root.addLink("child2"); + GraphNode shared = child1.addLink("shared"); + child2.addLink(shared); + + // Add a circular reference to get fancy + shared.addLink(root); + + System.out.println("Simple graph:"); + root.dump(" "); + + GraphNode rootClone = cloner.clone(root); + System.out.println("clone:"); + rootClone.dump(" "); + + System.out.println("original:"); + root.dump(" "); + + GraphNode reclone = Cloner.deepClone(root); + System.out.println("reclone:"); + reclone.dump(" "); + + System.out.println("------------------------------------"); + System.out.println(); + cloner = new Cloner(); + + ArrayHolder arrays = new ArrayHolder(5, 3, 7, 3, 7, 2, 1, 4); + System.out.println("Array holder:" + arrays); + ArrayHolder arraysClone = cloner.clone(arrays); + System.out.println("Array holder clone:" + arraysClone); + + + + } + + public static class RegularObject implements Cloneable { + protected int i; + + public RegularObject( int i ) { + this.i = i; + } + + public RegularObject clone() { + try { + return (RegularObject)super.clone(); + } catch( CloneNotSupportedException e ) { + throw new RuntimeException(e); + } + } + + public String toString() { + return getClass().getSimpleName() + "@" + System.identityHashCode(this) + + "[i=" + i + "]"; + } + } + + public static class RegularSubclass extends RegularObject { + protected String name; + + public RegularSubclass( int i, String name ) { + super(i); + this.name = name; + } + + public String toString() { + return getClass().getSimpleName() + "@" + System.identityHashCode(this) + + "[i=" + i + ", name=" + name + "]"; + } + } + + public static class Parent implements Cloneable, JmeCloneable { + + private RegularObject ro; + private RegularSubclass rsc; + + public Parent( String name, int age ) { + this.ro = new RegularObject(age); + this.rsc = new RegularSubclass(age, name); + } + + public Parent clone() { + try { + return (Parent)super.clone(); + } catch( CloneNotSupportedException e ) { + throw new RuntimeException(e); + } + } + + public void cloneFields( Cloner cloner, Object original ) { + this.ro = cloner.clone(ro); + this.rsc = cloner.clone(rsc); + } + + public String toString() { + return getClass().getSimpleName() + "@" + System.identityHashCode(this) + + "[ro=" + ro + ", rsc=" + rsc + "]"; + } + } + + public static class GraphNode implements Cloneable, JmeCloneable { + + private String name; + private List links = new ArrayList<>(); + + public GraphNode( String name ) { + this.name = name; + } + + public void dump( String indent ) { + dump(indent, new HashSet()); + } + + private void dump( String indent, Set visited ) { + if( visited.contains(this) ) { + // already been here + System.out.println(indent + this + " ** circular."); + return; + } + System.out.println(indent + this); + visited.add(this); + for( GraphNode n : links ) { + n.dump(indent + " ", visited); + } + visited.remove(this); + } + + public GraphNode addLink( String name ) { + GraphNode node = new GraphNode(name); + links.add(node); + return node; + } + + public GraphNode addLink( GraphNode node ) { + links.add(node); + return node; + } + + public List getLinks() { + return links; + } + + public GraphNode clone() { + try { + return (GraphNode)super.clone(); + } catch( CloneNotSupportedException e ) { + throw new RuntimeException(e); + } + } + + public void cloneFields( Cloner cloner, Object original ) { + this.links = cloner.clone(links); + /* + // manually clone the list for a sec + List cloneList = (List)((ArrayList)links).clone(); //new ArrayList(); + for( int i = 0; i < links.size(); i++ ) { + cloneList.set(i, cloner.clone(links.get(i))); + } + links = cloneList;*/ + } + + public String toString() { + return getClass().getSimpleName() + "@" + System.identityHashCode(this) + + "[name=" + name + "]"; + } + } + + public static class ArrayHolder implements JmeCloneable { + + private int[] intArray; + private int[][] intArray2D; + private Object[] objects; + private RegularObject[] regularObjects; + private String[] strings; + + public ArrayHolder( int... values ) { + this.intArray = values; + this.intArray2D = new int[values.length][2]; + for( int i = 0; i < values.length; i++ ) { + intArray2D[i][0] = values[i] + 1; + intArray2D[i][1] = values[i] * 2; + } + this.objects = new Object[values.length]; + this.regularObjects = new RegularObject[values.length]; + this.strings = new String[values.length]; + for( int i = 0; i < values.length; i++ ) { + objects[i] = values[i]; + regularObjects[i] = new RegularObject(values[i]); + strings[i] = String.valueOf(values[i]); + } + } + + public ArrayHolder clone() { + try { + return (ArrayHolder)super.clone(); + } catch( CloneNotSupportedException e ) { + throw new RuntimeException(e); + } + } + + public void cloneFields( Cloner cloner, Object original ) { + intArray = cloner.clone(intArray); + intArray2D = cloner.clone(intArray2D); + + // Boxed types are not cloneable so this will fail + //objects = cloner.clone(objects); + + regularObjects = cloner.clone(regularObjects); + + // Strings are also not cloneable + //strings = cloner.clone(strings); + } + + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("intArray=" + intArray); + for( int i = 0; i < intArray.length; i++ ) { + if( i == 0 ) { + sb.append("["); + } else { + sb.append(", "); + } + sb.append(intArray[i]); + } + sb.append("], "); + + sb.append("intArray2D=" + intArray2D); + for( int i = 0; i < intArray2D.length; i++ ) { + if( i == 0 ) { + sb.append("["); + } else { + sb.append(", "); + } + sb.append("intArray2D[" + i + "]=" + intArray2D[i]); + for( int j = 0; j < 2; j++ ) { + if( j == 0 ) { + sb.append("["); + } else { + sb.append(", "); + } + sb.append(intArray2D[i][j]); + } + sb.append("], "); + } + sb.append("], "); + + sb.append("objectArray=" + objects); + for( int i = 0; i < objects.length; i++ ) { + if( i == 0 ) { + sb.append("["); + } else { + sb.append(", "); + } + sb.append(objects[i]); + } + sb.append("], "); + + sb.append("objectArray=" + regularObjects); + for( int i = 0; i < regularObjects.length; i++ ) { + if( i == 0 ) { + sb.append("["); + } else { + sb.append(", "); + } + sb.append(regularObjects[i]); + } + sb.append("], "); + + sb.append("stringArray=" + strings); + for( int i = 0; i < strings.length; i++ ) { + if( i == 0 ) { + sb.append("["); + } else { + sb.append(", "); + } + sb.append(strings[i]); + } + sb.append("]"); + + return getClass().getSimpleName() + "@" + System.identityHashCode(this) + + "[" + sb + "]"; + } + } +}