Index: java/src/org/apache/xindice/core/Collection.java
===================================================================
RCS file: /home/cvs/xml-xindice/java/src/org/apache/xindice/core/Collection.java,v
retrieving revision 1.12
diff -u -u -b -B -r1.12 Collection.java
--- java/src/org/apache/xindice/core/Collection.java	22 Nov 2002 10:15:34 -0000	1.12
+++ java/src/org/apache/xindice/core/Collection.java	26 Nov 2002 05:34:38 -0000
@@ -68,6 +68,7 @@
 import org.apache.xindice.core.filer.Filer;
 import org.apache.xindice.core.indexer.IndexManager;
 import org.apache.xindice.core.indexer.Indexer;
+import org.apache.xindice.core.meta.MetaData;
 import org.apache.xindice.core.query.QueryEngine;
 import org.apache.xindice.util.Configurable;
 import org.apache.xindice.util.Configuration;
@@ -446,10 +447,15 @@
     * @return The canonical name
     */
    public final String getCanonicalDocumentName(Key key) {
+      return getCanonicalDocumentName(key.toString());
+   }
+
+   public final String getCanonicalDocumentName(String key)
+   {
       StringBuffer sb = new StringBuffer();
       sb.append(canonicalName);
       sb.append('/');
-      sb.append(key.toString());
+      sb.append(key);
       return sb.toString();
    }
 
@@ -470,6 +476,8 @@
    }
 
    public boolean create() throws DBException {
+      // update the meta information if necessary
+      updateCollectionMeta();
       return true;
    }
 
@@ -477,8 +485,16 @@
       if ( this == getDatabase() )
          throw new DBException(FaultCodes.DBE_CANNOT_DROP, "You Cannot Drop The Database");
 
+
       DBObserver.getInstance().dropCollection(this);
       
+      // drop the meta if necessary
+      if( isMetaEnabled() )
+      {
+         MetaSystemCollection metacol = getMetaSystemCollection();
+         metacol.dropCollectionMeta(this);
+      }
+	  
       // Drop Child Collections
       String[] cols = listCollections();
       for ( int i = 0; i < cols.length; i++ )
@@ -595,6 +611,95 @@
    }
 
    /**
+    * update the modified time of this collection when appropriate
+    */
+   protected void updateCollectionMeta()
+   {
+      // update the meta data if necessary
+      if( isMetaEnabled() )
+      {
+         MetaSystemCollection metacol = getMetaSystemCollection();
+         MetaData meta = null;
+         try
+         {
+            meta = metacol.getCollectionMeta(this);
+         } catch (DBException e) {
+            // something strange has happened.. can't get the
+            // meta data for this collection
+            if( log.isWarnEnabled() )
+               log.warn("Error fetching collection meta. "+e);
+            return;
+         }
+         long now = System.currentTimeMillis();
+         if( null == meta )
+         {
+            meta = new MetaData(MetaData.COLLECTION, getCanonicalName(), 
+                                now, now);
+         }
+         else
+         {
+            // this collection already has a meta.  so update its modified time.
+            meta.setContext(0,now);
+         }
+         try {
+            metacol.setCollectionMeta(this, meta);
+         } catch(DBException e) {
+            if( log.isWarnEnabled() )
+               log.warn("Error setting the collection meta. "+e);
+            return;
+         }
+      }
+   }	
+
+   /**
+    * update the modified time of this document when appropriate
+    */
+   protected void updateDocumentMeta(String id) throws DBException
+   {
+      // update the meta data if necessary
+      if( ! isMetaEnabled() )
+         return;
+
+      Document doc = getDocument(id);
+      if( null == doc )
+         throw new DBException(FaultCodes.COL_DOCUMENT_NOT_FOUND,
+                "Document " + id + " does not exist");
+
+      MetaSystemCollection metacol = getMetaSystemCollection();
+      MetaData meta = metacol.getDocumentMeta(this, id);
+
+      String path = getCanonicalDocumentName(id);
+
+
+      /*
+      TimeRecord rec = null;
+      if( null == meta || !meta.hasContext() )
+         rec = getDatabase().getTime(path);
+
+      long created = (null != rec) ? rec.getCreatedTime() : System.currentTimeMillis();
+      long modified = (null != rec) ? rec.getModifiedTime() : System.currentTimeMillis();
+      */
+
+      // this is wrong.. but it should work for now...
+      long created = System.currentTimeMillis();
+      long modified = System.currentTimeMillis();
+
+
+      if( null == meta )
+      {
+         meta = new MetaData(MetaData.DOCUMENT, path, created, modified);
+      }
+      else if( !meta.hasContext() )
+      {
+         meta.setContext(created, modified);
+      }
+      else
+      {
+         meta.setContext(0,modified);
+      }  
+      metacol.setDocumentMeta(this,id,meta);
+   }
+   /**
     * insertDocument inserts a new Document into a Xindice Collection.
     *
     * @param document The Document
@@ -603,6 +708,8 @@
    public final Key insertDocument(Document document) throws DBException {
       Key key = createNewOID();
       putDocument(key, document /*, true */);
