/*
 * XML Parser version 1.0f - 
 * written by Wesley Rast,
 * GE Power Systems, Inc.
 */

var xmlString = "";

var xmlStringPosition;
var tagStack = new Array();

var thisTag = new Function("aStack", "return aStack.length-1");
var nextAvailableSubResource = new Function("return tagStack[thisTag(tagStack)].subResources.length");
var nextAvailableNode = new Function("return tagStack[thisTag(tagStack)].nodeValues.length");
var nextOpenBracket = new Function("aString1", "return aString1.indexOf('<')");
var nextCloseBracket = new Function("aString2", "return aString2.indexOf('>')");
var root;

function readXML(xmlString)
{
    tagStack.length = 0;
    xmlString = removeNewLines(xmlString);
    root = new xmlElement("root", "", "", "", this);
    tagStack[0] = root;
    while (tagStack.length != 0)
    {
        if (nextOpenBracket(xmlString) == -1)
        {
            return root;
        }
        if (nextOpenBracket(xmlString) > 0)
        {
            tagStack[thisTag(tagStack)].nodeValues[nextAvailableNode()] = xmlString.substring(0, nextOpenBracket(xmlString));
            xmlString = xmlString.slice(nextOpenBracket(xmlString));
        }
        else if (nextOpenBracket == 0)
        {
            tagStack[thisTag(tagStack)].nodeValues[nextAvailableNode()] = "";
        }
        var decisionString = xmlString.substring(nextOpenBracket(xmlString), nextCloseBracket(xmlString) + 1);
        xmlString = xmlString.slice(nextCloseBracket(xmlString) + 1);
        if (decisionString.indexOf("</") != -1)
        {
            var tempArray1 = tagStack[thisTag(tagStack)].xmlText.split(/<|>/);
            var tempJoined1 = tempArray1.join("");
            if (tempJoined1.charAt(tempJoined1.length - 1) == " ") tempJoined1 = tempJoined1.slice(-1);
            var propertyRegExp = /\S+=.[^"]+./g;
            var tempArray2 = tempJoined1.match(propertyRegExp);
            var tempArray3 = tempJoined1.split(" ");
            tagStack[thisTag(tagStack)].tagName = tempArray3[0];
            tagStack[thisTag(tagStack)].tagEndValue = tagStack[thisTag(tagStack)].tagEndValue + "</" + tempArray3[0] + ">";
            if (tempArray2 != null)
            {
                var propArray = new Array();
                var propString = "";
                var propFinalArray = new Array();
                for (propCount = 0; propCount < tempArray2.length; propCount++)
                {
                    propArray = tempArray2[propCount].split("\"");
                    propString = propArray.join("");
                    propFinalArray = propString.split("=");
                    var szPropName = propFinalArray[0];
                    var szPropValue;
                    if (propFinalArray.length > 2)
                    {
                        szPropValue = propFinalArray.slice(1);
                        szPropValue = szPropValue.join("=");
                    }
                    else
                    {
                        szPropValue = propFinalArray[1];
                    }
                    tagStack[thisTag(tagStack)].props[tagStack[thisTag(tagStack)].props.length] = new property(szPropName, szPropValue);
                    propArray.length = 0;
                    propFinalArray.length = 0;
                }
            }//end if tempArray2.length
            tagStack.length = tagStack.length - 1;
        }
        else if ((decisionString.indexOf("</") == -1) && (decisionString.indexOf("/>") == -1))
        {
            tagStack[tagStack.length] = tagStack[thisTag(tagStack)].subResources[nextAvailableSubResource()] = new xmlElement("", "", decisionString, "", tagStack[thisTag(tagStack)]);
            tagStack[thisTag(tagStack)].nodeValues[nextAvailableNode()] = "";
        }//end else
        else
        {//must be self-closing tag
            tagStack[tagStack.length] = tagStack[thisTag(tagStack)].subResources[nextAvailableSubResource()] = new xmlElement("", "", decisionString, "", tagStack[thisTag(tagStack)]);
            tagStack[thisTag(tagStack)].nodeValues[nextAvailableNode()] = "";
            var tArray = tagStack[thisTag(tagStack)].xmlText.split(/\/+/);
            var tJoin = tArray.join("");
            var tArray1 = tJoin.split(/<|>/);
            var tJoined1 = tArray1.join("");
            if (tJoined1.charAt(tJoined1.length - 1) == " ") tJoined1 = tJoined1.slice(0, tJoined1.length - 1);
            var propRegExp = /\S+=.[^"]+./g;
            var tArray2 = tJoined1.match(propRegExp);
            var tArray3 = tJoined1.split(" ");
            tagStack[thisTag(tagStack)].tagName = tArray3[0];
            tagStack[thisTag(tagStack)].tagEndValue = tagStack[thisTag(tagStack)].tagEndValue + "";
            if (tArray2 != null)
            {
                var pArray = new Array();
                var pString = "";
                var pFinalArray = new Array();
                for (pCount = 0; pCount < tArray2.length; pCount++)
                {
                    pArray = tArray2[pCount].split("\"");
                    pString = pArray.join("");
                    pFinalArray = pString.split("=");
                    var szPropName = pFinalArray[0];
                    var szPropValue;
                    if (propFinalArray.length > 2)
                    {
                        szPropValue = pFinalArray.slice(1);
                        szPropValue = szPropValue.join("=");
                    }
                    else
                    {
                        szPropValue = pFinalArray[1];
                    }
                    tagStack[thisTag(tagStack)].props[tagStack[thisTag(tagStack)].props.length] = new property(szPropName, szPropValue);
                    pArray.length = 0;
                    pFinalArray.length = 0;
                }
            }
            tagStack.length = tagStack.length - 1;
        }
    }
    //end while tagStack.length
}
//end function readXML()

function removeNewLines(stringVar)
{
    var foo = stringVar.split(/\n+|\r+/);
    return foo.join("");
}

function buildTBV()
{
    var buildString = "";
    if (this.tagName != "root")
    {
        buildString = "<" + this.tagName;
        if (this.props.length != 0)
        {
            for (build = 0; build < this.props.length; build++)
            {
                buildString += " " + this.props[build].propName + "=\"" + this.props[build].propValue + "\"";
            }
        }
        (this.tagEndValue == "")?buildString += "/>":buildString += ">";
    }
    return buildString;
}

function xmlElement(tName, tContent, xml1, xml2, tagParent)
{
    this.tagName = tName;
    this.tagBeginValue = xml1;
    this.tagEndValue = xml2;
    this.thisParent = tagParent;
    this.props = new Array();
    this.subResources = new Array();
    this.isOpen = false;
    this.xmlText = xml1;
    this.nodeValues = new Array();

    //	this.structObj=_structObj;
    this.buildTagBeginValue = buildTBV;
    this.getArrayPosition = _getArrayPosition;
    this.getPropValue = _getPropValue;
}
//end constructor xmlElement()

function _getArrayPosition()
{
    for (b = 0; b < this.thisParent.subResources.length; b++)
    {
        if (this.thisParent.subResources[b] == this) return b;
    }
}
//end method _getArrayPosition()

function _getPropValue(propName1)
{
    for (i = 0; i < this.props.length; i++)
    {
        if (this.props[i].propName == propName1) return this.props[i].propValue;
    }
    return null;
}
//end method _getPropValue()

function property(pName, pValue)
{
    this.propName = pName;
    this.propValue = pValue;
}
//end constructor property()

//begin destructure code----------------------------------------------------------------------------------------------------------------------------------------------------------------------*

var XMLString = "";
var stackPointer = new Array();
var isBottomLevel = false;
var isDescending = false;

function parseIt(XMLObject)
{
    stackPointer.length = 0;
    stackPointer[0] = XMLObject;
    while (stackPointer.length != 0)
    {
        currentObject = (isDescending)?currentObject.subResources[0]:stackPointer[stackPointer.length - 1];
        if (currentObject.subResources.length != 0)
        {
            if (currentObject.isOpen == false)
            {
                XMLString += currentObject.buildTagBeginValue();
                addNodeText(currentObject);
                for (s = currentObject.subResources.length - 1; s >= 0; s--)
                {
                    stackPointer[stackPointer.length] = currentObject.subResources[s];
                }
                currentObject.isOpen = true;
                isDescending = true;
            }//end if isOpen
            else
            {
                addNodeText(currentObject);
                XMLString += currentObject.tagEndValue;

                if (currentObject.thisParent.nodeValues) addNodeText(currentObject.thisParent);
                currentObject.isOpen = false;
                stackPointer.length--;
                isDescending = false;
            }
        }
        else
        {
            XMLString += currentObject.buildTagBeginValue();
            addNodeText(currentObject);
            addNodeText(currentObject);
            XMLString += currentObject.tagEndValue;

            if (currentObject.thisParent.nodeValues) addNodeText(currentObject.thisParent);
            currentObject.isOpen = false;
            stackPointer.length--;
            isDescending = false;
        }
        //end else
    }
    //end while
    return XMLString;
}
//end function parseIt


function addNodeText(currObject)
{
    if (currObject.nodeValues.length > 0)
    {
        currObject.nodeValues.reverse();
        var temp1 = currObject.nodeValues[currObject.nodeValues.length - 1];
        XMLString += temp1;
        currObject.nodeValues.length--;
        currObject.nodeValues.reverse();
    }
}

// begin tools section---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*

//flagged for production version removal
var debugStack = new Array();
var debugObjArrayString = "";
function debugObjArrays(objectToRecurse)
{
    debugObjArrayString = "";
    isDescendingTree = false;
    debugStack.length = 0;
    debugStack[0] = objectToRecurse;
    while (debugStack.length != 0)
    {
        currentObject = (isDescendingTree)?currentObject.subResources[0]:debugStack[debugStack.length - 1];
        if (currentObject.subResources.length != 0)
        {
            if (!currentObject.isOpen)
            {
                //insert commands to run below this comment
                var count = 0;
                var valueString = "";
                for (sibObj in currentObject)
                {
                    debugObjArrayString += "Object number " + count + " in " + currentObject + " is: " + sibObj + " --- and its value is: " + currentObject[sibObj] + "\n";
                    count++;
                }
                debugObjArrayString += "\n";
                //insert commands to run above this comment
                currentObject.isOpen = true;
                for (s = currentObject.subResources.length - 1; s >= 0; s--)
                {
                    debugStack[debugStack.length] = currentObject.subResources[s];
                }
                isDescendingTree = true;
            }
            else
            {
                currentObject.isOpen = false;
                debugStack.length--;
            }
        }
        else
        {
            //insert commands to run below this comment
            var count = 0;
            var valueString = "";
            for (sibObj in currentObject)
            {
                debugObjArrayString += "Object number " + count + " in " + currentObject + " is: " + sibObj + " --- and its value is: " + currentObject[sibObj] + "\n";
                count++;
            }
            //insert commands to run above this comment
            currentObject.isOpen = false;
            debugStack.length--;
            isDescendingTree = false;
        }
        //end else
    }
    //end while
    //now alert the debug string
    var splitted = debugObjArrayString.split("\n");
    var temporaryString = "";
    for (x = 1; x < splitted.length; x++)
    {
        temporaryString += splitted[x - 1] + "\n";
        if (x % 51 == 0)
        {
            alert(temporaryString);
            temporaryString = "";
        }
    }
    alert(temporaryString);
}
//end function debugObjArrays()

var searchStack = new Array();
function getObjectsByObjValue(objectToSearch, propToTest, valueToFind)
{
    isDescendingTree = false;
    searchStack.length = 0;
    searchStack[0] = objectToSearch;
    var findHits = new Array();
    while (searchStack.length != 0)
    {
        currentObject = (isDescendingTree)?currentObject.subResources[0]:searchStack[searchStack.length - 1];
        if (currentObject.subResources.length != 0)
        {
            if (!currentObject.isOpen)
            {
                if (currentObject[propToTest] == valueToFind) findHits[findHits.length] = currentObject;
                currentObject.isOpen = true;
                for (s = currentObject.subResources.length - 1; s >= 0; s--)
                {
                    searchStack[searchStack.length] = currentObject.subResources[s];
                }
                isDescendingTree = true;
            }
            else
            {
                currentObject.isOpen = false;
                searchStack.length--;
            }
        }
        else
        {
            if (currentObject[propToTest] == valueToFind) findHits[findHits.length] = currentObject;
            currentObject.isOpen = false;
            searchStack.length--;
            isDescendingTree = false;
        }
        //end else
    }
    //end while
    return findHits;
}
//end function getObjectsByObjValue()

function HitObject(toObj, toPElem)
{
    this.toObject = toObj;
    this.toPropsElement = toPElem;
}
//end constructor HitObject()

var propSearchStack = new Array();
function getObjectsByPropValue(objectToSearch, propToTest, valueToFind)
{
    isDescendingTree = false;
    propSearchStack.length = 0;
    propSearchStack[0] = objectToSearch;
    var findHits = {
        hitsPropName:new Array(),
        hitsPropValue:new Array(),
        hitsBoth:new Array()
    };
    while (propSearchStack.length != 0)
    {
        currentObject = (isDescendingTree)?currentObject.subResources[0]:propSearchStack[propSearchStack.length - 1];
        if (currentObject.subResources.length != 0)
        {
            if (!currentObject.isOpen)
            {
                for (c = 0; c < currentObject.props.length; c++)
                {
                    if (currentObject.props[c].propName == propToTest) findHits.hitsPropName[findHits.hitsPropName.length] = new HitObject(currentObject, currentObject.props[c]);
                    if (currentObject.props[c].propValue == valueToFind) findHits.hitsPropValue[findHits.hitsPropValue.length] = new HitObject(currentObject, currentObject.props[c]);
                    if ((currentObject.props[c].propName == propToTest) && (currentObject.props[c].propValue == valueToFind)) findHits.hitsBoth[findHits.hitsBoth.length] = new HitObject(currentObject, currentObject.props[c]);
                }
                currentObject.isOpen = true;
                for (s = currentObject.subResources.length - 1; s >= 0; s--)
                {
                    propSearchStack[propSearchStack.length] = currentObject.subResources[s];
                }
                isDescendingTree = true;
            }
            else
            {
                currentObject.isOpen = false;
                propSearchStack.length--;
            }
        }
        else
        {
            for (d = 0; d < currentObject.props.length; d++)
            {
                if (currentObject.props[d].propName == propToTest) findHits.hitsPropName[findHits.hitsPropName.length] = new HitObject(currentObject, currentObject.props[d]);
                if (currentObject.props[d].propValue == valueToFind) findHits.hitsPropValue[findHits.hitsPropValue.length] = new HitObject(currentObject, currentObject.props[d]);
                if ((currentObject.props[d].propName == propToTest) && (currentObject.props[d].propValue == valueToFind)) findHits.hitsBoth[findHits.hitsBoth.length] = new HitObject(currentObject, currentObject.props[d]);
            }
            currentObject.isOpen = false;
            propSearchStack.length--;
            isDescendingTree = false;
        }
        //end else
    }
    //end while
    return findHits;
}
//end function getObjectsByObjValue()

var recurseStack = new Array();
function recurseObjArray(objectToRecurse, stringToRun)
{
    recurseStack.length = 0;
    var returnValue = new Object();
    isDescendingTree = false;
    recurseStack[0] = objectToRecurse;
    while (recurseStack.length != 0)
    {
        currentObject = (isDescendingTree)?currentObject.subResources[0]:recurseStack[recurseStack.length - 1];
        if (currentObject.subResources.length != 0)
        {
            if (!currentObject.isOpen)
            {
                eval(stringToRun);

                currentObject.isOpen = true;
                for (s = currentObject.subResources.length - 1; s >= 0; s--)
                {
                    recurseStack[recurseStack.length] = currentObject.subResources[s];
                }
                isDescendingTree = true;
            }
            else
            {
                currentObject.isOpen = false;
                recurseStack.length--;
            }
        }
        else
        {

            eval(stringToRun);

            currentObject.isOpen = false;
            recurseStack.length--;
            isDescendingTree = false;
        }
        //end else
    }
    //end while
    return returnValue;
}
//end function recurseObjArray()


//flagged for production version removal
function checkResults(propVal, valueVal)
{
    var arrayResult = new Array();
    arrayResult = getObjectsByObjValue(blah, propVal, valueVal);
    var alertString = "";
    for (y = 0; y < arrayResult.length; y++)
    {
        alertString += "the value of match " + (y + 1) + " is: " + arrayResult[0] + "\n";
    }
    alert("Search Complete. the number of matches to your search is: " + arrayResult.length + "\n" + alertString);
}
//end function checkResults

//flagged for production version removal
var resultObject;
function checkPropResults(searchThisObject, findThisProp, findThisValue)
{
    resultObject = getObjectsByPropValue(searchThisObject, findThisProp, findThisValue);
    var resultString = "";
    resultString += "Name Hits are:\n";
    for (x = 0; x < resultObject.hitsPropName.length; x++)
    {
        resultString += "Hit no.:" + x + " = " + resultObject.hitsPropName[x].toPropsElement.propName + "\n";
    }
    resultString += "Value Hits are:\n";
    for (y = 0; y < resultObject.hitsPropValue.length; y++)
    {
        resultString += "Hit no.:" + y + " = " + resultObject.hitsPropValue[y].toPropsElement.propValue + "\n";
    }
    alert(resultString);
}