diff --git a/simplCore/NIOLoggingServer.launch b/simplCore/NIOLoggingServer.launch index 0ff3e103..d263407d 100644 --- a/simplCore/NIOLoggingServer.launch +++ b/simplCore/NIOLoggingServer.launch @@ -1,12 +1,13 @@ <?xml version="1.0" encoding="UTF-8" standalone="no"?> <launchConfiguration type="org.eclipse.jdt.launching.localJavaApplication"> <listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_PATHS"> -<listEntry value="/ecologylabFundamental/ecologylab/oodss/logging/NIOLoggingServer.java"/> +<listEntry value="/ecologylabFundamental/src/ecologylab/oodss/logging/NIOLoggingServer.java"/> </listAttribute> <listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_TYPES"> <listEntry value="1"/> </listAttribute> <booleanAttribute key="org.eclipse.debug.core.appendEnvironmentVariables" value="true"/> +<booleanAttribute key="org.eclipse.jdt.launching.ATTR_USE_START_ON_FIRST_THREAD" value="true"/> <stringAttribute key="org.eclipse.jdt.launching.MAIN_TYPE" value="ecologylab.oodss.logging.NIOLoggingServer"/> <stringAttribute key="org.eclipse.jdt.launching.PROGRAM_ARGUMENTS" value="/logs/ 9999999"/> <stringAttribute key="org.eclipse.jdt.launching.PROJECT_ATTR" value="ecologylabFundamental"/> diff --git a/simplCore/src/ecologylab/appframework/ApplicationEnvironment.java b/simplCore/src/ecologylab/appframework/ApplicationEnvironment.java index b0f68e15..8f823dcd 100644 --- a/simplCore/src/ecologylab/appframework/ApplicationEnvironment.java +++ b/simplCore/src/ecologylab/appframework/ApplicationEnvironment.java @@ -242,7 +242,7 @@ protected static final SimplTypesScope prefsClassArrayToTranslationScope( Class<? extends Pref<?>>[] customPrefs) { // configure the PrefSet translation scope, incorporating custom translations, if any - if (customPrefs == null) + if (customPrefs == null || customPrefs.length == 0) customPrefs = PrefSetBaseClassProvider.STATIC_INSTANCE.provideClasses(); return SimplTypesScope.get(PrefSet.PREFS_TRANSLATION_SCOPE, customPrefs); diff --git a/simplCore/src/ecologylab/appframework/types/prefs/PrefSetBaseClassProvider.java b/simplCore/src/ecologylab/appframework/types/prefs/PrefSetBaseClassProvider.java index 81d6b613..c5b447ae 100644 --- a/simplCore/src/ecologylab/appframework/types/prefs/PrefSetBaseClassProvider.java +++ b/simplCore/src/ecologylab/appframework/types/prefs/PrefSetBaseClassProvider.java @@ -17,6 +17,7 @@ public class PrefSetBaseClassProvider extends TranslationsClassProvider protected PrefSetBaseClassProvider() { + super(); } /** @@ -26,13 +27,15 @@ protected PrefSetBaseClassProvider() protected Class<? extends Pref<?>>[] specificSuppliedClasses() { Class[] prefSetClasses = - { MetaPref.class, MetaPrefSet.class, MetaPrefBoolean.class, MetaPrefFloat.class, - MetaPrefInt.class, MetaPrefString.class, - - Pref.class, PrefSet.class, PrefBoolean.class, PrefDouble.class, PrefFloat.class, + { + Pref.class, PrefBoolean.class, PrefDouble.class, PrefFloat.class, PrefInt.class, PrefLong.class, PrefString.class, PrefElementState.class, PrefFile.class, PrefOp.class, + // XXX THIS MAY NOT SOLVE PROBLEMS WITH CUSTOM PREF TRANSLATIONS! + // XXX Putting PrefSet last helps with a circular dependency where PrefSet's ClassDescriptor + // needs the PrefSetBaseClassProvider's list of classes to compute its scope + PrefSet.class }; return prefSetClasses; diff --git a/simplCore/src/ecologylab/io/XMLFileFilter.java b/simplCore/src/ecologylab/io/XMLFileFilter.java index 0f019235..c4846843 100644 --- a/simplCore/src/ecologylab/io/XMLFileFilter.java +++ b/simplCore/src/ecologylab/io/XMLFileFilter.java @@ -7,7 +7,7 @@ public class XMLFileFilter implements FileFilter { static XMLFileFilter singleton; - static XMLFileFilter get() + public static XMLFileFilter get() { XMLFileFilter result = singleton; if (result == null) diff --git a/simplCore/src/ecologylab/serialization/deserializers/pullhandlers/stringformats/XMLPullDeserializer.java b/simplCore/src/ecologylab/serialization/deserializers/pullhandlers/stringformats/XMLPullDeserializer.java index 64e8a3a8..9c43aec5 100644 --- a/simplCore/src/ecologylab/serialization/deserializers/pullhandlers/stringformats/XMLPullDeserializer.java +++ b/simplCore/src/ecologylab/serialization/deserializers/pullhandlers/stringformats/XMLPullDeserializer.java @@ -19,6 +19,7 @@ import ecologylab.serialization.SIMPLTranslationException; import ecologylab.serialization.SimplTypesScope; import ecologylab.serialization.TranslationContext; +import ecologylab.serialization.annotations.simpl_nowrap; import ecologylab.serialization.types.element.IMappable; /** @@ -32,8 +33,8 @@ public class XMLPullDeserializer extends StringPullDeserializer // private CharSequence test; - XMLParser xmlParser; - + XMLParser xmlParser; + /** * * @param translationScope @@ -68,36 +69,38 @@ public Object parse(InputStream inputStream, Charset charSet) throws SIMPLTransl result = parse(); return result; } - catch(SIMPLTranslationException ex) + catch (SIMPLTranslationException ex) { - throw ex; + throw ex; } catch (Exception ex) { - SIMPLTranslationException ste = new SIMPLTranslationException("exception occurred in deserialzation ", ex); + SIMPLTranslationException ste = new SIMPLTranslationException( + "exception occurred in deserialzation ", ex); ste.setRemnantObject(result); throw ste; } } - + @Override public Object parse(InputStream inputStream) throws SIMPLTranslationException { - // hold onto a black result to return. - Object result = null; + // hold onto a black result to return. + Object result = null; try { configure(inputStream); result = parse(); return result; } - catch(SIMPLTranslationException ex) + catch (SIMPLTranslationException ex) { - throw ex; + throw ex; } catch (Exception ex) { - SIMPLTranslationException toThrow = new SIMPLTranslationException("exception occurred in deserialzation ", ex); + SIMPLTranslationException toThrow = new SIMPLTranslationException( + "exception occurred in deserialzation ", ex); toThrow.setRemnantObject(result); throw toThrow; } @@ -117,21 +120,22 @@ public Object parse(InputStream inputStream) throws SIMPLTranslationException @Override public Object parse(CharSequence charSequence) throws SIMPLTranslationException { - // hold onto a black result to return. - Object result = null; + // hold onto a black result to return. + Object result = null; try { configure(charSequence); result = parse(); return result; } - catch(SIMPLTranslationException ex) + catch (SIMPLTranslationException ex) { - throw ex; + throw ex; } catch (Exception ex) { - SIMPLTranslationException ste = new SIMPLTranslationException("exception occurred in deserialzation ", ex); + SIMPLTranslationException ste = new SIMPLTranslationException( + "exception occurred in deserialzation ", ex); ste.setRemnantObject(result); throw ste; } @@ -149,7 +153,7 @@ private void configure(InputStream inputStream, Charset charSet) throws SIMPLTra { xmlParser = FundamentalPlatformSpecifics.get().getXMLParser(inputStream, charSet); } - + /** * * @param inputStream @@ -181,12 +185,11 @@ private void configure(CharSequence charSequence) throws SIMPLTranslationExcepti */ private Object parse() throws SIMPLTranslationException, IOException { - Object root = null; nextEvent(); - // We should expect the first element to be the START + // We should expect the first element to be the START if (xmlParser.getEventType() != XMLParser.START_ELEMENT) { throw new SIMPLTranslationException("start of an element expected"); @@ -204,16 +207,21 @@ private Object parse() throws SIMPLTranslationException, IOException } root = rootClassDescriptor.getInstance(); - - // Logic to set all field descritpro scalars to defaults. - for(FieldDescriptor fd : rootClassDescriptor.allFieldDescriptors()) + + // Logic to set all field descriptors scalars to defaults. + // Logic to identify no_wrap collections at root level + for (FieldDescriptor fd : rootClassDescriptor.allFieldDescriptors()) { - if(fd.isScalar() && (fd.isEnum() == false)) + if (fd.isScalar() && (fd.isEnum() == false)) { fd.setFieldToScalarDefault(root, translationContext); } - } + if (fd.isCollection() && fd.getField().isAnnotationPresent(simpl_nowrap.class)) + { + // rootClassDescriptor. + } + } deserializationPreHook(root, translationContext); if (deserializationHookStrategy != null) @@ -224,12 +232,12 @@ private Object parse() throws SIMPLTranslationException, IOException deserializationInHook(root, translationContext); if (deserializationHookStrategy != null) deserializationHookStrategy.deserializationInHook(root, null); - + createObjectModel(root, rootClassDescriptor, rootTag); - // Post hook is called at the end of createObjectModel. - // That should be pulled here at some point. - + // Post hook is called at the end of createObjectModel. + // That should be pulled here at some point. + return root; } @@ -252,103 +260,104 @@ private void createObjectModel(Object root, ClassDescriptor<? extends FieldDescriptor> rootClassDescriptor, String rootTag) throws IOException, SIMPLTranslationException { - int event = 0; - event = nextEvent(); + int event = 0; + event = nextEvent(); - - FieldDescriptor currentFieldDescriptor = null; // new FieldDescriptor(); + FieldDescriptor currentFieldDescriptor = null; // new FieldDescriptor(); - String xmlText = ""; + String xmlText = ""; - while ( event!= XMLParser.END_DOCUMENT - && (event != XMLParser.END_ELEMENT || !rootTag.equals(getTagName()))) + while (event != XMLParser.END_DOCUMENT + && (event != XMLParser.END_ELEMENT || !rootTag.equals(getTagName()))) + { + if (event != XMLParser.START_ELEMENT) { - if (event != XMLParser.START_ELEMENT) + if (event == XMLParser.CHARACTERS) { - if (event == XMLParser.CHARACTERS) - { - xmlText += xmlParser.getText(); - } - else if (event == XMLParser.END_ELEMENT && currentFieldDescriptor != null && currentFieldDescriptor.getType() == FieldType.WRAPPER) - { - currentFieldDescriptor = currentFieldDescriptor.getWrappedFD(); - } - - event = nextEvent(); - continue; + xmlText += xmlParser.getText(); + } + else if (event == XMLParser.END_ELEMENT && currentFieldDescriptor != null + && currentFieldDescriptor.getType() == FieldType.WRAPPER) + { + currentFieldDescriptor = currentFieldDescriptor.getWrappedFD(); } - String tag = getTagName(); + event = nextEvent(); + continue; + } - currentFieldDescriptor = currentFieldDescriptor != null &¤tFieldDescriptor.getType() == FieldType.WRAPPER - ? currentFieldDescriptor.getWrappedFD() - : rootClassDescriptor.getFieldDescriptorByTag(tag, translationScope, null); + String tag = getTagName(); - if (currentFieldDescriptor == null) - { - currentFieldDescriptor = FieldDescriptor.makeIgnoredFieldDescriptor(tag); - } + currentFieldDescriptor = + currentFieldDescriptor != null && currentFieldDescriptor.getType() == FieldType.WRAPPER + ? currentFieldDescriptor.getWrappedFD() + : rootClassDescriptor.getFieldDescriptorByTag(tag, translationScope, null); - - FieldType fieldType = currentFieldDescriptor.getType(); + if (currentFieldDescriptor == null) + { + currentFieldDescriptor = FieldDescriptor.makeIgnoredFieldDescriptor(tag); + } - switch (fieldType) - { - case SCALAR: - - // If we don't find a field declaration in the serialized representation for a scalar field... - // We'll never end up changing its value. So instead, let's automatically set every scalar value to its corresponding default value first. - event = deserializeScalar(root, currentFieldDescriptor); - break; - - case COLLECTION_SCALAR: - event = deserializeScalarCollection(root, currentFieldDescriptor); - break; - - case COMPOSITE_ELEMENT: - event = deserializeComposite(root, currentFieldDescriptor); - break; - - case COLLECTION_ELEMENT: - event = deserializeCompositeCollection(root, currentFieldDescriptor); - break; - - case MAP_ELEMENT: - event = deserializeCompositeMap(root, currentFieldDescriptor); - break; - - case WRAPPER: - event = nextEvent(); - break; - - case IGNORED_ELEMENT: - event = ignoreTag(tag); - break; - - default: - event = nextEvent(); - - } + FieldType fieldType = currentFieldDescriptor.getType(); + + switch (fieldType) + { + case SCALAR: + + // If we don't find a field declaration in the serialized representation for a scalar + // field... + // We'll never end up changing its value. So instead, let's automatically set every scalar + // value to its corresponding default value first. + event = deserializeScalar(root, currentFieldDescriptor); + break; + + case COLLECTION_SCALAR: + event = deserializeScalarCollection(root, currentFieldDescriptor); + break; + + case COMPOSITE_ELEMENT: + event = deserializeComposite(root, currentFieldDescriptor); + break; + + case COLLECTION_ELEMENT: + event = deserializeCompositeCollection(root, currentFieldDescriptor); + break; + + case MAP_ELEMENT: + event = deserializeCompositeMap(root, currentFieldDescriptor); + break; + + case WRAPPER: + event = nextEvent(); + break; + + case IGNORED_ELEMENT: + event = ignoreTag(tag); + break; + + default: + event = nextEvent(); - if (event == XMLParser.END_DOCUMENT) - { - // no more data? but we are expecting so its not correct - throw new SIMPLTranslationException( - "premature end of file: check XML file for consistency"); - } } - if (rootClassDescriptor.hasScalarFD()) + if (event == XMLParser.END_DOCUMENT) { - rootClassDescriptor.getScalarTextFD().setFieldToScalar(root, xmlText, translationContext); + // no more data? but we are expecting so its not correct + throw new SIMPLTranslationException("premature end of file: check XML file for consistency"); } - - deserializationPostHook(root, translationContext); - if (deserializationHookStrategy != null) - deserializationHookStrategy.deserializationPostHook(root, - currentFieldDescriptor == null || currentFieldDescriptor.getType() == FieldType.IGNORED_ELEMENT - ? null : currentFieldDescriptor); -// deserializationHookStrategy.deserializationPostHook(root, null); + } + + if (rootClassDescriptor.hasScalarFD()) + { + rootClassDescriptor.getScalarTextFD().setFieldToScalar(root, xmlText, translationContext); + } + + deserializationPostHook(root, translationContext); + if (deserializationHookStrategy != null) + deserializationHookStrategy.deserializationPostHook(root, currentFieldDescriptor == null + || currentFieldDescriptor.getType() == FieldType.IGNORED_ELEMENT ? null + : currentFieldDescriptor); + // deserializationHookStrategy.deserializationPostHook(root, null); } /** @@ -395,7 +404,7 @@ private int deserializeScalarCollection(Object root, FieldDescriptor fd) fd.addLeafNodeToCollection(root, value, translationContext); } - event = xmlParser.nextTag(); + event = xmlParser.nextTag(); tagName = getTagName(); } } @@ -447,7 +456,8 @@ private int deserializeCompositeMap(Object root, FieldDescriptor fd) String compositeTagName = getTagName(); subRoot = getSubRoot(fd, compositeTagName, root); - final Object key = (subRoot instanceof IMappable<?>) ? ((IMappable<?>) subRoot).key() : fd.getMapKeyFieldValue(subRoot); + final Object key = (subRoot instanceof IMappable<?>) ? ((IMappable<?>) subRoot).key() : fd + .getMapKeyFieldValue(subRoot); if (key != null) { Map map = (Map) fd.automaticLazyGetCollectionOrMap(root); @@ -490,12 +500,11 @@ private int deserializeCompositeCollection(Object root, FieldDescriptor fd) } subRoot = getSubRoot(fd, tagName, root); - - + Collection collection = (Collection) fd.automaticLazyGetCollectionOrMap(root); collection.add(subRoot); - event = xmlParser.nextTag(); + event = xmlParser.nextTag(); tagName = getTagName(); } } @@ -523,7 +532,7 @@ private int deserializeScalar(Object root, FieldDescriptor currentFieldDescripto while (nextEvent() != XMLParser.END_ELEMENT); String value = text.toString(); - + currentFieldDescriptor.setFieldToScalar(root, value, translationContext); return nextEvent(); @@ -577,11 +586,11 @@ private Object getSubRoot(FieldDescriptor currentFieldDescriptor, String tagName else { subRoot = subRootClassDescriptor.getInstance(); - - // Logic to set all field descritpro scalars to defaults. - for(FieldDescriptor fd : subRootClassDescriptor.allFieldDescriptors()) + + // Logic to set all field descritpro scalars to defaults. + for (FieldDescriptor fd : subRootClassDescriptor.allFieldDescriptors()) { - if(fd.isScalar() && (fd.isEnum() == false)) + if (fd.isScalar() && (fd.isEnum() == false)) { fd.setFieldToScalarDefault(subRoot, translationContext); } @@ -600,17 +609,18 @@ private Object getSubRoot(FieldDescriptor currentFieldDescriptor, String tagName } deserializeAttributes(subRoot, subRootClassDescriptor); - + deserializationInHook(subRoot, translationContext); if (deserializationHookStrategy != null) deserializationHookStrategy.deserializationInHook(subRoot, currentFieldDescriptor); - + createObjectModel(subRoot, subRootClassDescriptor, tagName); } - + if (deserializationHookStrategy != null && subRoot != null) { - Object newSubRoot= deserializationHookStrategy.changeObjectIfNecessary(subRoot, currentFieldDescriptor); + Object newSubRoot = deserializationHookStrategy.changeObjectIfNecessary(subRoot, + currentFieldDescriptor); if (newSubRoot != null) subRoot = newSubRoot; } @@ -713,7 +723,7 @@ private int nextEvent() throws SIMPLTranslationException } /** - * @throws SIMPLTranslationException + * @throws SIMPLTranslationException * */ protected void debug() @@ -723,18 +733,18 @@ protected void debug() int event = xmlParser.getEventType(); switch (event) { - case XMLParser.START_ELEMENT: - System.out.println(getTagName()); - break; - case XMLParser.END_ELEMENT: - System.out.println(getTagName()); - break; - case XMLParser.CHARACTERS: - System.out.println(xmlParser.getText()); - break; - case XMLParser.CDATA: - System.out.println("cdata " + xmlParser.getText()); - break; + case XMLParser.START_ELEMENT: + System.out.println(getTagName()); + break; + case XMLParser.END_ELEMENT: + System.out.println(getTagName()); + break; + case XMLParser.CHARACTERS: + System.out.println(xmlParser.getText()); + break; + case XMLParser.CDATA: + System.out.println("cdata " + xmlParser.getText()); + break; } // end switch } catch (SIMPLTranslationException e) @@ -796,6 +806,6 @@ protected void printParse() throws SIMPLTranslationException } // end switch } while (xmlParser.next() != XMLParser.END_DOCUMENT); - + } } diff --git a/simplCore/src/ecologylab/serialization/types/CrossLanguageTypeConstants.java b/simplCore/src/ecologylab/serialization/types/CrossLanguageTypeConstants.java index e4077b27..a12ae813 100644 --- a/simplCore/src/ecologylab/serialization/types/CrossLanguageTypeConstants.java +++ b/simplCore/src/ecologylab/serialization/types/CrossLanguageTypeConstants.java @@ -145,6 +145,8 @@ public interface CrossLanguageTypeConstants public static final String JAVA_DATE = "Date"; + public static final String JAVA_CALENDAR = "Calendar"; + public static final String JAVA_STRING_BUILDER = "StringBuilder"; public static final String JAVA_URL = "Url"; diff --git a/simplCore/src/ecologylab/serialization/types/FundamentalTypes.java b/simplCore/src/ecologylab/serialization/types/FundamentalTypes.java index 8d4dcbec..d56e0cef 100644 --- a/simplCore/src/ecologylab/serialization/types/FundamentalTypes.java +++ b/simplCore/src/ecologylab/serialization/types/FundamentalTypes.java @@ -5,7 +5,9 @@ import java.net.URL; import java.nio.ByteBuffer; import java.util.ArrayList; +import java.util.Calendar; import java.util.Date; +import java.util.GregorianCalendar; import java.util.HashMap; import java.util.UUID; import java.util.regex.Pattern; @@ -13,7 +15,39 @@ import ecologylab.collections.Scope; import ecologylab.generic.HashMapArrayList; import ecologylab.net.ParsedURL; -import ecologylab.serialization.types.scalar.*; +import ecologylab.serialization.types.scalar.BinaryDataType; +import ecologylab.serialization.types.scalar.BooleanType; +import ecologylab.serialization.types.scalar.ByteType; +import ecologylab.serialization.types.scalar.CalendarType; +import ecologylab.serialization.types.scalar.CharType; +import ecologylab.serialization.types.scalar.ClassType; +import ecologylab.serialization.types.scalar.CollectionTypeType; +import ecologylab.serialization.types.scalar.CompositeAsScalarType; +import ecologylab.serialization.types.scalar.DateType; +import ecologylab.serialization.types.scalar.DoubleType; +import ecologylab.serialization.types.scalar.EnumeratedType; +import ecologylab.serialization.types.scalar.FieldType; +import ecologylab.serialization.types.scalar.FileType; +import ecologylab.serialization.types.scalar.FloatType; +import ecologylab.serialization.types.scalar.GregorianCalendarType; +import ecologylab.serialization.types.scalar.IntType; +import ecologylab.serialization.types.scalar.LongType; +import ecologylab.serialization.types.scalar.ParsedURLType; +import ecologylab.serialization.types.scalar.PatternType; +import ecologylab.serialization.types.scalar.ReferenceBooleanType; +import ecologylab.serialization.types.scalar.ReferenceByteType; +import ecologylab.serialization.types.scalar.ReferenceCharType; +import ecologylab.serialization.types.scalar.ReferenceDoubleType; +import ecologylab.serialization.types.scalar.ReferenceFloatType; +import ecologylab.serialization.types.scalar.ReferenceIntegerType; +import ecologylab.serialization.types.scalar.ReferenceLongType; +import ecologylab.serialization.types.scalar.ReferenceShortType; +import ecologylab.serialization.types.scalar.ScalarTypeType; +import ecologylab.serialization.types.scalar.ShortType; +import ecologylab.serialization.types.scalar.StringBuilderType; +import ecologylab.serialization.types.scalar.StringType; +import ecologylab.serialization.types.scalar.URLType; +import ecologylab.serialization.types.scalar.UUIDType; public class FundamentalTypes implements CrossLanguageTypeConstants @@ -84,6 +118,10 @@ public class FundamentalTypes public static final ScalarType<Date> DATE_TYPE = new DateType(); + public static final ScalarType<Calendar> CALENDAR_TYPE = new CalendarType(); + + public static final ScalarType<GregorianCalendar> GREGORIAN_CALENDAR_TYPE = new GregorianCalendarType(); + public static final ScalarType<ScalarType> SCALAR_TYPE_TYPE = new ScalarTypeType(); public static final ScalarType<CollectionType> COLLECTION_TYPE_TYPE = new CollectionTypeType(); diff --git a/simplCore/src/ecologylab/serialization/types/scalar/CalendarType.java b/simplCore/src/ecologylab/serialization/types/scalar/CalendarType.java new file mode 100644 index 00000000..638486da --- /dev/null +++ b/simplCore/src/ecologylab/serialization/types/scalar/CalendarType.java @@ -0,0 +1,265 @@ +/* + * Created on Jan 2, 2005 at the Interface Ecology Lab. + */ +package ecologylab.serialization.types.scalar; + +import java.io.IOException; +import java.text.DateFormat; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Calendar; +import java.util.Date; + +import org.json.simple.JSONObject; + +import ecologylab.serialization.ClassDescriptor; +import ecologylab.serialization.FieldDescriptor; +import ecologylab.serialization.ScalarUnmarshallingContext; +import ecologylab.serialization.TranslationContext; +import ecologylab.serialization.XMLTools; +import ecologylab.serialization.annotations.simpl_inherit; +import ecologylab.serialization.formatenums.Format; +import ecologylab.serialization.types.CrossLanguageTypeConstants; + +/** + * Type system entry for {@link java.util.Calendar Calendar}. + * + * @author Zachary O. Toups (ztoups@nmsu.edu) + */ +@simpl_inherit +public class CalendarType extends ReferenceType<Calendar> implements + CrossLanguageTypeConstants +{ + static final String datePatterns[] = + { + "EEE MMM dd kk:mm:ss zzz yyyy", + "yyyy:MM:dd HH:mm:ss", + "yyyy:MM:dd HH:mm", + "yyyy-MM-dd HH:mm:ss", + "yyyy-MM-dd HH:mm", + "MMM dd, yyyy", + "yyyyMMdd", + "MM/dd/yyyy", + "MM/dd/yyyy K:mm aa", + }; + + static final DateFormat dateFormats[] = new DateFormat[datePatterns.length + 1]; + + static final DateFormat plainDf = DateFormat.getDateTimeInstance(); + + static + { + for (int i = 0; i < datePatterns.length; i++) + dateFormats[i] = new SimpleDateFormat(datePatterns[i]); + dateFormats[datePatterns.length] = plainDf; + } + + public CalendarType() + { + super(Calendar.class, JAVA_CALENDAR, null, null, null); + } + + /** + * Uses the format specified by the first entry in simpl_format; if that fails, cycles through + * additional patterns specified by datePatterns[] until one succeeds. + * + * @param value + * @see ecologylab.serialization.types.ScalarType#getInstance(java.lang.String, String[], + * ScalarUnmarshallingContext) + */ + @Override + public Calendar getInstance(String value, String[] formatStrings, + ScalarUnmarshallingContext scalarUnmarshallingContext) + { + if (formatStrings[0] != null && !"".equals(formatStrings[0])) + try + { + DateFormat df = new SimpleDateFormat(formatStrings[0]); + Date d = df.parse(value); + Calendar c = Calendar.getInstance(); + c.setTimeInMillis(d.getTime()); + + return c; + } + catch (ParseException e) + { // simply try all the patterns + } + + for (DateFormat dateFormatParser : dateFormats) + { + try + { + Date d = dateFormatParser.parse(value); + Calendar c = Calendar.getInstance(); + c.setTimeInMillis(d.getTime()); + + return c; + } + catch (java.text.ParseException ex) + { // simply try the next pattern + } + } + + error("Failed to parse date: " + value); + return null; + } + + @Override + public void appendValue(StringBuilder buffy, FieldDescriptor fieldDescriptor, Object context) + throws IllegalArgumentException, IllegalAccessException + { + try + { + Calendar instance = (Calendar) fieldDescriptor.getField().get(context); + + appendValue(instance, fieldDescriptor.getFormat(), buffy, !fieldDescriptor.isCDATA(), null); + } + catch (IllegalArgumentException e) + { + throw e; + } + } + + /** + * Append the String directly, unless it needs escaping, in which case, call escapeXML. + * + * @param instance + * @param buffy + * @param needsEscaping + */ + public void appendValue( + Calendar instance, + String[] formatDescriptors, + StringBuilder buffy, + boolean needsEscaping, + TranslationContext serializationContext) + { + String instanceString = marshall(instance, formatDescriptors, serializationContext);// instance.toString(); + if (needsEscaping) + XMLTools.escapeXML(buffy, instanceString); + else + buffy.append(instanceString); + } + + @Override + public void appendValue(Calendar instance, StringBuilder buffy, boolean needsEscaping, + TranslationContext serializationContext) + { + ClassDescriptor compositeElement = ClassDescriptor.getClassDescriptor(instance); + FieldDescriptor scalarValueFD = compositeElement.getScalarValueFieldDescripotor(); + String instanceString = marshall(instance, scalarValueFD.getFormat(), serializationContext);// instance.toString(); + if (needsEscaping) + XMLTools.escapeXML(buffy, instanceString); + else + buffy.append(instanceString); + } + + // @Override + // public void appendValue(Calendar instance, Appendable buffy, boolean needsEscaping, + // TranslationContext serializationContext, Format format) throws IOException + // { + // String instanceString = ""; + // if (instance != null && serializationContext != null) + // { + // ClassDescriptor compositeElement = ClassDescriptor.getClassDescriptor(instance); + // FieldDescriptor scalarValueFD = compositeElement.getScalarValueFieldDescripotor(); + // + // if (scalarValueFD != null) + // instanceString = marshall(instance, scalarValueFD.getFormat(), serializationContext); // + // andruid + // // 1/4/10 + // else + // instanceString = marshall(instance, new String[0], serializationContext); + // } + // // instance.toString(); + // if (needsEscaping) + // { + // switch (format) + // { + // case JSON: + // buffy.append(JSONObject.escape(instanceString)); + // break; + // case XML: + // XMLTools.escapeXML(buffy, instanceString); + // break; + // default: + // XMLTools.escapeXML(buffy, instanceString); + // break; + // } + // + // } + // else + // buffy.append(instanceString); + // } + + /** + * Get the value from the Field, in the context. Append its value to the buffy. + * <p/> + * Should only be called *after* checking !isDefault() yourself. + * + * @param buffy + * @param context + * @param serializationContext + * TODO + * @param field + * @param needsEscaping + * TODO + * @throws IllegalAccessException + * @throws IllegalArgumentException + */ + @Override + public void appendValue(Appendable buffy, FieldDescriptor fieldDescriptor, Object context, + TranslationContext serializationContext, Format format) + throws IllegalArgumentException, IllegalAccessException, IOException + { + Calendar instance = (Calendar) fieldDescriptor.getValue(context); + boolean needsEscaping = !fieldDescriptor.isCDATA(); + // appendValue((T) instance, buffy, !fieldDescriptor.isCDATA(), serializationContext, format); + + String instanceString = ""; + if (instance != null && serializationContext != null) + instanceString = marshall(instance, fieldDescriptor.getFormat(), serializationContext); // andruid + // instance.toString(); + if (needsEscaping) + { + switch (format) + { + case JSON: + buffy.append(JSONObject.escape(instanceString)); + break; + case XML: + XMLTools.escapeXML(buffy, instanceString); + break; + default: + XMLTools.escapeXML(buffy, instanceString); + break; + } + + } + else + buffy.append(instanceString); + } + + /** + * Get a String representation of the instance, using this. The default just calls the toString() + * method on the instance. + * + * @param instance + * @param serializationContext + * TODO + * @return + */ + public String marshall(Calendar instance, String[] formatDescriptors, + TranslationContext serializationContext) + { + String pattern = null; + if (formatDescriptors.length > 0 && formatDescriptors[0] != null) + pattern = formatDescriptors[0]; + else + pattern = datePatterns[0]; + + DateFormat df = new SimpleDateFormat(pattern); + Date d = instance.getTime(); + return df.format(d); + } +} diff --git a/simplCore/src/ecologylab/serialization/types/scalar/GregorianCalendarType.java b/simplCore/src/ecologylab/serialization/types/scalar/GregorianCalendarType.java new file mode 100644 index 00000000..ebda375e --- /dev/null +++ b/simplCore/src/ecologylab/serialization/types/scalar/GregorianCalendarType.java @@ -0,0 +1,217 @@ +/* + * Created on Jan 2, 2005 at the Interface Ecology Lab. + */ +package ecologylab.serialization.types.scalar; + +import java.io.IOException; +import java.text.DateFormat; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Calendar; +import java.util.Date; +import java.util.GregorianCalendar; + +import org.json.simple.JSONObject; + +import ecologylab.serialization.ClassDescriptor; +import ecologylab.serialization.FieldDescriptor; +import ecologylab.serialization.ScalarUnmarshallingContext; +import ecologylab.serialization.TranslationContext; +import ecologylab.serialization.XMLTools; +import ecologylab.serialization.annotations.simpl_inherit; +import ecologylab.serialization.formatenums.Format; +import ecologylab.serialization.types.CrossLanguageTypeConstants; + +/** + * Type system entry for {@link java.util.Calendar Calendar}. + * + * @author Zachary O. Toups (ztoups@nmsu.edu) + */ +@simpl_inherit +public class GregorianCalendarType extends ReferenceType<GregorianCalendar> implements + CrossLanguageTypeConstants +{ + static final String datePatterns[] = + { + "EEE MMM dd kk:mm:ss zzz yyyy", + "yyyy:MM:dd HH:mm:ss", + "yyyy:MM:dd HH:mm", + "yyyy-MM-dd HH:mm:ss", + "yyyy-MM-dd HH:mm", + "MMM dd, yyyy", + "yyyyMMdd", + "MM/dd/yyyy", + "MM/dd/yyyy K:mm aa", + }; + + static final DateFormat dateFormats[] = new DateFormat[datePatterns.length + 1]; + + static final DateFormat plainDf = DateFormat.getDateTimeInstance(); + + static + { + for (int i = 0; i < datePatterns.length; i++) + dateFormats[i] = new SimpleDateFormat(datePatterns[i]); + dateFormats[datePatterns.length] = plainDf; + } + + public GregorianCalendarType() + { + super(GregorianCalendar.class, JAVA_CALENDAR, null, null, null); + } + + /** + * Uses the format specified by the first entry in simpl_format; if that fails, cycles through + * additional patterns specified by datePatterns[] until one succeeds. + * + * @param value + * @see ecologylab.serialization.types.ScalarType#getInstance(java.lang.String, String[], + * ScalarUnmarshallingContext) + */ + @Override + public GregorianCalendar getInstance(String value, String[] formatStrings, + ScalarUnmarshallingContext scalarUnmarshallingContext) + { + if (formatStrings[0] != null && !"".equals(formatStrings[0])) + try + { + DateFormat df = new SimpleDateFormat(formatStrings[0]); + Date d = df.parse(value); + GregorianCalendar c = (GregorianCalendar) Calendar.getInstance(); + c.setTimeInMillis(d.getTime()); + + return c; + } + catch (ParseException e) + { // simply try all the patterns + } + + for (DateFormat dateFormatParser : dateFormats) + { + try + { + Date d = dateFormatParser.parse(value); + GregorianCalendar c = (GregorianCalendar) Calendar.getInstance(); + c.setTimeInMillis(d.getTime()); + + return c; + } + catch (java.text.ParseException ex) + { // simply try the next pattern + } + } + + error("Failed to parse date: " + value); + return null; + } + + @Override + public void appendValue(StringBuilder buffy, FieldDescriptor fieldDescriptor, Object context) + throws IllegalArgumentException, IllegalAccessException + { + try + { + GregorianCalendar instance = (GregorianCalendar) fieldDescriptor.getField().get(context); + + appendValue(instance, fieldDescriptor.getFormat(), buffy, !fieldDescriptor.isCDATA(), null); + } + catch (IllegalArgumentException e) + { + throw e; + } + } + + /** + * Append the String directly, unless it needs escaping, in which case, call escapeXML. + * + * @param instance + * @param buffy + * @param needsEscaping + */ + public void appendValue( + GregorianCalendar instance, + String[] formatDescriptors, + StringBuilder buffy, + boolean needsEscaping, + TranslationContext serializationContext) + { + String instanceString = marshall(instance, formatDescriptors, serializationContext);// instance.toString(); + if (needsEscaping) + XMLTools.escapeXML(buffy, instanceString); + else + buffy.append(instanceString); + } + + @Override + public void appendValue(GregorianCalendar instance, StringBuilder buffy, boolean needsEscaping, + TranslationContext serializationContext) + { + ClassDescriptor compositeElement = ClassDescriptor.getClassDescriptor(instance); + FieldDescriptor scalarValueFD = compositeElement.getScalarValueFieldDescripotor(); + String instanceString = marshall(instance, scalarValueFD.getFormat(), serializationContext);// instance.toString(); + if (needsEscaping) + XMLTools.escapeXML(buffy, instanceString); + else + buffy.append(instanceString); + } + + @Override + public void appendValue(GregorianCalendar instance, Appendable buffy, boolean needsEscaping, + TranslationContext serializationContext, Format format) throws IOException + { + String instanceString = ""; + if (instance != null && serializationContext != null) + { + ClassDescriptor compositeElement = ClassDescriptor.getClassDescriptor(instance); + FieldDescriptor scalarValueFD = compositeElement.getScalarValueFieldDescripotor(); + + if (scalarValueFD != null) + instanceString = marshall(instance, scalarValueFD.getFormat(), serializationContext); // andruid + // 1/4/10 + else + instanceString = marshall(instance, new String[0], serializationContext); + } + // instance.toString(); + if (needsEscaping) + { + switch (format) + { + case JSON: + buffy.append(JSONObject.escape(instanceString)); + break; + case XML: + XMLTools.escapeXML(buffy, instanceString); + break; + default: + XMLTools.escapeXML(buffy, instanceString); + break; + } + + } + else + buffy.append(instanceString); + } + + /** + * Get a String representation of the instance, using this. The default just calls the toString() + * method on the instance. + * + * @param instance + * @param serializationContext + * TODO + * @return + */ + public String marshall(GregorianCalendar instance, String[] formatDescriptors, + TranslationContext serializationContext) + { + String pattern = null; + if (formatDescriptors.length > 0 && formatDescriptors[0] != null) + pattern = formatDescriptors[0]; + else + pattern = datePatterns[0]; + + DateFormat df = new SimpleDateFormat(pattern); + Date d = instance.getTime(); + return df.format(d); + } +}