/*
 * $Header: /home/cvspublic/jakarta-slide/proposals/tamino/src/store/org/apache/slide/store/tamino/tools/stores/XNamespace.java,v 1.3 2004/07/30 06:52:06 ozeigermann Exp $
 * $Revision: 1.3 $
 * $Date: 2004/07/30 06:52:06 $
 *
 * ====================================================================
 *
 * Copyright 1999-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.store.tamino.tools.stores;


import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.apache.slide.util.JDom;
import org.apache.slide.util.XAssertionFailed;
import org.apache.slide.util.XException;
import org.apache.slide.util.XUri;
import org.jdom.Element;
import org.jdom.JDOMException;

/**
 ** Represents a namespace element.
 **
 ** @author michael.hartmeier@softwareag.com
 ** @version $Revision: 1.3 $
 **/
public class XNamespace {
    public final String name;
    
    /** namespace element, will not be changed by this class **/
    private final Element template;
    
    /** list of store groups **/
    private final List groups;
    
    private final XNamespaceConfig config;
    
    public XNamespace(String name) {
        this(name, createTemplate(), XNamespaceConfig.create());
    }
    
    public XNamespace(String name, Element template, XNamespaceConfig config) {
        try {
            checkTemplate(template);
        } catch (XException e) {
            throw new XAssertionFailed(e);
        }
        this.template = template;
        this.name = name;
        this.groups = new ArrayList();
        this.config = config;
    }
    
    public void removeStoreGroup(String name) throws XException {
        groups.remove(getStoreGroup(name));
    }
    
    public void addStoreGroup(XStoreGroup name) {
        groups.add(name);
    }
    
    public XStoreGroup lookupStoreGroup(String name) {
        Iterator i;
        XStoreGroup group;
        
        i = groups.iterator();
        while (i.hasNext()) {
            group = (XStoreGroup) i.next();
            if (group.name.equals(name)) {
                return group;
            }
        }
        return null;
    }
    
    public XStoreGroup getStoreGroup(String name) throws XException {
        XStoreGroup group;
        
        group = lookupStoreGroup(name);
        if (group == null) {
            throw new XException("store group not found: " + name);
        }
        return group;
    }
    
    public XStore getStore(String name) throws XException {
        XStore store;
        
        store = lookupStore(name);
        if (store == null) {
            throw new XException("store not found: " + name);
        } else {
            return store;
        }
    }
    
    public XStore lookupStore(String name) throws XException {
        Iterator iter;
        XStoreGroup group;
        XStore store;
        
        iter = groups.iterator();
        while (iter.hasNext()) {
            group = (XStoreGroup) iter.next();
            store = group.lookupStore(name);
            if (store != null) {
                return store;
            }
        }
        return null;
    }
    
    public XStore getStoreByScope(XUri scope) throws XException {
        XStore store;
        
        store = lookupStoreByScope(scope);
        if (store == null) {
            throw new XException("store not found for scope " + scope);
        } else {
            return store;
        }
    }
    
    public XStore lookupStoreByScope(XUri scope) {
        Iterator iter;
        XStoreGroup group;
        XStore store;
        
        iter = groups.iterator();
        while (iter.hasNext()) {
            group = (XStoreGroup) iter.next();
            store = group.lookupByScope(scope);
            if (store != null) {
                return store;
            }
        }
        return null;
    }
    
    public List getStoresByType(String typeName) {
        List result;
        Iterator iter;
        XStoreGroup group;
        XStore store;
        
        result = new ArrayList();
        iter = groups.iterator();
        while (iter.hasNext()) {
            group = (XStoreGroup) iter.next();
            store = group.getByType(typeName);
            if (store != null) {
                result.add(store);
            }
        }
        return result;
    }
    
    
    /** TODO: dump this method? **/
    public List getPublicStoreGroups() {
        List result;
        Iterator stores;
        XStoreGroup group;
        
        stores = groups.iterator();
        result = new ArrayList();
        while (stores.hasNext()) {
            group = (XStoreGroup) stores.next();
            if (!group.internal) {
                result.add(group);
            }
        }
        return result;
    }
    
    /** TODO: dump this method? **/
    public List getPublicStoreGroupNames() {
        List result;
        int i;
        int max;
        XStoreGroup group;
        
        result = getPublicStoreGroups();
        max = result.size();
        for (i = 0; i < max; i++) {
            group = (XStoreGroup) result.get(i);
            result.set(i, group.name);
        }
        return result;
    }
    
    public XNamespaceConfig getConfig() {
        return config;
    }
    
    //-- security stuff
    
    public static final String SECURITY_GROUP_NAME = "$security";
    public static final String XDAV_GROUP_NAME = "$xdav";
    
    //-- xml
    
    public static XNamespace fromXml(XStoreGroupTypeList groupTypes, Element nsElementOrig) throws XException {
        Element nsElement;
        XNamespace ns;
        XNamespaceConfig config;
        Element definition;
        List stores;
        List groups;
        Iterator iter;
        
        nsElement = (Element) nsElementOrig.clone();
        checkTemplate(nsElementOrig);   // check here because the constructor would report an internal error
        config = XNamespaceConfig.extractFromXml(JDom.getElement(nsElement, XDomainConstants.CONFIGURATION));
        ns = new XNamespace(JDom.getAttribute(nsElement, XDomainConstants.NAME), nsElement, config);
        // TODO: nsElement is modified after assigning it as a template
        definition = JDom.getElement(nsElement, XDomainConstants.DEFINITION);
        stores = XStore.extractListFromXml(definition);
        XStore.extractXmlData(new ArrayList(stores), JDom.getElement(nsElement, XDomainConstants.DATA));
        groups = XStoreGroup.fromStores(groupTypes, stores);
        iter = groups.iterator();
        while (iter.hasNext()) {
            ns.addStoreGroup((XStoreGroup) iter.next());
        }
        return ns;
    }
    
    //-- templates
    
    private static Element createTemplate() {
        Element template;
        
        try {
            template = JDom.forResource(XDomainConstants.RESOURCE_PREFIX + "namespace.xml").getRootElement();
        }
        catch (IOException e) {
            throw new XAssertionFailed(e);
        }
        catch (JDOMException e) {
            throw new XAssertionFailed(e);
        }
        return template;
    }
    
    private static void checkTemplate(Element template) throws XException {
        JDom.getElement(template, XDomainConstants.DEFINITION);
        JDom.getElement(template, XDomainConstants.DATA);
        if (!template.getName().equals(XDomainConstants.NAMESPACE)) {
            throw new XException("illegal element name, expected 'namespace', found '" + template.getName() + "'");
        }
    }
    
    public Element toXml() {
        Element result;
        Element definition;
        Element data;
        Iterator iter;
        XStoreGroup group;
        List stores;
        
        result = (Element) template.clone();
        if (result.getParent() != null) {
            throw new XAssertionFailed();
        }
        result.setAttribute(XDomainConstants.NAME, name);
        definition = JDom.getXElement(result, XDomainConstants.DEFINITION);
        data = JDom.getXElement(result, XDomainConstants.DATA);
        iter = groups.iterator();
        stores = new ArrayList();
        // TODO: sort data stuff before writing, otherwise, I might get "objectNode" exists ...
        while (iter.hasNext()) {
            group = (XStoreGroup) iter.next();
            group.addXmlDefinition(definition, stores);
        }
        config.addXml(JDom.getXElement(result, XDomainConstants.CONFIGURATION));
        XStore.addXmlData(stores, data);
        return result;
    }
}



