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