001    
002    /*
003     * Copyright (C) 2012 Archie L. Cobbs. All rights reserved.
004     *
005     * $Id: PersistentObjectDelegate.java 255 2012-01-27 23:32:12Z archie.cobbs $
006     */
007    
008    package org.dellroad.stuff.pobj;
009    
010    import java.io.IOException;
011    import java.util.Set;
012    
013    import javax.validation.ConstraintViolation;
014    import javax.xml.transform.Result;
015    import javax.xml.transform.Source;
016    
017    /**
018     * Delegate interface required for {@link PersistentObject}s.
019     * Instances provide methods for converting to/from XML, validation, etc.
020     *
021     * @param <T> type of the root persistent object
022     * @see PersistentObject
023     */
024    public interface PersistentObjectDelegate<T> {
025    
026        /**
027         * Serialize a root object into XML.
028         *
029         * <p>
030         * Note that this method effectively defines what is contained in the object graph
031         * rooted at {@code obj}.
032         *
033         * <p>
034         * This method must not modify {@code obj} or any other object in its object graph.
035         *
036         * @param obj object to serialize; must not be modified
037         * @param result XML destination
038         * @throws PersistentObjectException if an error occurs
039         */
040        void serialize(T obj, Result result) throws IOException;
041    
042        /**
043         * Deserialize a root object from XML.
044         *
045         * @param source XML source
046         * @return deserialized object
047         * @throws PersistentObjectException if an error occurs
048         */
049        T deserialize(Source source) throws IOException;
050    
051        /**
052         * Make a deep copy of the given object.
053         *
054         * <p>
055         * For correct behavior, this behavior of this method should be equivalent to a
056         * {@linkplain #serialize serialization} followed by a {@linkplain #deserialize deserialization}.
057         *
058         * <p>
059         * This method must not modify {@code original} or any other object in its object graph.
060         *
061         * @throws IllegalArgumentException if {@code original} is null
062         * @throws PersistentObjectException if an error occurs
063         */
064        T copy(T original);
065    
066        /**
067         * Attempt to determine whether two object graphs are identical.
068         *
069         * <p>
070         * This optional method is an optimization to detect invocations to {@link PersistentObject#setRoot PersistentObject.setRoot()}
071         * where the new object graph and the old object graph are identical. In such cases, no change is applied,
072         * the version number does not increase, and no notifications are sent.
073         *
074         * <p>
075         * It is always safe and correct for this method to return false. If it returns true, then it must be the case
076         * that the two object graphs are identical.
077         *
078         * <p>
079         * This method must not modify {@code oldRoot} or {@code newRoot} or any other object in their object respective graphs.
080         *
081         * @param root1 root of first object graph
082         * @param root2 root of second object graph
083         * @throws IllegalArgumentException if {@code oldRoot} or {@code newRoot} is null
084         * @throws PersistentObjectException if an error occurs
085         */
086        boolean isSameGraph(T root1, T root2);
087    
088        /**
089         * Validate the given object.
090         *
091         * <p>
092         * This method must not modify {@code obj} or any other object in its object graph.
093         *
094         * @throws IllegalArgumentException if {@code obj} is null
095         * @return set of zero or more constraint violations
096         */
097        Set<ConstraintViolation<T>> validate(T obj);
098    
099        /**
100         * Handle an exception thrown during a delayed write-back attempt. {@link ThreadDeath} exceptions are not
101         * passed to this method, but all others are.
102         *
103         * @param pobj the instance that encountered the exception
104         * @param t the exception thrown
105         */
106        void handleWritebackException(PersistentObject<T> pobj, Throwable t);
107    }
108