/*
** Module   : ProjectIndexLoader.java
** Abstract : instantiates a project index from an XML definition 
**
** Copyright (c) 2009, Golden Code Development Corporation.
**
** -#- -I- --Date-- -----------------------Description------------------------
** 001 GES 20090122 Instantiates a project index from an XML definition.
*/

/*
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU Affero General Public License as
** published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
**
** You should have received a copy of the GNU Affero General Public License
** along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

package com.goldencode.harness;

import org.w3c.dom.*;
import com.goldencode.harness.test.*;

/**
 * Instantiates a project index from an XML definition.
 */
public class ProjectIndexLoader
implements DefinitionConstants
{
   /**
    * Read the project index definition stored in the specified XML file and
    * instantiate all resources using the parsed content.
    *
    * @param    index
    *           The project index in which to store loaded definitions.
    * @param    filename
    *           Path and filename of the project index definition.
    * @param    rc
    *           Object in which to store the details of any failure.
    */
   public static void load(ProjectIndex        index,
                           String              filename,
                           FailureNotification rc)
   {
      Document dom = XmlHelper.loadDocument(filename, rc);
      
      if (dom == null)
      {
         // any failures have already been logged in the rc
         return;
      }
      
      loadIndex(index, dom, rc);
   }
   
   /**
    * Read the parsed document and create the project index that is defined
    * there.
    *
    * @param    index
    *           The project index in which to store loaded definitions.
    * @param    dom
    *           The document repsenting the XML file.
    * @param    rc
    *           Object in which to store the details of any failure.
    */
   private static void loadIndex(ProjectIndex        index,
                                 Document            dom,
                                 FailureNotification rc)
   {
      if (index != null && dom != null && rc != null)
      {
         Element root = dom.getDocumentElement();
         
         if (root != null)
         {
            NodeList nodes = root.getChildNodes();
            
            if (nodes != null)
            {
               int len = nodes.getLength();
               
               for (int i = 0; i < len; i++)
               {
                  Node next = nodes.item(i);
                  
                  if (next.getNodeType() != Node.ELEMENT_NODE)
                     continue;
                  
                  Element elem = (Element) next;
                  String  name = elem.getTagName().toLowerCase();
                  
                  if (ELEM_NAMED_RECTANGLES.equals(name))
                  {
                     NodeList rects = elem.getElementsByTagName(ELEM_RECTANGLE);
                     int rlen = rects.getLength();
                     
                     for (int j = 0; j < rlen; j++)
                     {
                        Element namedRect = (Element) rects.item(j);
                        String  rname     = namedRect.getAttribute(ATTR_NAME);
                        
                        if (rname == null || rname.length() == 0)
                        {
                           rc.setResult(ExitCode.MISSING_CONTENT);
                           String spec = "Missing rectangle name at index %d " +
                                         "in the project-index.";
                           rc.setDetails(String.format(spec, j));
                           return;
                        }
                        
                        Rectangle rect = TestFactory.readRectangle(namedRect,
                                                                   index,
                                                                   -1,
                                                                   -1);
                        index.putRectangle(rname, rect);
                     }
                  }
                  else if (ELEM_DEFAULTS.equals(name))
                  {
                     NodeList attrs = elem.getElementsByTagName(ELEM_ATTRIBUTE);
                     int alen = attrs.getLength();
                     
                     for (int k = 0; k < alen; k++)
                     {
                        Element attribute = (Element) attrs.item(k);
                        String  aname     = attribute.getAttribute(ATTR_NAME);
                        String  aval      = attribute.getAttribute(ATTR_VALUE);
                        
                        if (aname == null || aname.length() == 0)
                        {
                           rc.setResult(ExitCode.MISSING_CONTENT);
                           String spec = "Missing attribute name at index %d " +
                                         "in the project-index.";
                           rc.setDetails(String.format(spec, k));
                           return;
                        }
                        
                        if (aval == null || aval.length() == 0)
                        {
                           rc.setResult(ExitCode.MISSING_CONTENT);
                           String spec = "Missing attribute value at index %d " +
                                         "in the project-index.";
                           rc.setDetails(String.format(spec, k));
                           return;
                        }
                        
                        index.putDefaultAttr(aname, aval);
                     }
                  }
                  else if (ELEM_PATHS.equals(name))
                  {
                     NodeList paths = elem.getChildNodes();
                     int plen = paths.getLength();
                     
                     for (int x = 0; x < plen; x++)
                     {
                        Node item = paths.item(x);
                        
                        if (item.getNodeType() != Node.ELEMENT_NODE)
                           continue;
                        
                        Element path  = (Element) item;
                        String  type  = path.getTagName().toLowerCase();
                        String  fname = path.getAttribute(ATTR_PATH);
                        
                        if (ELEM_TEST.equals(type))
                        {
                           index.addTestPath(fname);
                        }
                        else if (ELEM_BASELINE.equals(type))
                        {
                           index.addBaseLinePath(fname);
                        }
                        else
                        {
                           rc.setResult(ExitCode.INVALID_CONTENT);
                           rc.setDetails(String.format("Unknown project-index" +
                                                       " paths sub-element %s.",
                                                       type));
                           return;
                        }
                     }
                  }
                  else
                  {
                     rc.setResult(ExitCode.INVALID_CONTENT);
                     rc.setDetails(String.format("Unknown project-index " +
                                                 "element %s.",
                                                 name));
                     return;
                  }
               }
            }
         }
      }
   }
}
