Package net.sourceforge.javautil.common.xml

Source Code of net.sourceforge.javautil.common.xml.XMLDocumentElementDefinition

package net.sourceforge.javautil.common.xml;

import java.util.LinkedHashMap;
import java.util.Map;

import net.sourceforge.javautil.common.reflection.ObjectManager;
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.annotation.XmlClassRegistry;
import net.sourceforge.javautil.common.xml.annotation.XmlCollection;
import net.sourceforge.javautil.common.xml.annotation.XmlMap;
import net.sourceforge.javautil.common.xml.annotation.XmlParent;
import net.sourceforge.javautil.common.xml.annotation.XmlTag;
import net.sourceforge.javautil.common.xml.annotation.XmlCollection.CollectionType;
import net.sourceforge.javautil.common.xml.annotation.XmlMap.MapType;
import net.sourceforge.javautil.common.xml.annotation.XmlTag.ElementType;

/**
* The definition of an {@link XMLDocumentElement} and how it should be
* interpreted.
*
* @author elponderador
* @author $Author: ponderator $
* @version $Id: XMLDocumentElementDefinition.java 2466 2010-10-24 11:43:57Z ponderator $
*/
public class XMLDocumentElementDefinition implements Comparable<XMLDocumentElementDefinition> {

  /**
   * The class property this element is related to.
   */
  protected String propertyName;
  protected Class<?> propertyType;
  protected ClassProperty property;
  protected XMLDocumentElementDefinition parent;
 
  protected String tagName;
  protected String tagNamespace;
  protected Class<?> tagType;
  protected ClassDescriptor<?> tagTypeDescriptor;
  protected Map<String, XMLDocumentElementDefinition> properties = new LinkedHashMap<String, XMLDocumentElementDefinition>();
  protected boolean searchedAll = false;
 
  protected XmlTag tagDef;
  protected XmlCollection collection;
  protected XmlMap map;
  protected XmlClassRegistry classRegistry;
  protected CollectionType collectionType;
  protected ElementType elementType = ElementType.Unspecified;
  protected String actualTagName;
 
  protected String before;
  protected String after;
 
  protected XMLTranslationGuide guide;
 
  protected boolean xml = true;
 
  public XMLDocumentElementDefinition(Class<?> clazz) {
    this(null, clazz, null);
  }
 
  public XMLDocumentElementDefinition(XMLDocumentElementDefinition parent, Class<?> clazz, String name) {
    this.parent = parent;
    if (clazz == XMLDocumentMapEntry.class && parent != null) {
      this.tagDef = parent.tagDef;
      this.propertyName = parent.propertyName;
      this.propertyType = parent.propertyType;
     
      this.tagName = parent.tagName;
      this.tagNamespace = parent.tagNamespace;
      this.tagType = clazz;
      this.tagTypeDescriptor = ClassCache.getFor(clazz);
     
      this.elementType = ElementType.Complex;
     
      this.map = parent.map;
      this.actualTagName = name;

      this.properties.put(map.keyName(), new XMLDocumentElementDefinition(this, this.tagTypeDescriptor.getProperty("key")));
      this.properties.put(name == null ? map.valueName() : name, new XMLDocumentElementDefinition(this, this.tagTypeDescriptor.getProperty("value")));
     
      this.properties.get(map.keyName()).before = map.valueName();
      this.searchedAll = true;
    } else {
      this.describe(parent, clazz);
    }
  }


  public XMLDocumentElementDefinition(XMLDocumentElementDefinition parent, ClassProperty property) {
    this.property = property;
    if (parent.map != null) {
      if ("key".equals( property.getName() )) {
        this.describe(parent, parent.map.keyClass());
        this.tagName = parent.map.keyName();
        this.propertyName = "key";
      } else {
        this.describe(parent, parent.map.valueClass());
        this.tagName = parent.map.valueName();
        this.propertyName = "value";
      }
    } else {
      this.propertyName = property.getName();
      this.propertyType = property.getType();
      this.parent = parent;
   
      this.describe(property);
    }
  }
 
  public XMLDocumentElementDefinition(XMLDocumentElementDefinition original, ElementType newType, Class concrete) {
    this.propertyName = original.propertyName;
    this.propertyType = original.propertyType;
    this.parent = original.parent;
   
    this.map = original.map;
    this.collection = original.collection;
    this.collectionType = original.collectionType;
   
    this.properties = original.properties;
   
    this.searchedAll = original.searchedAll;
   
    this.tagDef = original.tagDef;
    this.tagName = original.tagName;
    this.tagNamespace = original.tagNamespace;
   
    this.tagType = concrete;
    this.tagTypeDescriptor = ClassCache.getFor(concrete);
   
    this.elementType = newType;
  }
 
