Package net.sourceforge.javautil.database.jpa.xml

Source Code of net.sourceforge.javautil.database.jpa.xml.JPATranslationGuide$EntityDocumentVisitor

package net.sourceforge.javautil.database.jpa.xml;

import java.lang.annotation.Annotation;

import javax.persistence.Entity;
import javax.persistence.EntityManager;
import javax.persistence.Id;
import javax.persistence.ManyToMany;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.OneToOne;
import javax.persistence.Transient;

import org.xml.sax.Attributes;

import net.sourceforge.javautil.common.ReflectionUtil;
import net.sourceforge.javautil.common.reflection.ObjectVisitorBase;
import net.sourceforge.javautil.common.reflection.cache.ClassCache;
import net.sourceforge.javautil.common.reflection.cache.ClassDescriptor;
import net.sourceforge.javautil.common.reflection.cache.ClassProperty;
import net.sourceforge.javautil.common.xml.XMLDocument;
import net.sourceforge.javautil.common.xml.XMLDocumentElement;
import net.sourceforge.javautil.common.xml.XMLDocumentElementBase;
import net.sourceforge.javautil.common.xml.XMLDocumentElementDefinition;
import net.sourceforge.javautil.common.xml.XMLDocumentElementNoOp;
import net.sourceforge.javautil.common.xml.XMLTranslationGuideBase;
import net.sourceforge.javautil.common.xml.XMLWriter;

/**
* This will translate special cases for {@link XMLDocument}'s that are also JPA entities.
* {@link ManyToMany} relationships are not currently supported.
*
* @author elponderador
* @author $Author: ponderator $
* @version $Id: JPATranslationGuide.java 1149 2009-10-21 21:34:58Z ponderator $
*/
public class JPATranslationGuide extends XMLTranslationGuideBase {
 
  protected final EntityManager em;
 
  public JPATranslationGuide() { this(null); }
  public JPATranslationGuide(EntityManager em) {
    this.em = em;
  }

  public XMLDocumentElement createElement(XMLDocumentElement parent, XMLDocumentElementDefinition definition, Object instanceOverride) {
    boolean translate = false;
   
    ClassProperty type = definition.getProperty();
    if (type != null) {
      OneToOne oto = type.getAnnotation(OneToOne.class);
      if (oto != null) {
        if ("".equals( oto.mappedBy() )) translate = true; else return new XMLDocumentElementNoOp(parent, definition);
      }
      else if (type.getAnnotation(ManyToOne.class) != null) translate = true;
      else if (type.getAnnotation(OneToMany.class) != null) return new XMLDocumentElementNoOp(parent, definition);
      else if (type.getAnnotation(ManyToMany.class) != null) return new XMLDocumentElementNoOp(parent, definition);
     
      if (type.getAnnotation(Transient.class) != null) return new XMLDocumentElementNoOp(parent, definition);
    }
   
    return translate ? new JPAEntityElementReference(parent, definition, instanceOverride) : null;
  }

  /**
   * @param <T> The type of entity
   * @param type The type's class
   * @param id The id of the entity
   * @return The instance that corresponds to the entity
   */
  public Object getEntity (XMLDocumentElement parent, Class clazz, ClassProperty idProperty, Object id) {
    if (em != null) {
      Object entity = em.find(clazz, id);
      if (entity != null) return entity;
    }
   
    EntityDocumentVisitor visitor = (EntityDocumentVisitor) parent.getDocumentRoot().getManager().accept(new EntityDocumentVisitor(clazz, idProperty, id));
   
    return visitor.instance;
  }
 
  /**
   * This is used to search an object for elements to resolve entities.
   *
   * @author elponderador
   * @author $Author: ponderator $
   * @version $Id: JPATranslationGuide.java 1149 2009-10-21 21:34:58Z ponderator $
   */
  public class EntityDocumentVisitor extends ObjectVisitorBase {
   
    protected Class clazz;
    protected Object id;
    protected ClassProperty idProperty;
   
    protected Object instance;

    public EntityDocumentVisitor(Class clazz, ClassProperty idProperty, Object id, Class... exclude) {
      super(exclude);
      this.clazz = clazz;
      this.id = id;
      this.idProperty = idProperty;
    }

    @Override public boolean visitObject(Object instance, ClassProperty property) {
      if (property != null && clazz.isAssignableFrom( instance.getClass() )) {
        if (id.equals( idProperty.getValue(instance) )) {
          this.instance = instance;
          return false;
        }
      }
      return true;
    }
   
  }
 
  /**
   * This represents a complex type that is also a JPA {@link Entity} and
   * will be translated using its {@link Id} property.
   *
   * @author elponderador
   * @author $Author: ponderator $
   * @version $Id: JPATranslationGuide.java 1149 2009-10-21 21:34:58Z ponderator $
   */
  protected class JPAEntityElementReference extends XMLDocumentElementBase {
   
    protected Object id;
    protected ClassDescriptor desc;
    protected ClassProperty idProperty;
    protected Object instance;

    public JPAEntityElementReference(XMLDocumentElement parent, XMLDocumentElementDefinition definition, Object instance) {
      super(parent, definition);
      this.desc = ClassCache.getFor(definition.getTagType());
      this.idProperty = desc.getProperty(Id.class);
      this.instance = instance;
     
      if (this.instance != null) {
        this.id = idProperty.getValue(instance);
      }
    }

    public void appendContents(char[] contents, int offset, int length, boolean cdata, boolean ignorable) {}

    public void applyAttributes(Attributes attributes) {
      for (int a=0; a<attributes.getLength(); a++) {
        String name = attributes.getLocalName(a);
        if ("id".equals(name)) {
          instance = getEntity(parent, definition.getTagType(), idProperty,
            ReflectionUtil.coerceString(idProperty.getType(), attributes.getValue(a)));
          return;
        }
      }
      throw new IllegalStateException("Id not available for entity translation: " + definition.getTagName() + "/" + definition.getTagType());
    }

    public void endElement(XMLDocumentElement element) {
      parent.setProperty(definition.getName(), instance);
    }

    public XMLDocumentElement startElement(String namespace, String prefix, String name) { return null; }

    public void write(XMLWriter writer) {
      if (id == null) throw new IllegalArgumentException("Cannot translate entities that do not have an id");
     
      writer.startElement(getDefinition().getTagName());
      writer.writeAttribute(null, "id", ReflectionUtil.coerce(String.class, idProperty.getValue(instance)));
      writer.endElement(getDefinition().getTagName());
    }
   
  }

}
TOP

Related Classes of net.sourceforge.javautil.database.jpa.xml.JPATranslationGuide$EntityDocumentVisitor

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.