Package com.lunatech.doclets.jax.jpa.model

Source Code of com.lunatech.doclets.jax.jpa.model.JPAClass

/*
    Copyright 2009-2011 Lunatech Research
    Copyright 2009-2011 Stéphane Épardaud
   
    This file is part of jax-doclets.

    jax-doclets is free software: you can redistribute it and/or modify
    it under the terms of the GNU Lesser General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    jax-doclets is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public License
    along with jax-doclets.  If not, see <http://www.gnu.org/licenses/>.
*/
package com.lunatech.doclets.jax.jpa.model;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;

import javax.persistence.Id;
import javax.persistence.ManyToMany;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.OneToOne;
import javax.persistence.Table;
import javax.persistence.Transient;

import com.lunatech.doclets.jax.JAXConfiguration;
import com.lunatech.doclets.jax.Utils;
import com.lunatech.doclets.jax.jpa.JPADoclet;
import com.lunatech.doclets.jax.jpa.writers.JPAClassWriter;
import com.sun.javadoc.AnnotationDesc;
import com.sun.javadoc.ClassDoc;
import com.sun.javadoc.Doc;
import com.sun.javadoc.FieldDoc;
import com.sun.javadoc.MethodDoc;
import com.sun.javadoc.ProgramElementDoc;

public class JPAClass implements Comparable<JPAClass> {

  private Set<Column> columns = new TreeSet<Column>();

  private Set<Relation> relations = new TreeSet<Relation>();

  private ClassDoc klass;

  private String name;

  private Registry registry;

  private JPADoclet doclet;

  private Map<String, JPAMember> members = new HashMap<String, JPAMember>();

  public JPAClass(ClassDoc klass, Registry registry, JPADoclet doclet) {
    // System.err.println("Root: " + klass.name());
    this.klass = klass;
    this.registry = registry;
    this.doclet = doclet;
    AnnotationDesc tableAnnotation = Utils.findAnnotation(klass, Table.class);
    if (tableAnnotation != null) {
      name = (String) Utils.getAnnotationValue(tableAnnotation, "name");
    }
    if (name == null)
      name = klass.simpleTypeName();
    setupMembers(klass, isIDOnField(klass));
  }

  private boolean isIDOnField(ClassDoc klass) {
    for (FieldDoc field : klass.fields(false)) {
      if (Utils.findAnnotation(field, Id.class) != null)
        return true;
    }
    for (MethodDoc method : klass.methods(false)) {
      if (Utils.findAnnotation(method, Id.class) != null)
        return false;
    }
    ClassDoc superClass = klass.superclass();
    if (superClass != null && !superClass.qualifiedTypeName().startsWith("java."))
      return isIDOnField(superClass);
    // default to true?
    return true;
  }

  private void setupMembers(ClassDoc klass, boolean isIDOnField) {
    for (FieldDoc field : klass.fields(false)) {
      addProperty(field, isIDOnField);
    }
    for (MethodDoc method : klass.methods(false)) {
      addProperty(method, !isIDOnField);
    }
    ClassDoc superClass = klass.superclass();
    if (superClass != null && !superClass.qualifiedTypeName().startsWith("java."))
      setupMembers(superClass, isIDOnField);
  }

  private void addProperty(ProgramElementDoc property, boolean includeByDefault) {
    if (property.isMethod() && !isProperty((MethodDoc) property))
      return;
    if (property.isStatic())
      return;

    AnnotationDesc columnAnnotation = Utils.findAnnotation(property, javax.persistence.Column.class);
    if (columnAnnotation == null)
      columnAnnotation = Utils.findAnnotation(property, javax.persistence.JoinColumn.class);
    AnnotationDesc transientAnnotation = Utils.findAnnotation(property, Transient.class);
    boolean hasJPAAnnotation = columnAnnotation != null;
    boolean isTransient = transientAnnotation != null;
    if (property.isField()) {
      isTransient |= ((FieldDoc) property).isTransient();
    }
    // all annotated non-transient properties
    boolean include = !isTransient && (includeByDefault || hasJPAAnnotation);
    if (include)
      addElement(property, columnAnnotation);

  }

  private boolean isProperty(MethodDoc method) {
    String name = method.name();
    if (method.parameters().length != 0)
      return false;
    if (name.startsWith("get"))
      return name.length() > 3;
    if (name.startsWith("is") && method.returnType().toString().equals("boolean"))
      return name.length() > 2;
    return false;
  }

  private void addElement(ProgramElementDoc property, AnnotationDesc columnAnnotation) {
    String name = property.name();
    if (property.isMethod()) {
      if (name.startsWith("get"))
        name = name.substring(3);
      else
        name = name.substring(2);
      name = name.substring(0, 1).toLowerCase() + name.substring(1);
    }
    if (!members.containsKey(name))
      addElement(property, name, columnAnnotation);
  }

  private void addElement(ProgramElementDoc property, String name, AnnotationDesc columnAnnotation) {
    AnnotationDesc relation = Utils.findAnnotation(property, OneToMany.class, ManyToOne.class, OneToOne.class, ManyToMany.class);
    if (relation == null)
      addColumn(property, name, columnAnnotation);
    else {
      addRelation(property, name, columnAnnotation, relation);
    }
  }

  private void addRelation(ProgramElementDoc property, String propertyName, AnnotationDesc columnAnnotation, AnnotationDesc relation) {
    String name = propertyName;
    if (columnAnnotation != null) {
      String overriddenName = (String) Utils.getAnnotationValue(columnAnnotation, "name");
      if (overriddenName != null)
        name = overriddenName;
    }
    Relation element = new Relation(this, property, name, columnAnnotation, relation);
    members.put(propertyName, element);
    relations.add(element);
  }

  private void addColumn(ProgramElementDoc property, String propertyName, AnnotationDesc columnAnnotation) {
    String name = propertyName;
    if (columnAnnotation != null) {
      String overriddenName = (String) Utils.getAnnotationValue(columnAnnotation, "name");
      if (overriddenName != null)
        name = overriddenName;
    }
    Column element = new Column(this, property, name, columnAnnotation);
    members.put(propertyName, element);
    columns.add(element);
  }

  public String getQualifiedClassName() {
    return klass.qualifiedName();
  }

  public JPADoclet getDoclet() {
    return doclet;
  }

  public String getName() {
    return name;
  }

  public void write(JAXConfiguration configuration) {
    new JPAClassWriter(configuration, this).write();
  }

  public Doc getJavaDoc() {
    return klass;
  }

  public Collection<Column> getColumns() {
    return columns;
  }

  public Collection<Relation> getRelations() {
    return relations;
  }

  public Registry getRegistry() {
    return registry;
  }

  public String getPackageName() {
    return klass.containingPackage().name();
  }

  public String getShortClassName() {
    return klass.name();
  }

  public int compareTo(JPAClass other) {
    return name.compareToIgnoreCase(other.name);
  }

  public List<JPAMember> getMembers() {
    List<JPAMember> list = new ArrayList<JPAMember>(columns.size());
    list.addAll(columns);
    list.addAll(relations);
    return list;
  }

  public JPAMember getID() {
    return null;
  }

  public Relation getRelation(String name) {
    JPAMember member = members.get(name);
    if (member instanceof Relation)
      return (Relation) member;
    return null;
  }
}
TOP

Related Classes of com.lunatech.doclets.jax.jpa.model.JPAClass

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.