Package com.dooapp.gaedo.blueprints.transformers

Source Code of com.dooapp.gaedo.blueprints.transformers.SerializableTransformer

package com.dooapp.gaedo.blueprints.transformers;

import java.beans.XMLDecoder;
import java.beans.XMLEncoder;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.Serializable;

import javax.persistence.CascadeType;

import com.dooapp.gaedo.blueprints.AbstractBluePrintsBackedFinderService;
import com.dooapp.gaedo.blueprints.GraphDatabaseDriver;
import com.dooapp.gaedo.blueprints.GraphUtils;
import com.dooapp.gaedo.blueprints.Kind;
import com.dooapp.gaedo.blueprints.ObjectCache;
import com.dooapp.gaedo.blueprints.operations.Updater;
import com.dooapp.gaedo.blueprints.strategies.GraphMappingStrategy;
import com.dooapp.gaedo.finders.FinderCrudService;
import com.dooapp.gaedo.finders.repository.ServiceRepository;
import com.dooapp.gaedo.properties.TypeProperty;
import com.tinkerpop.blueprints.Graph;
import com.tinkerpop.blueprints.Vertex;

/**
* Serializable handling is quite particular. Instead of saving a simple node type, this transformer checks the contained value and try to save it according to its inner type
* (using {@link LiteralTransformer}, others {@link TupleTransformer} and services). This provide compact DB with good performances, at the cost of a complex class ... this one.
* @author ndx
*
*/
public class SerializableTransformer implements TupleTransformer<Serializable> {
  private Serializable readSerializable(String valueString) {
    ByteArrayInputStream stream = new ByteArrayInputStream(valueString.getBytes());
    XMLDecoder decoder = new XMLDecoder(stream);
    return (Serializable) decoder.readObject();
  }

  private String writeSerializable(Serializable value) {
    ByteArrayOutputStream stream = new ByteArrayOutputStream();
    XMLEncoder encoder = new XMLEncoder(stream);
    encoder.writeObject(value);
    encoder.close();
    try {
      stream.close();
      return new String(stream.toByteArray());
    } catch (IOException e) {
      throw new UnableToStoreSerializableException("impossible to store serializable value "+value, e);
    }
  }

  @Override
    public <DataType> void deleteVertex(AbstractBluePrintsBackedFinderService<? extends Graph, DataType, ?> service, GraphDatabaseDriver driver, Vertex objectVertex, Vertex valueVertex, Serializable value, ObjectCache objectsBeingUpdated) {
    ServiceRepository repository = driver.getRepository();
    // some first-level check to see if someone else than this transformer has any knowledge of value (because, well, this id will be longer than hell)
    Class<? extends Serializable> valueClass = value.getClass();
    if(repository.containsKey(valueClass)) {
      FinderCrudService dedicated = repository.get(valueClass);
      if (dedicated instanceof AbstractBluePrintsBackedFinderService) {
        AbstractBluePrintsBackedFinderService blueprints= (AbstractBluePrintsBackedFinderService) dedicated;
        blueprints.deleteOutEdgeVertex(objectVertex, valueVertex, value, objectsBeingUpdated);
        return;
      }
    }
    GraphUtils.removeSafely(service.getDatabase(), valueVertex);
  }

  /**
   * Get vertex for the value. To get that vertex, we first check the effective value type. If a literal or a tuple (other than serializable), we use that vertex value.
   * If a managed object, we use the service associated to that object. Finally, if an unknown serializable ... well, we serialize it
   * @param service
   * @param cast
   * @param objectsBeingUpdated
   * @return
   * @see com.dooapp.gaedo.blueprints.transformers.TupleTransformer#getVertexFor(AbstractBluePrintsBackedFinderService<? extends Graph, DataType, ?>, java.lang.Object, java.util.Map)
   */
  @Override
  public <DataType> Vertex getVertexFor(AbstractBluePrintsBackedFinderService<? extends Graph, DataType, ?> service, GraphDatabaseDriver driver, Serializable cast, CascadeType cascade,
          ObjectCache objectsBeingUpdated) {
    ServiceRepository repository = service.getRepository();
    // some first-level check to see if someone else than this transformer has any knowledge of value (because, well, this id will be longer than hell)
    Class<? extends Serializable> valueClass = cast.getClass();
    if(Tuples.containsKey(valueClass)) {
      if(Tuples.get(valueClass).equals(this)) {
        return getVertextForUnknownSerializable(service, repository, cast);
      }
    }
    // Gently ask service for effective access to value
    return service.getVertexFor(cast, CascadeType.REFRESH, objectsBeingUpdated);
  }


  private Vertex getVertextForUnknownSerializable(AbstractBluePrintsBackedFinderService<? extends Graph, ?, ?> service, ServiceRepository repository, Serializable value) {
    String serialized = writeSerializable(value);
    // Then indexed vertex id (for neo4j, typically)
    Class<? extends Serializable> valueClass = value.getClass();
    Vertex returned = service.loadVertexFor(serialized, valueClass.getName());
    // Finally create vertex
    if(returned==null) {
      returned = service.getDriver().createEmptyVertex(Serializable.class, serialized, value);
      service.getDriver().setValue(returned, serialized);
    }
    new Updater().updateLiteralPropertyIn(service.getDatabase(), serialized, returned, new TypeProperty(), valueClass);
    return returned;
  }

  @Override
  public String getIdOfTuple(ServiceRepository repository, Serializable value, CascadeType cascade, ObjectCache cache) {
    // some first-level check to see if someone else than this transformer has any knowledge of value (because, well, this id will be longer than hell)
    Class<? extends Serializable> valueClass = value.getClass();
    if(Tuples.containsKey(valueClass)) {
      if(Tuples.get(valueClass).equals(this)) {
        return writeSerializable(value);
      }
    }
    // Delegate to the rest of the world
    return GraphUtils.getIdOf(repository, value);
  }

  /**
   * For loading object, reverse job iof persisting is done, but way simpler, as using other persistences mechanisms allows us to load known serializable
   * using their assocaited literal transformers/services, which is WAAAAYYYYYYY cooler.
   * So, this method simple job is just to read value and deserialize it. Nice, no ?
   * @param classLoader
   * @param effectiveClass
   * @param key
   * @param repository
   * @param objectsBeingAccessed
   * @return
   * @see com.dooapp.gaedo.blueprints.transformers.TupleTransformer#loadObject(java.lang.ClassLoader, java.lang.Class, com.tinkerpop.blueprints.pgm.Vertex, com.dooapp.gaedo.finders.repository.ServiceRepository, java.util.Map)
   */
  @Override
  public Object loadObject(GraphDatabaseDriver driver, GraphMappingStrategy strategy, ClassLoader classLoader, Class effectiveClass, Vertex key, ServiceRepository repository, ObjectCache objectsBeingAccessed) {
    return readSerializable(driver.getValue(key).toString());
  }

  @Override
  public Object loadObject(GraphDatabaseDriver driver, GraphMappingStrategy strategy, ClassLoader classLoader, String effectiveType, Vertex key, ServiceRepository repository, ObjectCache objectsBeingAccessed) {
    return readSerializable(driver.getValue(key).toString());
  }

  @Override
  public boolean canHandle(ClassLoader classLoader, String effectiveType) {
    // TODO Auto-generated method stub
    throw new UnsupportedOperationException("method "+Transformer.class.getName()+"#canHandle has not yet been implemented AT ALL");
  }

  @Override
  public Kind getKind() {
    return Kind.bnode;
  }
}
TOP

Related Classes of com.dooapp.gaedo.blueprints.transformers.SerializableTransformer

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.