[Bedework-commit] rpiutil r190 - in trunk/src/edu/rpi: cmt/calendar sss/util sss/util/xml sss/util/xml/tagdefs

svnadmin at bedework.org svnadmin at bedework.org
Wed Sep 15 11:05:07 EDT 2010


Author: douglm
Date: 2010-09-15 11:05:06 -0400 (Wed, 15 Sep 2010)
New Revision: 190

Added:
   trunk/src/edu/rpi/sss/util/xml/XmlEmitNamespaces.java
Modified:
   trunk/src/edu/rpi/cmt/calendar/PropertyIndex.java
   trunk/src/edu/rpi/sss/util/Options.java
   trunk/src/edu/rpi/sss/util/xml/XmlEmit.java
   trunk/src/edu/rpi/sss/util/xml/tagdefs/XcalTags.java
Log:
Pay some attention to the ACCEPT values or the data type in the calendar-data element. Allow for different default content-types for caldav and web service.

Implement generation of XML and produce that when appropriate

Modified: trunk/src/edu/rpi/cmt/calendar/PropertyIndex.java
===================================================================
--- trunk/src/edu/rpi/cmt/calendar/PropertyIndex.java	2010-09-09 14:08:43 UTC (rev 189)
+++ trunk/src/edu/rpi/cmt/calendar/PropertyIndex.java	2010-09-15 15:05:06 UTC (rev 190)
@@ -25,9 +25,13 @@
 */
 package edu.rpi.cmt.calendar;
 
+import edu.rpi.sss.util.xml.tagdefs.XcalTags;
+
 import java.io.Serializable;
 import java.util.HashMap;
 
+import javax.xml.namespace.QName;
+
 /** Define an (arbitrary) index associated with calendar properties
  *
  * @author Mike Douglass   douglm at rpi.edu
@@ -119,6 +123,249 @@
   private static boolean NOT_IMMUTABLE = false;
 
   /** */