+      // update the meta information if necessary
+      updateCollectionMeta();
       return key;
    }
 
@@ -614,6 +721,8 @@
     */
    public final void insertDocument(Object docKey, Document document) throws DBException {
       putDocument(createNewKey(docKey), document /*, true */);
+      // update the meta information if necessary
+      updateCollectionMeta();
    }
 
    /**
@@ -625,6 +734,8 @@
     */
    public final void setDocument(Object docKey, Document document) throws DBException {
       putDocument(createNewKey(docKey), document /*, false */);
+      // update the meta for this document
+      updateDocumentMeta(docKey.toString());
    }
 
    /**
@@ -648,6 +759,13 @@
       if ( !filer.deleteRecord(objKey) )
          throw new DBException(FaultCodes.COL_DOCUMENT_NOT_FOUND, "Document Does Not Exist");
 
+      // update the meta for this collection if necessary
+      updateCollectionMeta();
+      // remove the document meta
+      if( isMetaEnabled() )
+      {
+         getMetaSystemCollection().dropDocumentMeta(this,objKey.toString());
+      }
       DBObserver.getInstance().dropDocument(this, objKey);
    }
 
@@ -882,6 +1000,171 @@
       }
    }
 
+   // META DATA RELATED DOCS
+   /**
+    * Returns whether or not meta data is enabled.
+    * @return boolean whether or not meta data is enabled.
+    */
+   public boolean isMetaEnabled()
+   {
+      return getDatabase().isMetaEnabled();
+   }
+
+   /**
+    * Return the MetaData for this collection.
+    * 
+    * If metadata is not enabled in the configuration, the MetaData object
+    * returned will be null.
+    * @return MetaData this collection's metadata.
+    */
+   public MetaData getCollectionMeta() throws DBException
+   {
+      MetaData meta = null;
+      if( ! isMetaEnabled() )
+      {
+         if(log.isWarnEnabled())
+         {
+            log.warn("Meta information requested but not enabled in config!");
+         }
+         return meta;
+      }
+      MetaSystemCollection metacol = getMetaSystemCollection();
+      meta = metacol.getCollectionMeta(this);
+      long now = System.currentTimeMillis();
+      if( null == meta )
+      {
+         meta = new MetaData(MetaData.COLLECTION, getCanonicalName(), now, now);
+         metacol.setCollectionMeta(this, meta);
+      }
+      return meta;
+   }
+
+   /**
+    * Reset the metadata object for this collection.
+    * @param meta the Metadata to use
+    */
+   public void setCollectionMeta(MetaData meta) throws DBException
+   {
+      if( ! isMetaEnabled() )
+      {
+         if(log.isWarnEnabled())
+         {
+            log.warn("Meta information requested but not enabled in config!");
+         }
+         return;
+      }
+      if( null != meta )
+      {
+         if( meta.getType() != MetaData.COLLECTION )
+            throw new DBException( FaultCodes.GEN_UNKNOWN,
+                    "Mismatch type of meta data for collection " +
+                    getCanonicalName());
+
+         MetaSystemCollection metacol = getMetaSystemCollection();
+         metacol.setCollectionMeta(this, meta);
+      }
+   }
+
+   /**
+    * Return the MetaData object for a document within this collection.
+    * 
+    * If metadata is not enabled, the MetaData object returned will be null.
+    * @param id the document whose metadata you want
+    */
+   public MetaData getDocumentMeta( String id ) throws DBException
+   {
+      MetaData meta = null;
+      if( ! isMetaEnabled() )
+      {
+         if(log.isWarnEnabled())
+         {
+            log.warn("Meta information requested but not enabled in config!");
+         }
+         return meta;
+      }
+      Document doc = getDocument(id);
+      if( null == doc )
+         throw new DBException(FaultCodes.COL_DOCUMENT_NOT_FOUND,
+                "Document " + id + " does not exist");
+
+      MetaSystemCollection metacol = getMetaSystemCollection();
+      meta = metacol.getDocumentMeta(this, id);
+
+      String path = getCanonicalDocumentName(id);
+
+
+      /*
+      TimeRecord rec = null;
+      if( null == meta || !meta.hasContext() )
+         rec = getDatabase().getTime(path);
+
+      long created = (null != rec) ? rec.getCreatedTime() : System.currentTimeMillis();
+      long modified = (null != rec) ? rec.getModifiedTime() : System.currentTimeMillis();
+      */
+
+      // this is wrong.. but it should work for now...
+      long created = System.currentTimeMillis();
+      long modified = System.currentTimeMillis();
+
+
+      if( null == meta )
+      {
+         meta = new MetaData(MetaData.DOCUMENT, path, created, modified);
+         metacol.setDocumentMeta(this, id, meta);
+      }
+      else if( !meta.hasContext() )
+      {
+         meta.setContext(created, modified);
+      }
+
+      return meta;
+   }
+
+   /**
+    * Set the metadata associated with a document within this collection.
+    * 
+    * @param id the document name
+    * @param meta the metadata object to be used.
+    */
+   public void setDocumentMeta(String id, MetaData meta) throws DBException
+   {
+      if( ! isMetaEnabled() )
+      {
+         if(log.isWarnEnabled())
+         {
+            log.warn("Meta information requested but not enabled in config!");
+         }
+         return;
+      }
+      Document doc = getDocument(id);
+      if( null == doc )
+         throw new DBException(FaultCodes.COL_DOCUMENT_NOT_FOUND,
+                "Document " + id + " does not exist");
+
+      if( null != meta )
+      {
+         if( meta.getType() == MetaData.UNKNOWN ||
+             meta.getType() == MetaData.COLLECTION )
+            throw new DBException( FaultCodes.GEN_UNKNOWN,
+                    "Mismatch type of meta data for document " +
+                    getCanonicalDocumentName(id));
+
+         MetaSystemCollection metacol = getMetaSystemCollection();
+         metacol.setDocumentMeta(this,id, meta);
+      }
+   }
+
+   /**
+    * Return the MetaSystemCollection for the database containing this
+    * collection.
+    * 
+    * @return MetaSystemCollection
+    */
+   private MetaSystemCollection getMetaSystemCollection() //throws DBException
+   {
+      return getDatabase().getMetaSystemCollection();
+   }
+
    
    /**
     * ColDocumentSet
Index: java/src/org/apache/xindice/core/Database.java
===================================================================
RCS file: /home/cvs/xml-xindice/java/src/org/apache/xindice/core/Database.java,v
retrieving revision 1.15
diff -u -u -b -B -r1.15 Database.java
--- java/src/org/apache/xindice/core/Database.java	18 Nov 2002 17:18:04 -0000	1.15
+++ java/src/org/apache/xindice/core/Database.java	26 Nov 2002 05:34:38 -0000
@@ -63,6 +63,7 @@
 import org.apache.xindice.util.Configuration;
 import org.apache.xindice.util.Named;
 import org.apache.xindice.util.XindiceException;
+import org.apache.xindice.core.meta.TimeRecord;
 
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
@@ -84,8 +85,10 @@
    private static final String QUERYENGINE = "queryengine";
    private static final String DATABASE = "database";
    private static final String COLKEY = "database.xml";
+   private static final String METADATA = "use-metadata";
    public static final String NAME = "name";
 
+
    private static Log log = LogFactory.getLog("org.apache.xindice.core");
 
    public static final String PROP_XINDICE_HOME = "xindice.home";
@@ -96,7 +99,13 @@
    
    private SystemCollection sysCol = null;
 
+   private MetaSystemCollection metaCol = null;
+
    private boolean sysInit = false;
+   private boolean metaInit = false;
+   private boolean metaEnabled = false;
+   // key = canonical name, value = timerecord
+   private Map timestamps = new HashMap();
 
    private QueryEngine engine = new QueryEngine(this);
 
@@ -176,6 +185,33 @@
       // Register the Database with the VM
       databases.put(getName(), this);
 
+      // initialize the meta collection
+      // but only if it's turned on in the config.
+      String metaCfg = config.getAttribute(METADATA);
+      if ( metaCfg.equalsIgnoreCase("on") )
+      {
+         metaEnabled = true;
+         if (!metaInit)
+         {
+            metaCol = new MetaSystemCollection(this);
+            try {
+               metaCol.init();
+            }
+            catch ( XindiceException e ) {
+               if (log.isDebugEnabled()) {
+                  log.debug("Error initializing the meta collection", e);
+               }
+            }
+            // should this attach the meta collection to the database?
+
+            collections.put(metaCol.getName(), metaCol);
+            metaInit = true;
+            if (log.isInfoEnabled()) {
+               log.info("Meta information initialized");
+            }
+         }
+      }
+
       // observer 
       DBObserver.getInstance().setDatabaseConfig(this, collections, config);
    }
@@ -184,6 +220,25 @@
       return sysCol;
    }
 
+   /**
+    * Return the MetaSystem collection for this database.
+    * 
+    * It will return null if metadata is not enabled on this database.
+    * @return MetaSystemCollection
+    */
+   public MetaSystemCollection getMetaSystemCollection() {
+      return metaCol;
+   }
+   
+   /**
+    * Return whether or not metadata is enabled on this database.
+    * @return boolean
+    */
+   public boolean isMetaEnabled()
+   {
+      return metaEnabled;
+   }
+
    public Database getDatabase() {
       return this;
    }
