package com.dbxml.db.enterprise.sync;

/*
 * dbXML - Native XML Database
 * Copyright (C) 1999-2004  The dbXML Group, L.L.C.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 *
 * $Id: Manifest.java,v 1.2 2004/02/12 00:17:57 bradford Exp $
 */

import java.util.*;

import com.dbxml.labrador.types.Variant;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

/**
 * Manifest represents a Content update manifest.
 */

public final class Manifest {
   private static final String[] EmptyStrings = new String[0];

   private Date date;
   private Map content = Collections.synchronizedMap(new TreeMap()); // String to Content
   private Map groups = Collections.synchronizedMap(new TreeMap());  // String to GroupInfo

   public Manifest(Document doc) {
      this(doc.getDocumentElement());
   }

   public Manifest(Element elem) {
      date = new Variant(elem.getAttribute(Constants.DATE)).getDate();

      NodeList nl = elem.getChildNodes();
      for ( int i = 0; i < nl.getLength(); i++ ) {
         Node n = nl.item(i);
         if ( n.getNodeType() == Node.ELEMENT_NODE ) {
            Element groupElem = (Element)n;
            if ( groupElem.getTagName().equals(Constants.GROUP) ) {
               String name = groupElem.getAttribute(Constants.NAME);
               double version = Double.parseDouble(groupElem.getAttribute(Constants.VERSION));
               int status = Constants.getStatusValue(groupElem.getAttribute(Constants.VERSION));
               GroupInfo gi = new GroupInfo(name, version, status);
               groups.put(name, gi);
   
               NodeList el = groupElem.getChildNodes();
               for ( int j = 0; j < el.getLength(); j++ ) {
                  Node en = el.item(j);
                  if ( en.getNodeType() == Node.ELEMENT_NODE ) {
                     Element contentElem = (Element)en;
                     if ( contentElem.getTagName().equals(Constants.CONTENT) ) {
                        Content c = new Content();
                        c.streamFromXML(contentElem);
                        String path = c.getPath();
                        content.put(path, c);
                        gi.addContent(path);
                     }
                  }
               }
            }
         }
      }
   }

   public Date getDate() {
      return date;
   }

   public void setDate(Date date) {
      this.date = date;
   }

   public Content getContent(String path) {
      return (Content)content.get(path);
   }

   public String[] getGroupNames() {
      return (String[])groups.keySet().toArray(EmptyStrings);
   }

   public double getGroupVersion(String group) {
      GroupInfo gi = (GroupInfo)groups.get(group);
      if ( group != null )
         return gi.version;
      else
         return 0.0;
   }

   public int getGroupStatus(String group) {
      GroupInfo gi = (GroupInfo)groups.get(group);
      if ( group != null )
         return gi.status;
      else
         return Constants.STATUS_UNKNOWN;
   }

   public String[] getGroupContent(String group) {
      GroupInfo gi = (GroupInfo)groups.get(group);
      if ( group != null )
         return (String[])gi.content.toArray(EmptyStrings);
      else
         return EmptyStrings;
   }


   /**
    * GroupInfo
    */

   private class GroupInfo {
      public String name;
      public double version;
      public int status;
      public Set content = new TreeSet();

      public GroupInfo(String name, double version, int status) {
         this.name = name;
         this.version = version;
         this.status = status;
      }

      public void addContent(String path) {
         content.add(path);
      }
   }
}
