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

org.simpleframework.xml.core.Signature Maven / Gradle / Ivy

Go to download

Simple is a high performance XML serialization and configuration framework for Java

There is a newer version: 2.7.1
Show newest version
/*
 * Signature.java February 2005
 *
 * Copyright (C) 2005, Niall Gallagher 
 *
 * This library 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.
 *
 * This library 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 this library; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
 * Boston, MA  02111-1307  USA
 */

package org.simpleframework.xml.core;

import java.lang.annotation.Annotation;
import org.simpleframework.xml.Root;
import java.beans.Introspector;

/**
 * The Signature object is used to determine the details
 * to use for an annotated field or method using both the field an
 * annotation details. This allows defaults to be picked up from the
 * method or field type if that have not been explicitly overridden
 * in the annotation. 
 * 
 * @author Niall Gallagher
 */
class Signature {
   
   /**
    * This is the actual annotation from the specified contact.
    */
   private Annotation marker;
   
   /**
    * This is the field or method contact that has been annotated.
    */
   private Contact contact; 
   
   /**
    * This is the label used to expose the annotation details.
    */
   private Label label;
   
   /**
    * Constructor for the Signature object. This is 
    * used to create an object that will use information available
    * within the field and annotation to determine exactly what 
    * the name of the XML element is to be and the type to use.
    * 
    * @param contact this is the method or field contact used
    * @param label this is the annotation on the contact object
    */
   public Signature(Contact contact, Label label) {
      this.marker = contact.getAnnotation();
      this.contact = contact;
      this.label = label;
   }
   
   /**
    * This is used to acquire the Contact for this. The
    * contact is the actual method or field that has been annotated
    * and is used to set or get information from the object instance.
    * 
    * @return the method or field that this signature represents
    */
   public Contact getContact() {
      return contact;
   }
   
   /**
    * This returns the dependent type for the annotation. This type
    * is the type other than the annotated field or method type that
    * the label depends on. For the ElementList this 
    * can be the generic parameter to an annotated collection type.
    * 
    * @return this is the type that the annotation depends on
    */
   public Class getDependent() throws Exception {
      return label.getDependent();
   }

   /**
    * This method is used to get the entry name of a label using 
    * the type of the label. This ensures that if there is no
    * entry XML element name declared by the annotation that a
    * suitable name can be calculated from the annotated type.
    * 
    * @return this returns a suitable XML entry element name
    */
   public String getEntry() throws Exception {
      Class type = getDependent();   
      
      if(type.isArray()) {
         type = type.getComponentType();
      }
      String name = getName(type);
      
      if(name == null) {
         return null;
      }
      return name.intern();
   }
   
   /**
    * This is used to acquire the name of the specified type using
    * the Root annotation for the class. This will 
    * use either the name explicitly provided by the annotation or
    * it will use the name of the class that the annotation was
    * placed on if there is no explicit name for the root.
    * 
    * @param type this is the type to acquire the root name for
    * 
    * @return this returns the name of the type from the root
    * 
    * @throws Exception if the class contains an illegal schema
    */
   private String getName(Class type) throws Exception {
      String name = getRoot(type);
      
      if(name != null) {
         return name;
      } else {
         name = type.getSimpleName();
      }
      return Introspector.decapitalize(name);
   }
   
   /**
    * This will acquire the name of the Root annotation
    * for the specified class. This will traverse the inheritance
    * heirarchy looking for the root annotation, when it is found it
    * is used to acquire a name for the XML element it represents.
    *  
    * @param type this is the type to acquire the root name with
    * 
    * @return the root name for the specified type if it exists
    */
   private String getRoot(Class type) { 
      Class real = type;
         
      while(type != null) {
         String name = getRoot(real, type);
         
         if(name != null) {
           return name;
         }
         type = type.getSuperclass();
      }
      return null;     
   }
   
   /**
    * This will acquire the name of the Root annotation
    * for the specified class. This will traverse the inheritance
    * heirarchy looking for the root annotation, when it is found it
    * is used to acquire a name for the XML element it represents.
    *  
    * @param real the actual type of the object being searched
    * @param type this is the type to acquire the root name with    
    * 
    * @return the root name for the specified type if it exists
    */
   private String getRoot(Class real, Class type) {
      String name = type.getSimpleName();
      
      if(type.isAnnotationPresent(Root.class)) {
         Root root = type.getAnnotation(Root.class);
         String text = root.name();
          
         if(!isEmpty(text)) {
            return text;
         }
         return Introspector.decapitalize(name);
      }
      return null;
   }
   
   /**
    * This is used to determine the name of the XML element that the
    * annotated field or method represents. This will determine based
    * on the annotation attributes and the dependent type required
    * what the name of the XML element this represents is. 
    * 
    * @return this returns the name of the XML element expected
    */
   public String getName() throws Exception {
      String entry = label.getEntry(); 
         
      if(!label.isInline()) {
         entry = getDefault();
      }
      return entry.intern();
   }
   
   /**
    * This is used to acquire the name for an element by firstly
    * checking for an override in the annotation. If one exists
    * then this is returned if not then the name of the field
    * or method contact is returned. 
    * 
    * @return this returns the XML element name to be used
    */
   private String getDefault() throws Exception {
      String name = label.getOverride();

      if(!isEmpty(name)) {
         return name;
      }
      return contact.getName();
   }  
   
   /**
    * This method is used to determine if a root annotation value is
    * an empty value. Rather than determining if a string is empty
    * be comparing it to an empty string this method allows for the
    * value an empty string represents to be changed in future.
    * 
    * @param value this is the value to determine if it is empty
    * 
    * @return true if the string value specified is an empty value
    */
   public boolean isEmpty(String value) {
      if(value != null) {
         return value.length() == 0;
      }
      return true;      
   }
   
   /**
    * This method is used to construct a string that describes the
    * signature of an XML annotated field or method. This will use
    * the Contact object and the annotation used for
    * that contact to construct a string that has sufficient
    * information such that it can be used in error reporting.
    * 
    * @return returns a string used to represent this signature 
    */
   public String toString() {
      return String.format("%s on %s", marker, contact);
   }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy