001 // Copyright 2008 Waterken Inc. under the terms of the MIT X license 002 // found at http://www.opensource.org/licenses/mit-license.html 003 package org.waterken.syntax; 004 005 import java.io.Serializable; 006 import java.lang.reflect.Constructor; 007 import java.lang.reflect.Type; 008 009 import org.joe_e.Powerless; 010 import org.joe_e.Struct; 011 import org.joe_e.reflect.Reflection; 012 import org.ref_send.Record; 013 import org.ref_send.deserializer; 014 import org.ref_send.name; 015 016 /** 017 * A serialization syntax. 018 */ 019 public class 020 Syntax extends Struct implements Powerless, Record, Serializable { 021 static private final long serialVersionUID = 1L; 022 023 /** 024 * file extension 025 */ 026 public final String ext; 027 028 /** 029 * serializer 030 */ 031 public final Serializer serializer; 032 033 /** 034 * deserializer 035 */ 036 public final Deserializer deserializer; 037 038 /** 039 * Constructs an instance. 040 * @param ext {@link #ext} 041 * @param serializer {@link #serializer} 042 * @param deserializer {@link #deserializer} 043 */ 044 public @deserializer 045 Syntax(@name("ext") final String ext, 046 @name("serializer") final Serializer serializer, 047 @name("deserializer") final Deserializer deserializer) { 048 this.ext = ext; 049 this.serializer = serializer; 050 this.deserializer = deserializer; 051 } 052 053 /** 054 * Finds a corresponding {@link deserializer}. 055 * @param type type to construct 056 * @return constructor, or <code>null</code> if none 057 */ 058 static public Constructor<?> 059 deserializer(final Class<?> type) { 060 for (Class<?> i = type; null != i; i = i.getSuperclass()) { 061 // Check for an explicit deserializer constructor. 062 for (final Constructor<?> c : Reflection.constructors(i)) { 063 if (c.isAnnotationPresent(deserializer.class)) { return c; } 064 } 065 // Check for a default constructor of a pass-by-copy type. 066 if (Throwable.class.isAssignableFrom(i) || 067 Record.class.isAssignableFrom(i)) { 068 try { 069 return Reflection.constructor(i); 070 } catch (final NoSuchMethodException e) { 071 if (Record.class.isAssignableFrom(i)) { 072 throw new MissingDeserializer(Reflection.getName(i)); 073 } 074 } 075 } 076 // Look for one in the superclass. 077 } 078 return null; 079 } 080 081 /** 082 * Gets the default value of a specified type. 083 * @param required required type 084 * @return default value 085 */ 086 static public Object 087 defaultValue(final Type required) { 088 return boolean.class == required ? Boolean.FALSE : 089 char.class == required ? Character.valueOf('\0') : 090 byte.class == required ? Byte.valueOf((byte)0) : 091 short.class == required ? Short.valueOf((short)0) : 092 int.class == required ? Integer.valueOf(0) : 093 long.class == required ? Long.valueOf(0) : 094 float.class == required ? Float.valueOf(0.0f) : 095 double.class == required ? Double.valueOf(0.0) : 096 (Object)null; 097 } 098 }