Home » apache-openjpa-1.1.0-source » org.apache.openjpa » meta » [javadoc | source]
    1   /*
    2    * Licensed to the Apache Software Foundation (ASF) under one
    3    * or more contributor license agreements.  See the NOTICE file
    4    * distributed with this work for additional information
    5    * regarding copyright ownership.  The ASF licenses this file
    6    * to you under the Apache License, Version 2.0 (the
    7    * "License"); you may not use this file except in compliance
    8    * with the License.  You may obtain a copy of the License at
    9    *
   10    * http://www.apache.org/licenses/LICENSE-2.0
   11    *
   12    * Unless required by applicable law or agreed to in writing,
   13    * software distributed under the License is distributed on an
   14    * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
   15    * KIND, either express or implied.  See the License for the
   16    * specific language governing permissions and limitations
   17    * under the License.    
   18    */
   19   package org.apache.openjpa.meta;
   20   
   21   import java.io.InputStream;
   22   import java.io.Reader;
   23   import java.io.Serializable;
   24   import java.lang.reflect.Array;
   25   import java.math.BigDecimal;
   26   import java.math.BigInteger;
   27   import java.util.ArrayList;
   28   import java.util.Arrays;
   29   import java.util.Calendar;
   30   import java.util.Collection;
   31   import java.util.Date;
   32   import java.util.HashMap;
   33   import java.util.Iterator;
   34   import java.util.List;
   35   import java.util.Locale;
   36   import java.util.Map;
   37   import java.util.Properties;
   38   
   39   import org.apache.openjpa.enhance.PersistenceCapable;
   40   import org.apache.openjpa.lib.meta.CFMetaDataParser;
   41   import org.apache.openjpa.lib.util.Localizer;
   42   import org.apache.openjpa.util.MetaDataException;
   43   import serp.util.Numbers;
   44   import serp.util.Strings;
   45   
   46   /**
   47    * Type constants for managed fields.
   48    *
   49    * @author Abe White
   50    */
   51   public class JavaTypes {
   52   
   53       public static final int BOOLEAN = 0;
   54       public static final int BYTE = 1;
   55       public static final int CHAR = 2;
   56       public static final int DOUBLE = 3;
   57       public static final int FLOAT = 4;
   58       public static final int INT = 5;
   59       public static final int LONG = 6;
   60       public static final int SHORT = 7;
   61       // keep OBJECT as first non-primitive type code; other code relies on it
   62       public static final int OBJECT = 8;
   63       public static final int STRING = 9;
   64       public static final int NUMBER = 10;
   65       public static final int ARRAY = 11;
   66       public static final int COLLECTION = 12;
   67       public static final int MAP = 13;
   68       public static final int DATE = 14;
   69       public static final int PC = 15;
   70       public static final int BOOLEAN_OBJ = 16;
   71       public static final int BYTE_OBJ = 17;
   72       public static final int CHAR_OBJ = 18;
   73       public static final int DOUBLE_OBJ = 19;
   74       public static final int FLOAT_OBJ = 20;
   75       public static final int INT_OBJ = 21;
   76       public static final int LONG_OBJ = 22;
   77       public static final int SHORT_OBJ = 23;
   78       public static final int BIGDECIMAL = 24;
   79       public static final int BIGINTEGER = 25;
   80       public static final int LOCALE = 26;
   81       public static final int PC_UNTYPED = 27;
   82       public static final int CALENDAR = 28;
   83       public static final int OID = 29;
   84       public static final int INPUT_STREAM = 30;
   85       public static final int INPUT_READER = 31;
   86   
   87       private static final Localizer _loc = Localizer.forPackage(JavaTypes.class);
   88   
   89       private static final Map _typeCodes = new HashMap();
   90   
   91       static {
   92           _typeCodes.put(String.class, Numbers.valueOf(STRING));
   93           _typeCodes.put(Boolean.class, Numbers.valueOf(BOOLEAN_OBJ));
   94           _typeCodes.put(Byte.class, Numbers.valueOf(BYTE_OBJ));
   95           _typeCodes.put(Character.class, Numbers.valueOf(CHAR_OBJ));
   96           _typeCodes.put(Double.class, Numbers.valueOf(DOUBLE_OBJ));
   97           _typeCodes.put(Float.class, Numbers.valueOf(FLOAT_OBJ));
   98           _typeCodes.put(Integer.class, Numbers.valueOf(INT_OBJ));
   99           _typeCodes.put(Long.class, Numbers.valueOf(LONG_OBJ));
  100           _typeCodes.put(Short.class, Numbers.valueOf(SHORT_OBJ));
  101           _typeCodes.put(Date.class, Numbers.valueOf(DATE));
  102           _typeCodes.put(java.sql.Date.class, Numbers.valueOf(DATE));
  103           _typeCodes.put(java.sql.Timestamp.class, Numbers.valueOf(DATE));
  104           _typeCodes.put(java.sql.Time.class, Numbers.valueOf(DATE));
  105           _typeCodes.put(BigInteger.class, Numbers.valueOf(BIGINTEGER));
  106           _typeCodes.put(BigDecimal.class, Numbers.valueOf(BIGDECIMAL));
  107           _typeCodes.put(Number.class, Numbers.valueOf(NUMBER));
  108           _typeCodes.put(Locale.class, Numbers.valueOf(LOCALE));
  109           _typeCodes.put(Object.class, Numbers.valueOf(OBJECT));
  110           _typeCodes.put(PersistenceCapable.class, Numbers.valueOf(PC_UNTYPED));
  111           _typeCodes.put(Properties.class, Numbers.valueOf(MAP));
  112           _typeCodes.put(Calendar.class, Numbers.valueOf(CALENDAR));
  113       }
  114   
  115       /**
  116        * Return the field metadata type code for the given class. First class
  117        * objects are not recognized in this method.
  118        */
  119       public static int getTypeCode(Class type) {
  120           if (type == null)
  121               return OBJECT;
  122   
  123           if (type.isPrimitive()) {
  124               switch (type.getName().charAt(0)) {
  125                   case 'b':
  126                       return (type == boolean.class) ? BOOLEAN : BYTE;
  127                   case 'c':
  128                       return CHAR;
  129                   case 'd':
  130                       return DOUBLE;
  131                   case 'f':
  132                       return FLOAT;
  133                   case 'i':
  134                       return INT;
  135                   case 'l':
  136                       return LONG;
  137                   case 's':
  138                       return SHORT;
  139               }
  140           }
  141   
  142           Integer code = (Integer) _typeCodes.get(type);
  143           if (code != null)
  144               return code.intValue();
  145   
  146           // have to do this first to catch custom collection and map types;
  147           // on resolve we figure out if these custom types are
  148           // persistence-capable
  149           if (Collection.class.isAssignableFrom(type))
  150               return COLLECTION;
  151           if (Map.class.isAssignableFrom(type))
  152               return MAP;
  153           if (type.isArray())
  154               return ARRAY;
  155           if (Calendar.class.isAssignableFrom(type))
  156               return CALENDAR;
  157   
  158           if (type.isInterface()) {
  159               if (type == Serializable.class)
  160                   return OBJECT;
  161               return PC_UNTYPED;
  162           }
  163           if (type.isAssignableFrom(Reader.class))
  164               return INPUT_READER;
  165           if (type.isAssignableFrom (InputStream.class))
  166               return INPUT_STREAM;
  167               
  168           return OBJECT;
  169       }
  170    
  171       /**
  172        * Check the given name against the same set of standard packages used
  173        * when parsing metadata.
  174        */
  175       public static Class classForName(String name, ClassMetaData context) {
  176           return classForName(name, context, null);
  177       }
  178   
  179       /**
  180        * Check the given name against the same set of standard packages used
  181        * when parsing metadata.
  182        */
  183       public static Class classForName(String name, ClassMetaData context,
  184           ClassLoader loader) {
  185           return classForName(name, context, context.getDescribedType(), null,
  186               loader);
  187       }
  188   
  189       /**
  190        * Check the given name against the same set of standard packages used
  191        * when parsing metadata.
  192        */
  193       public static Class classForName(String name, ValueMetaData context) {
  194           return classForName(name, context, null);
  195       }
  196   
  197       /**
  198        * Check the given name against the same set of standard packages used
  199        * when parsing metadata.
  200        */
  201       public static Class classForName(String name, ValueMetaData context,
  202           ClassLoader loader) {
  203           return classForName(name,
  204               context.getFieldMetaData().getDefiningMetaData(),
  205               context.getFieldMetaData().getDeclaringType(), context, loader);
  206       }
  207   
  208       /**
  209        * Check the given name against the same set of standard packages used
  210        * when parsing metadata.
  211        */
  212       private static Class classForName(String name, ClassMetaData meta,
  213           Class dec, ValueMetaData vmd, ClassLoader loader) {
  214           // special case for PersistenceCapable and Object
  215           if ("PersistenceCapable".equals(name)
  216               || "javax.jdo.PersistenceCapable".equals(name)) // backwards compat
  217               return PersistenceCapable.class;
  218           if ("Object".equals(name))
  219               return Object.class;
  220   
  221           MetaDataRepository rep = meta.getRepository();
  222           boolean runtime = (rep.getValidate() & rep.VALIDATE_RUNTIME) != 0;
  223           if (loader == null)
  224               loader = rep.getConfiguration().getClassResolverInstance().
  225                   getClassLoader(dec, meta.getEnvClassLoader());
  226   
  227           // try the owner's package
  228           String pkg = Strings.getPackageName(dec);
  229           Class cls = CFMetaDataParser.classForName(name, pkg, runtime, loader);
  230           if (cls == null && vmd != null) {
  231               // try against this value type's package too
  232               pkg = Strings.getPackageName(vmd.getDeclaredType());
  233               cls = CFMetaDataParser.classForName(name, pkg, runtime, loader);
  234           }
  235           if (cls == null)
  236               throw new MetaDataException(_loc.get("bad-class", name,
  237                   (vmd == null) ? (Object) meta : (Object) vmd));
  238           return cls;
  239       }
  240   
  241       /**
  242        * Convert the given object to the given type if possible. If the type is
  243        * a numeric primitive, this method only guarantees that the return value
  244        * is a {@link Number}. If no known conversion or the value is null,
  245        * returns the original value.
  246        */
  247       public static Object convert(Object val, int typeCode) {
  248           if (val == null)
  249               return null;
  250   
  251           switch (typeCode) {
  252               case BIGDECIMAL:
  253                   if (val instanceof BigDecimal)
  254                       return val;
  255                   if (val instanceof Number)
  256                       return new BigDecimal(((Number) val).doubleValue());
  257                   if (val instanceof String)
  258                       return new BigDecimal(val.toString());
  259                   return val;
  260               case BIGINTEGER:
  261                   if (val instanceof BigInteger)
  262                       return val;
  263                   if (val instanceof Number || val instanceof String)
  264                       return new BigInteger(val.toString());
  265                   return val;
  266               case BOOLEAN:
  267               case BOOLEAN_OBJ:
  268                   if (val instanceof String)
  269                       return Boolean.valueOf(val.toString());
  270                   return val;
  271               case BYTE_OBJ:
  272                   if (val instanceof Byte)
  273                       return val;
  274                   if (val instanceof Number)
  275                       return new Byte(((Number) val).byteValue());
  276                   // no break
  277               case BYTE:
  278                   if (val instanceof String)
  279                       return new Byte(val.toString());
  280                   return val;
  281               case CHAR:
  282               case CHAR_OBJ:
  283                   if (val instanceof Character)
  284                       return val;
  285                   if (val instanceof String)
  286                       return new Character(val.toString().charAt(0));
  287                   if (val instanceof Number)
  288                       return new Character((char) ((Number) val).intValue());
  289                   return val;
  290               case DATE:
  291                   if (val instanceof String)
  292                       return new Date(val.toString());
  293                   return val;
  294               case DOUBLE_OBJ:
  295                   if (val instanceof Double)
  296                       return val;
  297                   if (val instanceof Number)
  298                       return new Double(((Number) val).doubleValue());
  299                   // no break
  300               case DOUBLE:
  301                   if (val instanceof String)
  302                       return new Double(val.toString());
  303                   return val;
  304               case FLOAT_OBJ:
  305                   if (val instanceof Float)
  306                       return val;
  307                   if (val instanceof Number)
  308                       return new Float(((Number) val).floatValue());
  309                   // no break
  310               case FLOAT:
  311                   if (val instanceof String)
  312                       return new Float(val.toString());
  313                   return val;
  314               case INT_OBJ:
  315                   if (val instanceof Integer)
  316                       return val;
  317                   if (val instanceof Number)
  318                       return Numbers.valueOf(((Number) val).intValue());
  319                   // no break
  320               case INT:
  321                   if (val instanceof String)
  322                       return new Integer(val.toString());
  323                   return val;
  324               case LONG_OBJ:
  325                   if (val instanceof Long)
  326                       return val;
  327                   if (val instanceof Number)
  328                       return Numbers.valueOf(((Number) val).longValue());
  329                   // no break
  330               case LONG:
  331                   if (val instanceof String)
  332                       return new Long(val.toString());
  333                   return val;
  334               case NUMBER:
  335                   if (val instanceof Number)
  336                       return val;
  337                   if (val instanceof String)
  338                       return new BigDecimal(val.toString());
  339                   return val;
  340               case SHORT_OBJ:
  341                   if (val instanceof Short)
  342                       return val;
  343                   if (val instanceof Number)
  344                       return new Short(((Number) val).shortValue());
  345                   // no break
  346               case SHORT:
  347                   if (val instanceof String)
  348                       return new Short(val.toString());
  349                   return val;
  350               case STRING:
  351                   return val.toString();
  352               default:
  353                   return val;
  354           }
  355       }
  356   
  357       /**
  358        * Return true if the (possibly unresolved) field or its elements might be
  359        * persistence capable objects.
  360        */
  361       public static boolean maybePC(FieldMetaData field) {
  362           switch (field.getDeclaredTypeCode()) {
  363               case JavaTypes.ARRAY:
  364               case JavaTypes.COLLECTION:
  365                   return maybePC(field.getElement());
  366               case JavaTypes.MAP:
  367                   return maybePC(field.getKey()) || maybePC(field.getElement());
  368               default:
  369                   return maybePC((ValueMetaData) field);
  370           }
  371       }
  372   
  373       /**
  374        * Return true if the (possibly unresolved) value might be a first class
  375        * object.
  376        */
  377       public static boolean maybePC(ValueMetaData val) {
  378           return maybePC(val.getDeclaredTypeCode(), val.getDeclaredType());
  379       }
  380   
  381       /**
  382        * Return true if the given unresolved typecode/type pair may represent a
  383        * persistent object.
  384        */
  385       static boolean maybePC(int typeCode, Class type) {
  386           if (type == null)
  387               return false;
  388           switch (typeCode) {
  389               case JavaTypes.OBJECT:
  390               case JavaTypes.PC:
  391               case JavaTypes.PC_UNTYPED:
  392                   return true;
  393               case JavaTypes.COLLECTION:
  394               case JavaTypes.MAP:
  395                   return !type.getName().startsWith("java.util.");
  396               default:
  397                   return false;
  398           }
  399       }
  400   
  401       /**
  402        * Helper method to return the given array value as a collection.
  403        */
  404       public static List toList(Object val, Class elem, boolean mutable) {
  405           if (val == null)
  406               return null;
  407   
  408           List l;
  409           if (!elem.isPrimitive()) {
  410               // if an object array, use built-in list function
  411               l = Arrays.asList((Object[]) val);
  412               if (mutable)
  413                   l = new ArrayList(l);
  414           } else {
  415               // convert to list of wrapper objects
  416               int length = Array.getLength(val);
  417               l = new ArrayList(length);
  418               for (int i = 0; i < length; i++)
  419                   l.add(Array.get(val, i));
  420           }
  421           return l;
  422       }
  423   
  424       /**
  425        * Helper method to return the given collection as an array.
  426        */
  427       public static Object toArray(Collection coll, Class elem) {
  428           if (coll == null)
  429               return null;
  430   
  431           Object array = Array.newInstance(elem, coll.size());
  432           int idx = 0;
  433           for (Iterator itr = coll.iterator(); itr.hasNext(); idx++)
  434               Array.set(array, idx, itr.next ());
  435   		return array;
  436   	}
  437   }

Save This Page
Home » apache-openjpa-1.1.0-source » org.apache.openjpa » meta » [javadoc | source]