All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.backendless.Persistence Maven / Gradle / Ivy

There is a newer version: 3.1.0
Show newest version
/*
 * ********************************************************************************************************************
 *  

* BACKENDLESS.COM CONFIDENTIAL *

* ******************************************************************************************************************** *

* Copyright 2012 BACKENDLESS.COM. All Rights Reserved. *

* NOTICE: All information contained herein is, and remains the property of Backendless.com and its suppliers, * if any. The intellectual and technical concepts contained herein are proprietary to Backendless.com and its * suppliers and may be covered by U.S. and Foreign Patents, patents in process, and are protected by trade secret * or copyright law. Dissemination of this information or reproduction of this material is strictly forbidden * unless prior written permission is obtained from Backendless.com. *

* ******************************************************************************************************************** */ package com.backendless; import com.backendless.async.callback.AsyncCallback; import com.backendless.core.responder.AdaptingResponder; import com.backendless.core.responder.policy.PoJoAdaptingPolicy; import com.backendless.exceptions.BackendlessException; import com.backendless.exceptions.BackendlessFault; import com.backendless.exceptions.ExceptionMessage; import com.backendless.persistence.BackendlessDataQuery; import com.backendless.persistence.QueryOptions; import com.backendless.property.ObjectProperty; import com.backendless.utils.ResponderHelper; import weborb.types.Types; import weborb.writer.IObjectSubstitutor; import weborb.writer.MessageWriter; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.util.*; public final class Persistence { private final static String PERSISTENCE_MANAGER_SERVER_ALIAS = "com.backendless.services.persistence.PersistenceService"; private final static String DEFAULT_OBJECT_ID_GETTER = "getObjectId"; public final static String DEFAULT_OBJECT_ID_FIELD = "objectId"; public final static String DEFAULT_CREATED_FIELD = "created"; public final static String DEFAULT_UPDATED_FIELD = "updated"; public final static String DEFAULT_META_FIELD = "__meta"; public final static String LOAD_ALL_RELATIONS = "*"; public final static DataPermission Permissions = new DataPermission(); private static final Persistence instance = new Persistence(); private static final Class backendlessUserClass = BackendlessUser.class; static Persistence getInstance() { return instance; } private Persistence() { Types.addClientClassMapping( "com.backendless.services.persistence.BackendlessDataQuery", BackendlessDataQuery.class ); Types.addClientClassMapping( "com.backendless.services.persistence.BackendlessCollection", BackendlessCollection.class ); Types.addClientClassMapping( "com.backendless.services.persistence.ObjectProperty", ObjectProperty.class ); Types.addClientClassMapping( "com.backendless.services.persistence.QueryOptions", QueryOptions.class ); } public void mapTableToClass( String tableName, Class clazz ) { weborb.types.Types.addClientClassMapping( tableName, clazz ); } public E save( final E entity ) throws BackendlessException { if( entity == null ) throw new IllegalArgumentException( ExceptionMessage.NULL_ENTITY ); checkDeclaredType( entity.getClass() ); final Map serializedEntity = serializeToMap( entity ); MessageWriter.setObjectSubstitutor( new IObjectSubstitutor() { @Override public Object substitute( Object o ) { if( o == entity ) return serializedEntity; else return o; } } ); FootprintsManager.getInstance().Inner.putMissingPropsToEntityMap( entity, serializedEntity ); try { E newEntity; if( serializedEntity.get( Footprint.OBJECT_ID_FIELD_NAME ) == null ) { newEntity = (E) create( entity.getClass(), serializedEntity ); FootprintsManager.getInstance().Inner.duplicateFootprintForObject( entity, newEntity ); } else { newEntity = (E) update( entity.getClass(), serializedEntity ); FootprintsManager.getInstance().Inner.updateFootprintForObject( newEntity, entity ); } return newEntity; } finally { MessageWriter.setObjectSubstitutor( null ); } } public void save( final E entity, final AsyncCallback responder ) { try { if( entity == null ) throw new IllegalArgumentException( ExceptionMessage.NULL_ENTITY ); checkDeclaredType( entity.getClass() ); final Map serializedEntity = serializeToMap( entity ); MessageWriter.setObjectSubstitutor( new IObjectSubstitutor() { @Override public Object substitute( Object o ) { if( o == entity ) return serializedEntity; else return o; } } ); FootprintsManager.getInstance().Inner.putMissingPropsToEntityMap( entity, serializedEntity ); if( serializedEntity.get( Footprint.OBJECT_ID_FIELD_NAME ) == null ) create( (Class) entity.getClass(), serializedEntity, new AsyncCallback() { @Override public void handleResponse( E newEntity ) { MessageWriter.setObjectSubstitutor( null ); FootprintsManager.getInstance().Inner.duplicateFootprintForObject( entity, newEntity ); if( responder != null ) responder.handleResponse( newEntity ); } @Override public void handleFault( BackendlessFault fault ) { MessageWriter.setObjectSubstitutor( null ); if( responder != null ) responder.handleFault( fault ); } } ); else update( (Class) entity.getClass(), serializedEntity, new AsyncCallback() { @Override public void handleResponse( E newEntity ) { FootprintsManager.getInstance().Inner.updateFootprintForObject( newEntity, entity ); if( responder != null ) responder.handleResponse( newEntity ); } @Override public void handleFault( BackendlessFault fault ) { if( responder != null ) responder.handleFault( fault ); } } ); } catch( Throwable e ) { if( responder != null ) responder.handleFault( new BackendlessFault( e ) ); } } private E create( Class aClass, Map entity ) throws BackendlessException { if( entity == null ) throw new IllegalArgumentException( ExceptionMessage.NULL_ENTITY ); return (E) Invoker.invokeSync( PERSISTENCE_MANAGER_SERVER_ALIAS, "create", new Object[] { Backendless.getApplicationId(), Backendless.getVersion(), getSimpleName( aClass ), entity }, ResponderHelper.getPOJOAdaptingResponder( aClass ) ); } private void create( final Class aClass, final Map entity, final AsyncCallback responder ) { try { if( entity == null ) throw new IllegalArgumentException( ExceptionMessage.NULL_ENTITY ); Invoker.invokeAsync( PERSISTENCE_MANAGER_SERVER_ALIAS, "create", new Object[] { Backendless.getApplicationId(), Backendless.getVersion(), getSimpleName( aClass ), entity }, responder, ResponderHelper.getPOJOAdaptingResponder( aClass ) ); } catch( Throwable e ) { if( responder != null ) responder.handleFault( new BackendlessFault( e ) ); } } private E update( Class aClass, Map entity ) throws BackendlessException { if( entity == null ) throw new IllegalArgumentException( ExceptionMessage.NULL_ENTITY ); return (E) Invoker.invokeSync( PERSISTENCE_MANAGER_SERVER_ALIAS, "update", new Object[] { Backendless.getApplicationId(), Backendless.getVersion(), getSimpleName( aClass ), entity }, ResponderHelper.getPOJOAdaptingResponder( aClass ) ); } private void update( final Class aClass, final Map entity, final AsyncCallback responder ) { try { if( entity == null ) throw new IllegalArgumentException( ExceptionMessage.NULL_ENTITY ); Invoker.invokeAsync( PERSISTENCE_MANAGER_SERVER_ALIAS, "update", new Object[] { Backendless.getApplicationId(), Backendless.getVersion(), getSimpleName( aClass ), entity }, responder, ResponderHelper.getPOJOAdaptingResponder( aClass ) ); } catch( Throwable e ) { if( responder != null ) responder.handleFault( new BackendlessFault( e ) ); } } protected Long remove( final E entity ) throws BackendlessException { if( entity == null ) throw new IllegalArgumentException( ExceptionMessage.NULL_ENTITY ); String id = getEntityId( entity ); if( id == null ) throw new IllegalArgumentException( ExceptionMessage.NULL_ID ); Object result = Invoker.invokeSync( PERSISTENCE_MANAGER_SERVER_ALIAS, "remove", new Object[] { Backendless.getApplicationId(), Backendless.getVersion(), getSimpleName( entity.getClass() ), id } ); FootprintsManager.getInstance().Inner.removeFootprintForObject( entity ); return ((Number) result).longValue(); } protected void remove( final E entity, final AsyncCallback responder ) { try { if( entity == null ) throw new IllegalArgumentException( ExceptionMessage.NULL_ENTITY ); String id = getEntityId( entity ); if( id == null ) throw new IllegalArgumentException( ExceptionMessage.NULL_ID ); Invoker.invokeAsync( PERSISTENCE_MANAGER_SERVER_ALIAS, "remove", new Object[] { Backendless.getApplicationId(), Backendless.getVersion(), getSimpleName( entity.getClass() ), id }, new AsyncCallback() { @Override public void handleResponse( Object response ) { FootprintsManager.getInstance().Inner.removeFootprintForObject( entity ); if( responder == null ) return; responder.handleResponse( ((Number) response).longValue() ); } @Override public void handleFault( BackendlessFault fault ) { if( responder != null ) responder.handleFault( fault ); } } ); } catch( Throwable e ) { if( responder != null ) responder.handleFault( new BackendlessFault( e ) ); } } protected E findById( final Class entity, final String id, final List relations ) throws BackendlessException { if( entity == null ) throw new IllegalArgumentException( ExceptionMessage.NULL_ENTITY_NAME ); if( id == null ) throw new IllegalArgumentException( ExceptionMessage.NULL_ID ); return (E) Invoker.invokeSync( PERSISTENCE_MANAGER_SERVER_ALIAS, "findById", new Object[] { Backendless.getApplicationId(), Backendless.getVersion(), getSimpleName( entity ), id, relations }, ResponderHelper.getPOJOAdaptingResponder( entity ) ); } protected E findById( final Class entity, final String id, final List relations, final int relationsDepth ) throws BackendlessException { if( entity == null ) throw new IllegalArgumentException( ExceptionMessage.NULL_ENTITY_NAME ); if( id == null ) throw new IllegalArgumentException( ExceptionMessage.NULL_ID ); return (E) Invoker.invokeSync( PERSISTENCE_MANAGER_SERVER_ALIAS, "findById", new Object[] { Backendless.getApplicationId(), Backendless.getVersion(), entity.getSimpleName(), id, relations, relationsDepth }, ResponderHelper.getPOJOAdaptingResponder( entity ) ); } protected void findById( final Class entity, final String id, final List relations, AsyncCallback responder ) { try { if( entity == null ) throw new IllegalArgumentException( ExceptionMessage.NULL_ENTITY ); if( id == null ) throw new IllegalArgumentException( ExceptionMessage.NULL_ID ); Invoker.invokeAsync( PERSISTENCE_MANAGER_SERVER_ALIAS, "findById", new Object[] { Backendless.getApplicationId(), Backendless.getVersion(), getSimpleName( entity ), id, relations }, responder, ResponderHelper.getPOJOAdaptingResponder( entity ) ); } catch( Throwable e ) { if( responder != null ) responder.handleFault( new BackendlessFault( e ) ); } } protected void findById( final Class entity, final String id, final List relations, final int relationsDepth, AsyncCallback responder ) { try { if( entity == null ) throw new IllegalArgumentException( ExceptionMessage.NULL_ENTITY ); if( id == null ) throw new IllegalArgumentException( ExceptionMessage.NULL_ID ); Invoker.invokeAsync( PERSISTENCE_MANAGER_SERVER_ALIAS, "findById", new Object[] { Backendless.getApplicationId(), Backendless.getVersion(), entity.getSimpleName(), id, relations, relationsDepth }, responder ); } catch( Throwable e ) { if( responder != null ) responder.handleFault( new BackendlessFault( e ) ); } } protected void loadRelations( final E entity, final List relations ) throws Exception { if( entity == null ) throw new IllegalArgumentException( ExceptionMessage.NULL_ENTITY_NAME ); String id = getEntityId( entity ); if( id == null ) throw new IllegalArgumentException( ExceptionMessage.NULL_ID ); E loadedRelations = (E) Invoker.invokeSync( PERSISTENCE_MANAGER_SERVER_ALIAS, "loadRelations", new Object[] { Backendless.getApplicationId(), Backendless.getVersion(), getSimpleName( entity.getClass() ), id, relations }, new AdaptingResponder( (Class) entity.getClass(), new PoJoAdaptingPolicy() ) ); loadRelationsToEntity( entity, loadedRelations, relations ); } protected void loadRelations( final E entity, final List relations, final AsyncCallback responder ) { try { if( entity == null ) throw new IllegalArgumentException( ExceptionMessage.NULL_ENTITY ); String id = getEntityId( entity ); if( id == null ) throw new IllegalArgumentException( ExceptionMessage.NULL_ID ); Invoker.invokeAsync( PERSISTENCE_MANAGER_SERVER_ALIAS, "loadRelations", new Object[] { Backendless.getApplicationId(), Backendless.getVersion(), getSimpleName( entity.getClass() ), id, relations }, new AsyncCallback() { @Override public void handleResponse( E loadedRelations ) { try { loadRelationsToEntity( entity, loadedRelations, relations ); if( responder != null ) responder.handleResponse( entity ); } catch( Exception e ) { if( responder != null ) responder.handleFault( new BackendlessFault( e ) ); } } @Override public void handleFault( BackendlessFault fault ) { if( responder != null ) responder.handleFault( fault ); } }, new AdaptingResponder( (Class) entity.getClass(), new PoJoAdaptingPolicy() ) ); } catch( Throwable e ) { if( responder != null ) responder.handleFault( new BackendlessFault( e ) ); } } private void loadRelationsToEntity( E entity, E loadedRelations, List relations ) throws IllegalAccessException { if( entity.getClass().equals( backendlessUserClass ) ) { BackendlessUser userWithRelations = (BackendlessUser) loadedRelations; BackendlessUser sourceUser = (BackendlessUser) entity; sourceUser.putProperties( userWithRelations.getProperties() ); } else { Field[] declaredFields = entity.getClass().getDeclaredFields(); for( Field declaredField : declaredFields ) { if( !relations.contains( declaredField.getName() ) ) continue; if( !declaredField.isAccessible() ) declaredField.setAccessible( true ); declaredField.set( entity, declaredField.get( loadedRelations ) ); } } } public List describe( String classSimpleName ) throws BackendlessException { if( classSimpleName == null || classSimpleName.equals( "" ) ) throw new IllegalArgumentException( ExceptionMessage.NULL_ENTITY_NAME ); ObjectProperty[] response = Invoker.invokeSync( PERSISTENCE_MANAGER_SERVER_ALIAS, "describe", new Object[] { Backendless.getApplicationId(), Backendless.getVersion(), classSimpleName } ); return Arrays.asList( response ); } public void describe( String classSimpleName, final AsyncCallback> responder ) { try { if( classSimpleName == null || classSimpleName.equals( "" ) ) throw new IllegalArgumentException( ExceptionMessage.NULL_ENTITY_NAME ); Invoker.invokeAsync( PERSISTENCE_MANAGER_SERVER_ALIAS, "describe", new Object[] { Backendless.getApplicationId(), Backendless.getVersion(), classSimpleName }, new AsyncCallback() { @Override public void handleResponse( ObjectProperty[] response ) { if( responder != null ) responder.handleResponse( Arrays.asList( response ) ); } @Override public void handleFault( BackendlessFault fault ) { if( responder != null ) responder.handleFault( fault ); } } ); } catch( Throwable e ) { if( responder != null ) responder.handleFault( new BackendlessFault( e ) ); } } protected BackendlessCollection find( Class entity, BackendlessDataQuery dataQuery ) throws BackendlessException { if( entity == null ) throw new IllegalArgumentException( ExceptionMessage.NULL_ENTITY ); checkPageSizeAndOffset( dataQuery ); Object[] args = new Object[] { Backendless.getApplicationId(), Backendless.getVersion(), getSimpleName( entity ), dataQuery }; BackendlessCollection result = (BackendlessCollection) Invoker.invokeSync( PERSISTENCE_MANAGER_SERVER_ALIAS, "find", args, ResponderHelper.getCollectionAdaptingResponder( entity ) ); result.setQuery( dataQuery ); result.setType( entity ); return result; } protected void find( final Class entity, final BackendlessDataQuery dataQuery, final AsyncCallback> responder ) { try { if( entity == null ) throw new IllegalArgumentException( ExceptionMessage.NULL_ENTITY ); checkPageSizeAndOffset( dataQuery ); AsyncCallback> callback = new AsyncCallback>() { @Override public void handleResponse( BackendlessCollection response ) { if( responder != null ) { response.setQuery( dataQuery ); response.setType( entity ); responder.handleResponse( response ); } } @Override public void handleFault( BackendlessFault fault ) { if( responder != null ) responder.handleFault( fault ); } }; Object[] args = new Object[] { Backendless.getApplicationId(), Backendless.getVersion(), getSimpleName( entity ), dataQuery }; Invoker.invokeAsync( PERSISTENCE_MANAGER_SERVER_ALIAS, "find", args, callback, ResponderHelper.getCollectionAdaptingResponder( entity ) ); } catch( Throwable e ) { if( responder != null ) responder.handleFault( new BackendlessFault( e ) ); } } protected E first( final Class entity ) throws BackendlessException { if( entity == null ) throw new IllegalArgumentException( ExceptionMessage.NULL_ENTITY ); return (E) Invoker.invokeSync( PERSISTENCE_MANAGER_SERVER_ALIAS, "first", new Object[] { Backendless.getApplicationId(), Backendless.getVersion(), getSimpleName( entity ) }, ResponderHelper.getPOJOAdaptingResponder( entity ) ); } protected E first( final Class entity, final List relations, final int relationsDepth ) throws BackendlessException { if( entity == null ) throw new IllegalArgumentException( ExceptionMessage.NULL_ENTITY ); return (E) Invoker.invokeSync( PERSISTENCE_MANAGER_SERVER_ALIAS, "first", new Object[] { Backendless.getApplicationId(), Backendless.getVersion(), entity.getSimpleName(), relations, relationsDepth }, ResponderHelper.getPOJOAdaptingResponder( entity ) ); } protected void first( final Class entity, final AsyncCallback responder ) { try { if( entity == null ) throw new IllegalArgumentException( ExceptionMessage.NULL_ENTITY ); Invoker.invokeAsync( PERSISTENCE_MANAGER_SERVER_ALIAS, "first", new Object[] { Backendless.getApplicationId(), Backendless.getVersion(), getSimpleName( entity ) }, responder, ResponderHelper.getPOJOAdaptingResponder( entity ) ); } catch( Throwable e ) { if( responder != null ) responder.handleFault( new BackendlessFault( e ) ); } } protected void first( final Class entity, final List relations, final int relationsDepth, final AsyncCallback responder ) { try { if( entity == null ) throw new IllegalArgumentException( ExceptionMessage.NULL_ENTITY ); Invoker.invokeAsync( PERSISTENCE_MANAGER_SERVER_ALIAS, "first", new Object[] { Backendless.getApplicationId(), Backendless.getVersion(), entity.getSimpleName(), relations, relationsDepth }, responder, ResponderHelper.getPOJOAdaptingResponder( entity ) ); } catch( Throwable e ) { if( responder != null ) responder.handleFault( new BackendlessFault( e ) ); } } protected E last( final Class entity ) throws BackendlessException { if( entity == null ) throw new IllegalArgumentException( ExceptionMessage.NULL_ENTITY ); return (E) Invoker.invokeSync( PERSISTENCE_MANAGER_SERVER_ALIAS, "last", new Object[] { Backendless.getApplicationId(), Backendless.getVersion(), getSimpleName( entity ) }, ResponderHelper.getPOJOAdaptingResponder( entity ) ); } protected E last( final Class entity, final List relations, final int relationsDepth ) throws BackendlessException { if( entity == null ) throw new IllegalArgumentException( ExceptionMessage.NULL_ENTITY ); return (E) Invoker.invokeSync( PERSISTENCE_MANAGER_SERVER_ALIAS, "last", new Object[] { Backendless.getApplicationId(), Backendless.getVersion(), entity.getSimpleName(), relations, relationsDepth }, ResponderHelper.getPOJOAdaptingResponder( entity ) ); } protected void last( final Class entity, final AsyncCallback responder ) { try { if( entity == null ) throw new IllegalArgumentException( ExceptionMessage.NULL_ENTITY ); Invoker.invokeAsync( PERSISTENCE_MANAGER_SERVER_ALIAS, "last", new Object[] { Backendless.getApplicationId(), Backendless.getVersion(), getSimpleName( entity ) }, responder, ResponderHelper.getPOJOAdaptingResponder( entity ) ); } catch( Throwable e ) { if( responder != null ) responder.handleFault( new BackendlessFault( e ) ); } } protected void last( final Class entity, final List relations, final int relationsDepth, final AsyncCallback responder ) { try { if( entity == null ) throw new IllegalArgumentException( ExceptionMessage.NULL_ENTITY ); Invoker.invokeAsync( PERSISTENCE_MANAGER_SERVER_ALIAS, "last", new Object[] { Backendless.getApplicationId(), Backendless.getVersion(), entity.getSimpleName(), relations, relationsDepth }, responder, ResponderHelper.getPOJOAdaptingResponder( entity ) ); } catch( Throwable e ) { if( responder != null ) responder.handleFault( new BackendlessFault( e ) ); } } public IDataStore of( final Class entityClass ) { if( entityClass == null ) throw new IllegalArgumentException( ExceptionMessage.NULL_ENTITY ); return DataStoreFactory.createDataStore( entityClass ); } /*private Map getEntityMapWithFootprint( Object entity ) { }*/ static String getEntityId( Object entity ) throws BackendlessException { String id; try { Method declaredMethod = entity.getClass().getMethod( DEFAULT_OBJECT_ID_GETTER, new Class[ 0 ] ); if( !declaredMethod.isAccessible() ) declaredMethod.setAccessible( true ); id = (String) declaredMethod.invoke( entity ); } catch( Exception e ) { id = null; } if( id == null ) id = FootprintsManager.getInstance().getObjectId( entity ); return id; } private void checkDeclaredType( Class entityClass ) { if( entityClass.isArray() || entityClass.isAssignableFrom( Iterable.class ) || entityClass.isAssignableFrom( Map.class ) ) throw new IllegalArgumentException( ExceptionMessage.WRONG_ENTITY_TYPE ); try { Constructor[] constructors = entityClass.getConstructors(); if( constructors.length > 0 ) entityClass.getConstructor( new Class[ 0 ] ); } catch( NoSuchMethodException e ) { throw new IllegalArgumentException( ExceptionMessage.ENTITY_MISSING_DEFAULT_CONSTRUCTOR ); } } private void checkPageSizeAndOffset( BackendlessDataQuery dataQuery ) throws BackendlessException { if( dataQuery != null ) { if( dataQuery.getOffset() < 0 ) throw new IllegalArgumentException( ExceptionMessage.WRONG_OFFSET ); if( dataQuery.getPageSize() < 0 ) throw new IllegalArgumentException( ExceptionMessage.WRONG_PAGE_SIZE ); } } static Map serializeToMap( T entity ) { if( entity.getClass().equals( backendlessUserClass ) ) return ((BackendlessUser) entity).getProperties(); HashMap result = new HashMap(); weborb.util.ObjectInspector.getObjectProperties( entity.getClass(), entity, result, new ArrayList(), true, true ); return result; } private String getSimpleName( Class clazz ) { if( clazz.equals( backendlessUserClass ) ) return "Users"; else return clazz.getSimpleName(); } }