Hi Ian,

or you use attached class as a base to make shallow clones.

Regards
Ralf

Simon Lord schrieb:
Have a read of this article: http://www.javaworld.com/javaworld/javatips/jw-javatip76.html

It provides a class for doing deep copies of serializable objects (of which castor objects are - i think!).

The article ends saying that it's not the fastest deep copy, but it is very generic.


Hope that helps


Simon Lord




Ian Stokes-Rees wrote:
Hi,

Is there some easy/obvious way to make a copy of a Java object which has been created out of an XML Schema definition? I have managed to do this by piping marshall into unmarshall, but I need to write a method for every object I want to copy (see example below).

Thanks,

Ian

  <xs:element name="Algorithm">
    <xs:complexType>
<xs:attribute name="timeIntervalsPerYear" type="xs:long" use="required" />
      <xs:attribute name="type" type="xs:string" use="required">
        <xs:simpleType>
          <xs:restriction base="xs:string">
            <xs:enumeration value="EuropeanSimple"/>
            <xs:enumeration value="EuropeanBarrier"/>
            <xs:enumeration value="EuropeanBasket"/>
          </xs:restriction>
        </xs:simpleType>
      </xs:attribute>
      <xs:attribute name="iterations" type="xs:double" use="required" />
      <xs:attribute name="queuedIts"  type="xs:double" use="optional" />
    </xs:complexType>
  </xs:element>

    <Algorithm
        type="EuropeanSimple"
        timeIntervalsPerYear="50"
        iterations="1e5"
    />

    static public Algorithm copyAlgorithm(Algorithm alg) {
        Algorithm    new_alg = new Algorithm();

        try {
            PipedReader  reader  = new PipedReader();
            PipedWriter  writer  = new PipedWriter(reader);
            alg.marshal(writer);
            writer.close();
new_alg = (Algorithm)Unmarshaller.unmarshal(Algorithm.class, reader);
        } catch (Exception ex) {
            log.error("Could not copy object");
            ex.printStackTrace();
        }

        return new_alg;
    }

---------------------------------------------------------------------
To unsubscribe from this list please visit:

    http://xircles.codehaus.org/manage_email

---------------------------------------------------------------------
To unsubscribe from this list please visit:

   http://xircles.codehaus.org/manage_email

--

Syscon Ingenieurbüro für Meß- und Datentechnik GmbH
Ralf Joachim
Raiffeisenstraße 11
72127 Kusterdingen
Germany

Tel.   +49 7071 3690 52
Mobil: +49 173 9630135
Fax    +49 7071 3690 98

Internet: www.syscon.eu
E-Mail: [EMAIL PROTECTED]

Sitz der Gesellschaft: D-72127 Kusterdingen
Registereintrag: Amtsgericht Stuttgart, HRB 382295
Geschäftsleitung: Jens Joachim, Ralf Joachim
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Modifier;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

public final class Cloner {
    private static final Log LOG = LogFactory.getLog(Cloner.class);

    public Cloner() { }

    public Object clone(final Object origin) {
        if (origin == null) {
            throw new NullPointerException("parameter 'origin' must not be null");
        }

        Object target = null;

        try {
            Constructor c = origin.getClass().getDeclaredConstructor(null);
            c.setAccessible(true);
            target = c.newInstance(null);
        } catch (InvocationTargetException e) {
            String msg = "Unable to reproduce specified origin " + origin.getClass().getName();
            msg += ". Cause: " + e.getCause().getClass().getName() + ". Check default constructor.";
            throw new IllegalArgumentException(msg);
        } catch (Exception e) {
            String msg = "Unable to reproduce specified origin " + origin.getClass().getName();
            msg += ". Cause: " + e.getClass().getName() + ". Check default constructor.";
            throw new IllegalArgumentException(msg);
        }
        copyAllDeclaredFields(origin.getClass(), origin, target);

        return target;
    }

    protected void copyAllDeclaredFields(final Class cls, final Object origin, 
            final Object target) {
        if (cls == null) { return; }
        copyDeclaredFields(cls, origin, target);
        copyAllDeclaredFields(cls.getSuperclass(), origin, target);
    }

    protected void copyDeclaredFields(final Class cls, final Object origin, final Object target) {
        if (cls == null) { return; }
        Field[] fields = cls.getDeclaredFields();
        Field.setAccessible(fields, true);
        try {
            for (int i = 0; i < fields.length; i++) {
                // transient and final properties must not be copied:
                if (((fields[i].getModifiers() & Modifier.TRANSIENT) == 0) 
                        && ((fields[i].getModifiers() & Modifier.FINAL) == 0)) {
                    Object value = fields[i].get(origin);
                    // deep copy for cloneable objects (like ArrayList, etc.)
                    if (value instanceof Cloneable) {
                        try {
                            fields[i].set(target, value.getClass().getMethod("clone", null)
                                    .invoke(value, null));
                        } catch (Exception e) {
                            String msg = "Cloning of field " + fields[i].getName() + " for " 
                                    + origin.getClass().getName() + " failed.";
                            LOG.error(msg, e);
                        }
                    } else {
                        fields[i].set(target, value);
                    }
                }
            }
        } catch (IllegalAccessException e) {
            // Should not happen, cause fields are set accessible before accessing them
            e.printStackTrace();
        }
    }

    public boolean isEqual(final Object obj1, final Object obj2) {
        if (obj1 == obj2) { return true; }
        if (obj1.getClass() != obj2.getClass()) { return false; }

        return areAllDeclaredFieldsEqual(obj1.getClass(), obj1, obj2);
    }

    protected boolean areAllDeclaredFieldsEqual(final Class cls, 
            final Object obj1, final Object obj2) {
        if (cls == null) { return true; }

        if (areDeclaredFieldsEqual(cls, obj1, obj2)) {
            return areAllDeclaredFieldsEqual(cls.getSuperclass(), obj1, obj2);
        } else {
            return false;
        }
    }

    protected boolean areDeclaredFieldsEqual(final Class cls, 
            final Object obj1, final Object obj2) {
        Field[] fields = cls.getDeclaredFields();
        Field.setAccessible(fields, true);
        try {
            for (int i = 0; i < fields.length; i++) {
                // transient and final properties must not be considered:
                if (((fields[i].getModifiers() & Modifier.TRANSIENT) == 0) 
                        && ((fields[i].getModifiers() & Modifier.FINAL) == 0)) {
                    // TODO remove next line when timestamp is mapped to database
                    if (!fields[i].getName().equals("_jdoTimeStamp")) {
                        // For java.lang.reflect.Proxy do not compare their InvocationHandlers
                        if (!fields[i].getName().equals("h")) {
                            Object value1 = fields[i].get(obj1);
                            Object value2 = fields[i].get(obj2);
                            if (!ReproHelpers.isEqual(value1, value2)) {
                                if (LOG.isDebugEnabled()) {
                                    LOG.debug("Field " + fields[i].getName() + " unequals for " 
                                            + obj1.getClass().getName() 
                                            + " (" + value1 + " / " + value2 + ")");
                                }
                                return false;
                            }
                        }
                    }
                }
            }
        } catch (IllegalAccessException e) {
            // Should not happen, cause fields are set accessible before accessing them
            e.printStackTrace();
        }

        return true;
    }
}

---------------------------------------------------------------------
To unsubscribe from this list please visit:

    http://xircles.codehaus.org/manage_email

Reply via email to