/*
* This is a common dao with basic CRUD operations and is not limited to any
* persistent layer implementation
*
* Copyright (C) 2008 Imran M Yousuf (imyousuf@smartitengineering.com)
*
* 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; either
* version 3 of the License, or (at your option) any later version.
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
package com.smartitengineering.exim;
import java.util.Collection;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* A configuration API for all association in an exim-able object. Since in Java
* all types are of type {@link Object} we will considering every member (a
* field or a property) an association and thus store a configuration for it.
* @author imyousuf
* @since 0.4
*/
public interface AssociationConfig {
/**
* The accessor name for the property, if field is being used to access then
* it will be the name of the field else it will be the name of the method
* being used to read it.
* @return Accessor string, it will be non-blank
*/
public String getAccessorName();
/**
* Defines whether the associate is to be exported as URI or not.
* @return True if its expected to export as URI else false
*/
public boolean isItToBeExportedAsUri();
/**
* Defines whether the association is to be ignored for when the domain is
* exported or imported.
* @return True if it is to be ignored for Ex-Im.
*/
public boolean isTransient();
/**
* Defines whether the object should be imported eagerly or on demand. It
* will only be supported if the resource is exported using properties. If
* any association config has it set then it will use CGLIB for proxying the
* resources.
* @return True if association is to be fetched eagerly.
* @see AssociationConfig#isItToBeExportedAsUri()
* @see AssociationConfig#isTransient()
*/
public boolean isEagerSet();
/**
* Defines the name representing the association in the exported doc.
* @return Name to be used in export/import; if null then field/property
* name will be used instead.
*/
public String getName();
/**
* Defines whether the association has its own string value generator
* implementation, (if its not exported as URI) if it does have a provider
* then it will be used else toString will be used.
* @return True if it has a string provider implemented.
* @see AssociationConfig#isItToBeExportedAsUri()
*/
public boolean isStringProviderImplemented();
/**
* Defines the type of association this configuration represents
* @return Type of the associaiton
*/
public AssociationType getAssociationType();
/**
* It defimes types that impacts how the data is used in order to be
* exported.
*/
public enum AssociationType {
/**
* Represents anything thats not any form of collection
*/
TYPE_OBJECT("array", Object.class),
/**
* Represents List
*/
TYPE_LIST("list", List.class),
/**
* Represents Set
*/
TYPE_SET("set", Set.class),
/**
* Represents Collection
*/
TYPE_COLLECTION("collection", Collection.class),
/**
* Represents Array
*/
TYPE_ARRAY("object", Object.class),
/**
* Represents Map
*/
TYPE_MAP("map", Map.class),
/**
* Represents type 'double'
*/
TYPE_DOUBLE("double", double.class, Double.class),
/**
* Represents type 'float'
*/
TYPE_FLOAT("float", float.class, Float.class),
/**
* Represents type 'long'
*/
TYPE_LONG("long", long.class, Long.class),
/**
* Represents type 'int'
*/
TYPE_INTEGER("integer", int.class, Integer.class),
/**
* Represents type 'String'
*/
TYPE_STRING("string", String.class),
/**
* Represents type 'boolean'
*/
TYPE_BOOLEAN("boolean", boolean.class, Boolean.class),
/**
* Represents type 'java.util.Date'
*/
TYPE_DATE("date", Date.class),;
private Class[] rootClasses;
private String simpleName;
AssociationType(String simpleName,
Class... rootClass) {
if (rootClass == null || rootClass.length <= 0) {
throw new IllegalArgumentException(
"There should be at least one type!");
}
this.rootClasses = rootClass;
this.simpleName = simpleName;
}
/**
* The root {@link Class} of the type its representing
* @return The class type
*/
public Class[] getRootClasses() {
return rootClasses;
}
public String getSimpleName() {
return simpleName;
}
public boolean isAssignableFrom(Class clazz) {
if (clazz == null) {
return false;
}
for (Class myClazz : getRootClasses()) {
if (myClazz.isAssignableFrom(clazz)) {
return true;
}
}
return false;
}
/**
* Given any {@link Class} it will determine the {@link AssociationType}
* for that class.
* @param clazz The class whose type to determine
* @return Type of the clazz
* @throws NullPointerException If clazz is null
*/
public static AssociationType getAssociationType(Class clazz)
throws NullPointerException {
if (clazz.isArray()) {
return TYPE_ARRAY;
}
if (TYPE_MAP.isAssignableFrom(clazz)) {
return TYPE_MAP;
}
if (TYPE_LIST.isAssignableFrom(clazz)) {
return TYPE_LIST;
}
if (TYPE_SET.isAssignableFrom(clazz)) {
return TYPE_SET;
}
if (TYPE_COLLECTION.isAssignableFrom(clazz)) {
return TYPE_COLLECTION;
}
if (TYPE_DATE.isAssignableFrom(clazz)) {
return TYPE_DATE;
}
if (TYPE_BOOLEAN.isAssignableFrom(clazz)) {
return TYPE_BOOLEAN;
}
if (TYPE_STRING.isAssignableFrom(clazz)) {
return TYPE_STRING;
}
if (TYPE_INTEGER.isAssignableFrom(clazz)) {
return TYPE_INTEGER;
}
if (TYPE_LONG.isAssignableFrom(clazz)) {
return TYPE_LONG;
}
if (TYPE_FLOAT.isAssignableFrom(clazz)) {
return TYPE_FLOAT;
}
if (TYPE_DOUBLE.isAssignableFrom(clazz)) {
return TYPE_DOUBLE;
}
return TYPE_OBJECT;
}
}
}