  public ClassProperty getProperty() { return property; }

  public String getPropertyName() { return propertyName; }

  public Class<?> getPropertyType() { return propertyType; }

  /**
   * @return A new instance of the property type
   */
  public Object newInstance () { return this.tagTypeDescriptor.newInstance(); }
 
  /**
   * @return The type of property
   */
  public Class getClassType() { return propertyType; }

  /**
   * @return The property name, which may differ from the tag name
   */
  public String getName () { return this.propertyName; }

  /**
   * @return The type of element this is
   */
  public ElementType getElementType() { return elementType; }

  /**
   * @return The real tag name to use
   */
  public String getTagName() { return tagName; }

  /**
   * @return The tag namespace
   */
  public String getTagNamespace() { return tagNamespace; }

  /**
   * @return The real type of the tag
   */
  public Class getTagType() { return tagType; }

  /**
    * @return The corresponding tag def, or none if this is a default element
   */
  public XmlTag getTagDef() { return tagDef; }
 
  /**
   * @return True if this property is to be used with XML, otherwise false
   */
  public boolean isXml () { return tagDef != null ? !tagDef.ignore() : xml; }

  /**
   * @return The collection info if this is {@link ElementType#Collection}
   */
  public XmlCollection getCollection() { return collection; }

  /**
   * @return The map info if this is {@link ElementType#Map}
   */
  public XmlMap getMap() { return map; }

  /**
   * @return The type of collection
   */
  public CollectionType getCollectionType() { return collectionType; }

  public String getActualTagName() { return actualTagName; }

  public XmlClassRegistry getClassRegistry() { return classRegistry; }
 
  public XMLTranslationGuide getGuide () { return guide; }

  /**
   * This will use a {@link ClassDescriptor} for the {@link #getTagType()}
   * in order to lookup properties.
   *
   * @param name The name of the property
   * @return A corresponding definition, or null if there is no such property
   */
  public XMLDocumentElementDefinition getComplexProperty (String name) {
    if (!this.properties.containsKey(name) && !this.searchedAll) {
      Map<String, ClassProperty> properties = this.tagTypeDescriptor.getProperties();
      for (String propertyName : properties.keySet()) {
        ClassProperty property = this.tagTypeDescriptor.getProperty(propertyName);
        XMLDocumentElementDefinition xmlDef = new XMLDocumentElementDefinition(this, property);
        if (xmlDef.isXml()) {
          this.properties.put(xmlDef.getTagName(), xmlDef);
          if (name.equals(xmlDef.getTagName())) return xmlDef;
        }
      }
      this.searchedAll = true;
    }
    return this.properties.get(name);
  }
 
  /**
   * @return The collection definition for a collection type element
   */
  public XMLDocumentElementDefinition getCollectionDefinition (String tagName) {
    return this.map == null ? new XMLDocumentElementDefinition(this, this.collection.value(), null) : this.getMapDefinition(tagName);
  }

  /**
   * @return The collection definition for a collection type element
   */
  public XMLDocumentElementDefinition getMapDefinition (String tagName) {
    return map.mapType() == MapType.CONTENT_KEY ?
        new XMLDocumentElementDefinition(this, XMLDocumentMapEntry.class, null) :
        new XMLDocumentElementDefinition(this, XMLDocumentMapEntry.class, tagName);
  }
 
  public int compareTo(XMLDocumentElementDefinition o) {
    if (o == null) return 1;
   
    if (o.before != null && !"".equals(o.before) && o.before.equals(propertyName)) return 1;
    if (o.after != null && !"".equals(o.after) && o.after.equals(propertyName)) return -1;
   
    if (this.before != null && !"".equals(this.before) && this.before.equals(o.propertyName)) return -1;
    if (this.after != null && !"".equals(this.after) && this.after.equals(o.propertyName)) return 1;
   
    return propertyName.compareTo(o.propertyName);
  }
 
