Files
Brainstorm/Foundation/src/com/foundation/controller/ModelInterface.java

477 lines
18 KiB
Java
Raw Normal View History

2014-05-30 10:31:51 -07:00
package com.foundation.controller;
import java.io.IOException;
import com.common.debug.Debug;
import com.common.exception.MethodNotSupportedException;
import com.common.io.IExternalizable;
import com.common.io.IObjectInputStream;
import com.common.io.IObjectOutputStream;
import com.common.orb.Orb;
import com.common.util.IList;
import com.common.util.LiteList;
import com.foundation.attribute.IReflectable;
import com.foundation.attribute.IReflectableCollection;
import com.foundation.common.Entity;
import com.foundation.common.IEntity;
import com.foundation.metadata.Attribute;
import com.foundation.transaction.ReadTransaction;
import com.foundation.util.IManagedList;
/**
* The interface used by application components to access shared models regardless of where they are located.
*
* TODO: Reflect all results from a remote source. This should be "pass-through" in that any synchronizations automatically get forwarded to the reflected object and don't get applied if the reflected object rejects the change set.
*
* TODO: Listen to remote sources for lost connections - automatically reconnect the reflection(s) when a source is lost.
*
* TODO: Allow calls to some methods to not return the reflected object; Allow additional result information to be returned - such as the "duplicate value for Customer.LOGIN found" error.
*
*/
public class ModelInterface {
/** The one and only instance of this class. */
private static final ModelInterface singleton = new ModelInterface();
/**
* ModelInterface constructor.
*/
private ModelInterface() {
}//ModelInterface()//
/**
* Adds the entity to the shared set of models.
* <p>This is used for Mapped and List type models.</p>
* @param entity The entity to be added. This object must be serializable in the event that the model management occurs on a remote process.
* @param returnAddition Whether to return the added value. This will be a local reflection if the model management is remote.
* @return A result object containing the reflection of the added value if successful.
*/
public static ReflectionResult addEntity(IEntity entity, boolean returnAddition) {
ReflectionResult result = null;
Class type = entity != null ? entity.getClass() : null;
if(type != null) {
IModelManager modelManager = singleton.locateModelManager(type);
if(entity.isObjectRepositoryBound()) {
if(!entity.isObjectNew()) {
throw new IllegalArgumentException("Must only add new objects to the manager.");
}//if//
else if(entity.isReflection()) {
throw new IllegalArgumentException("Cannot send a reflection.");
}//else if//
}//if//
if(modelManager != null) {
if(modelManager instanceof ISingleListModelManager) {
result = ((ISingleListModelManager) modelManager).addEntity(entity, returnAddition);
}//if//
else if(modelManager instanceof ISingleMappedModelManager) {
result = ((ISingleMappedModelManager) modelManager).addEntity(entity, returnAddition);
}//else if//
else {
throw new IllegalArgumentException("Invalid model manager type.");
}//else//
//Reflect the added value if it is returned and the management is remote.//
if(returnAddition && !Orb.isLocal(modelManager) && result instanceof ReflectionSuccess && ((ReflectionSuccess) result).getResult() != null) {
//TODO: Reflect the result with a weak & pass through reflection manager.
//TODO: Must ensure that synchronization to the reflection propegates automatically to the remote reflected object and any failures propegate back to the synchronizer.
// reflect((IReflectable) ((ReflectionSuccess) result).getResult());
}//if//
}//if//
else {
//TODO: Specify an identifier.
result = new ReflectionNetworkError(0, "Failed to locate a Model Manager.");
}//else//
}//if//
return result;
}//addEntity()//
/**
* Adds the entities to the shared set of models.
* <p>This is used for Mapped and List type models.</p>
* @param entities The list of entity instances to be added. This object must be serializable in the event that the model management occurs on a remote process.
* @param returnAdditions
* @return A result object containing an IList collection of reflectable references to the entities added. These may not be the same objects as was passed to this method.
*/
public static ReflectionResult addEntities(IList entities, boolean returnAdditions) {
ReflectionResult result = null;
Class type = entities == null || entities.getSize() == 0 || entities.getFirst() == null ? null : entities.getFirst().getClass();
if(type != null) {
IModelManager modelManager = singleton.locateModelManager(type);
if(modelManager != null) {
for(int index = 0, size = entities.getSize(); index < size; index++) {
Entity next = (Entity) entities.get(index);
if(!next.isObjectNew()) {
throw new IllegalArgumentException("Must only add new objects to the manager.");
}//if//
else if(next.isReflection()) {
throw new IllegalArgumentException("Cannot send a reflection.");
}//else if//
}//for//
if(modelManager instanceof ISingleListModelManager) {
result = ((ISingleListModelManager) modelManager).addEntities(entities, returnAdditions);
}//if//
else if(modelManager instanceof ISingleMappedModelManager) {
result = ((ISingleMappedModelManager) modelManager).addEntities(entities, returnAdditions);
}//else if//
else {
throw new IllegalArgumentException("Invalid model manager type.");
}//else//
//If results were returned then reflect them using a pass through & weak reflection manager so that we have a single point to recover from failures.//
if(returnAdditions && !Orb.isLocal(modelManager) && result instanceof ReflectionSuccess && ((ReflectionSuccess) result).getResult() instanceof IList && ((IList) ((ReflectionSuccess) result).getResult()).getSize() > 0) {
//Reflect the results.//
// reflectAll((IList) ((ReflectionSuccess) result).getResult());
}//if//
}//if//
else {
//TODO: Specify an identifier.
result = new ReflectionNetworkError(0, "Failed to locate a Model Manager.");
}//else//
}//if//
else {
result = new ReflectionSuccess(LiteList.EMPTY_LIST);
}//else//
return result;
}//addEntity()//
/**
* Removes (deletes) the entity from the shared set of models. The values will also be deleted to any attached repository.
* <p>This is used for Mapped and List type models.</p>
* @param entity The entity to be removed. This object must be serializable in the event that the model management occurs on a remote process. The value may be a reflection or proxy - the code will de-reflect and de-proxy where possible.
* @return A result object reporting success or failure of the operation.
*/
public static ReflectionResult removeEntity(IEntity entity) {
ReflectionResult result = null;
try {
if(entity != null) {
Class type = Orb.isProxy(entity) ? Orb.getNonProxyClass(entity) : entity.getClass();
if(type != null) {
IModelManager modelManager = singleton.locateModelManager(type);
if(modelManager != null) {
//First ensure we are not using a local proxy.//
if(Orb.isProxy(entity) && Orb.isLocal(entity)) {
entity = (IEntity) Orb.getLocal(entity);
}//if//
//Ensure we don't send a reflection (it can't be a reflection if it is a proxy).//
while(!Orb.isProxy(entity) && entity.isReflection()) {
entity = (IEntity) entity.getReflected();
//De-proxy the object if possible.//
if(Orb.isProxy(entity) && Orb.isLocal(entity)) {
entity = (IEntity) Orb.getLocal(entity);
}//if//
}//while//
if(modelManager instanceof ISingleListModelManager) {
((ISingleListModelManager) modelManager).removeEntity(entity);
}//if//
else if(modelManager instanceof ISingleMappedModelManager) {
((ISingleMappedModelManager) modelManager).removeEntity(entity);
}//else if//
else {
throw new IllegalArgumentException("Invalid model manager type.");
}//else//
result = new ReflectionSuccess(null);
}//if//
else {
//TODO: Specify an identifier.
result = new ReflectionNetworkError(0, "Failed to locate a Model Manager.");
}//else//
}//if//
else {
//Shouldn't ever get here.//
throw new ClassNotFoundException();
}//else//
}//if//
else {
throw new NullPointerException();
}//else//
}//try//
catch(ClassNotFoundException e) {
Debug.log(e);
result = new ReflectionCustomError(e);
}//catch//
return result;
}//removeEntity()//
/**
* Removes (deletes) the entities from the shared set of models. The values will also be deleted to any attached repository.
* <p>This is used for Mapped and List type models.</p>
* @param entities The list of entity instances to be removed. This object must be serializable in the event that the model management occurs on a remote process. List values may be reflections or proxies - the code will de-reflect and de-proxy where possible.
* @return A result object reporting success or failure of the operation.
*/
public static ReflectionResult removeEntities(IList entities) {
ReflectionResult result;
try {
IReflectable first = entities == null || entities.getSize() == 0 || entities.getFirst() == null ? null : (IReflectable) entities.getFirst();
Class type = Orb.isProxy(first) ? Orb.getNonProxyClass(first) : first.getClass();
if(type != null) {
IModelManager modelManager = singleton.locateModelManager(type);
if(modelManager != null) {
//Iterate over the entities and de-reflect and de-proxy where ever possible.//
for(int index = 0, size = entities.getSize(); index < size; index++) {
IReflectable next = (IReflectable) entities.get(index);
//First ensure we are not using a local proxy.//
if(Orb.isProxy(next) && Orb.isLocal(next)) {
next = (IReflectable) Orb.getLocal(next);
}//if//
//Ensure we don't send a reflection (it can't be a reflection if it is a proxy).//
while(!Orb.isProxy(next) && next.isReflection()) {
next = next.getReflected();
//De-proxy the object if possible.//
if(Orb.isProxy(next) && Orb.isLocal(next)) {
next = (IReflectable) Orb.getLocal(next);
}//if//
}//while//
entities.set(index, next);
}//for//
if(modelManager instanceof ISingleListModelManager) {
((ISingleListModelManager) modelManager).removeEntities(entities);
}//if//
else if(modelManager instanceof ISingleMappedModelManager) {
((ISingleMappedModelManager) modelManager).removeEntities(entities);
}//else if//
else {
throw new IllegalArgumentException("Invalid model manager type.");
}//else//
result = new ReflectionSuccess(null);
}//if//
else {
//TODO: Specify an identifier.
result = new ReflectionNetworkError(0, "Failed to locate a Model Manager.");
}//else//
}//if//
else {
//Shouldn't ever get here.//
throw new ClassNotFoundException();
}//else//
}//try//
catch(ClassNotFoundException e) {
Debug.log(e);
result = new ReflectionCustomError(e);
}//catch//
return result;
}//removeEntities()//
/**
* Finds the first entity matching the query.
* @param query The query by example object.
* @return A result object containing an IReflectable instance of the first result if the operation was successful.
*/
public static ReflectionResult findEntity(IEntity query) {
ReflectionResult result = null;
try {
Class type = query != null ? query.getClass() : null;
if(type != null) {
IModelManager modelManager = singleton.locateModelManager(type);
if(modelManager != null) {
if(query.isReflection()) {
throw new IllegalArgumentException("Cannot send a reflection.");
}//if//
if(modelManager instanceof ISingleListModelManager) {
throw new MethodNotSupportedException("The class " + type.getName() + " uses a list model manager which doesn't support querying for elements.");
}//if//
else if(modelManager instanceof ISingleMappedModelManager) {
result = ((ISingleMappedModelManager) modelManager).findEntity(query);
}//else if//
else {
throw new IllegalArgumentException("Invalid model manager type.");
}//else//
}//if//
else {
//TODO: Specify an identifier.
result = new ReflectionNetworkError(0, "Failed to locate a Model Manager.");
}//else//
}//if//
else {
throw new IllegalArgumentException();
}//else//
}//try//
// catch(ClassNotFoundException e) {
// Debug.log(e);
// result = new ReflectionCustomError(e);
// }//catch//
finally {}
return result;
}//findEntity()//
/**
* Finds all entities matching the query.
* @param query The query by example object.
* @return A result object containing an IList containing IReflectable instances matching the query if the operation was successful.
*/
public static ReflectionResult findEntities(IEntity query) {
ReflectionResult result = null;
Class type = query != null ? query.getClass() : null;
if(type != null) {
IModelManager modelManager = singleton.locateModelManager(type);
if(modelManager != null) {
if(query.isReflection()) {
throw new IllegalArgumentException("Cannot send a reflection.");
}//if//
if(modelManager instanceof ISingleListModelManager) {
throw new MethodNotSupportedException("The class " + type.getName() + " uses a list model manager which doesn't support querying for elements.");
}//if//
else if(modelManager instanceof ISingleMappedModelManager) {
result = ((ISingleMappedModelManager) modelManager).findEntities(query);
}//else if//
else {
throw new IllegalArgumentException("Invalid model manager type.");
}//else//
}//if//
else {
//TODO: Specify an identifier.
result = new ReflectionNetworkError(0, "Failed to locate a Model Manager.");
}//else//
}//if//
else {
throw new IllegalArgumentException();
}//else//
return result;
}//findEntity()//
/**
* Gets all entities of the given type.
* @param type The model type whose instances will be returned.
* @return A result object containing an IReflectableCollection (reflect this which will contain reflections of all instances of the given type) if the operation was successful.
*/
public static ReflectionResult getEntities(Class type) {
ReflectionResult result = null;
if(type != null) {
IModelManager modelManager = singleton.locateModelManager(type);
if(modelManager != null) {
if(modelManager instanceof ISingleListModelManager) {
result = ((ISingleListModelManager) modelManager).getEntities();
}//if//
else if(modelManager instanceof ISingleMappedModelManager) {
throw new MethodNotSupportedException("The class " + type.getName() + " uses a mapped model manager which doesn't support retrieving a collection of all elements.");
}//else if//
else {
throw new IllegalArgumentException("Invalid model manager type.");
}//else//
}//if//
else {
//TODO: Specify an identifier.
result = new ReflectionNetworkError(0, "Failed to locate a Model Manager.");
}//else//
}//if//
else {
throw new IllegalArgumentException();
}//else//
return result;
}//getEntities()//
/**
* Gets all (or first) entities of the given type.
* @param type The model type whose instances will be returned.
* @param transaction The read many or read single transaction to be run. The transaction must result in instance(s) of the passed <code>type</code>.
* @return A result object containing an IReflectableCollection (reflect this which will contain reflections of all instances of the given type) if the operation was successful.
*/
public static ReflectionResult findEntities(Class type, ReadTransaction transaction) {
ReflectionResult result = null;
if(type != null) {
IModelManager modelManager = singleton.locateModelManager(type);
if(modelManager != null) {
if(modelManager instanceof ISingleListModelManager) {
result = ((ISingleListModelManager) modelManager).findEntities(transaction);
}//if//
else if(modelManager instanceof ISingleMappedModelManager) {
result = ((ISingleMappedModelManager) modelManager).findEntities(transaction);
}//else if//
else {
throw new IllegalArgumentException("Invalid model manager type.");
}//else//
}//if//
else {
//TODO: Specify an identifier.
result = new ReflectionNetworkError(0, "Failed to locate a Model Manager.");
}//else//
}//if//
else {
throw new IllegalArgumentException();
}//else//
return result;
}//findEntities()//
/**
* Gets all entities of the given type.
* @param type The model type whose instances will be returned.
* @param keys The set of keys that uniquely identify each model to be found.
* @return A result object containing an IReflectableCollection (reflect this which will contain reflections of all instances of the given type) if the operation was successful.
*/
public static ReflectionResult findEntities(Class type, Object[] keys) {
ReflectionResult result = null;
if(type != null) {
IModelManager modelManager = singleton.locateModelManager(type);
if(modelManager != null) {
if(modelManager instanceof ISingleListModelManager) {
result = ((ISingleListModelManager) modelManager).findEntities(keys);
}//if//
else if(modelManager instanceof ISingleMappedModelManager) {
result = ((ISingleMappedModelManager) modelManager).findEntities(keys);
}//else if//
else {
throw new IllegalArgumentException("Invalid model manager type.");
}//else//
}//if//
else {
//TODO: Specify an identifier.
result = new ReflectionNetworkError(0, "Failed to locate a Model Manager.");
}//else//
}//if//
else {
throw new IllegalArgumentException();
}//else//
return result;
}//findEntities()//
/**
* Locates the model manager
* @param type The class whose model manager is to be found.
* @return The non-null model manager reference.
*/
private IModelManager locateModelManager(Class type) {
IModelManager result = null;
//The model manager will always be local. Each process has its own model manager which synchronizes with others via the ADA server network (when the app is deployed).//
result = ModelManagerContainer.getSingleton().getModelManager(type);
if(result == null) {
throw new IllegalArgumentException("The class " + type.getName() + " either is not marked for management or a model manager could not be found. The type should contain something similar to this code: static {registerTypeMetadata(xxxx.class, Entity.AO_MANAGEMENT_TYPE_LOAD_AS_NEEDED);}");
}//if//
return result;
}//locateModelManager()//
}//ModelInterface//