/*
 * $Header: /home/cvspublic/jakarta-slide/projector/src/java/org/apache/slide/projector/processor/tree/Sitemap.java,v 1.5 2004/11/28 13:54:09 dflorey Exp $
 * $Revision: 1.5 $
 * $Date: 2004/11/28 13:54:09 $
 *
 * ====================================================================
 *
 * Copyright 2004 The Apache Software Foundation 
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * 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.
 *
 */

package org.apache.slide.projector.processor.tree;

import java.io.InputStream;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Stack;
import java.util.logging.Level;
import java.util.logging.Logger;

import org.apache.commons.contract.Context;
import org.apache.commons.contract.Result;
import org.apache.commons.contract.constraints.ArrayConstraints;
import org.apache.commons.contract.descriptor.ParameterDescriptor;
import org.apache.commons.contract.descriptor.ResultDescriptor;
import org.apache.commons.contract.descriptor.ResultEntryDescriptor;
import org.apache.commons.contract.descriptor.StateDescriptor;
import org.apache.commons.i18n.LocalizedMessage;
import org.apache.commons.xmlio.in.DefaultSimpleImportHandler;
import org.apache.commons.xmlio.in.SimpleImporter;
import org.apache.commons.xmlio.in.SimplePath;
import org.apache.slide.projector.processor.ConfigurableProcessor;
import org.apache.slide.projector.processor.ConfigurationException;
import org.apache.slide.projector.processor.SimpleProcessor;
import org.apache.slide.projector.value.Streamable;
import org.xml.sax.InputSource;
import org.xml.sax.helpers.AttributesImpl;

/**
 * The Sitemap class
 * 
 */
public class Sitemap implements ConfigurableProcessor {
    private static Logger logger = Logger.getLogger(Sitemap.class.getName());

    private final static ParameterDescriptor[] parameterDescriptors = new ParameterDescriptor[0];
    private final static ResultDescriptor[] resultDescriptors = new ResultDescriptor[] {
            new ResultDescriptor(
                    StateDescriptor.OK_DESCRIPTOR,
                    new ResultEntryDescriptor[] {
                        new ResultEntryDescriptor(SimpleProcessor.OUTPUT, new LocalizedMessage("sitemap/output"), ArrayConstraints.UNCONSTRAINED)
                    })};

    private static Result result = new Result(StateDescriptor.OK);

    public void configure(Streamable config) throws ConfigurationException {
        try {
            InputStream configuration = config.getInputStream();
            SimpleImporter importer = new SimpleImporter();
            ConfigurationHandler handler = new ConfigurationHandler();
            importer.addSimpleImportHandler(handler);
            importer.parse(new InputSource(configuration));
            Page rootPage = handler.getRootPage();
            List resources = new ArrayList();
            buildArray(resources, rootPage);
            Object[] array = resources.toArray();
            result.addResultEntry(SimpleProcessor.OUTPUT, array);
        } catch (Exception exception) {
            logger.log(Level.SEVERE, "Error while parsing sitemap configuration", exception);
        }
    }

    private void buildArray(List resources, Page page) {
        for ( Iterator j = page.getChildren().iterator(); j.hasNext(); ) {
            Page child = (Page)j.next();
            if ( child.getId() != null ) {
                resources.add(new String(child.getId()));
            }
            if ( child.getChildren().size() > 0 ) {
                List childrenResources = new ArrayList();
                buildArray(childrenResources, child);
                Object[] array = new Object[childrenResources.size()];
                resources.add(array);
            }
        }
    }

    public Result process(Map parameter, Context context) throws Exception {
        return result;
    }

    public ParameterDescriptor[] getParameterDescriptors() {
        return parameterDescriptors;
    }

    public ResultDescriptor[] getResultDescriptors() {
        return resultDescriptors;
    }

    class Page {
        private List children = new ArrayList();
        private String id;

        public Page(String id) {
            this.id = id;
        }

        public String getId() {
            return id;
        }

        public void addChild(Page page) {
            children.add(page);
        }

        public List getChildren() {
            return children;
        }
    }

    class ConfigurationHandler extends DefaultSimpleImportHandler {
        private Stack pageStack = new Stack();
        private Page rootPage;

        public Page getRootPage() {
            return rootPage;
        }

        public void startElement(SimplePath path, String name, AttributesImpl attributes, String leadingCDdata) {
            if ( path.matches("page") ) {
                String id = attributes.getValue(org.apache.slide.projector.processor.tree.TreeRenderer.ID);
                Page page = new Page(id);
                Page parentPage = (Page)pageStack.peek();
                parentPage.addChild(page);
                pageStack.push(page);
            } else if ( path.matches("sitemap" ) ) {
                Page page = new Page(null);
                pageStack.push(page);
                rootPage = page;
            }
        }

        public void endElement(SimplePath path, String name) {
            if ( path.matches("page") ) {
                pageStack.pop();
            }
        }
    }
}