+  public static enum DataType {
+    /** */
+    BINARY(XcalTags.binary),
+
+    /** */
+    BOOLEAN(XcalTags._boolean),
+
+    /** */
+    CUA(XcalTags.calAddress),
+
+    /** */
+    DATE(XcalTags.date),
+
+    /** */
+    DATE_TIME(XcalTags.dateTime),
+
+    /** */
+    DURATION(XcalTags.duration),
+
+    /** */
+    FLOAT(XcalTags._float),
+
+    /** */
+    INTEGER(XcalTags.integer),
+
+    /** */
+    PERIOD(XcalTags.period),
+
+    /** */
+    RECUR(XcalTags.recur),
+
+    /** */
+    TEXT(XcalTags.text),
+
+    /** */
+    TIME(XcalTags.time),
+
+    /** */
+    URI(XcalTags.uri),
+
+    /** */
+    UTC_OFFSET(XcalTags.utcOffset),
+
+    /** More work */
+    SPECIAL(null),
+
+    /** Non-ical */
+    HREF(null);
+
+    private QName xcalType;
+
+    DataType(final QName xcalType) {
+      this.xcalType = xcalType;
+    }
+
+    /**
+     * @return type or null
+     */
+    public QName getXcalType() {
+      return xcalType;
+    }
+  };
+
+  /** */
+  public static enum ParameterInfoIndex {
+    /** */
+    UNKNOWN_PARAMETER(null),
+
+    /**
+     * Region abbreviation.
+     */
+    ABBREV("ABBREV"),
+
+    /**
+     * Alternate text representation.
+     */
+    ALTREP("ALTREP"),
+
+    /**
+     * Common name.
+     */
+    CN("CN"),
+
+    /**
+     * Calendar user type.
+     */
+    CUTYPE("CUTYPE"),
+
+    /**
+     * Delegator.
+     */
+    DELEGATED_FROM("DELEGATED-FROM"),
+
+    /**
+     * Delegatee.
+     */
+    DELEGATED_TO("DELEGATED-TO"),
+
+    /**
+     * Directory entry.
+     */
+    DIR("DIR"),
+
+    /**
+     * Inline encoding.
+     */
+    ENCODING("ENCODING"),
+
+    /**
+     * Format type.
+     */
+    FMTTYPE("FMTTYPE"),
+
+    /**
+     * Free/busy time type.
+     */
+    FBTYPE("FBTYPE"),
+
+    /**
+     * Language for text.
+     */
+    LANGUAGE("LANGUAGE"),
+
+    /**
+     * Group or list membership.
+     */
+    MEMBER("MEMBER"),
+
+    /**
+     * Participation status.
+     */
+    PARTSTAT("PARTSTAT"),
+
+    /**
+     * Recurrence identifier range.
+     */
+    RANGE("RANGE"),
+
+    /**
+     * Alarm trigger relationship.
+     */
+    RELATED("RELATED"),
+
+    /**
+     * Relationship type.
+     */
+    RELTYPE("RELTYPE"),
+
+    /**
+     * Participation role.
+     */
+    ROLE("ROLE"),
+
+    /**
+     * RSVP expectation.
+     */
+    RSVP("RSVP"),
+
+    /**
+     * Schedule agent.
+     */
+    SCHEDULE_AGENT("SCHEDULE-AGENT"),
+
+    /**
+     * Schedule status.
+     */
+    SCHEDULE_STATUS("SCHEDULE-STATUS"),
+
+    /**
+     * Sent by.
+     */
+    SENT_BY("SENT-BY"),
+
+    /**
+     * Type.
+     */
+    TYPE("TYPE"),
+
+    /**
+     * Reference to time zone object.
+     */
+    TZID("TZID"),
+
+    /**
+     * Property value data type.
+     */
+    VALUE("VALUE");
+
+    private String pname;
+
+    private DataType ptype;
+
+    private static HashMap<String, ParameterInfoIndex> pnameLookup =
+      new HashMap<String, ParameterInfoIndex>();
+
+    static {
+      for (ParameterInfoIndex pii: values()) {
+        String pname = pii.getPname();
+
+        if (pname != null) {
+          pname = pname.toLowerCase();
+        }
+        pnameLookup.put(pname, pii);
+      }
+    }
+
+    ParameterInfoIndex(final String pname) {
+      this(pname, DataType.TEXT);
+    }
+
+    ParameterInfoIndex(final String pname,
+                      final DataType ptype) {
+      this.pname = pname;
+      this.ptype = ptype;
+    }
+
+    /** get the parameter name
+     *
+     * @return parameter name
+     */
+    public String getPname() {
+      return pname;
+    }
+
+    /** get the parameter type
+     *
+     * @return parameter type
+     */
+    public DataType getPtype() {
+      return ptype;
+    }
+
+    /** get the index given the parameter name
+     *
+     * @param val
+     * @return ParameterInfoIndex
+     */
+    public static ParameterInfoIndex lookupPname(final String val) {
+      return pnameLookup.get(val.toLowerCase());
+    }
+  }
+
+  /** */
   public static enum PropertyInfoIndex {
     /** */
     UNKNOWN_PROPERTY(null, IS_SINGLE, noComponent),
@@ -127,42 +374,51 @@
     CLASS("CLASS", IS_SINGLE, event_Todo_Journal),
 
     /** */
-    CREATED("CREATED", IS_SINGLE, event_Todo_Journal_Freebusy),
+    CREATED("CREATED", DataType.DATE_TIME,
+            IS_SINGLE, event_Todo_Journal_Freebusy),
 
     /** */
     DESCRIPTION("DESCRIPTION", IS_SINGLE, IS_MULTI, event_Todo_Journal_Alarm),
 
     /** */
-    DTSTAMP("DTSTAMP", IS_SINGLE, event_Todo_Journal_Freebusy,
+    DTSTAMP("DTSTAMP", DataType.DATE_TIME,
+            IS_SINGLE, event_Todo_Journal_Freebusy,
             NOT_PARAM, NOT_IMMUTABLE),
 
     /** */
-    DTSTART("DTSTART", IS_SINGLE, notAlarm),
+    DTSTART("DTSTART", DataType.DATE_TIME,
+            IS_SINGLE, notAlarm),
 
     /** */
-    DURATION("DURATION", IS_SINGLE, event_Todo_Freebusy),
+    DURATION("DURATION", DataType.DURATION,
+             IS_SINGLE, event_Todo_Freebusy),
 
     /** */
     GEO("GEO", IS_SINGLE, event_Todo),
 
     /** */
-    LAST_MODIFIED("LAST-MODIFIED", IS_SINGLE, event_Todo_Journal_Timezone,
+    LAST_MODIFIED("LAST-MODIFIED", DataType.DATE_TIME,
+                  IS_SINGLE, event_Todo_Journal_Timezone,
                   NOT_PARAM, NOT_IMMUTABLE),
 
     /** */
     LOCATION("LOCATION", IS_SINGLE, event_Todo),
 
     /** */
-    ORGANIZER("ORGANIZER", IS_SINGLE, event_Todo_Journal_Freebusy),
+    ORGANIZER("ORGANIZER", DataType.CUA,
+              IS_SINGLE, event_Todo_Journal_Freebusy),
 
     /** */
-    PRIORITY("PRIORITY", IS_SINGLE, event_Todo),
+    PRIORITY("PRIORITY", DataType.INTEGER,
+             IS_SINGLE, event_Todo),
 
     /** */
-    RECURRENCE_ID("RECURRENCE-ID", IS_SINGLE, event_Todo_Journal_Freebusy),
+    RECURRENCE_ID("RECURRENCE-ID", DataType.DATE_TIME,
+                  IS_SINGLE, event_Todo_Journal_Freebusy),
 
     /** */
-    SEQUENCE("SEQUENCE", IS_SINGLE, event_Todo_Journal,
+    SEQUENCE("SEQUENCE", DataType.INTEGER,
+             IS_SINGLE, event_Todo_Journal,
              NOT_PARAM, NOT_IMMUTABLE),
 
     /** */
@@ -175,12 +431,14 @@
     UID("UID", IS_SINGLE, event_Todo_Journal_Freebusy),
 
     /** */
-    URL("URL", IS_SINGLE, event_Todo_Journal_Freebusy),
+    URL("URL", DataType.URI,
+        IS_SINGLE, event_Todo_Journal_Freebusy),
 
     /* Event only */
 
     /** */
-    DTEND("DTEND", IS_SINGLE, event_Freebusy),
+    DTEND("DTEND", DataType.DATE_TIME,
+          IS_SINGLE, event_Freebusy),
 
     /** */
     TRANSP("TRANSP", IS_SINGLE, eventOnly),
@@ -188,10 +446,12 @@
     /* Todo only */
 
     /** */
-    COMPLETED("COMPLETED", IS_SINGLE, todoOnly),
+    COMPLETED("COMPLETED", DataType.DATE_TIME,
+              IS_SINGLE, todoOnly),
 
     /** */
-    DUE("DUE", IS_SINGLE, todoOnly),
+    DUE("DUE", DataType.DATE_TIME,
+        IS_SINGLE, todoOnly),
 
     /** */
     PERCENT_COMPLETE("PERCENT-COMPLETE", IS_SINGLE, todoOnly),
@@ -201,10 +461,12 @@
     /* Event and Todo */
 
     /** */
-    ATTACH("ATTACH", IS_MULTI, event_Todo_Journal_Alarm),
+    ATTACH("ATTACH", DataType.SPECIAL,
+           IS_MULTI, event_Todo_Journal_Alarm),
 
     /** */
-    ATTENDEE("ATTENDEE", IS_MULTI, notTimezone),
+    ATTENDEE("ATTENDEE", DataType.CUA,
+             IS_MULTI, notTimezone),
 
     /** */
     CATEGORIES("CATEGORIES", IS_MULTI, event_Todo_Journal_Alarm),
@@ -216,10 +478,12 @@
     CONTACT("CONTACT", IS_MULTI, event_Todo_Journal_Freebusy),
 
     /** */
-    EXDATE("EXDATE", IS_MULTI, event_Todo_Journal_Timezone),
+    EXDATE("EXDATE", DataType.DATE_TIME,
+           IS_MULTI, event_Todo_Journal_Timezone),
 
     /** */
-    EXRULE("EXRULE", IS_MULTI, event_Todo_Journal_Timezone),
+    EXRULE("EXRULE", DataType.SPECIAL,
+           IS_MULTI, event_Todo_Journal_Timezone),
 
     /** */
     REQUEST_STATUS("REQUEST-STATUS", IS_MULTI, event_Todo_Journal_Freebusy),
@@ -231,15 +495,18 @@
     RESOURCES("RESOURCES", IS_MULTI, event_Todo),
 
     /** */
-    RDATE("RDATE", IS_MULTI, event_Todo_Journal_Timezone),
+    RDATE("RDATE", DataType.DATE_TIME,
+          IS_MULTI, event_Todo_Journal_Timezone),
 
     /** */
-    RRULE ("RRULE", IS_MULTI, event_Todo_Journal_Timezone),
+    RRULE ("RRULE", DataType.SPECIAL,
+           IS_MULTI, event_Todo_Journal_Timezone),
 
     /* -------------- Other non-event, non-todo ---------------- */
 
     /** */
-    FREEBUSY("FREEBUSY", IS_SINGLE, freebusyOnly),
+    FREEBUSY("FREEBUSY", DataType.PERIOD,
+             IS_SINGLE, freebusyOnly),
 
     /** */
     TZID("TZID", IS_SINGLE, timezoneOnly),
@@ -248,31 +515,36 @@
     TZNAME("TZNAME", IS_SINGLE, timezoneOnly),
 
     /** */
-    TZOFFSETFROM("TZOFFSETFROM", IS_SINGLE, timezoneOnly),
+    TZOFFSETFROM("TZOFFSETFROM", DataType.UTC_OFFSET,
+                 IS_SINGLE, timezoneOnly),
 
     /** */
-    TZOFFSETTO("TZOFFSETTO", IS_SINGLE, timezoneOnly),
+    TZOFFSETTO("TZOFFSETTO", DataType.UTC_OFFSET,
+               IS_SINGLE, timezoneOnly),
 
     /** */
-    TZURL("TZURL", IS_SINGLE, timezoneOnly),
+    TZURL("TZURL", DataType.URI,
+          IS_SINGLE, timezoneOnly),
 
     /** */
     ACTION("ACTION", IS_SINGLE, alarmOnly),
 
     /** */
-    REPEAT("REPEAT", IS_SINGLE, alarmOnly),
+    REPEAT("REPEAT", DataType.INTEGER,
+           IS_SINGLE, alarmOnly),
 
     /** */
-    TRIGGER("TRIGGER", IS_SINGLE, alarmOnly),
+    TRIGGER("TRIGGER", DataType.SPECIAL,
+            IS_SINGLE, alarmOnly),
 
     /* -------------- Non-ical ---------------- */
 
     /** non ical */
-    CREATOR("CREATOR", IS_SINGLE, event_Todo_Journal,
+    CREATOR("CREATOR", DataType.HREF, IS_SINGLE, event_Todo_Journal,
             NOT_PARAM, IS_IMMUTABLE),
 
     /** non ical */
-    OWNER("OWNER", IS_SINGLE, event_Todo_Journal,
+    OWNER("OWNER", DataType.HREF, IS_SINGLE, event_Todo_Journal,
           NOT_PARAM, IS_IMMUTABLE),
 
     /** non ical */
@@ -282,21 +554,22 @@
     COST("COST", IS_SINGLE, event_Todo),
 
     /** non ical */
-    CTAG("CTAG", IS_SINGLE, noComponent,
+    CTAG("CTAG", DataType.TEXT, IS_SINGLE, noComponent,
          NOT_PARAM, IS_IMMUTABLE),
 
     /** non ical */
     DELETED("DELETED", IS_SINGLE, event_Todo),
 
     /** non ical */
-    ETAG("ETAG", IS_SINGLE, noComponent,
+    ETAG("ETAG", DataType.TEXT, IS_SINGLE, noComponent,
          NOT_PARAM, IS_IMMUTABLE),
 
     /** non ical */
     COLLECTION("COLLECTION", IS_SINGLE, event_Todo_Journal),
 
     /** non ical */
-    ENTITY_TYPE("ENTITY_TYPE", IS_SINGLE, event_Todo_Journal,
+    ENTITY_TYPE("ENTITY_TYPE", DataType.INTEGER,
+                IS_SINGLE, event_Todo_Journal,
                 NOT_PARAM, IS_IMMUTABLE),
 
     /** treat VALARM sub-component as a property */
@@ -308,16 +581,18 @@
     /** ----------------------------- Following are parameters ----------- */
 
     /** */
-    LANG("LANGUAGE", IS_SINGLE, noComponent,
+    LANG("LANGUAGE", DataType.TEXT, IS_SINGLE, noComponent,
          IS_PARAM, NOT_IMMUTABLE),
 
     /** */
-    TZIDPAR("TZID", IS_SINGLE, noComponent,
+    TZIDPAR("TZID", DataType.TEXT, IS_SINGLE, noComponent,
             IS_PARAM, NOT_IMMUTABLE),
             ;
 
     private String pname;
 
+    private DataType ptype;
+
     /* true if the standard says it's multi */
     private boolean multiValued;
 
@@ -352,19 +627,29 @@
       dbMultiValued = multiValued;
     }
 
+    PropertyInfoIndex(final String pname,
+                      final DataType ptype, final boolean multiValued,
+                      final ComponentFlags components) {
+      this(pname, multiValued, components);
+      this.ptype = ptype;
+    }
+
     PropertyInfoIndex(final String pname, final boolean multiValued,
                       final boolean dbMultiValued,
                       final ComponentFlags components) {
-      this(pname, multiValued, components,
+      this(pname, DataType.TEXT, multiValued, components,
            NOT_PARAM, NOT_IMMUTABLE);
       this.dbMultiValued = dbMultiValued;
     }
 
-    PropertyInfoIndex(final String pname, final boolean multiValued,
+    PropertyInfoIndex(final String pname,
+                      final DataType ptype,
+                      final boolean multiValued,
                       final ComponentFlags components,
                       final boolean param,
                       final boolean immutable) {
       this(pname, multiValued, components);
+      this.ptype = ptype;
       this.param = param;
       this.immutable = immutable;
     }
@@ -377,6 +662,14 @@
       return pname;
     }
 
+    /** get the property type
+     *
+     * @return property type
+     */
+    public DataType getPtype() {
+      return ptype;
+    }
+
     /** May need some elaboration - this is for the standard
      *
      * @return boolean

Modified: trunk/src/edu/rpi/sss/util/Options.java
===================================================================
--- trunk/src/edu/rpi/sss/util/Options.java	2010-09-09 14:08:43 UTC (rev 189)
+++ trunk/src/edu/rpi/sss/util/Options.java	2010-09-15 15:05:06 UTC (rev 190)
@@ -28,6 +28,11 @@
 import edu.rpi.sss.util.xml.XmlEmit;
 import edu.rpi.sss.util.xml.XmlUtil;
 
+import org.apache.log4j.Logger;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.xml.sax.InputSource;
+
 import java.io.InputStream;
 import java.io.InputStreamReader;
 import java.io.OutputStream;
@@ -44,11 +49,6 @@
 import javax.xml.parsers.DocumentBuilder;
 import javax.xml.parsers.DocumentBuilderFactory;
 
-import org.apache.log4j.Logger;
-import org.w3c.dom.Document;
-import org.w3c.dom.Element;
-import org.xml.sax.InputSource;
-
 /** Access properties in an xml format.
  *
  * @author Mike Douglass    douglm @ rpi.edu
@@ -76,11 +76,11 @@
 
   private OptionElement localOptionsRoot;
 
-  public void init(String globalPrefix,
-                   String appPrefix,
-                   String optionsFile,
-                   String outerTagName,
-                   boolean debug) throws OptionsException {
+  public void init(final String globalPrefix,
+                   final String appPrefix,
+                   final String optionsFile,
+                   final String outerTagName,
+                   final boolean debug) throws OptionsException {
     this.globalPrefix = globalPrefix;
     this.appPrefix = appPrefix;
     this.optionsFile = optionsFile;
@@ -90,7 +90,7 @@
     initOptions();
   }
 
-  public void initFromStream(InputStream is) throws OptionsException {
+  public void initFromStream(final InputStream is) throws OptionsException {
     useSystemwideValues = false;
     localOptionsRoot = parseOptions(is);
   }
@@ -110,7 +110,7 @@
    * @return OptionElement root of parsed options.
    * @exception OptionsException Some error occurred.
    */
-  public OptionElement parseOptions(InputStream is) throws OptionsException{
+  public OptionElement parseOptions(final InputStream is) throws OptionsException{
     Reader rdr = null;
 
     try {
@@ -156,11 +156,11 @@
    * @param str
    * @throws OptionsException
    */
-  public void toXml(OptionElement root, OutputStream str) throws OptionsException {
+  public void toXml(final OptionElement root, final OutputStream str) throws OptionsException {
     Writer wtr = null;
 
     try {
-      XmlEmit xml = new XmlEmit(true, true);
+      XmlEmit xml = new XmlEmit(true);
 
       wtr = new OutputStreamWriter(str);
       xml.startEmit(wtr);
@@ -185,8 +185,8 @@
     }
   }
 
-  private static void childToXml(OptionElement subRoot,
-                                 XmlEmit xml) throws OptionsException {
+  private static void childToXml(final OptionElement subRoot,
+                                 final XmlEmit xml) throws OptionsException {
     try {
       Object val = subRoot.val;
       QName tag = new QName(null, subRoot.name);
@@ -236,9 +236,9 @@
     }
   }
 
-  private static void methodToXml(Method meth,
-                                  Object val,
-                                  XmlEmit xml) throws OptionsException {
+  private static void methodToXml(final Method meth,
+                                  final Object val,
+                                  final XmlEmit xml) throws OptionsException {
     try {
       String methodName = meth.getName();
 
@@ -319,7 +319,7 @@
    * @return Object value
    * @throws OptionsException
    */
-  public Object getProperty(String name) throws OptionsException {
+  public Object getProperty(final String name) throws OptionsException {
     Object val = getOptProperty(name);
 
     if (val == null) {
@@ -335,7 +335,7 @@
    * @return Object value
    * @throws OptionsException
    */
-  public Object getOptProperty(String name) throws OptionsException {
+  public Object getOptProperty(final String name) throws OptionsException {
     if (useSystemwideValues) {
       return findValue(optionsRoot, makePathElements(name), -1);
     }
@@ -349,7 +349,7 @@
    * @return String value of property
    * @throws OptionsException
    */
-  public String getStringProperty(String name) throws OptionsException {
+  public String getStringProperty(final String name) throws OptionsException {
     Object val = getProperty(name);
 
     if (!(val instanceof String)) {
@@ -365,7 +365,7 @@
    * @return String value
    * @throws OptionsException
    */
-  public String getOptStringProperty(String name) throws OptionsException {
+  public String getOptStringProperty(final String name) throws OptionsException {
     Object val = getOptProperty(name);
 
     if (val == null) {
@@ -385,7 +385,7 @@
    * @return boolean value of property
    * @throws OptionsException
    */
-  public boolean getBoolProperty(String name) throws OptionsException {
+  public boolean getBoolProperty(final String name) throws OptionsException {
     String val = getStringProperty(name);
 
     val = val.toLowerCase();
@@ -399,7 +399,7 @@
    * @return int value of property
    * @throws OptionsException
    */
-  public int getIntProperty(String name) throws OptionsException {
+  public int getIntProperty(final String name) throws OptionsException {
     String val = getStringProperty(name);
 
     try {
@@ -416,28 +416,28 @@
   /* (non-Javadoc)
    * @see org.bedework.calfacade.env.CalOptionsI#getGlobalProperty(java.lang.String)
    */
-  public Object getGlobalProperty(String name) throws OptionsException {
+  public Object getGlobalProperty(final String name) throws OptionsException {
     return getProperty(globalPrefix + name);
   }
 
   /* (non-Javadoc)
    * @see org.bedework.calfacade.env.CalOptionsI#getGlobalStringProperty(java.lang.String)
    */
-  public String getGlobalStringProperty(String name) throws OptionsException {
+  public String getGlobalStringProperty(final String name) throws OptionsException {
     return getStringProperty(globalPrefix + name);
   }
 
   /* (non-Javadoc)
    * @see org.bedework.calfacade.env.CalOptionsI#getGlobalBoolProperty(java.lang.String)
    */
-  public boolean getGlobalBoolProperty(String name) throws OptionsException {
+  public boolean getGlobalBoolProperty(final String name) throws OptionsException {
     return getBoolProperty(globalPrefix + name);
   }
 
   /* (non-Javadoc)
    * @see org.bedework.calfacade.env.CalOptionsI#getGlobalIntProperty(java.lang.String)
    */
-  public int getGlobalIntProperty(String name) throws OptionsException {
+  public int getGlobalIntProperty(final String name) throws OptionsException {
     return getIntProperty(globalPrefix + name);
   }
 
@@ -451,7 +451,7 @@
    * @return Object value
    * @throws OptionsException
    */
-  public Object getAppProperty(String name) throws OptionsException {
+  public Object getAppProperty(final String name) throws OptionsException {
     return getProperty(appPrefix + name);
   }
 
@@ -461,7 +461,7 @@
    * @return String value
    * @throws OptionsException
    */
-  public String getAppStringProperty(String name) throws OptionsException {
+  public String getAppStringProperty(final String name) throws OptionsException {
     return getStringProperty(appPrefix + name);
   }
 
@@ -471,7 +471,7 @@
    * @return Object value or null
    * @throws OptionsException
    */
-  public Object getAppOptProperty(String name) throws OptionsException {
+  public Object getAppOptProperty(final String name) throws OptionsException {
     return getOptProperty(appPrefix + name);
   }
 
@@ -481,7 +481,7 @@
    * @return String value or null
    * @throws OptionsException
    */
-  public String getAppOptStringProperty(String name) throws OptionsException {
+  public String getAppOptStringProperty(final String name) throws OptionsException {
     return getOptStringProperty(appPrefix + name);
   }
 
@@ -491,14 +491,14 @@
    * @return boolean value of global property
    * @throws OptionsException
    */
-  public boolean getAppBoolProperty(String name) throws OptionsException {
+  public boolean getAppBoolProperty(final String name) throws OptionsException {
     return getBoolProperty(appPrefix + name);
   }
 
   /* (non-Javadoc)
    * @see org.bedework.calfacade.env.CalOptionsI#getAppIntProperty(java.lang.String)
    */
-  public int getAppIntProperty(String name) throws OptionsException {
+  public int getAppIntProperty(final String name) throws OptionsException {
     return getIntProperty(appPrefix + name);
   }
 
@@ -509,9 +509,9 @@
   /* (non-Javadoc)
    * @see org.bedework.calfacade.env.CalOptionsI#setValue(java.lang.String, java.lang.String, java.lang.Object)
    */
-  public void setValue(String optionObjectName,
-                       String optionName,
-                       Object val) throws OptionsException {
+  public void setValue(final String optionObjectName,
+                       final String optionName,
+                       final Object val) throws OptionsException {
     if (!useSystemwideValues) {
       // No screwing round with them
       throw new OptionsException("cannot.set.values");
@@ -533,8 +533,8 @@
   /* (non-Javadoc)
    * @see org.bedework.calfacade.env.CalOptionsI#getValue(java.lang.String, java.lang.String)
    */
-  public Object getValue(String optionObjectName,
-                         String optionName) throws OptionsException {
+  public Object getValue(final String optionObjectName,
+                         final String optionName) throws OptionsException {
     if (useSystemwideValues) {
       // No screwing round with them
       throw new OptionsException("cannot.set.values");
@@ -559,7 +559,7 @@
   /* (non-Javadoc)
    * @see edu.rpi.sss.util.OptionsI#getNames(java.lang.String)
    */
-  public Collection<String> getNames(String name) throws OptionsException {
+  public Collection<String> getNames(final String name) throws OptionsException {
     if (useSystemwideValues) {
       return getNames(optionsRoot, makePathElements(name), -1);
     }
@@ -573,7 +573,7 @@
    * @return Collection
    * @throws OptionsException
    */
-  public Collection match(String name) throws OptionsException {
+  public Collection match(final String name) throws OptionsException {
     if (useSystemwideValues) {
       return match(optionsRoot, makePathElements(name), -1);
     }
@@ -592,8 +592,8 @@
    * @param pos
    * @return Collection<String>
    */
-  private static Collection<String> getNames(OptionElement subroot,
-                                             String[] pathElements, int pos) {
+  private static Collection<String> getNames(final OptionElement subroot,
+                                             final String[] pathElements, int pos) {
     if (pos >= 0) {
       // Not at root.
       if (!pathElements[pos].equals(subroot.name)) {
@@ -638,8 +638,8 @@
    * @param pos
    * @return Collection
    */
-  private static Collection match(OptionElement subroot,
-                                  String[] pathElements, int pos) {
+  private static Collection match(final OptionElement subroot,
+                                  final String[] pathElements, int pos) {
 
     if (pos >= 0) {
       // Not at root.
@@ -687,8 +687,8 @@
   /* Given the root and a path element array find the corresponding value(s)
    *
    */
-  private static Object findValue(OptionElement subroot,
-                                  String[] pathElements, int pos) {
+  private static Object findValue(final OptionElement subroot,
+                                  final String[] pathElements, int pos) {
     if (pos >= 0) {
       // Not at root.
       if (!pathElements[pos].equals(subroot.name)) {
@@ -737,7 +737,7 @@
     return singleRes;
   }
 
-  private static void appendResult(Object res, ArrayList<Object> multiRes) {
+  private static void appendResult(final Object res, final ArrayList<Object> multiRes) {
     if (res instanceof Collection) {
       multiRes.addAll((Collection<? extends Object>)res);
     } else {
@@ -745,8 +745,8 @@
     }
   }
 
-  private void doChildren(OptionElement oel, Element subroot,
-                          Stack<Object> objStack) throws OptionsException {
+  private void doChildren(final OptionElement oel, final Element subroot,
+                          final Stack<Object> objStack) throws OptionsException {
     try {
       if (!XmlUtil.hasChildren(subroot)) {
         // Leaf node
@@ -851,23 +851,23 @@
     }
   }
 
-  private static void error(String msg) {
+  private static void error(final String msg) {
     Logger.getLogger(Options.class).error(msg);
   }
 
-  private static void warn(String msg) {
+  private static void warn(final String msg) {
     Logger.getLogger(Options.class).warn(msg);
   }
 
   /* We've been dealing with property names - convert the dotted notation to a path
    */
-  private static String[] makePathElements(String val) {
+  private static String[] makePathElements(final String val) {
     synchronized (splitPathPattern) {
       return splitPathPattern.split(val, 0);
     }
   }
 
-  private Method findSetter(Object val, String name) throws OptionsException {
+  private Method findSetter(final Object val, final String name) throws OptionsException {
     String methodName = "set" + name.substring(0, 1).toUpperCase() +
                         name.substring(1);
     Method[] meths = val.getClass().getMethods();
@@ -894,7 +894,7 @@
     return meth;
   }
 
-  private static Method findGetter(Object val, String name) throws OptionsException {
+  private static Method findGetter(final Object val, final String name) throws OptionsException {
     String methodName = "get" + name.substring(0, 1).toUpperCase() +
                         name.substring(1);
     Method[] meths = val.getClass().getMethods();
@@ -923,8 +923,8 @@
     return meth;
   }
 
-  private static Method findMethod(Object val,
-                                   String methodName) throws OptionsException {
+  private static Method findMethod(final Object val,
+                                   final String methodName) throws OptionsException {
     Method[] meths = val.getClass().getMethods();
     Method meth = null;
 
@@ -949,7 +949,7 @@
     return meth;
   }
 
-  private static Collection<Method> findGetters(Object val) throws OptionsException {
+  private static Collection<Method> findGetters(final Object val) throws OptionsException {
     Method[] meths = val.getClass().getMethods();
     Collection<Method> getters = new ArrayList<Method>();
 

Modified: trunk/src/edu/rpi/sss/util/xml/XmlEmit.java
===================================================================
--- trunk/src/edu/rpi/sss/util/xml/XmlEmit.java	2010-09-09 14:08:43 UTC (rev 189)
+++ trunk/src/edu/rpi/sss/util/xml/XmlEmit.java	2010-09-15 15:05:06 UTC (rev 190)
@@ -29,7 +29,6 @@
 import java.io.IOException;
 import java.io.Reader;
 import java.io.Writer;
-import java.util.HashMap;
 
 import javax.xml.namespace.QName;
 
@@ -39,10 +38,17 @@
  */
 public class XmlEmit {
   private Writer wtr;
-  private boolean mustEmitNS;
 
   private boolean noHeaders = false;
 
+  private String dtd;
+
+  private boolean started;
+
+  private int scopeLevel; // So we can pop namespaces
+
+  private XmlEmitNamespaces nameSpaces = new XmlEmitNamespaces();
+
   /**
    * @author douglm
    */
@@ -51,6 +57,10 @@
 
     String abbrev;
 
+    int level;
+
+    boolean defaultNs;
+
     /**
      * @param ns
      * @param abbrev
@@ -72,16 +82,6 @@
     }
   }
 
-  /** We need to map the namespaces onto a set of reasonable abbreviations
-   * for the generated xml. New set created each request
-   */
-  private HashMap<String, NameSpace> nsMap;
-
-  private int nsIndex;
-
-  private boolean noDefaultns;
-  private String defaultNs;
-
   /** The following allow us to tidy up the output a little.
    */
   int indent;
@@ -93,20 +93,16 @@
    * during the first phase and emit xml after startEmit is called.
    */
   public XmlEmit() {
-    this(false, false);
+    this(false);
   }
 
   /** construct an object which will be used to collect namespace names
    * during the first phase and emit xml after startEmit is called.
    *
    * @param noHeaders    boolean true to suppress headers
-   * @param noDefaultns  boolean true if we don't have a default namespace
    */
-  public XmlEmit(final boolean noHeaders, final boolean noDefaultns) {
-    nsMap = new HashMap<String, NameSpace>();
-
+  public XmlEmit(final boolean noHeaders) {
     this.noHeaders = noHeaders;
-    this.noDefaultns = noDefaultns;
   }
 
   /** Emit any headers and namespace declarations
@@ -116,13 +112,6 @@
    */
   public void startEmit(final Writer wtr) throws IOException {
     this.wtr = wtr;
-
-    if (!noHeaders) {
-      mustEmitNS = true;
-
-      writeHeader(null);
-    }
-    newline();
   }
 
   /** Emit any headers, dtd and namespace declarations
@@ -133,15 +122,11 @@
    */
   public void startEmit(final Writer wtr, final String dtd) throws IOException {
     this.wtr = wtr;
-
-    if (!noHeaders) {
-      mustEmitNS = true;
-
-      writeHeader(dtd);
-    }
-    newline();
+    this.dtd = dtd;
   }
 
+  /* ===================================== Tag start ======================== */
+
   /**
    * @param tag
    * @throws IOException
@@ -154,6 +139,7 @@
   }
 
   /** open with attribute
+   *
    * @param tag
    * @param attrName
    * @param attrVal
@@ -198,10 +184,11 @@
   public void openTagSameLine(final QName tag) throws IOException {
     lb();
     emitQName(tag);
-    rb();
+    endOpeningTag();
   }
 
-  /**
+  /** Emit an opening tag ready for nested values. No new line
+   *
    * @param tag
    * @param attrName
    * @param attrVal
@@ -213,77 +200,50 @@
     lb();
     emitQName(tag);
     attribute(attrName, attrVal);
-    rb();
+    endOpeningTag();
   }
 
-  /**
+  /** Start tag ready for attributes
+   *
    * @param tag
    * @throws IOException
    */
-  public void closeTag(final QName tag) throws IOException {
-    indent -= 2;
-    if (indent < 0) {
-      indent = 0;
-    }
+  public void startTag(final QName tag) throws IOException {
     blanks();
-    closeTagSameLine(tag);
-    newline();
+    startTagSameLine(tag);
   }
 
-  /**
+  /** Start tag ready for attributes - new line and indent
+   *
    * @param tag
    * @throws IOException
    */
-  public void closeTagNoblanks(final QName tag) throws IOException {
-    indent -= 2;
-    if (indent < 0) {
-      indent = 0;
-    }
-    closeTagSameLine(tag);
-    newline();
+  public void startTagIndent(final QName tag) throws IOException {
+    blanks();
+    startTagSameLine(tag);
+    indent += 2;
   }
 
-  /**
+  /** Start a tag ready for some attributes. No new line
+   *
    * @param tag
    * @throws IOException
    */
-  public void closeTagSameLine(final QName tag) throws IOException {
+  public void startTagSameLine(final QName tag) throws IOException {
     lb();
-    wtr.write("/");
     emitQName(tag);
-    rb();
   }
 
-  /**
-   * @param tag
-   * @throws IOException
-   */
-  public void emptyTag(final QName tag) throws IOException {
-    blanks();
-    emptyTagSameLine(tag);
-    newline();
-  }
-
-  /** Start tag ready for attributes
+  /** End a tag we are opening
    *
-   * @param tag
    * @throws IOException
    */
-  public void startTag(final QName tag) throws IOException {
-    blanks();
-    startTagSameLine(tag);
+  public void endOpeningTag() throws IOException {
+    scopeIn();
+    rb();
   }
 
-  /** Start tag ready for attributes and indent
-   *
-   * @param tag
-   * @throws IOException
-   */
-  public void startTagIndent(final QName tag) throws IOException {
-    blanks();
-    startTagSameLine(tag);
-    indent += 2;
-  }
+  /* ===================================== Attributes ======================= */
 
   /** Add an attribute
    *
@@ -292,9 +252,9 @@
    * @throws IOException
    */
   public void attribute(final String attrName, final String attrVal) throws IOException {
-    wtr.write(" ");
-    wtr.write(attrName);
-    wtr.write("=");
+    out(" ");
+    out(attrName);
+    out("=");
     quote(attrVal);
   }
 
@@ -305,24 +265,55 @@
    * @throws IOException
    */
   public void attribute(final QName attr, final String attrVal) throws IOException {
-    wtr.write(" ");
+    out(" ");
 
     emitQName(attr);
 
-    wtr.write("=");
+    out("=");
     quote(attrVal);
 
-    if (!noHeaders && mustEmitNS) {
-      emitNs();
+    emitNs();
+  }
+
+  /* ===================================== Tag end ========================== */
+
+  /**
+   * @param tag
+   * @throws IOException
+   */
+  public void closeTag(final QName tag) throws IOException {
+    indent -= 2;
+    if (indent < 0) {
+      indent = 0;
     }
+    blanks();
+    closeTagSameLine(tag);
+    newline();
   }
 
-  /** End a tag
-   *
+  /**
+   * @param tag
    * @throws IOException
    */
-  public void endTag() throws IOException {
+  public void closeTagNoblanks(final QName tag) throws IOException {
+    indent -= 2;
+    if (indent < 0) {
+      indent = 0;
+    }
+    closeTagSameLine(tag);
+    newline();
+  }
+
+  /**
+   * @param tag
+   * @throws IOException
+   */
+  public void closeTagSameLine(final QName tag) throws IOException {
+    lb();
+    out("/");
+    emitQName(tag);
     rb();
+    scopeOut();
   }
 
   /** End an empty tag
@@ -330,38 +321,33 @@
    * @throws IOException
    */
   public void endEmptyTag() throws IOException {
-    wtr.write(" /");
+    out(" /");
     rb();
   }
 
+  /* ===================================== Tag start and end ================ */
+
   /**
    * @param tag
    * @throws IOException
    */
-  public void emptyTagSameLine(final QName tag) throws IOException {
-    lb();
-    emitQName(tag);
-    wtr.write("/");
-    rb();
+  public void emptyTag(final QName tag) throws IOException {
+    blanks();
+    emptyTagSameLine(tag);
+    newline();
   }
 
   /**
    * @param tag
    * @throws IOException
    */
-  public void startTagSameLine(final QName tag) throws IOException {
+  public void emptyTagSameLine(final QName tag) throws IOException {
     lb();
     emitQName(tag);
+    out("/");
+    rb();
   }
 
-  private void quote(final String val) throws IOException {
-    if (val.indexOf("\"") < 0) {
-      value(val, "\"");
-    } else {
-      value(val, "'");
-    }
-  }
-
   /** Create the sequence<br>
    *  <tag>val</tag>
    *
@@ -377,46 +363,6 @@
     newline();
   }
 
-  /** Write out a value
-   *
-   * @param val
-   * @throws IOException
-   */
-  public void value(final String val) throws IOException {
-    value(val, null);
-  }
-
-  /** Write out a value
-   *
-   * @param val
-   * @param quoteChar
-   * @throws IOException
-   */
-  private void value(final String val,
-                     final String quoteChar) throws IOException {
-    if (val == null) {
-      return;
-    }
-
-    String q = quoteChar;
-    if (q == null) {
-      q = "";
-    }
-
-    if ((val.indexOf('&') >= 0) ||
-        (val.indexOf('<') >= 0)) {
-      wtr.write("<![CDATA[");
-      wtr.write(q);
-      wtr.write(val);
-      wtr.write(q);
-      wtr.write("]]>");
-    } else {
-      wtr.write(q);
-      wtr.write(val);
-      wtr.write(q);
-    }
-  }
-
   /** Create the sequence<br>
    *  <tag>val</tag>
    *
@@ -427,42 +373,7 @@
   public void cdataProperty(final QName tag, final String val) throws IOException {
     blanks();
     openTagSameLine(tag);
-    if (val != null) {
-      /*
-      if (val.indexOf("]]>") > 0) {
-        throw new IOException("Data contains CDATA end sequence");
-      }
-      wtr.write("<![CDATA[");
-      wtr.write(val);
-      wtr.write("]]>");
-      */
-      // We have to watch for text that includes "]]"
-
-      int start = 0;
-
-      while (start < val.length()) {
-        int end = val.indexOf("]]", start);
-        boolean lastSeg = end < 0;
-        String seg;
-
-        if (lastSeg) {
-          seg = val.substring(start);
-        } else {
-          seg = val.substring(start, end);
-        }
-
-        wtr.write("<![CDATA[");
-        wtr.write(seg);
-        wtr.write("]]>");
-
-        if (lastSeg) {
-          break;
-        }
-
-        wtr.write("]]");
-        start = end + 2;
-      }
-    }
+    cdataValue(val);
     closeTagSameLine(tag);
     newline();
   }
@@ -498,6 +409,95 @@
     newline();
   }
 
+  /* ===================================== Values =========================== */
+
+  /** Create the sequence<br>
+   *  <tag>val</tag>
+   *
+   * @param val
+   * @throws IOException
+   */
+  public void cdataValue(final String val) throws IOException {
+    if (val == null) {
+      return;
+    }
+
+    int start = 0;
+
+    while (start < val.length()) {
+      int end = val.indexOf("]]", start);
+      boolean lastSeg = end < 0;
+      String seg;
+
+      if (lastSeg) {
+        seg = val.substring(start);
+      } else {
+        seg = val.substring(start, end);
+      }
+
+      out("<![CDATA[");
+      out(seg);
+      out("]]>");
+
+      if (lastSeg) {
+        break;
+      }
+
+      out("]]");
+      start = end + 2;
+    }
+  }
+
+  /** Write out a value
+   *
+   * @param val
+   * @throws IOException
+   */
+  public void value(final String val) throws IOException {
+    value(val, null);
+  }
+
+  /** Write out a value
+   *
+   * @param val
+   * @param quoteChar
+   * @throws IOException
+   */
+  private void value(final String val,
+                     final String quoteChar) throws IOException {
+    if (val == null) {
+      return;
+    }
+
+    String q = quoteChar;
+    if (q == null) {
+      q = "";
+    }
+
+    if ((val.indexOf('&') >= 0) ||
+        (val.indexOf('<') >= 0)) {
+      out("<![CDATA[");
+      out(q);
+      out(val);
+      out(q);
+      out("]]>");
+    } else {
+      out(q);
+      out(val);
+      out(q);
+    }
+  }
+
+  /* ===================================== Misc ============================= */
+
+  /** Return the underlying writer. Should only be used to emit values.
+   *
+   * @return - the writer
+   */
+  public Writer getWriter() {
+    return wtr;
+  }
+
   /**
    * @throws IOException
    */
@@ -513,26 +513,7 @@
    */
   public void addNs(final NameSpace val,
                     final boolean makeDefaultNs) throws IOException {
-    if (val.abbrev == null) {
-      val.abbrev = "ns" + nsIndex;
-      nsIndex++;
-    }
-
-    for (NameSpace ns: nsMap.values()) {
-      if (val.equals(ns)) {
-        continue;
-      }
-
-      if (val.abbrev.equals(ns.abbrev)) {
-        throw new IOException("Duplicate namespace alias for " + val.ns);
-      }
-    }
-
-    nsMap.put(val.ns, val);
-
-    if (makeDefaultNs && !noDefaultns) {
-      defaultNs = val.ns;
-    }
+    nameSpaces.addNs(val, makeDefaultNs);
   }
 
   /**
@@ -540,7 +521,7 @@
    * @return NameSpace if present
    */
   public NameSpace getNameSpace(final String ns) {
-    return nsMap.get(ns);
+    return nameSpaces.getNameSpace(ns);
   }
 
   /**
@@ -548,13 +529,7 @@
    * @return namespace abrev
    */
   public String getNsAbbrev(final String ns) {
-    NameSpace n = nsMap.get(ns);
-
-    if (n == null) {
-      return null;
-    }
-
-    return n.abbrev;
+    return nameSpaces.getNsAbbrev(ns);
   }
 
   /** Write a new line
@@ -562,9 +537,21 @@
    * @throws IOException
    */
   public void newline() throws IOException {
-    wtr.write("\n");
+    out("\n");
   }
 
+  /* ====================================================================
+   *                         Private methods
+   * ==================================================================== */
+
+  private void quote(final String val) throws IOException {
+    if (val.indexOf("\"") < 0) {
+      value(val, "\"");
+    } else {
+      value(val, "'");
+    }
+  }
+
   /* Write out the tag name, adding the ns abbreviation.
    * Also add the namespace declarations if this is the first tag
    *
@@ -572,78 +559,31 @@
    * @throws IOException
    */
   private void emitQName(final QName tag) throws IOException {
-    String ns = tag.getNamespaceURI();
+    nameSpaces.emitNsAbbr(tag.getNamespaceURI(), wtr);
 
-    if ((ns != null) && !ns.equals(defaultNs)) {
-      String abbr = getNsAbbrev(ns);
+    out(tag.getLocalPart());
 
-      if (abbr != null) {
-        wtr.write(abbr);
-        wtr.write(":");
-      }
-    }
-
-    wtr.write(tag.getLocalPart());
-
-    if (!noHeaders && mustEmitNS) {
-      emitNs();
-    }
+    emitNs();
   }
 
   private void emitNs() throws IOException {
-    /* First tag so emit the name space declarations.
-     */
-    String delim = "";
-
-    for (String nsp: nsMap.keySet()) {
-      wtr.write(delim);
-      delim = "\n             ";
-
-      wtr.write(" xmlns");
-
-      String abbr = getNsAbbrev(nsp);
-
-      if ((abbr != null) && !nsp.equals(defaultNs)) {
-        wtr.write(":");
-        wtr.write(abbr);
-      }
-
-      wtr.write("=\"");
-      wtr.write(nsp);
-      wtr.write("\"");
-    }
-
-    mustEmitNS = false;
+    nameSpaces.emitNs(wtr);
   }
 
-  /* Write out the xml header
-   */
-  private void writeHeader(final String dtd) throws IOException {
-    wtr.write("<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n");
-
-    if (dtd == null) {
-      return;
-    }
-
-    wtr.write("<!DOCTYPE properties SYSTEM \"");
-    wtr.write(dtd);
-    wtr.write("\">\n");
-  }
-
   private void blanks() throws IOException {
     if (indent >= blankLen) {
-      wtr.write(blank);
+      out(blank);
     } else {
-      wtr.write(blank.substring(0, indent));
+      out(blank.substring(0, indent));
     }
   }
 
   private void lb() throws IOException {
-    wtr.write("<");
+    out("<");
   }
 
   private void rb() throws IOException {
-    wtr.write(">");
+    out(">");
   }
 
   /* size of buffer used for copying content to response.
@@ -673,4 +613,41 @@
       } catch (Throwable t) {}
     }
   }
+
+  private void scopeIn() {
+    scopeLevel++;
+    nameSpaces.startScope();
+  }
+
+  private void scopeOut() {
+    scopeLevel--;
+    nameSpaces.endScope();
+  }
+
+  private void out(final String val) throws IOException {
+    if (!started) {
+      started = true;
+
+      if (!noHeaders) {
+        writeHeader(dtd);
+        wtr.write("\n");
+      }
+    }
+
+    wtr.write(val);
+  }
+
+  /* Write out the xml header
+   */
+  private void writeHeader(final String dtd) throws IOException {
+    wtr.write("<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n");
+
+    if (dtd == null) {
+      return;
+    }
+
+    wtr.write("<!DOCTYPE properties SYSTEM \"");
+    wtr.write(dtd);
+    wtr.write("\">\n");
+  }
 }

Added: trunk/src/edu/rpi/sss/util/xml/XmlEmitNamespaces.java
===================================================================
--- trunk/src/edu/rpi/sss/util/xml/XmlEmitNamespaces.java	                        (rev 0)
+++ trunk/src/edu/rpi/sss/util/xml/XmlEmitNamespaces.java	2010-09-15 15:05:06 UTC (rev 190)
@@ -0,0 +1,200 @@
+/* **********************************************************************
+    Copyright 2006 Rensselaer Polytechnic Institute. All worldwide rights reserved.
+
+    Redistribution and use of this distribution in source and binary forms,
+    with or without modification, are permitted provided that:
+       The above copyright notice and this permission notice appear in all
+        copies and supporting documentation;
+
+        The name, identifiers, and trademarks of Rensselaer Polytechnic
+        Institute are not used in advertising or publicity without the
+        express prior written permission of Rensselaer Polytechnic Institute;
+
+    DISCLAIMER: The software is distributed" AS IS" without any express or
+    implied warranty, including but not limited to, any implied warranties
+    of merchantability or fitness for a particular purpose or any warrant)'
+    of non-infringement of any current or pending patent rights. The authors
+    of the software make no representations about the suitability of this
+    software for any particular purpose. The entire risk as to the quality
+    and performance of the software is with the user. Should the software
+    prove defective, the user assumes the cost of all necessary servicing,
+    repair or correction. In particular, neither Rensselaer Polytechnic
+    Institute, nor the authors of the software are liable for any indirect,
+    special, consequential, or incidental damages related to the software,
+    to the maximum extent the law permits.
+*/
+
+package edu.rpi.sss.util.xml;
+
+import edu.rpi.sss.util.xml.XmlEmit.NameSpace;
+
+import java.io.IOException;
+import java.io.Writer;
+import java.util.HashMap;
+import java.util.Stack;
+
+/** Class to handle namespaces when emitting xml
+ *
+ * @author Mike Douglass  douglm at rpi.edu
+ */
+class XmlEmitNamespaces {
+  private boolean mustEmitNS; // Emit this scopes namespaces.
+
+  private int scopeLevel; // So we can pop namespaces
+
+  private Stack<NameSpace> namespaces = new Stack<NameSpace>();
+
+  /** We need to map the namespaces onto a set of reasonable abbreviations
+   * for the generated xml. New set created each request
+   */
+  private HashMap<String, NameSpace> nsMap;
+
+  private int nsIndex;
+
+  private String defaultNs;
+
+  /** construct an object which will be used to collect namespace names
+   * during the first phase and emit xml after startEmit is called.
+   */
+  public XmlEmitNamespaces() {
+    nsMap = new HashMap<String, NameSpace>();
+  }
+
+  /**
+   *
+   * @param val
+   * @param makeDefaultNs - true => make this the default
+   * @throws IOException
+   */
+  public void addNs(final NameSpace val,
+                    final boolean makeDefaultNs) throws IOException {
+    if (val.abbrev == null) {
+      val.abbrev = "ns" + nsIndex;
+      nsIndex++;
+    }
+
+    val.level = scopeLevel;
+    val.defaultNs = makeDefaultNs;
+
+    for (NameSpace ns: nsMap.values()) {
+      if (val.equals(ns)) {
+        continue;
+      }
+
+      if ((val.level == ns.level) && val.abbrev.equals(ns.abbrev)) {
+        throw new IOException("Duplicate namespace alias for " + val.ns);
+      }
+    }
+
+    nsMap.put(val.ns, val);
+    mustEmitNS = true;
+    namespaces.push(val);
+
+    if (makeDefaultNs) {
+      defaultNs = val.ns;
+    }
+  }
+
+  public void startScope() {
+    scopeLevel++;
+  }
+
+  public void endScope() {
+    while (!namespaces.empty()) {
+      NameSpace ns = namespaces.peek();
+
+      if (ns.level < scopeLevel) {
+        //popped enough
+        break;
+      }
+
+      namespaces.pop();
+    }
+
+    // Rebuild the map.
+    nsMap.clear();
+
+    for (int i = 0; i < namespaces.size(); i++) {
+      NameSpace ns = namespaces.elementAt(i);
+
+      nsMap.put(ns.ns, ns);
+    }
+
+    scopeLevel--;
+  }
+
+  /**
+   * @param ns
+   * @return NameSpace if present
+   */
+  public NameSpace getNameSpace(final String ns) {
+    return nsMap.get(ns);
+  }
+
+  /**
+   * @param ns
+   * @return namespace abrev
+   */
+  public String getNsAbbrev(final String ns) {
+    NameSpace n = nsMap.get(ns);
+
+    if (n == null) {
+      return null;
+    }
+
+    return n.abbrev;
+  }
+
+  /**
+   * @param ns - full namespace from qname
+   * @param wtr
+   * @throws IOException
+   */
+  public void emitNsAbbr(final String ns,
+                         final Writer wtr) throws IOException {
+    if ((ns == null) || ns.equals(defaultNs)) {
+      return;
+    }
+
+    String abbr = getNsAbbrev(ns);
+
+    if (abbr != null) {
+      wtr.write(abbr);
+      wtr.write(":");
+    }
+  }
+
+  /**
+   * @param wtr
+   * @throws IOException
+   */
+  public void emitNs(final Writer wtr) throws IOException {
+    if (!mustEmitNS) {
+      return;
+    }
+
+    /* First tag so emit the name space declarations.
+     */
+    String delim = "";
+
+    for (String nsp: nsMap.keySet()) {
+      wtr.write(delim);
+      delim = "\n             ";
+
+      wtr.write(" xmlns");
+
+      String abbr = getNsAbbrev(nsp);
+
+      if ((abbr != null) && !nsp.equals(defaultNs)) {
+        wtr.write(":");
+        wtr.write(abbr);
+      }
+
+      wtr.write("=\"");
+      wtr.write(nsp);
+      wtr.write("\"");
+    }
+
+    mustEmitNS = false;
+  }
+}

Modified: trunk/src/edu/rpi/sss/util/xml/tagdefs/XcalTags.java
===================================================================
--- trunk/src/edu/rpi/sss/util/xml/tagdefs/XcalTags.java	2010-09-09 14:08:43 UTC (rev 189)
+++ trunk/src/edu/rpi/sss/util/xml/tagdefs/XcalTags.java	2010-09-15 15:05:06 UTC (rev 190)
@@ -35,6 +35,9 @@
   /** */
   public static final String namespace = "urn:ietf:params:xml:ns:icalendar-2.0";
 
+  /** */
+  public static final String mimetype = "application/calendar+xml";
+
   /* =====================================================================
                               values
      ===================================================================== */
@@ -145,4 +148,14 @@
 
   /**   */
   public static final QName vcalendar = new QName(namespace, "vcalendar");
+
+  /* =====================================================================
+                              properties
+     ===================================================================== */
+
+  /**   */
+  public static final QName prodid = new QName(namespace, "prodid");
+
+  /**   */
+  public static final QName version = new QName(namespace, "version");
 }



More information about the Bedework-commit mailing list