001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017:
018: package java.beans;
019:
020: /**
021: * <code>PersistenceDelegate</code> instances write received bean objects to
022: * encoders in the form of expressions and statements, which can be evaluated or
023: * executed to reconstruct the recorded bean objects in a new environment during
024: * decoding. Expressions are usually used to instantiate bean objects in the new
025: * environment, and statements are used to initialize their properties if
026: * necessary. As a result, the reconstructed bean objects become equivalent to
027: * the original recorded ones in terms of their public states.
028: *
029: */
030: public abstract class PersistenceDelegate {
031:
032: /**
033: * Default constructor.
034: */
035: public PersistenceDelegate() {
036: // empty
037: }
038:
039: /**
040: * Produces a series of expressions and statements for the initialization of
041: * a bean object's properties. The default implementation simply invokes the
042: * initialization provided by the super class's
043: * <code>PersisteneceDelegate</code> instance.
044: *
045: * @param type
046: * the type of the bean
047: * @param oldInstance
048: * the original bean object to be recorded
049: * @param newInstance
050: * the simmulating new bean object to be initialized
051: * @param enc
052: * the encoder to write the outputs to
053: */
054: protected void initialize(Class<?> type, Object oldInstance,
055: Object newInstance, Encoder enc) {
056: Class<?> c = type.getSuperclass();
057: if (null != c) {
058: PersistenceDelegate pd = enc.getPersistenceDelegate(c);
059: pd.initialize(c, oldInstance, newInstance, enc);
060: }
061: }
062:
063: /**
064: * Constructs an expression for instantiating an object of the same type as
065: * the old instance. Any exceptions occured during this process could be
066: * reported to the exception listener registered in the given encoder.
067: *
068: * @param oldInstance
069: * the old instance
070: * @param enc
071: * the encoder that wants to record the old instance
072: * @return an expression for instantiating an object of the same type as the
073: * old instance
074: */
075: protected abstract Expression instantiate(Object oldInstance,
076: Encoder enc);
077:
078: /**
079: * Determines whether one object mutates to the other object. One object is
080: * considered able to mutate to another object if they are indistinguishable
081: * in terms of behaviors of all public APIs. The default implementation here
082: * is to return true only if the two objects are instances of the same
083: * class.
084: *
085: * @param o1
086: * one object
087: * @param o2
088: * the other object
089: * @return true if second object mutates to the first object, otherwise
090: * false
091: */
092: protected boolean mutatesTo(Object o1, Object o2) {
093: if (null == o1 || null == o2) {
094: return false;
095: }
096: return o1.getClass() == o2.getClass();
097: }
098:
099: /**
100: * Writes a bean object to the given encoder. First it is checked whether
101: * the simulating new object can be mutated to the old instance. If yes, it
102: * is initialized to produce a series of expressions and statements that can
103: * be used to restore the old instance. Otherwise, remove the new object in
104: * the simulating new environment and writes an expression that can
105: * instantiate a new instance of the same type as the old one to the given
106: * encoder.
107: *
108: * @param oldInstance
109: * the old instance to be written
110: * @param out
111: * the encoder that the old instance will be written to
112: */
113: public void writeObject(Object oldInstance, Encoder out) {
114: Object newInstance = out.get(oldInstance);
115: if (mutatesTo(oldInstance, newInstance)) {
116: initialize(oldInstance.getClass(), oldInstance,
117: newInstance, out);
118: } else {
119: out.remove(oldInstance);
120: Expression exp = instantiate(oldInstance, out);
121: out.writeExpression(exp);
122: newInstance = out.get(oldInstance);
123:
124: if (newInstance != null) {
125: initialize(oldInstance.getClass(), oldInstance,
126: newInstance, out);
127: }
128: }
129: }
130:
131: }
|