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

uqbar.arena.persistence.mapping.RelationMapping.scala Maven / Gradle / Ivy

The newest version!
package uqbar.arena.persistence.mapping

import java.lang.reflect.Type
import org.neo4j.graphdb.Node
import uqbar.arena.persistence.ConfigurationException
import uqbar.arena.persistence.Session
import uqbar.arena.persistence.reflection.TypeWrapper
import org.uqbar.commons.utils.ReflectionUtils
import org.neo4j.graphdb.DynamicRelationshipType
import org.neo4j.graphdb.Direction
import org.uqbar.commons.model.Entity
import scala.collection.JavaConversions._
import java.util.Collection

object RelationMapping {
  def create(name: String, fieldType: Type): RelationMapping = {
    val wrappedType = new TypeWrapper(fieldType)
    if (wrappedType.isCollectionOfPersistent)
      new CollectionRelationMapping(name, wrappedType)
    else
      new SimpleRelationMapping(name, wrappedType)
  }
}

abstract class RelationMapping(name: String, wrappedType: TypeWrapper) extends Mapping {
  checkRelation();

  def checkRelation() {
    if (wrappedType.isNative && wrappedType.isEnum && wrappedType.isBuiltinType) {
      throw new ConfigurationException(name + ":la annotation Relation no es aplicable a tipos nativos, Enum, String o java.util.Date:" + wrappedType.name);
    }
    if (!wrappedType.isCollectionOfPersistent && !wrappedType.isPersistent) {
      throw new ConfigurationException(name + ": la annotation Relation es solo aplicable a PersistentClass o a colecciones de PersistentClass:" + wrappedType.name);
    }
  }
  
  def invokeGetter(target: Object, propertyName: String) : Any = {
    try {
    	return ReflectionUtils.invokeGetter(target, propertyName)
    } catch {
      case e : RuntimeException => throw new Exception("Debe revisar el getter y setter de la propiedad " + propertyName + " para la entidad " + target.getClass)
    }
  }
  
  def invokeSetter(target: Object, propertyName: String, value: Any) {
    try {
    	ReflectionUtils.invokeSetter(target, propertyName, value)
    } catch {
      case e : RuntimeException => throw new Exception("Debe revisar el getter y setter de la propiedad " + propertyName + " para la entidad " + target.getClass)
    }
  }
}

class SimpleRelationMapping(name: String, wrappedType: TypeWrapper) extends RelationMapping(name, wrappedType) {

  def query(queryBuilder: QueryBuilder, target: Object) {
    val value = this.invokeGetter(target, this.name).asInstanceOf[Entity]
    if (value != null) {
      throw new Exception("Arena persistence no permite hacer query by example con relaciones entre objetos.")
    }
  }

  def persist(session: Session, node: Node, target: Object): Unit = {
    val value = this.invokeGetter(target, this.name) 
    val relType = DynamicRelationshipType.withName(this.name)
    val graphDB = session.graphDB

    val r = node.getSingleRelationship(relType, Direction.OUTGOING)
    if (r != null) {
      r.delete()
    }

    if (value == null) {
      return
    }

    val entity = value.asInstanceOf[Entity]
    if (entity.isNew())
      session.save(entity)

    val otherNode = graphDB.getNodeById(entity.getId().longValue())
    node.createRelationshipTo(otherNode, relType)
  }

  def hidrate(session: Session, node: Node, target: Object): Unit = {
    val relType = DynamicRelationshipType.withName(this.name)
    val graphDB = session.graphDB
    val r = node.getSingleRelationship(relType, Direction.OUTGOING)

    if (r == null) {
      this.invokeSetter(target, this.name, null)
      return
    }

    val otherNode = r.getEndNode()

    val entity: Any = session.get(otherNode.getProperty("clazzName").toString(), otherNode.getId().intValue())
    try {
    	this.invokeSetter(target, this.name, entity)
    } catch {
      case e : RuntimeException => throw new Exception("Debe revisar el getter y setter de la propiedad " + this.name + " para la entidad " + target.getClass)
    }
  }
}

class CollectionRelationMapping(name: String, wrappedType: TypeWrapper) extends RelationMapping(name, wrappedType) {
  def query(queryBuilder: QueryBuilder, target: Object) {
    val value = this.invokeGetter(target, this.name).asInstanceOf[Collection[Entity]]
    if (value != null && !value.isEmpty()) {
      throw new Exception("Arena persistence no permite hacer query by example con relaciones entre objetos.")
    }
  }

  def persist(session: Session, node: Node, target: Object): Unit = {
    val relType = DynamicRelationshipType.withName(this.name)
    val graphDB = session.graphDB
    val rels = node.getRelationships(relType, Direction.OUTGOING)
    for (r <- rels) {
      r.delete();
    }
    val value = this.invokeGetter(target, this.name).asInstanceOf[Collection[Entity]]
    if (value == null || value.isEmpty())
      return

    for (e <- value) {
      if (e.isNew())
        session.save(e)

      val otherNode = graphDB.getNodeById(e.getId().longValue())
      node.createRelationshipTo(otherNode, relType)
    }
  }

  def hidrate(session: Session, node: Node, target: Object): Unit = {
    val relType = DynamicRelationshipType.withName(this.name)
    val graphDB = session.graphDB
    val rels = node.getRelationships(relType, Direction.OUTGOING)

    var value = this.invokeGetter(target, this.name).asInstanceOf[Collection[Entity]]

    if (value == null || !value.isEmpty()) {
      value = this.wrappedType.newInstance();
      this.invokeSetter(target, this.name, value)
    }

    for (r <- rels) {
      val otherNode = r.getEndNode()
      val entity: Entity = session.get(otherNode.getProperty("clazzName").toString(), otherNode.getId().intValue()).asInstanceOf[Entity]
      value.add(entity)
    }
  }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy