All Downloads are FREE. Search and download functionalities are using the official Maven repository.
Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
com.backendless.persistence.BackendlessSerializer Maven / Gradle / Ivy
Go to download
Android SDK used by developers to provide Backendless API in apps.
/*
* ********************************************************************************************************************
*
* 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.persistence;
import com.backendless.Backendless;
import com.backendless.BackendlessUser;
import com.backendless.FootprintsManager;
import com.backendless.Persistence;
import com.backendless.exceptions.BackendlessException;
import com.backendless.exceptions.ExceptionMessage;
import com.backendless.geo.GeoPoint;
import java.lang.reflect.Array;
import java.util.*;
/**
* Handles object to Map serialization for Backendless services.
*/
public abstract class BackendlessSerializer
{
private static HashMap serializers = new HashMap();
private static IObjectSerializer DEFAULT_SERIALIZER = new DefaultSerializer();
public abstract boolean shouldTraverse();
public static void addSerializer( Class clazz, IObjectSerializer serializer )
{
serializers.put( clazz, serializer );
}
/**
* Serializes Object to Map using WebOrb's serializer.
*
* @param entity object to be serialized
* @return Map corresponding to given Object
*/
public static Map serializeToMap( Object entity )
{
IObjectSerializer serializer = getSerializer( entity.getClass() );
return (Map) serializer.serializeToMap( entity, new HashMap>() );
}
/**
* Uses pluggable serializers to locate one for the class and get the name which should be used for serialization.
* The name must match the table name where instance of clazz are persisted
*
* @param clazz
* @return Backendless-friendly class/table name
*/
public static String getSimpleName( Class clazz )
{
IObjectSerializer serializer = getSerializer( clazz );
return serializer.getClassName( clazz );
}
public static Class getClassForDeserialization( Class clazz )
{
IObjectSerializer serializer = getSerializer( clazz );
return serializer.getSerializationFriendlyClass( clazz );
}
public Object serializeToMap( Object entity, Map> serializedCache )
{
if( entity.getClass().isArray() )
return serializeArray( entity, serializedCache );
if( entity.getClass().isEnum() )
return ((Enum) entity).name();
Map serializedEntity = new HashMap();
if( entity.getClass() == BackendlessUser.class )
serializedEntity = ((BackendlessUser) entity).getProperties();
else
weborb.util.ObjectInspector.getObjectProperties( entity.getClass(), entity, (HashMap) serializedEntity, new ArrayList(), true, shouldTraverse() );
serializedCache.put( entity, serializedEntity );
FootprintsManager.getInstance().Inner.putMissingPropsToEntityMap( entity, serializedEntity );
//put ___class field, otherwise server will not be able to detect class
serializedEntity.put( Persistence.REST_CLASS_FIELD, getSimpleName( entity.getClass() ) );
//recursively serialize object properties
Iterator> entityIterator = serializedEntity.entrySet().iterator();
while( entityIterator.hasNext() )
{
Map.Entry entityEntry = entityIterator.next();
// ignoring properties which contain $. This occurs in InstantRun in AndroidStudio - it injects $change property.
if( entityEntry.getKey().contains( "$" ) )
{
entityIterator.remove();
continue;
}
// ignore Parcelable CREATOR field on Android
// http://developer.android.com/reference/android/os/Parcelable.html
if( Backendless.isAndroid() && entityEntry.getKey().equals( Persistence.PARCELABLE_CREATOR_FIELD_NAME ) )
{
entityIterator.remove();
continue;
}
Object entityEntryValue = entityEntry.getValue();
// ignore null entries and GeoPoints
if( entityEntryValue == null || entityEntryValue instanceof GeoPoint )
continue;
// check for anonymous class entry
if( entityEntryValue.getClass().isAnonymousClass() )
throw new BackendlessException( String.format( ExceptionMessage.ANONYMOUS_CLASSES_PROHIBITED, entityEntry.getKey() ) );
//check if entity entry is collection
if( entityEntryValue instanceof List )
{
List listEntry = (List) entityEntryValue;
// empty lists should not be sent to the server
if( listEntry.isEmpty() )
{
// if there is no object id, remove empty list
if( !serializedEntity.containsKey( Persistence.DEFAULT_OBJECT_ID_FIELD ) ||
serializedEntity.get( Persistence.DEFAULT_OBJECT_ID_FIELD ) == null )
entityIterator.remove();
continue;
}
//do nothing with lists of GeoPoints
if( listEntry.iterator().next() instanceof GeoPoint )
continue;
// check for anonymous class entry
if( listEntry.iterator().next().getClass().isAnonymousClass() )
throw new BackendlessException( String.format( ExceptionMessage.ANONYMOUS_CLASSES_PROHIBITED, entityEntry.getKey() ) );
List newCollection = new ArrayList();
for( Object listEntryItem : listEntry )
if( !isBelongsJdk( listEntryItem.getClass() ) )
newCollection.add( getOrMakeSerializedObject( listEntryItem, serializedCache ) );
else
newCollection.add( listEntryItem );
entityEntry.setValue( newCollection );
}
else if( entityEntryValue instanceof Object[] )
{
Object[] arrayEntry = (Object[]) entityEntryValue;
//do nothing with empty arrays and arrays of GeoPoints
if( arrayEntry.length == 0 || arrayEntry[ 0 ] instanceof GeoPoint )
continue;
// check for anonymous class entry
if( arrayEntry[ 0 ].getClass().isAnonymousClass() )
throw new BackendlessException( String.format( ExceptionMessage.ANONYMOUS_CLASSES_PROHIBITED, entityEntry.getKey() ) );
List newCollection = new ArrayList();
for( Object arrayEntryItem : arrayEntry )
if( !isBelongsJdk( arrayEntryItem.getClass() ) )
newCollection.add( getOrMakeSerializedObject( arrayEntryItem, serializedCache ) );
else
newCollection.add( arrayEntryItem );
entityEntry.setValue( newCollection );
}
else //not collection
{
if( !isBelongsJdk( entityEntryValue.getClass() ) )
entityEntry.setValue( getOrMakeSerializedObject( entityEntryValue, serializedCache ) );
}
}
return serializedEntity;
}
private Object serializeArray( Object entity, Map> serializedCache )
{
int length = Array.getLength( entity );
Object[] objects = new Object[ length ];
for( int i = 0; i < length; i++ )
{
objects[ i ] = getOrMakeSerializedObject( Array.get( entity, i ), serializedCache );
}
return objects;
}
/**
* Returns serialized object from cache or serializes object if it's not present in cache.
*
* @param entityEntryValue object to be serialized
* @return Map formed from given object
*/
private Object getOrMakeSerializedObject( Object entityEntryValue,
Map> serializedCache )
{
if( serializedCache.containsKey( entityEntryValue ) ) //cyclic relation
{
//take from cache and substitute
return serializedCache.get( entityEntryValue );
}
else //not cyclic relation
{
//serialize and put into result
return serializeToMap( entityEntryValue, serializedCache );
}
}
/**
* Serializes entities inside BackendlessUser properties.
*
* @param user BackendlessUser whose properties need to be serialized
*/
public static void serializeUserProperties( BackendlessUser user )
{
Map serializedProperties = user.getProperties();
Set> properties = serializedProperties.entrySet();
for( Map.Entry property : properties )
{
Object propertyValue = property.getValue();
if( propertyValue != null && !propertyValue.getClass().isArray() && !propertyValue.getClass().isEnum() && !isBelongsJdk( propertyValue.getClass() ) )
{
property.setValue( serializeToMap( propertyValue ) );
}
}
user.setProperties( serializedProperties );
}
/**
* Checks whether class is defined in JDK or it is user-defined class.
* http://stackoverflow.com/questions/8703678/how-can-i-check-if-a-class-belongs-to-java-jdk
*
* @param clazz Class to be checked
* @return true if this class is from JDK, false if class is user-defined
*/
public static boolean isBelongsJdk( Class clazz )
{
return clazz.getClassLoader() == "".getClass().getClassLoader();
}
/**
* Returns a serializer for the class
* @param clazz
* @return
*/
private static IObjectSerializer getSerializer( Class clazz )
{
Iterator> iterator = serializers.entrySet().iterator();
IObjectSerializer serializer = DEFAULT_SERIALIZER;
while( iterator.hasNext() )
{
Map.Entry entry = iterator.next();
if( entry.getKey().isAssignableFrom( clazz ) )
{
serializer = entry.getValue();
break;
}
}
return serializer;
}
}