  protected void describe (XMLDocumentElementDefinition parent, Class<?> clazz) {
    this.tagDef = clazz.getAnnotation(XmlTag.class);
    this.propertyName = parent == null ? clazz.getSimpleName() : parent.propertyName;
    this.propertyType = clazz;
    this.classRegistry = tagDef != null && tagDef.classRegistry().length > 0 ? tagDef.classRegistry()[0] : null;
   
    if (tagDef == null || (tagDef != null && "".equals(tagDef.name()))) {
      XmlTag tag = null;
      Class<?> c = clazz.getSuperclass();
      while (tag == null && c != null) {
        tag = c.getAnnotation(XmlTag.class);
        if (tag != null && !"".equals(tag.name())) {
          if (tagDef == null) tagDef = tag;
          tagName = tag.name(); break;
        }
        c = c.getSuperclass();
      }
    }

    if (tagName == null) {
      tagName = tagDef != null && !"".equals(tagDef.name()) ? tagDef.name() : (parent == null ? this.propertyName : parent.tagName);
    }
   
    this.tagNamespace = tagDef != null ? tagDef.namespace() : "";
    this.tagType = clazz;
    this.tagTypeDescriptor = ClassCache.getFor(clazz);
   
    if (tagDef != null) {
      this.elementType = tagDef.elementType();
      if (tagDef.translation().length > 0) {
        guide = ClassCache.getFor( tagDef.translation()[0].value() ).newInstance();
      }
    }
 
    if (this.elementType == ElementType.Unspecified) {
      this.elementType = XMLUtil.isSimpleType(clazz) ? ElementType.Simple : ElementType.Complex;
    }
  }

  /**
   * This will analyze the {@link #property} and detect annotations
   * and using basic defaults determine what kind of element this is
   * supposed to be.
   */
  protected void describe (ClassProperty property) {
    XmlParent parent = property.getAnnotation(XmlParent.class);
    if (parent != null) {
      this.xml = false;
      return;
    }
   
    // The property overrides all
    this.tagDef = property.getAnnotation(XmlTag.class);
   
    // Then we check the property type annotations
    if (tagDef == null) tagDef = property.getType().getAnnotation(XmlTag.class);

    if (tagDef != null) {
      if (Object.class != tagDef.concreteType()) this.tagType = tagDef.concreteType(); else this.tagType = property.getType();
     
//      if (tagDef.translation().length > 0) {
//        XMLTranslationGuide guide = ClassCache.getFor( tagDef.translation()[0].value() ).newInstance();
//        guide.
//      }
     
      XmlTag typeDef = null;
      if (tagType.getAnnotation(XmlTag.class) != null) typeDef = tagType.getAnnotation(XmlTag.class);
     
      if (tagDef.collection().length > 0) {
        this.collection = tagDef.collection()[0];
        this.collectionType = this.collection.type();
        this.tagType = this.collection.value();
       
        if (this.collectionType != CollectionType.WRAPPED)
          typeDef = this.collection.value().getAnnotation(XmlTag.class);
      }
      else if (tagDef.map().length > 0) {
        this.map = tagDef.map()[0];
        this.collectionType = this.map.type();
       
        if (this.collectionType != CollectionType.WRAPPED)
          typeDef = (XmlTag) this.map.valueClass().getAnnotation(XmlTag.class);
        else
          this.tagType = tagDef.concreteType() == Object.class ? LinkedHashMap.class : this.tagDef.concreteType();
      } else {
        if (this.elementType == ElementType.Unspecified)
          this.elementType = tagDef.elementType() == ElementType.Unspecified && typeDef != null ? typeDef.elementType() : tagDef.elementType();
      }
      this.tagName = "".equals( tagDef.name() ) && typeDef != null ? typeDef.name() : tagDef.name();
      if ("".equals(tagName)) tagName = property.getName();
     
      this.tagNamespace = "".equals( tagDef.namespace() ) && typeDef != null ? typeDef.namespace() : tagDef.namespace();
      this.classRegistry = tagDef.classRegistry().length > 0 ? tagDef.classRegistry()[0] :
        (typeDef != null && typeDef.classRegistry().length > 0 ? typeDef.classRegistry()[0] : null);
     
      if (this.elementType == ElementType.Unspecified) {
        if (XMLUtil.isSimpleType(this.tagType)) {
          this.elementType = ElementType.Simple;
        } else {
          this.elementType = ElementType.Complex;
        }
      }
     
      this.before = tagDef.before();
      this.after = tagDef.after();
    } else {
     
      this.tagName = property.getName();
      this.tagNamespace = "";
      this.tagType = property.getType();
      if (XMLUtil.isSimpleType(this.tagType)) {
        this.elementType = ElementType.Simple;
      } else {
        this.elementType = ElementType.Complex;
      }
     
    }
   
    this.tagTypeDescriptor = property.getDescriptor().getCache().getDescriptor(this.tagType)
  }
 
}
TOP

Related Classes of net.sourceforge.javautil.common.xml.XMLDocumentElementDefinition

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.