/*
* Copyright (c) 2009, SQL Power Group Inc.
*
* This file is part of SQL Power Library.
*
* SQL Power Library is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* SQL Power Library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package ca.sqlpower.dao;
import java.io.InputStream;
import ca.sqlpower.object.SPObject;
/**
* An interface for objects that persist {@link SPObject}s. The medium into
* which they are persisted is entirely up to the implementation.
*/
public interface SPPersister {
/**
* Defines each type of object that can be persisted by the SPPersister.
* Each object type can be converted to a simple type based on its name.
*/
public enum DataType {
STRING("String", String.class),
INTEGER("Integer", Integer.class),
DOUBLE("Double", Double.class),
BOOLEAN("Boolean", Boolean.class),
SHORT("Short", Short.class),
LONG("Long", Long.class),
FLOAT("Float", Float.class),
/**
* This is an {@link SPObject} reference.
*/
REFERENCE("Reference", String.class),
PNG_IMG("PNG_IMG", InputStream.class),
NULL("Null", null);
private final String name;
private final Class<?> representation;
private DataType(String name, Class<?> representation){
this.name = name;
this.representation = representation;
}
public String getTypeName() {
return name;
}
public Class<?> getRepresentation() {
return representation;
}
/**
* Returns a DataType that represents the given class type. The class given
* can be null
*/
public static DataType getTypeByClass(Class<?> lookupValue) {
for (DataType type : values()) {
if ((type.getRepresentation() == null && lookupValue == null) ||
(lookupValue != null && type.getRepresentation() != null &&
type.representation.isAssignableFrom(lookupValue))) {
return type;
}
}
throw new IllegalArgumentException("The class type " + lookupValue.getName() +
" does not exist as a type in this DataType enum");
}
}
/**
* An enumeration of possible SPPersister commands. The
* {@link MessageSender}s and {@link MessageDecoder}s can use this is a
* common reference for the type of persistence methods calls that can be
* sent through messages.
*/
public enum SPPersistMethod {
persistProperty("pp"),
persistObject("po"),
removeObject("ro"),
changeProperty("cp"), // Actually refers to persistPropety with old and new values
begin("b"),
commit("c"),
rollback("r");
/**
* This is a code that can be used to define the method. If the persists
* are used to write large object trees to text the text can get very
* large so these codes help reduce that text.
*/
private final String code;
private SPPersistMethod(String code) {
this.code = code;
}
public String getCode() {
return code;
}
public static SPPersistMethod getMethodForCode(String code) {
for (SPPersistMethod method : values()) {
if (method.getCode().equals(code)) return method;
}
return null;
}
}
/**
* Modifies the named property of the specified {@link SPObject} in this
* persister's workspace. It may throw an {@link Exception} if the actual
* previous value in persistent storage does not match the expected previous
* value as an indication to the object using this SPPersister that their
* cached copy of the {@link SPObject} may be out of sync with the
* persistent storage.
*
* @param uuid
* The UUID of the {@link SPObject} in which to set the
* property
* @param propertyName
* The JavaBeans property name of the property that changed, as
* it would be discovered by the java.beans.Introspector class
* @param propertyType
* The type, and Java representation, of this property
* @param oldValue
* The expected previous value of the property
* @param newValue
* The new value to set for the property
* @throws SPPersistenceException
* A general Exception that is thrown if any Exception occurs
* while persisting the property. It can be used to wrap the
* specific cause Exception and provide other details like the
* SPObject UUID. Some potential exceptional situations
* include:
* <ul>
* <li>The SPObject UUID is unknown to this persister</li>
* <li>The given property name does not exist</li>
* <li>The given property is not writable</li>
* <li>The property type of the given old/new values do not
* match each other or the actual property in the object</li>
* <li>The existing persistent value doesn't match expected
* oldValue</li>
* </ul>
*/
public void persistProperty(String uuid, String propertyName,
DataType propertyType, Object oldValue, Object newValue)
throws SPPersistenceException;
/**
* Modifies the named property of the specified SPObject in this
* persister's workspace. This version is an unconditional call, and does
* not check the previous state of the property. To ensure the
* {@link SPObject}s stay in synch, this method should only be called by
* the Persister representing the master copy of the SPObject.
*
* @param uuid
* The UUID of the {@link SPObject} in which to set the
* property
* @param propertyName
* The JavaBeans property name of the property that changed, as
* it would be discovered by the java.beans.Introspector class
* @param propertyType
* The type, and Java representation, of this property
* @param newValue
* The new value to set for the property
* @throws SPPersistenceException
* A general Exception that is thrown if any Exception occurs
* while persisting the property. It can be used to wrap the
* specific cause Exception and provide other details like the
* SPObject UUID. Some potential exceptional situations
* include:
* <ul>
* <li>The SPObject UUID is unknown to this persister</li>
* <li>The given property name does not exist</li>
* <li>The given property is not writable</li>
* <li>The property type of the given value does not match the
* actual property in the object</li>
*/
public void persistProperty(String uuid, String propertyName,
DataType propertyType, Object newValue)
throws SPPersistenceException;
/**
* Adds a {@link SPObject} into the persistent storage. If the
* SPObject already exists in persistent storage, then it will throw an
* exception Note that this will not persist its properties or any child
* objects.
*
* @param parentUUID
* The UUID of the parent {@link SPObject} of the object to
* persist. If the SPObject has no parent, then it can be set to null.
* @param type
* A String of the fully qualified class name of the SPObject to be persisted
* @param uuid
* The UUID of the {@link SPObject} to actually persist
* @param index
* The index of the {@link SPObject} in its parents' list of children
* @throws SPPersistenceException
* A general Exception that is thrown if any Exception occurs
* while persisting the SPObject. It can be used to wrap the
* specific cause Exception and provide other details like the
* SPObject UUID. Some potential exceptional situations
* include:
* <ul>
* <li>An SPObject with the given UUID already exists in the
* persistent storage</li>
* <li>An SPObject with the given parent UUID does not exist</li>
* </ul>
*/
public void persistObject(String parentUUID, String type, String uuid, int index) throws SPPersistenceException;
/**
* Removes an SPObject from persistent storage
*
* @param parentUUID
* The UUID of the parent {@link SPObject} of the object to
* remove
* @param uuid
* The UUID of the {@link SPObject} to remove
* @throws SPPersistenceException
* A general Exception that is thrown if any Exception occurs
* while persisting the SPObject. It can be used to wrap the
* specific cause Exception and provide other details like the
* SPObject UUID.
*/
public void removeObject(String parentUUID, String uuid)
throws SPPersistenceException;
/**
* Indicates the start of an atomic transaction of persisting multiple
* {@link SPObject}s. To be used with a paired call to {@link #commit()}
*
* @throws SPPersistenceException
* A general Exception that is thrown if any Exception occurs
* while persisting the SPObject. It can be used to wrap the
* specific cause Exception and provide other details like the
* SPObject UUID.
*/
public void begin() throws SPPersistenceException;
/**
* Causes a current {@link SPObject} persistence transaction to commit
* its results.
*
* @throws SPPersistenceException
* A general Exception that is thrown if any Exception occurs
* while committing the transaction. This could be caused by one
* being thrown by {@link #persistObject(String, String)},
* {@link #persistProperty(String, String, Object, Object)}, or
* {@link #removeObject(String, String)}. Some other exceptional
* situations include:
* <ul>
* <li>An update conflict with another transaction</li>
* <li>Network issues</li>
* <li>Insufficient permissions in the backing store</li>
* </ul>
*/
public void commit() throws SPPersistenceException;
/**
* Restores the persisted {@link SPObject} back to the state it was in before the
* transaction began (i.e. when the call to {@link #begin()} was made).
* Typically, this would be called if an exception occurs during an atomic
* transaction. In the event that a rollback() is called within a nested
* transaction (that is, a begin() call after another begin() call before
* commit()), then the state of the {@link SPObject}s must be rolled back to the
* state they were in before the highest level transaction began.
*/
public void rollback();
}