@@ -229,6 +284,34 @@
     */
    public QueryEngine getQueryEngine() {
       return engine;
+   }
+
+   // methods for recording the times when meta data is enabled.
+   public synchronized void recordTime( String path, long created, long modified )
+   {
+      TimeRecord rec = (TimeRecord)timestamps.get(path);
+      if( null == rec ) {
+         rec = new TimeRecord(created, modified);
+         timestamps.put(path, rec);
+      }
+      else
+      {
+         if( created > 0 )
+            rec.setCreatedTime(created);
+         if( modified > 0 )
+            rec.setModifiedTime(modified);
+      }
+   }
+
+   public synchronized void removeTime( String path )
+   {
+      timestamps.remove(path);
+   }
+
+   public synchronized TimeRecord getTime( String path )
+   {
+      TimeRecord rec = (TimeRecord)timestamps.get(path);
+      return rec;
    }
 }
 
Index: java/src/org/apache/xindice/server/rpc/RPCDefaultMessage.java
===================================================================
RCS file: /home/cvs/xml-xindice/java/src/org/apache/xindice/server/rpc/RPCDefaultMessage.java,v
retrieving revision 1.5
diff -u -u -b -B -r1.5 RPCDefaultMessage.java
--- java/src/org/apache/xindice/server/rpc/RPCDefaultMessage.java	21 Nov 2002 07:44:36 -0000	1.5
+++ java/src/org/apache/xindice/server/rpc/RPCDefaultMessage.java	26 Nov 2002 05:34:40 -0000
@@ -84,6 +84,7 @@
    public static final String QUERY = "query";
    public static final String NAMESPACES = "namespaces";
    public static final String CONFIGURATION = "configuration";
+   public static final String META = "meta";
 
    public static final String MISSING_COLLECTION_PARAM = "Required parameter 'collection' not found.";
    public static final String MISSING_NAME_PARAM = "Required parameter 'name' not found.";
@@ -93,6 +94,8 @@
    public static final String MISSING_QUERY_PARAM = "Required parameter 'query' not found.";
    public static final String MISSING_TIMESTAMP_PARAM = "For compressed results a timestamp must be provided.";
    public static final String MISSING_CONFIGURATION_PARAM = "You must either provide a document containing the configuration or specify the 'name' and 'patter' parameters.";
+   public static final String MISSING_META_CONFIGURATION = "Meta information requested but not enabled";
+   public static final String MISSING_META_PARAM = "Required parameter 'meta' not found";
 
    public Hashtable execute(Hashtable message) throws Exception {
       return null;
