<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
<Rule xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="Rule_Axmedis.xsd">
  <Header>
    <Rule_Name>Create_object_from_dir</Rule_Name>
    <AXRID>axcprule:e2a5e4b2-240d-438e-a7ee-d72db5b98448</AXRID>
    <Rule_Version>0.2</Rule_Version>
    <Rule_Type>AXCP</Rule_Type>
    <Software_Name></Software_Name>
    <Version_of_software></Version_of_software>
    <Date_of_production>2006-09-06</Date_of_production>
    <Author></Author>
    <Affiliation>ANSC</Affiliation>
    <URL></URL>
    <Comment>The _main script is a tester for the dir2obj script and Dir2Obj function. It takes all subdirs in a directory and feeds them to Dir2Obj
The function Dir2Obj adds all files in a directory with a certain mask to an Axmedis object.
Optionally an indexfile match can be specified (e.g. "index.htm". 
If matched the file will be added as the first resource in the object
Only htm* files are allowed for indexfile match.
Dublin Core can be added. It will be taken from the file DC_file. This file must have been created from the Axmedis editor DC editor and viewer
If an indexfile is searched and get_title is true title extraction will be tried on the indexfile and added as DCtitle to the object
A css file can be added as resource. 
In this case the contentID will be set to "css/style.css" by default. If the output_path doesn't exist it will be created
The function returns true upon success and saves the object. false otherwise</Comment>
    <Last_Modifications>2006-10-04</Last_Modifications>
    <Terminal_ID></Terminal_ID>
    <Cost></Cost>
    <Work_Item_ID></Work_Item_ID>
  </Header>
  <Schedule>
    <Run>
      <Date>2006-09-06</Date>
      <Time>12:00:00</Time>
      <Periodicity Unit="Minute">1</Periodicity>
      <Expiration_Date>2006-12-31</Expiration_Date>
      <Expiration_Time>13:38:23</Expiration_Time>
    </Run>
    <Status>Inactive</Status>
  </Schedule>
  <Definition>
    <AXCP_Rule>
      <Arguments>
        <Parameter Name="startdir" Type="String">C:\\axtest\\html</Parameter>
      
      </Arguments>
      <Rule_Body>
        <JS_Script name="dir2obj"><![CDATA[/* 
Function to add all files in a directory with a 
certain mask to an axmedis object.
Optionally an indexfile match can be specified (e.g. "index.htm")
if matched the file will be added as the first resource in the object
Only htm* files are allowed for indexfile match.

Dublin Core can be added.
It will be taken from the file DC_file.
This file must have been created from the Axmedis editor DC editor and viewer

If an indexfile is searched and get_title is true
title extraction will be tried on the indexfile and added as DCtitle to the object

A css file can be added as resource. 
In this case the contentID will be set to "css/style.css" by default

If the output_path doesn't exist it will be created

The function returns true upon success and saves the object. false otherwise
*/

function Dir2Obj 
(
dir,        // input dir (e.g. "c:\\dir") Use "\\" as path separator!
input_object,// for adding from an object. Complete with path and extension. Use "" for new
mask, 		// files to add (e.g. "*.*")
indexfile,	// a file (including extension) that if found  will be put at the start of the object. Use "" for none use_extensions, // if true adds file extension to resource's ContentID
DC_file,        // specify the DC XML file to use to add DC. "" for no Dublin Core
get_title,      // if true will add DC title trying to extract it from the <title> of indexfile
use_extensions, // add extensions to contentID
css_dir,         // dir containing the css file. "" to skip
css_name,        // css filename leave "" for default ("style.css")
output_path, // where the object will be saved
output_object // filename of the object to output INCLUDING extension eg. "out_obj.axm"
) 

{
var error =""; // here all the messages will be pushed
output_path = output_path +"\\";

// initial checks:
// check that the input dir exists
if (!existsDir(dir))
{
	print ("ERROR: The directory " + dir + " doesn't exist");
	return (false)
}
// check that an input_object specified really exists
if (input_object != "" && !existsFile(input_object))
   {
          print ("ERROR: Object file " + input_object + " doen't exist");
          return (false);
   }
// prevent the output object overwriting the input one
if (input_object == (output_path + output_object)) 
{
    print ("ERROR: I cannot overwrite the same object. Change the output object or select to create new");
    return (false);
}


   
// check that indexfile to search (if specified) contains "htm" // TODO this should be better
if (indexfile != "" && !indexfile.match ("htm"))
   {
          print ("ERROR: Sorry, I can only take \"htm*\" files as index");
          return (false);
   }

// check that if anindexfile has been specified also the mask includes htm or *.*
if (mask != "*.*" && !mask.match ("htm") && indexfile != "")
   {
          print ("ERROR: Sorry, Index file must be html and included in mask.\n You are using \""+mask+"\" as mask and \""+indexfile+"\" as index search.\nchange mask or remove index search");
          return (false);
   }
   
// check that output_path and output_object has been specified
if (output_object == "" || output_path == "\\")
{
          print ("ERROR: Please specify output path (e.g. \"c:\") and output filename (e.g. \"object001.axm\")");
          return (false);
}

    // warn about missing extension for output object
    if (!output_object.match (".axm")) 
    {
        error = error + "\nWARNING: no \".axm\" extension specified for output object!";
    }
    // If the output_path doesn't exist create it and warn.
    if (!existsDir(output_path))
    {
        if (makeDir (output_path))
        {
        error = error + ("\nWARNING: The output directory \"" + output_path + "\" doesn't exist: creating it");
        }
        else
        {
        // just in case
        print ("ERROR: Unable to create \"" + output_path + "\"");
        return (false);
        }
    }
    
    // get the files in an array
    files = getfilelist (dir, mask);     
    if (files.length <=0) //check that the folder isn't empty an that there are files
    {
        print ("ERROR: The directory "+ dir + " is empty or no files of type \""+mask+"\" found in it");  
        return (false);
    }
    error = error + "\nINFO: Taking files of the type "+mask;
    
    //start:
    print ("-----------creating object from \""+dir+"\""+"-----------------\n");
    var howmany = files.length; 	    // number of files found
    var resources = new Array(howmany); // array containing the resources that will be added
    if (indexfile != "")  //if an index file to match was specified
    {
        theindexfile =""; // this will be used later... if no match is found it will stay "" 
        for (i in files)
        {
   
            if (filefrompath(files[i]).match (indexfile) && filefrompath(files[i]).length ==indexfile.length) 
            //if the exact match for string in indexfile is found 
            {
                error = error +"\nINFO: I found a match for \""+indexfile+"\": Adding " + files[i] + " as first resource in the object";
                theindexfile = files[i]; // save the filename to theindexfile
                var res = new AxResource; 
                res.load (files[i]);    // load the resource
                resources.push (res);   //push it as firt element of the resources array
            }
        }
    if (theindexfile == "") // warn if no match was found
    {
    error = error +"\nWARNING: Didn't find any exact file match for \""+indexfile+"\" in "+dir;
    }
        for (i in files) //add all the other files
        {
            if (filefrompath(files[i]).match (indexfile) && filefrompath(files[i]).length ==indexfile.length) 
            // but not the index file!
                {
                }
            else
                {
                var res = new AxResource;
                res.load (files[i]);
                resources.push (res);
                }
        }
    }
    else // no index file to match was specified
    {
        error = error + "\nINFO: Adding resources: not using index file";
        for (i in files) //add the files
        {
            var res = new AxResource;
            res.load (files[i]);
            resources.push (res);
        }
    }
    if (input_object == "") //create a new empty axmedis object
    {
        var axObj = new AxmedisObject();  
        error = error + "\nINFO: Creating new object";
    }
    else
    {
        var axObj = new AxmedisObject(input_object);  //load an existing object
        error = error + "\nINFO: Using existing object "+ input_object;
    }
    if (DC_file != "") // if Dublin Core must be added
    {
    // put Dublin Core in the object
        if (indexfile != "" && theindexfile != "" && get_title) // if indexfile match was found
        {
            // try to extract the title from <title></title> in the indexfile found
            var DC_title = get_HTML_Title (theindexfile);
            var dc = axObj.getDublinCore ();
            dc.addDCElement("title", DC_title);
            error = error +"\nINFO: Explicitly adding DC title \""+DC_title+"\" taking it from " +dir + "\\" + theindexfile+" <title> tag";
            if (addDC (axObj, DC_file) != false) 
            {
                error = error +"\nINFO: Adding DC from file \""+DC_file+"\"";
            }
            else 
            {
                error = error +"\nWARINING: Problem trying to get DC from file \""+DC_file+"\" please refer to add_DC message";
            }
        }
        // just add the DC without any title
        else         
        {
            if (addDC (axObj, DC_file) != false) 
            {
                error = error +"\nINFO: Adding DC from file \""+DC_file+"\"";
            }
            else 
            {
                error = error +"\nWARINING: Problem trying to get DC from file \""+DC_file+"\" please refer to add_DC message";
            }
        }
    }
    else // if no DC must be added
    {
        error = error + "\nINFO: No Dublin Core being added"
    }
    for (i in resources)           	//add all the resources in to the object
    {
        if (use_extensions)    // if file extensions must be added to the contentID
        // add file extension to contentID (thanks to Ivan for this)
        {
          resources[i].contentID = resources[i].contentID + mimeTypeToExt(resources[i].mimeType); 
        }
        axObj.addContent (resources[i]);
    }
  if (use_extensions) // tell what happened about extensions
  {
          error = error +"\nINFO: Adding file extensions to resource ContentID";
  }
  else
  {
          error = error +"\nINFO: Not adding file extensions to resource ContentID";
  }
  var cssres = add_css (css_dir,css_name); //try to get the css
  if (css_dir == "" || !cssres) //if the css_dir is empty (skip) or if adding the css failed 
  {
      error = error + "\nWARNING: No css file being added.";
  }
  else  // if the css must be added and it was found
  {
      cssres.contentID = "css/style.css";       // this is specific to the ANSC instruments objects
      axObj.addContent (cssres);                //add the css to the object
      error = error + "\nINFO: Adding css file "+css_dir + "\\" + css_name +" with contentID \""+ cssres.contentID+ "\"";
  }
    // Save the axmedis object 
    axObj.save (output_path + output_object); // output_object is in the Arguments
    // print a report about the object and all the process (error contains all the messages)
    print (error+ "\n\nSUCCESS: Saved " + output_path + output_object+"\n");
    return (true);
}]]>
        </JS_Script>
        <JS_Script name="HTML_title">
          
          <![CDATA[/* tries to extract the title from an HTML file
the <title> tag must be within a <head></head> section
and the closing </title> tag must exists
The funcion will trim the contents from leading and trailing spaces, tabs newlines etc.
the function returns the title found or an exmpty string on unsuccess
*/
function get_HTML_Title (file)
{
    if (! existsFile(file))     // check that the file exists
    {
      print ("html title ERROR: File " + file + "doen't exist");
      return ("");
    }
    var all = readFromFile(file);  // read from the file into a string
    var headpos = all.indexOf("<head>"); //search for the <head> tag
    if (headpos < 0) // if the zhead> tag is not find: error
    {
      print ("html title ERROR: File " + file + " contains no <head> tag");
      return ("");
    }
    var titlepos = all.indexOf ("<title>",headpos); //search for the <title> tag
    if (titlepos < 0) // if not found: error
    {
      print ("html title ERROR: File " + file + "contains no <title> tag");
      return ("");
    }
    //search for the </title> closing tag
    // could be less strict and find the firts "</" ?
    var endtitlepos = all.indexOf ("</title>",titlepos); 
    if (endtitlepos < 0) // if not sound: error
    {
      print ("html title ERROR: File " + file + "contains no </title> end tag");
      return ("");
    }
    var output = all.slice (titlepos+7,endtitlepos); // get the substring in <title> ... </title> substring
    var trim = 0;
    for (i in output) // check for leading spaces, tabs and newlines...
    {
        if (output.charCodeAt(i) ==  32 || output.charCodeAt(i) ==  9 || output.charCodeAt(i) ==  10)
        {
            trim = trim + 1; //leading index for slice
        }
        else break   // ...up to the first nonspace char found
    }
    var trimlength = output.length;
    for (j = output.length-1; j >= 0; j--) // check for trailing spaces, tabs and newlines from ednd of string...
    {
        if (output.charCodeAt(j) ==  32 || output.charCodeAt(j) ==  9 || output.charCodeAt(j) ==  10)
        {
            trimlength = j ; //trailing index slice
        }
        else break   // ... down to the first nonspace char found
    }
    
    output = output.slice(trim,trimlength); // slice the string
    print ("html title SUCCESS: extracted \""+ output + "\" from " + file);
    return (output);
}]]>
        </JS_Script>
        <JS_Script name="add_the_css">
          
          <![CDATA[/*
Add a css file to a resource
Returns the AxResource with the css in or false on unsuccess
*/
function add_css (
    css_dir,    // dir containing the css
    css_file    // css filename if "" default is used: "style.css"
    )
{
    if (css_file == "")  // use the default filename
    {
        css_file = "style.css";
    }
    if (! existsFile(css_dir +"\\" +css_file)) // check if the file exists
    {
      print ("css ERROR: File " + css_dir + "\\" + css_file + " doesn't exist");
      return (false);
    }
    var css = new AxResource; // create the AxResource
    css.load (css_dir + "\\" + css_file); // load the css into the resource
    print ("css SUCCESS: addedd "+ css_dir + "\\" + css_file + " to resource");
    return (css);
}]]>
        </JS_Script>
        <JS_Script name="ANSC_DC">
          
          <![CDATA[// ANSC instruments specific DC template - adapted from the example in the docs
// TODO: majke it more generic: read the DC from a file passed to the function
function createDC(input_obj, title)
{
  var axObj = new AxmedisObject();
  var dc = axObj.getDublinCore ();
  
  if (title != "") 
  {
      dc.addDCElement("title",title);
  }
  return (axObj);
}]]>
        </JS_Script>
        <JS_Script name="filefromfullpath">
          
          <![CDATA[/*
Get the filename (or last level dir) in a filename
"\\" is assumed as path separator
*/
function filefrompath (
    file
    )
{
if (file=="")
{
    return (file);
}
var trim=file.length+1;
    for (l=file.length; l>=0; l--)
    {
        if (file[l] == "\\") {break;}
        trim= trim-1;
    }
file = file.slice (trim);
return (file)
}]]>
        </JS_Script>
        <JS_Script name="jsxml">
          
          <![CDATA[///////////////////////////////////////////////////////////////
////////// JSXML XML Tools               //////////////////////
////////// Ver 1.2 Jun 18 2001           //////////////////////
////////// Copyright 2000 Peter Tracey   //////////////////////
////////// http://jsxml.homestead.com/   //////////////////////
////
////	Objects:
////
////	REXML
////    Regular Expression-based XML parser
////
////	JSXMLIterator
////    Iterates through the tree structure without recursion
////
////	JSXMLBuilder
////    Loads xml into a linear structure and provides 
////	interface for adding and removing elements 
////	and setting attributes, generates XML
////
////	Utility functions:
////
////	ParseAttribute
////    Takes string of attibutes and attribute name
////    Returns attribute value
////
////	Array_Remove
////    Removes element in array
////
////	Array_Add
////    Adds element to array
////
////	RepeatChar
////    Repeats string specified number of times
////
///////////////////////////////////////////////////////////////
function REXML(XML) {
	this.XML = XML;
	this.rootElement = null;
	this.parse = REXML_parse;
	if (this.XML && this.XML != "") this.parse();
}
	function REXML_parse() {
		var reTag = new RegExp("<([^>/ ]*)([^>]*)>","g"); // matches that tag name $1 and attribute string $2
		var reTagText = new RegExp("<([^>/ ]*)([^>]*)>([^<]*)","g"); // matches tag name $1, attribute string $2, and text $3
		var strType = "";
		var strTag = "";
		var strText = "";
		var strAttributes = "";
		var strOpen = "";
		var strClose = "";
		var iElements = 0;
		var xmleLastElement = null;
		if (this.XML.length == 0) return;
		var arrElementsUnparsed = this.XML.match(reTag);
		var arrElementsUnparsedText = this.XML.match(reTagText);
		var i=0;
		if (arrElementsUnparsed[0].replace(reTag, "$1") == "?xml") i++;
		for (; i<arrElementsUnparsed.length; i++) {
			strTag = arrElementsUnparsed[i].replace(reTag,"$1");
			strAttributes = arrElementsUnparsed[i].replace(reTag,"$2");
			strText = arrElementsUnparsedText[i].replace(reTagText,"$3").replace(/[\r\n\t ]+/g, " "); // remove white space
			strClose = "";
			if (strTag.indexOf("![CDATA[") == 0) {
				strOpen = "<![CDATA[";
				strClose = "";
				strType = "cdata";
			} else if (strTag.indexOf("!--") == 0) {
				strOpen = "<!--";
				strClose = "-->";
				strType = "comment";
			} else if (strTag.indexOf("?") == 0) {
				strOpen = "<?";
				strClose = "?>";
				strType = "pi";
			} else strType = "element";
			if (strClose != "" && strType!="comment") { // added by Ivan Bruno
				strText = "";
				if (arrElementsUnparsedText[i].indexOf(strClose) > -1) strText = arrElementsUnparsedText[i];
				else {
					for (; i<arrElementsUnparsed.length && arrElementsUnparsedText[i].indexOf(strClose) == -1; i++) {
						strText += arrElementsUnparsedText[i];
					}
					strText += arrElementsUnparsedText[i];
				}
				if (strText.substring(strOpen.length, strText.indexOf(strClose)) != "")	{
					xmleLastElement.childElements[xmleLastElement.childElements.length] = new REXML_XMLElement(strType, "","",xmleLastElement,strText.substring(strOpen.length, strText.indexOf(strClose)));
					if (strType == "cdata") xmleLastElement.text += strText.substring(strOpen.length, strText.indexOf(strClose));
				}
				if (strText.indexOf(strClose)+ strClose.length < strText.length) {
					xmleLastElement.childElements[xmleLastElement.childElements.length] = new REXML_XMLElement("text", "","",xmleLastElement,strText.substring(strText.indexOf(strClose)+ strClose.length, strText.length));
					if (strType == "cdata") xmleLastElement.text += strText.substring(strText.indexOf(strClose)+ strClose.length, strText.length);
				}
				continue;
			}
			if (strText.replace(/ */, "") == "") strText = "";
			if (arrElementsUnparsed[i].substring(1,2) != "/") {
				if (iElements == 0) {
					xmleLastElement = this.rootElement = new REXML_XMLElement(strType, strTag,strAttributes,null,strText);
					iElements++;
					if (strText != "") xmleLastElement.childElements[xmleLastElement.childElements.length] = new REXML_XMLElement("text", "","",xmleLastElement,strText);
				} else if (arrElementsUnparsed[i].substring(arrElementsUnparsed[i].length-2,arrElementsUnparsed[i].length-1) != "/") {
					xmleLastElement = xmleLastElement.childElements[xmleLastElement.childElements.length] = new REXML_XMLElement(strType, strTag,strAttributes,xmleLastElement,"");
					iElements++;
					if (strText != "") {
						xmleLastElement.text += strText;
						xmleLastElement.childElements[xmleLastElement.childElements.length] = new REXML_XMLElement("text", "","",xmleLastElement,strText);
					}
				} else {
					xmleLastElement.childElements[xmleLastElement.childElements.length] = new REXML_XMLElement(strType, strTag,strAttributes,xmleLastElement,strText);
					if (strText != "") xmleLastElement.childElements[xmleLastElement.childElements.length] = new REXML_XMLElement("text", "","",xmleLastElement,strText);
				}
			} else {
				xmleLastElement = xmleLastElement.parentElement;
				iElements--;
				if (xmleLastElement && strText != "") {
					xmleLastElement.text += strText;
					xmleLastElement.childElements[xmleLastElement.childElements.length] = new REXML_XMLElement("text", "","",xmleLastElement,strText);
				}
			}
		}
	}
	function REXML_XMLElement(strType, strName, strAttributes, xmlParent, strText) {
		this.type = strType;
		this.name = strName;
		this.attributeString = strAttributes;
		this.attributes = null;
		this.childElements = new Array();
		this.parentElement = xmlParent;
		this.text = strText; // text of element
		this.getText = REXML_XMLElement_getText; // text of element and child elements
		this.childElement = REXML_XMLElement_childElement;
		this.attribute = REXML_XMLElement_attribute;
	}
		function REXML_XMLElement_getText() {
			if (this.type == "text" || this.type == "cdata") {
				return this.text;
			} else if (this.childElements.length) {
				var L = "";
				for (var i=0; i<this.childElements.length; i++) {
					L += this.childElements[i].getText();
				}
				return L;
			} else return "";
		}
		
		function REXML_XMLElement_childElement(strElementName) {
			for (var i=0; i<this.childElements.length; i++) if (this.childElements[i].name == strElementName) return this.childElements[i];
			return null;
		}
		function REXML_XMLElement_attribute(strAttributeName) {
			if (!this.attributes) {
				var reAttributes = new RegExp(" ([^= ]*)=","g"); // matches attributes
				if (this.attributeString.match(reAttributes) && this.attributeString.match(reAttributes).length) {
					var arrAttributes = this.attributeString.match(reAttributes);
					if (!arrAttributes.length) arrAttributes = null;
					else for (var j=0; j<arrAttributes.length; j++) {
						arrAttributes[j] = new Array(
							(arrAttributes[j]+"").replace(/[= ]/g,""),
							ParseAttribute(this.attributeString, (arrAttributes[j]+"").replace(/[= ]/g,""))
										);
					}
					this.attributes = arrAttributes;
				}
			}
			if (this.attributes) 
                for (var i=0; i<this.attributes.length; i++)
                {
                    pippo = this.attributes[i][0];
                    if (this.attributes[i][0] == strAttributeName)
                        return this.attributes[i][1];
                }
			return "";
		}
function JSXMLBuilder() {
	this.XML = "";
	this.elements = new Array();
	Array.prototype.remove = Array_Remove;
	Array.prototype.add = Array_Add;
	this.load = JSXMLBuilder_load;
	this.element = JSXMLBuilder_element;
	this.addElementAt = JSXMLBuilder_addElementAt;
	this.insertElementAt = JSXMLBuilder_insertElementAt;
	this.removeElement = JSXMLBuilder_removeElement;
	this.generateXML = JSXMLBuilder_generateXML;
	this.moveElement = JSXMLBuilder_moveElement;
}
	function JSXMLBuilder_load(strXML, xmleElem) {
		this.XML = strXML;
		if (!xmleElem) {
			if (strXML.length) xmleElem = (new REXML(strXML)).rootElement;
			else return false;
		}
		var xmlBuilder = new JSXMLIterator(xmleElem);
		while (true) {
			if (xmlBuilder.xmleElem.type == "element") {
				if (xmlBuilder.xmleElem.attributes) {
					this.addElementAt(xmlBuilder.xmleElem.name,xmlBuilder.xmleElem.attributes, xmlBuilder.xmleElem.text, this.elements.length, xmlBuilder.iElemLevel);
				} else {	
					this.addElementAt(xmlBuilder.xmleElem.name,xmlBuilder.xmleElem.attributeString, xmlBuilder.xmleElem.text, this.elements.length, xmlBuilder.iElemLevel);
				}
			}
			if (!xmlBuilder.getNextNode(false)) break;
		}
		for (var i=0; i<this.elements.length; i++) this.elements[i].index = i;
	}
	function JSXMLBuilder_element(iIndex) {
		return this.elements[iIndex];
	}
	function JSXMLBuilder_addElementAt(strElement,Attributes,strText,iElemIndex,iElemLevel) {
		iElemIndex = parseInt(iElemIndex);
		iElemLevel = parseInt(iElemLevel);
		if (iElemIndex < 0 || typeof(iElemIndex) != "number" || isNaN(iElemIndex)) iElemIndex = (this.elements.length>0) ? this.elements.length-1 : 0;
		if (iElemLevel < 0 || typeof(iElemLevel) != "number" || isNaN(iElemLevel)) iElemLevel = this.elements[iElemIndex-1].level;
		if (!Attributes) Attributes = "";
		var Elem = new Array();
		var iAddIndex = iElemIndex;
		if (iElemIndex > 0) {
			for (var i=iElemIndex; i<this.elements.length; i++) if (this.elements[i].level > iElemLevel) iAddIndex++;
			else if (this.elements[i].level <= this.elements[iElemIndex].level) break;
			Elem = new JSXMLBuilder_XMLElement(strElement,Attributes,strText,iElemLevel+1,this);
		} else {
			Elem = new JSXMLBuilder_XMLElement(strElement,Attributes,strText,1,this);
		}
		this.elements = this.elements.add(iAddIndex,Elem);
		for (var i=iAddIndex; i<this.elements.length; i++) this.elements[i].index = i;
	}
	function JSXMLBuilder_insertElementAt(strElement,Attributes,strText,iElemIndex,iElemLevel) {
		iElemIndex = parseInt(iElemIndex);
		iElemLevel = parseInt(iElemLevel);
		if (iElemIndex < 0 || typeof(iElemIndex) != "number" || isNaN(iElemIndex)) iElemIndex = (this.elements.length>0) ? this.elements.length-1 : 0;
		if (iElemLevel < 0 || typeof(iElemLevel) != "number" || isNaN(iElemLevel)) iElemLevel = this.elements[iElemIndex-1].level;
		if (!Attributes) Attributes = "";
		var Elem = null;
		var iAddIndex = iElemIndex;
		if (iElemIndex > 0 && iElemLevel > 0) {
			Elem = new JSXMLBuilder_XMLElement(strElement,Attributes,strText,iElemLevel+1,this);
		} else {
			Elem = new JSXMLBuilder_XMLElement(strElement,Attributes,strText,1,this);
		}
		this.elements = this.elements.add(iAddIndex,Elem);
		for (var i=iAddIndex; i<this.elements.length; i++) this.elements[i].index = i;
	}
	function JSXMLBuilder_removeElement(iElemIndex) {
		iElemIndex = parseInt(iElemIndex);
		for (var iAfterElem=iElemIndex+1; iAfterElem<this.elements.length; iAfterElem++) if (this.elements[iAfterElem].level < this.elements[iElemIndex].level+1) break;
		this.elements = this.elements.slice(0,iElemIndex).concat(this.elements.slice(iAfterElem,this.elements.length));
		for (var i=iElemIndex; i<this.elements.length; i++) this.elements[i].index = i;
	}
	function JSXMLBuilder_moveElement(iElem1Index,iElem2Index) {
		var arrElem1Elements = new Array(this.elements[iElem1Index]);
		var arrElem2Elements = new Array(this.elements[iElem2Index]);
		for (var i=iElem1Index; i<this.elements.length; i++) if (this.elements[i].level > this.elements[iElem1Index].level) arrElem1Elements[arrElem1Elements.length] = this.elements[i]; else if (i>iElem1Index) break;
		for (var i=iElem2Index; i<this.elements.length; i++) if (this.elements[i].level > this.elements[iElem2Index].level) arrElem2Elements[arrElem2Elements.length] = this.elements[i]; else if (i>iElem2Index) break;
		var arrMovedElements = new Array();
		if (iElem1Index < iElem2Index) {
			for (i=0; i<iElem1Index; i++) arrMovedElements[arrMovedElements.length] = this.elements[i]; // start to the 1st element
			for (i=iElem1Index+arrElem1Elements.length; i<iElem2Index+arrElem2Elements.length; i++) arrMovedElements[arrMovedElements.length] = this.elements[i]; // end of 1st element to end of 2nd element
			for (i=0; i<arrElem1Elements.length; i++) arrMovedElements[arrMovedElements.length] = arrElem1Elements[i]; // 1st element and all child elements
			for (i=iElem2Index+arrElem2Elements.length; i<this.elements.length; i++) arrMovedElements[arrMovedElements.length] = this.elements[i]; // end of 2nd element to end
			this.elements = arrMovedElements;
		} else {
			for (i=0; i<iElem2Index; i++) arrMovedElements[arrMovedElements.length] = this.elements[i]; // start to the 2nd element
			for (i=0; i<arrElem1Elements.length; i++) arrMovedElements[arrMovedElements.length] = arrElem1Elements[i]; // 1st element and all child elements
			for (i=iElem2Index; i<iElem1Index; i++) arrMovedElements[arrMovedElements.length] = this.elements[i]; // 2nd element to 1st element
			for (i=iElem1Index+arrElem1Elements.length; i<this.elements.length; i++) arrMovedElements[arrMovedElements.length] = this.elements[i]; // end of 1st element to end
			this.elements = arrMovedElements;
		}
		for (var i=0; i<this.elements.length; i++) this.elements[i].index = i;
	}
	function JSXMLBuilder_generateXML(bXMLTag) {
		var strXML = "";
		var arrXML = new Array();
		if (bXMLTag) strXML += '<?xml version="1.0"?>\n\n'
		for (var i=0; i<this.elements.length; i++) {
			strXML += RepeatChar("\t",this.elements[i].level-1);
			strXML += "<" + this.element(i).name // open tag
			if (this.element(i).attributes) {
				for (var j=0; j<this.element(i).attributes.length; j++) { // set attributes
					if (this.element(i).attributes[j]) {
						strXML += ' ' + this.element(i).attributes[j][0] + '="' + this.element(i).attributes[j][1] + '"';
					}
				}
			} else strXML += this.element(i).attributeString.replace(/[\/>]$/gi, "");
			if (((this.elements[i+1] && this.elements[i+1].level <= this.elements[i].level) || // next element is a lower or equal to
				(!this.elements[i+1] && this.elements[i-1])) // no next element, previous element
				&& this.element(i).text == "") {
				strXML += "/";
			}
			strXML += ">";
			if (this.element(i).text != "") strXML += this.element(i).text;
			else strXML += "\n";
			if (((this.elements[i+1] && this.elements[i+1].level <= this.elements[i].level) || // next element is a lower or equal to
				(!this.elements[i+1] && this.elements[i-1])) // no next element, previous element
				&& this.element(i).text != "") strXML += "</" + this.element(i).name + ">\n";
			if (!this.elements[i+1]) {
				lastelem = i;
				for (var j=i; j>-1; j--) {
					if (this.elements[j].level >= this.elements[i].level) continue;
					else {
						if (this.elements[j].level < this.elements[lastelem].level) {
							strXML += RepeatChar("\t",this.elements[j].level-1) + "</" + this.element(j).name + ">\n";
							lastelem = j;
						}
					}
				}
			} else {
				if (this.elements[i+1].level < this.elements[i].level) {
					lastelem = i;
					for (var j=i; this.elements[j].level>=this.elements[i+1].level; j--) {
						if (this.elements[i] && this.elements[j] && this.elements[j].level < this.elements[i].level && this.elements[j].level < this.elements[lastelem].level) {
							strXML += RepeatChar("\t",this.elements[j].level-1) + "</" + this.element(j).name + ">\n";
							lastelem = j;
						}
					}
				}
			}
			if (strXML.length > 1000) {
				arrXML[arrXML.length] = strXML;
				strXML = "";
			}
		}
		arrXML[arrXML.length] = strXML;
		return arrXML.join("");
	}
	function JSXMLBuilder_XMLElement(strName,Attributes,strText,iLevel,xmlBuilder) {
		this.type = "element";
		this.name = strName;
		this.attributes = (typeof(Attributes) != "string") ? Attributes : null;
		this.attributeString = (typeof(Attributes) == "string") ? Attributes : "";
		this.text = strText;
		this.level = iLevel;
		this.index = -1;
		this.xmlBuilder = xmlBuilder;
		this.parseAttributes = JSXMLBuilder_XMLElement_parseAttributes;
		this.attribute = JSXMLBuilder_XMLElement_attribute;
		this.setAttribute = JSXMLBuilder_XMLElement_setAttribute;
		this.removeAttribute = JSXMLBuilder_XMLElement_removeAttribute;
		this.parentElement = JSXMLBuilder_XMLElement_parentElement;
		this.childElement = JSXMLBuilder_XMLElement_childElement;
	}
		function JSXMLBuilder_XMLElement_parseAttributes() {
			if (!this.attributes) {
				var reAttributes = new RegExp(" ([^= ]*)=","g"); // matches attributes
				if (this.attributeString.match(reAttributes) && this.attributeString.match(reAttributes).length) {
					var arrAttributes = this.attributeString.match(reAttributes);
					if (!arrAttributes.length) arrAttributes = null;
					else for (var j=0; j<arrAttributes.length; j++) {
						arrAttributes[j] = new Array(
							(arrAttributes[j]+"").replace(/[= ]/g,""),
							ParseAttribute(this.attributeString, (arrAttributes[j]+"").replace(/[= ]/g,""))
										);
					}
					this.attributes = arrAttributes;
				}
			}
		}
	
		function JSXMLBuilder_XMLElement_attribute(AttributeName) {
			if (!this.attributes) this.parseAttributes();
			if (this.attributes) for (var i=0; i<this.attributes.length; i++) if (this.attributes[i][0] == AttributeName) return this.attributes[i][1];
			return "";
		}
		function JSXMLBuilder_XMLElement_setAttribute(AttributeName,Value) {
			if (!this.attributes) this.parseAttributes();
			if (this.attributes) for (var i=0; i<this.attributes.length; i++) if (this.attributes[i][0] == AttributeName) {
				this.attributes[i][1] = Value;
				return;
			}
			this.attributes[this.attributes.length] = new Array(AttributeName,Value);
		}
		function JSXMLBuilder_XMLElement_removeAttribute(AttributeName,Value) {
			if (!this.attributes) this.parseAttributes();
			if (this.attributes) for (var i=0; i<this.attributes.length; i++) if (this.attributes[i][0] == AttributeName) {
				this.attributes = this.attributes.remove(i);
				return;
			}
		}
		function JSXMLBuilder_XMLElement_parentElement() {
			for (var i=this.index; this.xmlBuilder.element(i) && this.xmlBuilder.element(i).level != this.level-1; i--);
			return this.xmlBuilder.element(i);
		}
		function JSXMLBuilder_XMLElement_childElement(Child) {
			var iFind = -1;
			for (var i=this.index+1; i<this.xmlBuilder.elements.length; i++) {
				if (this.xmlBuilder.elements[i].level == this.level+1) {
					iFind++;
					if (iFind == Child || this.xmlBuilder.elements[i].name == Child) return this.xmlBuilder.elements[i];
				} else if (this.xmlBuilder.elements[i].level <= this.level) break;
			}
			return null;
		}
function JSXMLIterator(xmleElem) {
	this.xmleElem = xmleElem;
	
	this.iElemIndex = 0;
	this.arrElemIndex = new Array(0);
	this.iElemLevel = 0;
	this.iElem = 0;
	this.arrElemIndex[this.iElemLevel] = -1;
	this.getNextNode = JSXMLIterator_getNextNode;
}
	function JSXMLIterator_getNextNode() {
		if (!this.xmleElem || this.iElemLevel<0)	return false;
		if (this.xmleElem.childElements.length) {  // move up
			this.arrElemIndex[this.iElemLevel]++;
			this.iElemIndex++;
			this.iElemLevel++;
			this.arrElemIndex[this.iElemLevel] = 0;
			this.xmleElem = this.xmleElem.childElements[0];
		} else { // move next
			this.iElemIndex++;
			this.arrElemIndex[this.iElemLevel]++;
			if (this.xmleElem.parentElement && this.xmleElem.parentElement.childElements.length && this.arrElemIndex[this.iElemLevel] < this.xmleElem.parentElement.childElements.length) this.xmleElem = this.xmleElem.parentElement.childElements[this.arrElemIndex[this.iElemLevel]];
			else {
				if (this.iElemLevel>0) { // move down
					for (; this.iElemLevel > 0; this.iElemLevel--) {
						if (this.xmleElem.parentElement && this.xmleElem.parentElement.childElements[this.arrElemIndex[this.iElemLevel]]) {
							this.xmleElem = this.xmleElem.parentElement.childElements[this.arrElemIndex[this.iElemLevel]];
							this.iElemLevel++;
							this.arrElemIndex = this.arrElemIndex.slice(0,this.iElemLevel+1);
							break;
						} else {
							this.xmleElem = this.xmleElem.parentElement;
						}
					}
					this.iElemLevel--;
				} else {
					return false;
				}
			}
		}
		return (typeof(this.xmleElem) == "object" && this.iElemLevel > -1);
	}
function ParseAttribute(str,Attribute) {
	var str =  str +  ">";
    str = str.replace(/[\n]/,"");
    if (str.indexOf(Attribute + "='")>-1)
        var Attr = new RegExp(".*" + Attribute + "='([^']*)'|([^'])'.*>");
	else if (str.indexOf(Attribute + '="')>-1) 
        var Attr = new RegExp(".*" + Attribute + '="([^"]*)"|([^"]*)".*>');
    a = str.match(Attr, "$1");
    return a[1]; 
}
function Array_Remove(c) {
	var tmparr = new Array();
	for (var i=0; i<this.length; i++) if (i!=c) tmparr[tmparr.length] = this[i];
	return tmparr;
}
function Array_Add(c, cont) {
	var tmparr = new Array();
	for (var i=0; i<this.length; i++) {
		if (i==c) tmparr[tmparr.length] = cont;
		tmparr[tmparr.length] = this[i];
	}
	if (!tmparr[c]) tmparr[c] = cont;
	return tmparr;
}
function RepeatChar(sChar,iNum) {
	var L = "";
	for (var i=0; i<iNum; i++) L += sChar;
	return L;
}]]>
        </JS_Script>
        <JS_Script name="get_sub_dirs">
          
          <![CDATA[/*
Get first level subdirs of a directory
Returns an array with the subdirs or null upon unsuccess
*/
function subdirs (
dir
)
{
    print ("Searching for subdirs in \""+dir +"\"...");
    if (!existsDir (dir))
    {
    print ("ERROR: \""+dir +"\" doesn't exist");
    return (null);
    }
    var list = listDir (dir)
    for (i in list)
    {
        print (list[i]);
    }
    return (list);
}]]>
        </JS_Script>
        <JS_Script name="get_file_list">
          
          <![CDATA[/* lists the files (only files, no directories) in a directory
with a certain mask
returns an array with the files.
If no file is found it will return an empty array 
*/
function getfilelist (
getflielist_dir,        //directory 
getflielist_mask        // mask e.g. "*.*"
)
{
  var list = new Array();
  if (!existsDir(getflielist_dir))  // check that the directory exists
  {
	return (list)
  }
  var file = getFirstFile(getflielist_dir, getflielist_mask);
  if (file != null)
  {
    list.push (file);
  }
  while (file != null)
  {
     var nextfile = getNextFile();
     if (nextfile == null)
     {
       break;
     }
     list.push (nextfile);
     nextfile = undefined;
    }
  return (list);
}]]>
        </JS_Script>
        <JS_Script name="add_DC_from_file">
          
          <![CDATA[/* add Dublin Core metadata to the object obj
taking it from an XML file as produced by the save DC
in the Axmedis Editor.
If DC is already present, it will be added after that.
the updated object is returned
false is returned in case of error.
CAUTION: no check for duplicates is made!!
*/
function addDC(obj, DC_file)
{
    // check if the file exists otherwise print an error and return false
    if (!existsFile (DC_file)) {
        print ("add_DC ERROR: "+ DC_file + " doesn't exist");
        return (false)
    }
    strXML = readFromFile (DC_file)
    var xmlDoc = new REXML(strXML);
    
    // these are the 15 possible DC elements
    var DC_elements = new Array ("title",
                                "creator",
                                "subject",
                                "description",
                                "publisher",
                                "contributor",
                                "date",
                                "type",
                                "format",
                                "identifier",
                                "source",
                                "language",
                                "relation",
                                "coverage",
                                "rights");                                
    // check that the XML file contains at least the <Description> element
    if ((xmlDoc.rootElement.name) != "Description") {    
        print ("add_DC ERROR: The file " + DC_file + " doesen't seem a valid DC XML file - Could not find \"Description\" root element");
        return (false);
    }
    //var axObj = new AxmedisObject(obj);
    var dc = obj.getDublinCore ();
    for (var xmlIterator=new JSXMLIterator(xmlDoc.rootElement); xmlIterator.getNextNode();) {
        for (j = 0; j < DC_elements.length; j++) {
            // just in case: check that the element is a valid DC one and that it is not empty            
            if ((xmlIterator.xmleElem.name == DC_elements[j]) && (xmlIterator.xmleElem.text.length >0)) {
                dc.addDCElement (xmlIterator.xmleElem.name, xmlIterator.xmleElem.text, xmlIterator.xmleElem.attribute ("lang"));
                //print ("Adding DC element *" + xmlIterator.xmleElem.name +"*\twith value: \"" + xmlIterator.xmleElem.text+ "\" and lang attribute: \""+xmlIterator.xmleElem.attribute ("lang")+"\"");
            }
        }    
    }
    return (obj);
}]]>
        </JS_Script>
        <JS_Script name="_main">
          
          <![CDATA[/* testing function: take a subdirectory and add its files to a new object
The object name will be the same as the subdir.
an index.htm match will be searched
a "style.css" will be added to every object taking it from a directory called "css" above the source dir
Dublin Core will also be added (including DCTitle extracted from the index.htm)
*/
function test ()
{
// get an array of the subdirs of startdir
// startdir is a parameter in the Arguments. Change it to change the strting dir
var directory = subdirs (startdir); 
// DC_xml is a file containin DCore as saved from the AX Editor
var DC_xml = "c:\\DC-ANSC-instruments.xml";
if (directory == null)
{
    print ("ERROR: no subdirs in "+startdir); 
    return (false);
}
for (m in directory)
{
var success = Dir2Obj 
(
    directory[m],        // input dir (e.g. "c:\\dir") Use "\\" as path separator! ITS in the arguments!!!
    "",                  // for adding from an object. Complete with path and extension. Use "" for new
    "*.*", 		         // files to add (e.g. "*.*")
    "index.htm",	    // a file (including extension) that if found  will be put at the start of the object. Use "" for none.
    DC_xml, //specify the DC XML file to use to add DC. "" for no Dublin Core
    true,      // if true will add DC title trying to extract it from the <title> of indexfile
    true,               // add extensions to contentID
    "c:\\axtest\\css",         // dir containing the css file. "" to skip
    "",                 // css filename leave "" for default : "style.css"
    "c:\\instruments", // where the object will be saved. (use "\\" as path separator)
    filefrompath(directory[m])+".axm" // filename of the object to output INCLUDING extension eg. "out_obj.axm"
    ) 
}
return (success);
}
test();]]>
        </JS_Script>
      </Rule_Body>
      <Dependencies/>
    </AXCP_Rule>
  </Definition>
</Rule>

