/*
 * Copyright 2002-2006 Jahia Ltd
 *
 * Licensed under the JAHIA COMMON DEVELOPMENT AND DISTRIBUTION LICENSE (JCDDL),
 * Version 1.0 (the "License"), or (at your option) any later version; you may
 * not use this file except in compliance with the License. You should have
 * received a copy of the License along with this program; if not, you may obtain
 * a copy of the License at
 *
 *  http://www.jahia.org/license/
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
/**
 * Creates a ComplexTreeDisplay instance. A Complex Tree is a DwtComposite nesting a DwtTree, a DwtSash and a DwtListView.
 *
 * @param headers       An Array of Arrays for the ListView column headers
 * @param treeData      An Array of Arrays for the initial tree data
 * @param style         The Style used (see ComplexTreeProperties)
 * @param title         The title for the tree
 * @param loadingText   The text to display when while wiating for the Ajax call to return
 * @param parentDiv     The HTML id of the HTML div element where to display the ComplexTreeDisplay.
 */
function ComplexTree(headers, entryPointKey, style, title, loadingText, parentDiv, entryPointURL,
                     expandServerUrl, collapseServerUrl, expandServerUrlLoaded, goToNode) {
    this.DATA_HEIGHT = ComplexTreeProperties.ROW_HEIGHT;
    this._loadingText = loadingText;
    this._treeItems = new AjxVector();
    this._parentDiv = parentDiv;
    this._goToNode = goToNode;
    var diveElem = document.getElementById(parentDiv);
    if (! diveElem) {
        alert("HTML element with id '" + parentDiv + "' does not exist ! Aborting !");
        return;
    }
    try {
        switch (style) {
            case ComplexTreeProperties.WORKFLOW_STYLE:
                this._props = new ComplexTreeProperties(ComplexTreeProperties.WORKFLOW_STYLE,
                        ComplexTreeProperties.WORKFLOW_TREE_STYLE_PATTERN,
                        ComplexTreeProperties.WORKFLOW_LIST_STYLE_PATTERN,
                        ComplexTreeProperties.OBJECT,
                        entryPointURL, expandServerUrl, collapseServerUrl, expandServerUrlLoaded,
                        parentDiv);
                if (AjxEnv.isIE) ComplexTreeProperties.ROW_HEIGHT = 29;
                break;

            case ComplexTreeProperties.SELECT_PAGE_STYLE:
                this._props = new ComplexTreeProperties(ComplexTreeProperties.SELECT_PAGE_STYLE,
                        ComplexTreeProperties.SELECT_TREE_STYLE_PATTERN,
                        ComplexTreeProperties.SELECT_LIST_STYLE_PATTERN,
                        ComplexTreeProperties.PAGE,
                        entryPointURL, expandServerUrl, collapseServerUrl, expandServerUrlLoaded,
                        parentDiv);
                break;

            case ComplexTreeProperties.SITEMAP_STYLE:
                this._props = new ComplexTreeProperties(ComplexTreeProperties.SITEMAP_STYLE,
                        ComplexTreeProperties.SITEMAP_TREE_STYLE_PATTERN,
                        ComplexTreeProperties.SITEMAP_LIST_STYLE_PATTERN,
                        ComplexTreeProperties.PAGE,
                        entryPointURL, expandServerUrl, collapseServerUrl, expandServerUrlLoaded,
                        parentDiv);
                if (AjxEnv.isIE) ComplexTreeProperties.ROW_HEIGHT = 29;
                break;

            case ComplexTreeProperties.VERSIONNING_STYLE:
                this._props = new ComplexTreeProperties(ComplexTreeProperties.VERSIONNING_STYLE,
                        ComplexTreeProperties.VERSIONNING_TREE_STYLE_PATTERN,
                        ComplexTreeProperties.VERSIONNING_LIST_STYLE_PATTERN,
                        ComplexTreeProperties.PAGE,
                        entryPointURL, expandServerUrl, collapseServerUrl, expandServerUrlLoaded,
                        parentDiv);
                break;

            case ComplexTreeProperties.SIMPLE_STYLE:
                this._props = new ComplexTreeProperties(ComplexTreeProperties.SIMPLE_STYLE,
                        ComplexTreeProperties.SIMPLE_TREE_STYLE_PATTERN,
                        ComplexTreeProperties.SIMPLE_LIST_STYLE_PATTERN,
                        ComplexTreeProperties.PAGE,
                        entryPointURL, expandServerUrl, collapseServerUrl, expandServerUrlLoaded,
                        parentDiv);
                break;

            case ComplexTreeProperties.FCK_STYLE:
                this._props = new ComplexTreeProperties(ComplexTreeProperties.FCK_STYLE,
                        ComplexTreeProperties.FCK_TREE_STYLE_PATTERN,
                        ComplexTreeProperties.FCK_LIST_STYLE_PATTERN,
                        ComplexTreeProperties.PAGE,
                        entryPointURL, expandServerUrl, collapseServerUrl, expandServerUrlLoaded,
                        parentDiv);
                break;

            case ComplexTreeProperties.WEBDAV_STYLE:
                this._props = new ComplexTreeProperties(ComplexTreeProperties.WEBDAV_STYLE,
                        ComplexTreeProperties.WEBDAV_TREE_STYLE_PATTERN,
                        ComplexTreeProperties.WEBDAV_LIST_STYLE_PATTERN,
                        ComplexTreeProperties.OBJECT,
                        entryPointURL, expandServerUrl, collapseServerUrl, expandServerUrlLoaded,
                        parentDiv);
                break;

            case ComplexTreeProperties.WEBDAV_SELECT_FOLDER_STYLE:
                this._props = new ComplexTreeProperties(ComplexTreeProperties.WEBDAV_SELECT_FOLDER_STYLE,
                        ComplexTreeProperties.WEBDAV_SELECT_FOLDER_STYLE_PATTERN,
                        ComplexTreeProperties.WEBDAV_LIST_STYLE_PATTERN,
                        ComplexTreeProperties.OBJECT,
                        entryPointURL, expandServerUrl, collapseServerUrl, expandServerUrlLoaded,
                        parentDiv);
                break;

            case ComplexTreeProperties.FILEMANAGER_STYLE:
                var listStyle;
                if (entryPointURL.indexOf("listView") > -1) {
                    listStyle = ComplexTreeProperties.FILEMANAGER_LIST_STYLE_PATTERN;
                } else if (entryPointURL.indexOf("iconsView") > -1) {
                    listStyle = ComplexTreeProperties.FILEMANAGER_ICONS_STYLE_PATTERN;
                } else if (entryPointURL.indexOf("thumbnailView") > -1) {
                    listStyle = ComplexTreeProperties.FILEMANAGER_TB_STYLE_PATTERN;
                } else {
                    listStyle = [];
                }
                this._props = new ComplexTreeProperties(ComplexTreeProperties.FILEMANAGER_STYLE,
                        ComplexTreeProperties.FILEMANAGER_TREE_STYLE_PATTERN,
                        listStyle,
                        ComplexTreeProperties.OBJECT,
                        entryPointURL, expandServerUrl, collapseServerUrl, expandServerUrlLoaded,
                        parentDiv);
                ComplexTreeProperties.TREE_WIDTH = 200;
                ComplexTreeProperties.LOAD_FOLDER = true;
                window.currentValue = "";
                window["treeItems"] = "";
                delete listStyle;
                break;

            case ComplexTreeProperties.ADMIN_CATEGORY_STYLE:
                this._props = new ComplexTreeProperties(ComplexTreeProperties.ADMIN_CATEGORY_STYLE,
                        ComplexTreeProperties.CATEGORY_ADMIN_TREE_STYLE_PATTERN,
                        [],
                        ComplexTreeProperties.CATEGORY,
                        entryPointURL, expandServerUrl, collapseServerUrl, expandServerUrlLoaded,
                        parentDiv);
                if (AjxEnv.isIE) ComplexTreeProperties.ROW_HEIGHT = 29;
                break;

            case ComplexTreeProperties.SELECT_CATEGORY_STYLE:
                this._props = new ComplexTreeProperties(ComplexTreeProperties.SELECT_CATEGORY_STYLE,
                        ComplexTreeProperties.CATEGORY_SELECT_TREE_STYLE_PATTERN,
                        [],
                        ComplexTreeProperties.CATEGORY,
                        entryPointURL, expandServerUrl, collapseServerUrl, expandServerUrlLoaded,
                        parentDiv);
                    if (AjxEnv.isIE && (AjxEnv.browserVersion > 6.9)) ComplexTreeProperties.ROW_HEIGHT = 29;
                break;

            case ComplexTreeProperties.MOVE_CATEGORY_STYLE:
                this._props = new ComplexTreeProperties(ComplexTreeProperties.MOVE_CATEGORY_STYLE,
                        ComplexTreeProperties.CATEGORY_MOVE_TREE_STYLE_PATTERN,
                        [],
                        ComplexTreeProperties.CATEGORY,
                        entryPointURL, expandServerUrl, collapseServerUrl, expandServerUrlLoaded,
                        parentDiv);
                if (AjxEnv.isIE) ComplexTreeProperties.ROW_HEIGHT = 29;
                break;

            case ComplexTreeProperties.PORTLET_CATEGORY_STYLE:
                this._props = new ComplexTreeProperties(ComplexTreeProperties.PORTLET_CATEGORY_STYLE,
                        ComplexTreeProperties.CATEGORY_PORTLET_TREE_STYLE_PATTERN,
                        [],
                        ComplexTreeProperties.CATEGORY,
                        entryPointURL, expandServerUrl, collapseServerUrl, expandServerUrlLoaded,
                        parentDiv);
                break;
        }

        // Create the application shell and hide it
        var theShell = DwtShell.getShell(window);
        if (theShell) {
            this._app = theShell;
        } else {
            this._app = new DwtShell("MainShell");
            this._app.setSize(0, 0);
        }
        delete theShell;

        // This Composite is the root composite of all the content. We need this extra composite in order
        // to make the scrollbars display correctly by setting the width of this object a bit bigger than
        // the actual size we want. The extra pixels are used for the scrollbar width.
        this._container = new DwtComposite(this._app, "RootDivContainer", DwtControl.RELATIVE_STYLE);

        // Shell is the root composite of all the objects used. Its width should be about 20 pixels
        // smaller than the parent composite so the parent has enough space for the scrollbars.
        this._shell = new DwtComposite(this._container, "MainDivContainer", DwtControl.RELATIVE_STYLE);
        //this._container.setScrollStyle(DwtControl.SCROLL);

        // The Tree instance for the ComplexTreeDisplay
        if (style == ComplexTreeProperties.FILEMANAGER_STYLE) {
            this._treeContainer = new DwtComposite(this._shell, null, DwtControl.RELATIVE_STYLE);
            this._treeContainer.setSize(ComplexTreeProperties.TREE_WIDTH, this.DATA_HEIGHT + ComplexTreeProperties.ROW_HEIGHT);
            this._treeContainer.setScrollStyle(DwtControl.SCROLL);
            this._tree = new DwtTree(this._treeContainer, DwtTree.SINGLE_STYLE, null, DwtControl.RELATIVE_STYLE);
        } else {
            this._tree = new DwtTree(this._shell, DwtTree.SINGLE_STYLE, null, DwtControl.RELATIVE_STYLE);
        }

        this._createRoot(title, entryPointKey);
        this._theTreeListener = new AjxListener(this, this._treeListener);
        this._tree.addTreeListener(this._theTreeListener);
        if (style == ComplexTreeProperties.FILEMANAGER_STYLE) {
            this._theSelectionListener = new AjxListener(this, this._treeSelectionListener);
            this._tree.addSelectionListener(this._theSelectionListener);
        }

        // The ListView instance for the ComplexTreeDisplay if one is defined for the current style
        if (this._props.CURRENT_LIST_PATTERN.length > 0) {
            this._itemLength = ComplexTreeProperties.getPatternItemLength(this._props.CURRENT_LIST_PATTERN);
            this._items = new AjxVector();
            this._pageInfoView = new PageInfoListView(this._shell, headers, this._props.CURRENT_LIST_PATTERN,
                    this._props);
            this._pageInfoView.set(this._items);
            this._pageInfoView.zShow(true);
            this._pageInfoView.setScrollStyle(DwtControl.SCROLL);

            // The Sash instance for the ComplexTreeDisplay
            this._sash = new DwtSash(this._shell, DwtSash.HORIZONTAL_STYLE, "AppSash-horiz", 2);
            this._sash.registerCallback(this._sashCallback, this);

            this._layout();
            this._layoutInfo = {treeW: ComplexTreeProperties.MIN_TREE_WIDTH, tableW: this._pageInfoView.getMinTableWidth()};
        }

        // Dump the HTML in the div of the HTML page if it exists. (tested at the beginning of the constructor)
        diveElem.appendChild(this._container.getHtmlElement());
        var neededHeight = this._container.getHtmlElement().scrollHeight;
        var height;
        if (neededHeight > ComplexTreeProperties.SHELL_HEIGHT) {
            diveElem.style.height = ComplexTreeProperties.SHELL_HEIGHT + "px";
            height = ComplexTreeProperties.SHELL_HEIGHT;
        } else {
            diveElem.style.height = neededHeight + "px";
            height = neededHeight;
            ComplexTreeProperties.SHELL_HEIGHT = height;
            if (this._plusButton) this._plusButton.setEnabled(false);
        }
        this._maxListener();
        //this._container.setSize(ComplexTreeProperties.SHELL_WIDTH + 20, height);
        // Bring the root composite to the upper layer
        this._container.zShow(true);
        this._tree.zShow(true);
        delete neededHeight;
        delete height;
    } catch (ex) {
        if (ex instanceof DwtException) {
            alert(ex.dump());
        } else {
            alert(ex);
        }
    }
}

ComplexTree.prototype.DATA_HEIGHT = 0;
ComplexTree.prototype.RETRIEVED_OBJECTS_EXPAND_ALL = 0;

ComplexTree.prototype.setUrlToUseOnclick =
function (urlToUseOnclick) {
    this._urlToUseOnclick = urlToUseOnclick;
}

/**
 * Clears all the resources used by the ComplexTree in order to avoid Memory Leak problems.
 */
ComplexTree.prototype.clear =
function () {
    this._tree.removeTreeListener(this._theTreeListener);
    this._theTreeListener = null;
    this._tree.removeSelectionListener(this._theSelectionListener);
    this._theSelectionListener = null;
    this._tree._children.removeAll();
    this._tree.dispose();
    this._tree = null;
    if (this._pageInfoView) {
        this._pageInfoView.clear();
        this._pageInfoView = null;
    }
    if (this._treeContainer) {
        this._treeContainer.dispose();
        this._treeContainer = null;
    }
    this._shell.dispose();
    this._shell = null;
    this._container.dispose();
    this._container = null;
    this.DATA_HEIGHT = null;
    this._loadingText = null;
    this._treeItems.removeAll();
    this._treeItems = null;
    this._parentDiv = null;
    this._goToNode = null;
    this._props = null;
    this._unlockChildrenCallback = null;
    this._getChildrenCallback = null;
    this._fileManagerCallback = null;
}

/**
 * Draws the UI.
 */
ComplexTree.prototype._layout =
function() {
    var x = 0, y = 0;
    var height = this._shell.getSize().y;

    // Sash
    if (this._sash) {
        //DBG.println(AjxDebug.DBG1, "sash: " + x + '/' + y + '/' + Dwt.DEFAULT + '/' + height);
        x = (this._sash.getBounds().x != ComplexTreeProperties.TREE_WIDTH ? this._sash.getBounds().x : ComplexTreeProperties.TREE_WIDTH);
        if (x == 0 || !x) x = ComplexTreeProperties.TREE_WIDTH;
        if (this._props.CURRENT_STYLE == ComplexTreeProperties.FILEMANAGER_STYLE) {
            this._sash.setBounds(x, y, Dwt.DEFAULT, this.DATA_HEIGHT + ComplexTreeProperties.ROW_HEIGHT);
            this._treeContainer.setSize(x, this.DATA_HEIGHT + ComplexTreeProperties.ROW_HEIGHT);
        } else {
            this._sash.setBounds(x, y, Dwt.DEFAULT, ComplexTreeProperties.SASH_HEIGHT + (AjxEnv.isIE ? 1 : 0));
        }
        x += this._sash.getSize().x;
    }

    // Page Info View
    if (this._pageInfoView) {
        var width = this._shell.getSize().x - x;
        //DBG.println(AjxDebug.DBG1, "ListView: " + x + '/' + y + '/' + width + '/' + height);
        this._pageInfoView.setBounds(x, y, width, this.DATA_HEIGHT + ComplexTreeProperties.ROW_HEIGHT);
        delete width;
    }
    delete x;
    delete y;
    delete height;
}

/**
 * Handles sash movement. An attempt to move the sash beyond the extent of the filter
 * panel or the tab view results in no movement at all.
 * @param delta An integer representing by how much the Sash was moved
 */
ComplexTree.prototype._sashCallback =
function(delta) {
    var viewBds = this._pageInfoView.getBounds();
    var filterSz;
    if (this._treeContainer) {
        filterSz = this._treeContainer.getSize();
    } else {
        filterSz = this._tree.getSize();
    }
    var sashSz = this._sash.getBounds();

    // make sure we aren't moving too far...
    // delta < 0 means moving to the left.
    if (delta > 0) {
        var move = sashSz.x - delta;
        if (move <= 0) {
            delta -= move;
        }
        delete move;
    } else if (delta < 0) {
        var move = filterSz.x + delta;
        if (move <= this._layoutInfo.treeW) {
            delta += this._layoutInfo.treeW - move;
        }
        delete move;
    }
    var info = {filterW: filterSz.x + delta, viewX: viewBds.x + delta, viewW: viewBds.width - delta};
    this._adjustSash(info);
    delete info;
    delete viewBds;
    delete filterSz;
    delete sashSz;
    return delta;
}

/**
 * Sets the tree and listview bounds based on sash movement
 * @param info Contains the information about the new position of the Sash
 */
ComplexTree.prototype._adjustSash =
function(info) {
    this._pageInfoView.setBounds(info.viewX, Dwt.DEFAULT, info.viewW, this.DATA_HEIGHT + ComplexTreeProperties.ROW_HEIGHT);
    if (this._treeContainer) {
        this._treeContainer.setSize(info.filterW, this.DATA_HEIGHT + ComplexTreeProperties.ROW_HEIGHT);
    } else {
        this._tree.setSize(info.filterW, Dwt.DEFAULT);
    }
}

/**
 * Creates the root TreeItem of the DwtTree
 * @param headerTitle Title off the Tree. No title if null or "" is passed
 * @param entryPoint The key of the root item. Used in an AJAX call to retrieve the info of the root item
 */
ComplexTree.prototype._createRoot =
function(headerTitle, entryPoint) {
    var title;
    if ((! headerTitle || headerTitle.length == 0) && this._props.CURRENT_LIST_PATTERN.length == 0) {
        title = new DwtTreeItem(this._tree, null, headerTitle, null, null, "hideHeader");
    } else {
        title = new DwtTreeItem(this._tree, null, headerTitle, null, null, "treeHeader");
    }
    title._index = 0;
    title._level = 1;
    var loadingNode = new DwtTreeItem(title, null, this._loadingText);
    loadingNode._key = ComplexTreeProperties.LOADING_ID;
    title.expandChild = true;
    title.setExpanded(true);

    // Get the root DwtTreeItem
    var jahiaCommand = new AsynchCommand();
    GlobalCallback[GlobalCallbackCount] = new AjxCallback(this, this._getChildrenCallback, title);
    jahiaCommand.addInvokeListener(GlobalCallback[GlobalCallbackCount]);
    GlobalCallbackCount++;

    var xmlDoc = AjxXmlDoc.createRoot("GetEntryPoint");
    xmlDoc.set("key", (entryPoint));

    jahiaCommand.invoke(xmlDoc, this._props.ENTRY_POINT_URL);
    delete title;
    delete loadingNode;
    delete jahiaCommand;
    delete xmlDoc;
}

/**
 * Method to add a single Tree node to an existring one
 * @param parent        The Parent DwtTreeItem of the current item
 * @param nodeData      An Array of values representing the data
 * @param index         An Index (integer) of the tree node. The index is used to link a tree node to a listView item
 * @param objectInfo    A HashMap containing information about the object returned by the AJAX call
 */
ComplexTree.prototype._addTreeItem =
function (parent, nodeData, index, objectInfo) {
    var value = ComplexTreeProperties.getHtmls(this._props.CURRENT_TREE_PATTERN, nodeData, !objectInfo.disable);
    //DBG.println("TreeData: " + value);
    var val;
    if (objectInfo.style) {
        val = "<span class='" + objectInfo.style + "'>" + value + "</span>";
    } else {
        val = value;
    }

    var expandAll = true;
    if (this._props.CURRENT_STYLE == ComplexTreeProperties.WEBDAV_STYLE ||
        this._props.CURRENT_STYLE == ComplexTreeProperties.FILEMANAGER_STYLE) {
        expandAll = false;
    }
    var ti = new DwtTreeItem(parent, null, val, null, null, null, null, expandAll);

    ti._key = nodeData[0];
    ti._index = index + 1;
    ti._level = parent._level + 1;
    ti._url = objectInfo.url;
    if (this._props.CURRENT_STYLE == ComplexTreeProperties.FILEMANAGER_STYLE ||
        this._props.CURRENT_STYLE == ComplexTreeProperties.ADMIN_CATEGORY_STYLE) {
        if (window["treeItem" + ti._key] == null) {
            window["treeItems"] += "," + ti._key;
        }
        window["treeItem" + ti._key] = ti;
    }

    //DBG.println("KEY: " + ti._key + " - index: " + ti._index);
    this._treeItems.add(ti, index);
    if (! objectInfo.NoChildren) {
        var loadingNode = new DwtTreeItem(ti, null, this._loadingText);
        loadingNode._key = ComplexTreeProperties.LOADING_ID;
        if (parent.expandChild) {
            ti.setExpanded(true);
        } else if (this._goToNode && this._goToNode != "null" && this._goToNode.indexOf(ti._key) == 0) {
            if (this._props.CURRENT_STYLE == ComplexTreeProperties.FILEMANAGER_STYLE) {
                this.getFolderWithKey(this._goToNode, this._goToNode);
                this._goToNode = null;
            }
        }
        delete loadingNode;
    }
    delete val;
    delete value;
    delete ti;
}

/**
 * Adjust the TreeItem indexes for all TreeItems after the expanded node
 */
ComplexTree.prototype._adjustTreeItemIndexes =
function (index) {
    var treeItem;
    for (var i = index; i < this._treeItems.size(); i++) {
        treeItem = this._treeItems.get(i);
        treeItem._index = i + 1;
        //DBG.println("KEY: " + treeItem._key + " - index: " + treeItem._index);
    }
    delete treeItem;
    delete i;
}

/**
 * This is the listener for events on the tree nodes
 * @param ev The event received by the listener
 */
ComplexTree.prototype._treeListener =
function(ev) {
    this._shell.setCursor("wait");
    this._tree.setCursor("wait");
    if (this._pageInfoView) this._pageInfoView.setCursor("wait");
    var source = ev.item;
    if (source.DisableTreeListener) {
        source.DisableTreeListener = false;
        this._shell.setCursor("default");
        this._tree.setCursor("default");
        if (this._pageInfoView) this._pageInfoView.setCursor("default");
        return;
    }
    switch (ev.detail) {
        case DwtTree.ITEM_EXPANDED:
            if (source.getItems()[0]._key != ComplexTreeProperties.LOADING_ID) {
                if (this._props.CURRENT_STYLE != ComplexTreeProperties.FILEMANAGER_STYLE) this._displayChildren(source, true);
                // If a node has allready been loaded, use the EXPAND_SERVER_URL_LOADED value
                if (source._key && this._props.EXPAND_SERVER_URL_LOADED) {
                    var jahiaCommand = new AsynchCommand();
                    GlobalCallback[GlobalCallbackCount] = new AjxCallback(this, this._lockChildrenCallback, source);
                    jahiaCommand.addInvokeListener(GlobalCallback[GlobalCallbackCount]);
                    GlobalCallbackCount++;

                    var xmlDoc = AjxXmlDoc.createRoot("LockChildren");
                    var keys = this._keys.getArray();
                    for (var i = 0; i < keys.length; i++) {
                        xmlDoc.set("key", (keys[i]));
                    }

                    jahiaCommand.invoke(xmlDoc, this._props.EXPAND_SERVER_URL_LOADED);
                    delete jahiaCommand;
                    delete xmlDoc;
                    delete keys;
                }
                break;
            }

            // The node has not yet been loaded, use the EXPAND_SERVER_URL value
            if (source._key && this._props.EXPAND_SERVER_URL) {
                var jahiaCommand = new AsynchCommand();
                GlobalCallback[GlobalCallbackCount] = new AjxCallback(this, this._getChildrenCallback, source);
                jahiaCommand.addInvokeListener(GlobalCallback[GlobalCallbackCount]);
                GlobalCallbackCount++;

                var xmlDoc = AjxXmlDoc.createRoot("GetChildren");
                xmlDoc.set("key", (source._key));

                if (this._props.CURRENT_STYLE == ComplexTreeProperties.FILEMANAGER_STYLE &&
                    this._props.EXPAND_SERVER_URL.indexOf("display=") < 0)
                    jahiaCommand.invoke(xmlDoc, this._props.EXPAND_SERVER_URL + "&display=directories_Only");
                else
                    jahiaCommand.invoke(xmlDoc, this._props.EXPAND_SERVER_URL);
                delete jahiaCommand;
                delete xmlDoc;
                if (this._props.CURRENT_STYLE == ComplexTreeProperties.ADMIN_CATEGORY_STYLE) {
                    ComplexTreeProperties.RELOAD_ON_COLLAPSE = false;
                }
            }
            break;

        case DwtTree.ITEM_COLLAPSED:
            if (this._props.CURRENT_STYLE != ComplexTreeProperties.FILEMANAGER_STYLE) this._hideChildren(source);
            if (source._key && this._props.COLLAPSE_SERVER_URL) {
                var keys = this._keys.getArray();
                if (keys.length == 0) break;
                var jahiaCommand = new AsynchCommand();
                GlobalCallback[GlobalCallbackCount] = new AjxCallback(this, this._unlockChildrenCallback, source);
                jahiaCommand.addInvokeListener(GlobalCallback[GlobalCallbackCount]);
                GlobalCallbackCount++;

                var xmlDoc = AjxXmlDoc.createRoot("UnlockChildren");
                for (var i = 0; i < keys.length; i++) {
                    xmlDoc.set("key", (keys[i]));
                }
                jahiaCommand.invoke(xmlDoc, this._props.COLLAPSE_SERVER_URL);
                delete jahiaCommand;
                delete xmlDoc;
                delete keys;
            }
            if (ComplexTreeProperties.RELOAD_ON_COLLAPSE && source._key) {
                var children = source.getItems();
                var size = children.length;
                var firstIndex = children[0]._index - 1;
                for (var i = 0; i < size; i++) {
                    var child = children[0];
                    source.removeChild(child);
                    child = null;
                    if (this._props.CURRENT_STYLE != ComplexTreeProperties.FILEMANAGER_STYLE && this._pageInfoView) {
                        this._pageInfoView.deleteRow(firstIndex);
                    }
                }

                children = null;
                size = null;
                firstIndex = null;
                var loadingNode = new DwtTreeItem(source, null, this._loadingText);
                loadingNode._key = ComplexTreeProperties.LOADING_ID;
                loadingNode = null;
            }

            if (this._expandTreeItem) {
                this._expandTreeItem = false;
                if (this._props.CURRENT_STYLE == ComplexTreeProperties.ADMIN_CATEGORY_STYLE) {
                    source.setExpanded(true);
                } else {
                    this.getFolderWithKey(source._key);
                }
            }
            break;
    }
    delete source;
    this._shell.setCursor("default");
    this._tree.setCursor("default");
    if (this._pageInfoView) this._pageInfoView.setCursor("default");
}

/**
 * Selection listener for the Tree in case we are using it as a filemanager
 * @param ev The event received by the listener
 */
ComplexTree.prototype._treeSelectionListener =
function (ev) {
    switch (ev.detail) {
        case DwtTree.ITEM_SELECTED:
            this.getFolder(ev.item);
            break;
    }
}

/**
 * Collapses and expands a TreeItem, in order to refresh its children
 * @param itemKey The key of the item to refresh
 */
ComplexTree.prototype.collapseExpand =
function (itemKey) {
    var item = window["treeItem" + itemKey];
    if (! item) return;
    this._expandTreeItem = true;
    var items = item.getItems();
    if (items && items.length > 0) {
        if (item.getExpanded()) {
            item.setExpanded(false);
        } else {
            item.setExpanded(true);
        }
    } else {
        this.addLoadingNodeAndExpand(item);
        if (this._props.CURRENT_STYLE == ComplexTreeProperties.ADMIN_CATEGORY_STYLE) {
            item.setExpanded(true);
        } else {
            this.getFolderWithKey(itemKey);
        }
    }
    delete item;
    delete items;
}

/**
 * Recursive function used to expand to a given treeNode if it exists. The reachDir argument is the targeted node
 * and is used in the recursion to remember to what point with have to go.
 * Only used for the filemanager
 * @param itemKey       TreeItem we are currently processing in the recursion
 * @param reachDir      Targeted TreeItem we want to reach
 * @param updateBar     Boolean in order to know if we need to update the FileManager menu bar
 * @param sortBy        Which column of the FileManager we should sort the result by
 */
ComplexTree.prototype.getFolderWithKey =
function (itemKey, reachDir, updateBar, sortBy) {
    //alert("getFolderWithKey: " + itemKey);
    if (updateBar == undefined) updateBar = true;
    if (sortBy == undefined) sortBy = "name";
    var item = window["treeItem" + itemKey];
    var parentKey = itemKey.substring(0, itemKey.lastIndexOf("/"));
    if (parentKey.length == 0) parentKey = "/";
    var parentItem = window["treeItem" + parentKey];

    if (item) {
        if (reachDir && reachDir != itemKey) item.reachDir = reachDir;
        var jahiaCommand = new AsynchCommand();
        GlobalCallback[GlobalCallbackCount] = new AjxCallback(this, this._fileManagerCallback, item);
        jahiaCommand.addInvokeListener(GlobalCallback[GlobalCallbackCount]);
        GlobalCallbackCount++;

        var xmlDoc = AjxXmlDoc.createRoot("GetDirContent");
        xmlDoc.set("key", (item._key));
        var reg = new RegExp("(&display=directories_Only)", "g");
        var theUrl = this._props.EXPAND_SERVER_URL.replace(reg, "&display=");
        var filters = document.getElementById("filters");
        if (filters && filters.value.length > 0) theUrl += '|' + filters.value;
        if (updateBar && itemKey == reachDir) this.updateBar = true;
        theUrl += "&sortBy=" + sortBy;
        jahiaCommand.invoke(xmlDoc, theUrl);
        delete reg;
        delete jahiaCommand;
        delete xmlDoc;
        delete reg;
        delete theUrl;
        delete filters;

    } else {
        this.updateBar = false;
        var dirs = itemKey.split("/");
        var ok = !parentItem || !parentItem.getExpanded();
        if (dirs.length > 2 && (itemKey.charAt(0) == "/") && ok) {
            var reachDirVar;
            if (! reachDir) {
                reachDirVar = itemKey;
            } else {
                reachDirVar = reachDir;
            }
            this.getFolderWithKey(parentKey, reachDirVar);
            delete reachDirVar;
        } else {
            var addressBar = document.getElementById("addressBarDisp");
            if (addressBar) addressBar.value = window.currentValue;
            delete addressBar;
        }
        delete dirs;
        delete ok;
    }
    delete item;
    delete parentKey;
    delete parentItem;
}

/**
 *
 */
ComplexTree.prototype.getFolder =
function (item) {
    var jahiaCommand = new AsynchCommand();
    GlobalCallback[GlobalCallbackCount] = new AjxCallback(this, this._fileManagerCallback, item);
    jahiaCommand.addInvokeListener(GlobalCallback[GlobalCallbackCount]);
    GlobalCallbackCount++;

    var xmlDoc = AjxXmlDoc.createRoot("GetDirContent");
    xmlDoc.set("key", (item._key));

    var reg = new RegExp("(&display=directories_Only)", "g");
    var theUrl = this._props.EXPAND_SERVER_URL.replace(reg, "&display=");
    var filters = document.getElementById("filters");
    if (filters && filters.value.length > 0) theUrl += '|' + filters.value;
    jahiaCommand.invoke(xmlDoc, theUrl);
    updateMenuBarAfterSelect(item._key);
    delete jahiaCommand;
    delete xmlDoc;
    delete reg;
    delete theUrl;
    delete filters;
}

/**
 * Callback function for the expand ajax call. args[1] is either an Exception or the XmlDoc sent by the server.
 */
ComplexTree.prototype._getChildrenCallback =
function (args) {
    DBG.println("getChildrenCallback invoked...");
    if (!args[1] || args[1] instanceof AjxException) {
        args[0].setExpanded(false);
        if (!args[0].doStop) {
            args[0].setExpanded(true);
            args[0].doStop = true;
        } else {
            alert("Exception during getChildrenCallback: " + args[1].dump());
        }
        return;
    }

    var treeItem = args[0];
    var msg = args[1];
    var children = XmlUtils.splitXml(msg.getDocXml(), this._props.CURRENT_XML_TAG_NAME);
    var objectInfo;
    var ignoredItems = 0;
    for (var i = 0; i < children.length; i++) {
        objectInfo = this._getAllObjectInfo(children[i], this._props.CURRENT_STYLE);
        // Do not display files in the filemanager tree (left panel) in case we only want to display directories
        if (objectInfo.dir != "dir" && objectInfo.dir != "root" && this._props.EXPAND_SERVER_URL.indexOf("directories_Only") > 0) {
            ignoredItems++;
            continue;
        }
        var data = new Array();
        var count = 0;
        for (var j = 0; j < this._props.CURRENT_TREE_PATTERN.length; j++) {
            var values = ComplexTreeProperties.getDataFromObjectInfo(objectInfo,
                    this._props.CURRENT_TREE_PATTERN[j], null, this._props, this);
            if (! values) continue;
            for (var k = 0; k < values.length; k++) {
                if (!values[k] && j > 2 && this._props.CURRENT_STYLE == ComplexTreeProperties.WORKFLOW_STYLE) continue;
                data[count] = values[k];
                count++;
            }
            delete values;
        }

        // index is used to calculate where to add the page info in the list view
        var index = treeItem._index + i;
        // Create and set the Tree item
        this._addTreeItem(treeItem, data, index, objectInfo);

        // Only if we have a listView shall we construct the corresponding listItem
        if (this._pageInfoView && this._props.CURRENT_STYLE != ComplexTreeProperties.FILEMANAGER_STYLE) {
            data = this._pageInfoView.makeListItemData(objectInfo, this);
            var listItem = new ListItem("item" + objectInfo.key, this._pageInfoView.getCurrentHeaders(), data,
                    false, this._itemLength);

            if (objectInfo.disable ||
                (!objectInfo.admin) && objectInfo.activeTab && objectInfo.activeTab != ComplexTreeProperties.activeTab) {
                listItem.disable();
            }

            // Create and set the ListView item
            this._pageInfoView.addItem(listItem, index);
            delete listItem;
        }
        delete index;
        delete data;
        this.RETRIEVED_OBJECTS_EXPAND_ALL++;
    }
    delete objectInfo;
    delete children;
    // Remove the "Loading..." TreeItem
    treeItem.removeChild(treeItem.getItems()[0]);
    this._adjustTreeItemIndexes(treeItem._index);
    if (this._props.CURRENT_STYLE != ComplexTreeProperties.FILEMANAGER_STYLE) {
        this._displayChildren(treeItem);
    } else {
        this.DATA_HEIGHT += (children.length - ignoredItems) * ComplexTreeProperties.ROW_HEIGHT;
        if (this._maximize) {
            this._adjustBestHeight();
        }
        this._layout();
    }

    if (treeItem._expandAll) {
        if (treeItem._startingPoint) {
            ComplexTreeProperties.GOTO = treeItem._startingPoint + ComplexTreeProperties.EXPANDALL_LEVEL;
            treeItem._startingPoint = null;
            this.RETRIEVED_OBJECTS_EXPAND_ALL = children.length;
        }

        if (treeItem._level < (ComplexTreeProperties.GOTO - 1) &&
            this.RETRIEVED_OBJECTS_EXPAND_ALL < ComplexTreeProperties.MAX_RETRIEVED_OBJECTS_EXPAND_ALL) {
            var a = treeItem.getChildren();
            for (var i = 0; i < a.length; i++) {
                a[i]._expandAll = true;
                a[i].setExpanded(true);
            }
            delete a;
        } else {
            treeItem._expandAll = false;
            treeItem._parent._expandAll = false;
            ComplexTreeProperties.GOTO = null;
        }
    }

    if (treeItem.reachDir) {
        this.getFolderWithKey(treeItem.reachDir, treeItem.reachDir);
        treeItem.reachDir = null;
    }
    delete msg;
    delete treeItem;
}

/**
 * Callback function for the filemanager. It simply reloads the listView with the dir content.
 */
ComplexTree.prototype._fileManagerCallback =
function (args) {
    DBG.println("fileManagerCallback invoked...");
    if (!args[1] || args[1] instanceof AjxException) {
        alert("Exception during fileManagerCallback: " + args[1].dump());
        return;
    }

    var treeItem = args[0];
    var msg = args[1];
    this._pageInfoView._list.removeAll();
    this._pageInfoView._resetList();
    var children = XmlUtils.splitXml(msg.getDocXml(), this._props.CURRENT_XML_TAG_NAME);

    if (! treeItem.reachDir) {
        if (children.length == 0) {
            this._pageInfoView._setNoResultsHtml();

        } else {
            for (var i = 0; i < children.length; i++) {
                var objectInfo = this._getAllObjectInfo(children[i], this._props.CURRENT_STYLE);
                var data = this._pageInfoView.makeListItemData(objectInfo, this);
                var listItem = new ListItem(objectInfo.key, this._pageInfoView.getCurrentHeaders(), data,
                        false, this._itemLength);
                listItem.dir = objectInfo.dir == "dir";
                listItem.position = i;

                if (objectInfo.disable ||
                    (!objectInfo.admin) && objectInfo.activeTab && objectInfo.activeTab != ComplexTreeProperties.activeTab) {
                    listItem.disable();
                }

                // Create and set the ListView item
                this._pageInfoView.addItem(listItem, null, null, (i == children.length - 1));
                delete objectInfo;
                delete data;
                delete listItem;
            }
        }
        var addressBar = document.getElementById("addressBar");
        var addressBarDisp = document.getElementById("addressBarDisp");
        if (addressBar) {
            addressBar.value = treeItem._key;
            addressBarDisp.value = treeItem._url;
        }
        treeItem.setText("<b>" + treeItem.getText() + "</b>");
        delete addressBar;
        delete addressBarDisp;
    }
    delete children;
    if (this._oldSelected) {
        var value = this._oldSelected.getText();
        if (value.indexOf("<b>") > -1)
            this._oldSelected.setText(value.substring(3, value.length - 4));
        delete value;
    }
    window.currentValue = treeItem._url;
    this._oldSelected = treeItem;
    if (! treeItem.getExpanded()) {
        // If the tree item is not expanded, but has been selected, we expand it but do not fire a new Event
        // which will send a new Request as all the information to build the sub-tree has already been retreived.
        treeItem.DisableTreeListener = true;
        treeItem.setExpanded(true);
        // Build the tree
        this._getChildrenCallback(args);
    } else if (treeItem.getItemCount() == 1 && treeItem.getItems()[0].getText() == this._loadingText) {
	    	// delete the 'Loading...' node
    		treeItem.removeChild(treeItem.getItems()[0]);
    } 

    if (this.updateBar) updateMenuBarAfterSelect(treeItem._key);
    this.updateBar = null;

    delete msg;
    delete treeItem;
}

/**
 * Adds a "LoadingNode" to a parentItem and expands the parent
 * @param treeItem The parent TreeItem
 */
ComplexTree.prototype.addLoadingNodeAndExpand =
function (treeItem) {
    var loadingNode = new DwtTreeItem(treeItem, null, this._loadingText);
    loadingNode._key = ComplexTreeProperties.LOADING_ID;
    treeItem.setExpanded(true);
    delete loadingNode;
}

/**
 * 2nd Callback function for the expand ajax call. args[1] is either an Exception or the XmlDoc sent by the server.
 *
 */
ComplexTree.prototype._lockChildrenCallback =
function (args) {
    DBG.println("lockChildrenCallback invoked...");
    if (!args[1] || args[1] instanceof AjxException) {
        alert("Exception during lockChildrenCallback: " + args[1].dump());
    }
}

/**
 * Callback function for the collapse ajax call. arg is either an Exception or the XmlDoc sent by the server.
 */
ComplexTree.prototype._unlockChildrenCallback =
function (args) {
    DBG.println("unlockChildrenCallback invoked...");
    if (!args[1] || args[1] instanceof AjxException) {
        alert("Exception during unlockChildrenCallback: " + args[1].dump());
    }
}

/**
 * Adjusts the size of the shell when a node is expanded and shows corresponding data in the listView
 */
ComplexTree.prototype._displayChildren =
function(treeItem, loaded) {
    this._showHideChildren(treeItem, false, loaded);
}

/**
 * Adjusts the size of the shell when a node is collapsed and hides corresponding data in the listView
 */
ComplexTree.prototype._hideChildren =
function(treeItem) {
    this._showHideChildren(treeItem, true, true);
}

/**
 * Display or hides the children of a given TreeItem
 * this._count holds the current number of children and this._keys their keys
 */
ComplexTree.prototype._showHideChildren =
function (treeItem, hide, loaded) {
    this._count = 0;
    this._keys = new AjxVector();
    this._getChildrenRecu(treeItem, hide);
    if (hide) {
        this.DATA_HEIGHT -= this._count * ComplexTreeProperties.ROW_HEIGHT;
    } else {
        this.DATA_HEIGHT += this._count * ComplexTreeProperties.ROW_HEIGHT;
    }

    if (loaded && this._pageInfoView) this._pageInfoView.setUI();

    if (this._maximize) {
        this._adjustBestHeight();
    }
    this._layout();
}

/**
 * Recursive methods to fetch how many childs are visible (expanded) or hidden (collapsed) in the whole tree
 */
ComplexTree.prototype._getChildrenRecu =
function (treeItem, hide) {
    if (treeItem._key == ComplexTreeProperties.LOADING_ID) {
        this._count--;
        return;
    }

    if (this._count > 0) {
        if (this._pageInfoView) {
            if (hide) {
                this._pageInfoView.hideRow(treeItem._index - 1);
            } else {
                this._pageInfoView.showRow(treeItem._index - 1);
            }
        }

        this._keys.add(treeItem._key);
        if (! treeItem.getExpanded()) return;
    }

    if (hide) treeItem._expandAll = false;
    this._count += treeItem.getItemCount();

    var children = treeItem.getItems();
    for (var i = 0; i < children.length; i++) {
        this._getChildrenRecu(children[i], hide);
    }
    delete children;
}

/**
 * Returns the object info in a Map. The list of keys can be retrieved by using property "keys" on the object.
 *
 *
 * In addition, each language state can be retrieved directly on the object returned. For example, if key "langs"
 * contains language "en", you may simply use "en" to get the value:
 * Ex:
 *  var objectInfo = this._getAllObjectInfo(...);
 *  var langState = objectInfo["en"];
 *  alert ("The state for language 'en' is " + langState);
 */
