javaa.beans.PersistenceDelegate Maven / Gradle / Ivy
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package javaa.beans;
import javaa.beans.Encoder;
import javaa.beans.Expression;
import javaa.beans.PersistenceDelegate;
/**
* PersistenceDelegate
instances write received bean objects to
* encoders in the form of expressions and statements, which can be evaluated or
* executed to reconstruct the recorded bean objects in a new environment during
* decoding. Expressions are usually used to instantiate bean objects in the new
* environment, and statements are used to initialize their properties if
* necessary. As a result, the reconstructed bean objects become equivalent to
* the original recorded ones in terms of their public states.
*
*/
public abstract class PersistenceDelegate {
/**
* Default constructor.
*/
public PersistenceDelegate() {
// empty
}
/**
* Produces a series of expressions and statements for the initialization of
* a bean object's properties. The default implementation simply invokes the
* initialization provided by the super class's
* PersisteneceDelegate
instance.
*
* @param type
* the type of the bean
* @param oldInstance
* the original bean object to be recorded
* @param newInstance
* the simmulating new bean object to be initialized
* @param enc
* the encoder to write the outputs to
*/
protected void initialize(Class> type, Object oldInstance,
Object newInstance, Encoder enc) {
Class> c = type.getSuperclass();
if (null != c) {
PersistenceDelegate pd = enc.getPersistenceDelegate(c);
pd.initialize(c, oldInstance, newInstance, enc);
}
}
/**
* Constructs an expression for instantiating an object of the same type as
* the old instance. Any exceptions occured during this process could be
* reported to the exception listener registered in the given encoder.
*
* @param oldInstance
* the old instance
* @param enc
* the encoder that wants to record the old instance
* @return an expression for instantiating an object of the same type as the
* old instance
*/
protected abstract Expression instantiate(Object oldInstance, Encoder enc);
/**
* Determines whether one object mutates to the other object. One object is
* considered able to mutate to another object if they are indistinguishable
* in terms of behaviors of all public APIs. The default implementation here
* is to return true only if the two objects are instances of the same
* class.
*
* @param o1
* one object
* @param o2
* the other object
* @return true if second object mutates to the first object, otherwise
* false
*/
protected boolean mutatesTo(Object o1, Object o2) {
if (null == o1 || null == o2 ) {
return false;
}
return o1.getClass() == o2.getClass();
}
/**
* Writes a bean object to the given encoder. First it is checked whether
* the simulating new object can be mutated to the old instance. If yes, it
* is initialized to produce a series of expressions and statements that can
* be used to restore the old instance. Otherwise, remove the new object in
* the simulating new environment and writes an expression that can
* instantiate a new instance of the same type as the old one to the given
* encoder.
*
* @param oldInstance
* the old instance to be written
* @param out
* the encoder that the old instance will be written to
*/
public void writeObject(Object oldInstance, Encoder out) {
Object newInstance = out.get(oldInstance);
if (mutatesTo(oldInstance, newInstance)) {
initialize(oldInstance.getClass(), oldInstance, newInstance, out);
} else {
out.remove(oldInstance);
Expression exp = instantiate(oldInstance, out);
out.writeExpression(exp);
newInstance = out.get(oldInstance);
if (newInstance != null) {
initialize(oldInstance.getClass(), oldInstance,
newInstance, out);
}
}
}
}