ComplexTree.prototype._getAllObjectInfo =
function(pageInfo, currentStyle) {
    var result = new Object();
    var _keys = new AjxVector();
    var _langs = new AjxVector();
    result.key = XmlUtils.getAttrValue(pageInfo, this._props.CURRENT_XML_TAG_NAME, "key");
    _keys.add("key");
    result.id = XmlUtils.getAttrValue(pageInfo, this._props.CURRENT_XML_TAG_NAME, "id");
    _keys.add("id");
    result.title = XmlUtils.getAttrValue(pageInfo, this._props.CURRENT_XML_TAG_NAME, "title");
    _keys.add("title");
    result.url = XmlUtils.getAttrValue(pageInfo, this._props.CURRENT_XML_TAG_NAME, "url");
    _keys.add("url");

    var dir = XmlUtils.getAttrValue(pageInfo, this._props.CURRENT_XML_TAG_NAME, "dir");
    if (dir) {
        result.dir = dir;
    }
    delete dir;

    var style = XmlUtils.getAttrValue(pageInfo, this._props.CURRENT_XML_TAG_NAME, "Style");
    if (style) {
        result.style = style;
    }
    delete style;

    var parentID = XmlUtils.getAttrValue(pageInfo, this._props.CURRENT_XML_TAG_NAME, "parentID");
    if (parentID) {
        result.parentID = parentID;
    }
    delete parentID;

    var disable = XmlUtils.getAttrValue(pageInfo, this._props.CURRENT_XML_TAG_NAME, "Disable");
    if (disable) {
        result.disable = disable;
    }
    delete disable;

    var admin = XmlUtils.getAttrValue(pageInfo, this._props.CURRENT_XML_TAG_NAME, "Admin");
    if (admin) {
        result.admin = admin;
    }
    delete admin;

    var NoChildren = XmlUtils.getAttrValue(pageInfo, this._props.CURRENT_XML_TAG_NAME, "NoChildren");
    if (NoChildren) {
        result.NoChildren = NoChildren;
    }
    delete NoChildren;

    var canWrite = XmlUtils.getAttrValue(pageInfo, this._props.CURRENT_XML_TAG_NAME, "canWrite");
    if (canWrite) {
        result.canWrite = canWrite;
    }
    delete canWrite;

    var canRead = XmlUtils.getAttrValue(pageInfo, this._props.CURRENT_XML_TAG_NAME, "canRead");
    if (canRead) {
        result.canRead = canRead;
    }
    delete canRead;

    if (currentStyle == ComplexTreeProperties.FILEMANAGER_STYLE) {
        var info = XmlUtils.getAttrValue(pageInfo, this._props.CURRENT_XML_TAG_NAME, "info");
        if (info) {
            _keys.add("info");
            result.info = ["javascript:openManager('" + result.key + "', 'info')", ComplexTreeProperties.INFO, "info"];
        }
        delete info;
        var props = XmlUtils.getAttrValue(pageInfo, this._props.CURRENT_XML_TAG_NAME, "props");
        if (props) {
            _keys.add("props");
            result.props = ["javascript:openManager('" + result.key + "', 'edit')", ComplexTreeProperties.PROPS, "props"];
        }
        delete props;
        var fileSize = XmlUtils.getAttrValue(pageInfo, this._props.CURRENT_XML_TAG_NAME, "fileSize");
        if (fileSize) {
            _keys.add("fileSize");
            result.fileSize = fileSize;
        }
        delete fileSize;
        var lastModif = XmlUtils.getAttrValue(pageInfo, this._props.CURRENT_XML_TAG_NAME, "lastModif");
        if (lastModif) {
            _keys.add("lastModif");
            result.lastModif = lastModif;
        }
        delete lastModif;
        var lockedUrl = XmlUtils.getAttrValue(pageInfo, this._props.CURRENT_XML_TAG_NAME, "locked");
        if (lockedUrl) {
            _keys.add("locked");
            result.locked = ["javascript:openManager('" + result.key + "','unlockFile')", ComplexTreeProperties.LOCKED_STATE, "unlockFile"];
        }
        delete lockedUrl;

    } else if (currentStyle == ComplexTreeProperties.WORKFLOW_STYLE) {
        // Only for the W-flow
        var warnings = XmlUtils.getAttrValue(pageInfo, this._props.CURRENT_XML_TAG_NAME, "warnings");
        if (warnings) {
            _keys.add("warnings");
            result.warnings = warnings;
        }
        delete warnings;

        // Only for the W-flow
        var partialWarnings = XmlUtils.getAttrValue(pageInfo, this._props.CURRENT_XML_TAG_NAME, "partialWarnings");
        if (partialWarnings) {
            _keys.add("partialWarnings");
            result.partialWarnings = partialWarnings;
        }
        delete partialWarnings;

        // Only for the W-flow
        var errors = XmlUtils.getAttrValue(pageInfo, this._props.CURRENT_XML_TAG_NAME, "errors");
        if (errors) {
            _keys.add("errors");
            result.errors = errors;
        }
        delete errors;

        // Only for the W-flow
        var activeTab = XmlUtils.getAttrValue(pageInfo, this._props.CURRENT_XML_TAG_NAME, "activeTab");
        if (activeTab) {
            _keys.add("activeTab");
            result.activeTab = activeTab;
        }
        delete activeTab;

        // Only for the W-flow
        var displayImage = XmlUtils.getAttrValue(pageInfo, this._props.CURRENT_XML_TAG_NAME, "displayImage");
        if (displayImage) {
            _keys.add("displayImage");
            result.displayImage = displayImage;
        }
        delete displayImage;

        var lockedUrl = XmlUtils.getAttrValue(pageInfo, this._props.CURRENT_XML_TAG_NAME, "locked");
        if (lockedUrl) {
            _keys.add("locked");
            result.locked = lockedUrl;
        }
        delete lockedUrl;

    } else if (currentStyle == ComplexTreeProperties.SELECT_PAGE_STYLE) {
        var displayImage = XmlUtils.getAttrValue(pageInfo, this._props.CURRENT_XML_TAG_NAME, "displayImage");
        if (displayImage) {
            _keys.add("displayImage");
            result.displayImage = displayImage;
        }
        delete displayImage;

        var actionURL = XmlUtils.getAttrValue(pageInfo, this._props.CURRENT_XML_TAG_NAME, "timeBasedPublishingActionURL");
        if (actionURL) {
            _keys.add("timeBasedPublishingActionURL");
            result.timeBasedPublishingActionURL = actionURL;
        }
        delete actionURL;

        var dialogTitle = XmlUtils.getAttrValue(pageInfo, this._props.CURRENT_XML_TAG_NAME, "timeBasedPublishingDialogTitle");
        if (actionURL) {
            _keys.add("timeBasedPublishingDialogTitle");
            result.timeBasedPublishingDialogTitle = dialogTitle;
        }
        delete dialogTitle;

        var pageId = XmlUtils.getAttrValue(pageInfo, this._props.CURRENT_XML_TAG_NAME, "timeBasedPublishingPageId");
        if (actionURL) {
            _keys.add("timeBasedPublishingPageId");
            result.timeBasedPublishingPageId = pageId;
        }
        delete pageId;

    } else if (currentStyle == ComplexTreeProperties.ADMIN_CATEGORY_STYLE) {
        var add = XmlUtils.getAttrValue(pageInfo, this._props.CURRENT_XML_TAG_NAME, "add");
        if (add) {
            _keys.add("add");
            result.add = add;
        }
        delete add;
        var edit = XmlUtils.getAttrValue(pageInfo, this._props.CURRENT_XML_TAG_NAME, "edit");
        if (edit) {
            _keys.add("edit");
            result.edit = edit;
        }
        delete edit;
        var move = XmlUtils.getAttrValue(pageInfo, this._props.CURRENT_XML_TAG_NAME, "move");
        if (move) {
            _keys.add("move");
            result.move = move;
        }
        delete move;
        var remove = XmlUtils.getAttrValue(pageInfo, this._props.CURRENT_XML_TAG_NAME, "remove");
        if (remove) {
            _keys.add("remove");
            result.remove = remove;
        }
        delete remove;

    } else if (currentStyle == ComplexTreeProperties.SELECT_CATEGORY_STYLE) {
        var checked = XmlUtils.getAttrValue(pageInfo, this._props.CURRENT_XML_TAG_NAME, "checked");
        if (checked) {
            _keys.add("checked");
            result.checked = checked;
        }
        delete checked;

    }else if (currentStyle == ComplexTreeProperties.PORTLET_CATEGORY_STYLE) {
        var checked = XmlUtils.getAttrValue(pageInfo, this._props.CURRENT_XML_TAG_NAME, "checked");
        if (checked) {
            _keys.add("checked");
            result.checked = checked;
        }
        delete checked;
        var allsources = XmlUtils.getAttrValue(pageInfo, this._props.CURRENT_XML_TAG_NAME, "allsources");
        if(allsources){
            _keys.add("allsources");
            result.allsources = allsources;
        }
        delete allsources;
    } else {
        var lockedUrl = XmlUtils.getAttrValue(pageInfo, this._props.CURRENT_XML_TAG_NAME, "locked");
        if (lockedUrl) {
            _keys.add("locked");
            result.locked = lockedUrl;
        }
        delete lockedUrl;
    }

    var langs = XmlUtils.splitXml(pageInfo, "lang");
    for (var i = 0; i < langs.length; i++) {
        var value = langs[i];
        var key = XmlUtils.getAttrValue(value, "lang", "code");
        var checked = XmlUtils.getAttrValue(value, "lang", "checked");
        var langURL = XmlUtils.getAttrValue(value, "lang", "langURL");
        var langDisabled = XmlUtils.getAttrValue(value, "lang", "Disable");

        // Only for the W-flow
        var additionalKey0 = XmlUtils.getAttrValue(value, "lang", "additionalKey0");
        var additionalKey1 = XmlUtils.getAttrValue(value, "lang", "additionalKey1");

        result[key] = [XmlUtils.getNodeValue(value, "lang"), checked, langURL, langDisabled, additionalKey0, additionalKey1];
        _langs.add(key);
    }
    result.langs = _langs;
    _keys.add("langs");
    delete langs;
    delete _langs;
    result.keys = _keys;
    delete _keys;
    return result;
}

/**
 * ActionListener for the "maximize" button. It increases the height of the MainDiv to the minimum required height
 * to display all the content with no scrollbars.
 */
ComplexTree.prototype._maxListener =
function(ev) {
    this._maximize = true;
    this._adjustBestHeight();
}

/**
 *
 */
ComplexTree.prototype._adjustBestHeight =
function () {
    /* max size for file manager even if this.DATA_HEIGHT < ComplexTreeProperties.MAX_DATA_HEIGHT*/
    if (this._props.CURRENT_STYLE == ComplexTreeProperties.FILEMANAGER_STYLE) {
        this.DATA_HEIGHT = ComplexTreeProperties.MAX_DATA_HEIGHT;
    }
    ComplexTreeProperties.SHELL_HEIGHT = this.DATA_HEIGHT + ComplexTreeProperties.ROW_HEIGHT;
    var parentDiv = document.getElementById(this._parentDiv);
    parentDiv.style.height = ComplexTreeProperties.SHELL_HEIGHT + "px";
    this._container.setSize(null, ComplexTreeProperties.SHELL_HEIGHT);
    if (this._plusButton) this._plusButton.setEnabled(false);
}

/**
 * Adds a Tab to the Worflow Engine tab list
 */
ComplexTree.prototype.addWflowTab =
function (param, name) {
    var tabs = document.getElementById("tabs");
    if (tabs) {
        if (! document.getElementById(param)) {
            tabs.innerHTML += "\n<a id=\"" + param + "\" href=\"javascript:handleActionChanges('display&display=" +
                              param + "')\">" + name + "</a>";
        }
    }
}

ComplexTree.prototype.toString =
function() {
    return "ComplexTree";
}

