/*
 * $Header: /home/cvspublic/jakarta-slide/proposals/tamino/src/store/org/apache/slide/store/tamino/tools/stores/XStoreTypeList.java,v 1.3 2004/07/30 06:52:07 ozeigermann Exp $
 * $Revision: 1.3 $
 * $Date: 2004/07/30 06:52:07 $
 *
 * ====================================================================
 *
 * 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.store.BindingStore;
import org.apache.slide.store.tamino.common.XGlobals;
import org.apache.slide.store.tamino.datastore.search.DummyBasicQuery;
import org.apache.slide.store.tamino.security.admin.URMActionsStore;
import org.apache.slide.store.tamino.security.admin.URMGroupsStore;
import org.apache.slide.store.tamino.security.admin.URMRolesStore;
import org.apache.slide.store.tamino.security.admin.URMUserDBStore;
import org.apache.slide.store.tamino.security.admin.URMUsersStore;
import org.apache.slide.store.tamino.store.XAdministrationStore;
import org.apache.slide.store.tamino.store.XDefaultStore;
import org.apache.slide.store.tamino.store.XFileStore;
import org.apache.slide.store.tamino.store.XMemoryStore;
import org.apache.slide.store.tamino.store.XParentStore;
import org.apache.slide.store.tamino.store.XPermissionStore;
import org.apache.slide.store.tamino.store.XSchemaStore;
import org.apache.slide.store.tamino.store.monitoring.XMonitoringStore;
import org.apache.slide.store.tamino.tools.Env;
import org.apache.slide.store.tamino.tools.repairer.XRepairerStore;
import org.apache.slide.store.txfile.TxFileContentStore;
import org.apache.slide.store.txfile.TxXMLFileDescriptorsStore;
import org.apache.slide.structure.ActionNode;
import org.apache.slide.util.JDom;
import org.apache.slide.util.Pattern;
import org.apache.slide.util.XAssertionFailed;
import org.apache.slide.util.XException;
import org.jdom.Element;
import org.jdom.JDOMException;

/**
 ** @author michael.hartmeier@softwareag.com
 ** @version $Revision: 1.3 $
 **/

public class XStoreTypeList {
    public final XStoreType[] all;
    
    //-- normal, user-visible stores

    public final XStoreType userNormal;
    public final XStoreType userHistory;
    public final XStoreType userWorkspace;
    public final XStoreType userWorkingResource;
    
    //-- internal stores: security
    
    public final XStoreType secUrmUserdb;
    public final XStoreType secUrmUsers;
    public final XStoreType secUrmGroups;
    public final XStoreType secUrmRoles;
    
    //-- internal stores: other
    
    public final XStoreType xdavDefault;
    public final XStoreType xdavStatistics;
    public final XStoreType xdavSecurity;
    public final XStoreType xdavActions;
    public final XStoreType xdavConfiguration;
    public final XStoreType xdavEtc;
    public final XStoreType xdavRepairer;
    public final XStoreType xdavSchema;

    //-- txFile store
    public final XStoreType txFile;
    
    /** helper var, only defined during construction */
    private final List tmp;

    public XStoreTypeList(XDomainConfig config) {
        tmp = new ArrayList();
        
        // user stores
        userNormal = user(NORMAL_NAME, config, XDomainConfig.NORMAL_SCOPE_PATTERN, false);
        userHistory = user(HISTORY_NAME, config, XDomainConfig.HISTORY_SCOPE_PATTERN, true);
        userWorkspace = user(WORKSPACE_NAME, config, XDomainConfig.WORKSPACE_SCOPE_PATTERN, true);
        userWorkingResource = user(WORKINGRESOURCE_NAME, config, XDomainConfig.WORKINGRESOURCE_SCOPE_PATTERN, true);
    
        // intern: security stores
        secUrmUserdb = sec("userdb", "$xdav_userdb", URMUserDBStore.class.getName());
        secUrmUsers = sec("userdb/users", XDAV_USERS_NAME, URMUsersStore.class.getName());
        secUrmGroups = sec("userdb/groups", "$xdav_groups", URMGroupsStore.class.getName());
        secUrmRoles = sec("userdb/roles", "$xdav_roles", URMRolesStore.class.getName());
    
        txFile = file();
        // internal: other stores
        xdavDefault = xdav("/", XDAV_DEFAULT_NAME,
                           new XStoreAspects(XDefaultStore.class.getName(), XPermissionStore.class.getName()),
                           XStore.DEFAULT_OBJECT_NODE_CLASS);
        xdavStatistics = xdav("/administration/statistics", "$xdav_statistics", XMonitoringStore.class.getName(),
             new Parameter[] {
                    new Parameter("WebDAV", "/"),
                    new Parameter("ParentStore", "/${store}"),
                    new Parameter("DatabaseHandler", "/${store}/DatabaseHandler"),
                    new Parameter("GlobalCache", "/${store}/DescriptorsStore/DescriptorsHandler/GlobalCache"),
                    new Parameter("ContentCache", "/${store}/ContentStore/ContentHandler/ContentCache"),
                    BASIC_QUERY_PARA
            });
        xdavSecurity = xdav("/administration/security", "$xdav_security", XMemoryStore.class.getName());
        xdavActions = xdav(ActionDeclaration.SCOPE, "$xdav_actions", new XStoreAspects(URMActionsStore.class.getName()),
             new Parameter[] { BASIC_QUERY_PARA },
                 ActionNode.class.getName(),
                 "<lst>" + ActionDeclaration.allToXml() + "</lst>"
                 );
        xdavConfiguration = xdav("/administration/configuration", "$xdav_configuration", XConfigurationStore.class.getName(),
             new Parameter[] { new Parameter("validating", true), BASIC_QUERY_PARA });
        xdavEtc = xdav("/administration/etc", "$xdav_etc", XFileStore.class.getName(),
             new Parameter[] { new Parameter("rootpath", "/${" + Env.PROPERTY_NAME + "}/etc"), BASIC_QUERY_PARA });
        xdavRepairer = xdav(XGlobals.REPAIRER_URI, "$xdav_repairer", XRepairerStore.class.getName(),
             new Parameter[] { new Parameter("rootpath", "/${" + Env.PROPERTY_NAME + "}/repairer"), BASIC_QUERY_PARA });
        xdavSchema = xdav("/administration/schema", "$xdav_schema", XSchemaStore.class.getName(),
             new Parameter[] {
                new Parameter("rootpath", "/${" + Env.PROPERTY_NAME + "}/schema"),
                    new Parameter("deleteCascades", false),
                    BASIC_QUERY_PARA,
                    new Parameter("XMLSchemaDefaultFileExtension", "xsd")
            });
        
        all = new XStoreType[tmp.size()];
        tmp.toArray(all);
    };
    
    /**
     * @return new Object[] { String groupStoreName, XStoreType }
     */
    public XStoreType lookup(XStore store) throws XException {
        int i;
        XStoreType result;
        XStoreType tmp;

        result = null;
        for (i = 0; i < all.length; i++) {
            tmp = all[i];
            if (tmp.isInstance(store)) {
                if (result != null) {
                    throw new XException("ambiguous store type: " + store.getName());
                }
                result = tmp;
            }
        }
        return result;
    }
    
    
    public String lookupGroupName(XStore store) throws XException {
        XStoreType type;
        
        type = lookup(store);
        if (type == null) {
            return null;
        }
        return type.getNamePattern().matches(store);
    }

    
    //-- helper methods to create types

    private XStoreType add(XStoreType type) {
        tmp.add(type);
        return type;
    }

    private XStoreType file() {
        return add(new XStoreType("txfile", new Pattern("/${store}"), null, "$txfile_${scope}",
                                  BindingStore.class.getName(), XStoreAspects.TXFILE_ASPECTS, NO_PARAS,
                                  XStore.DEFAULT_OBJECT_NODE_CLASS, new ArrayList()
                                 ));
    }

    private XStoreType user(String name, XDomainConfig config, Parameter scopeParameter, boolean withPrefix) {
        String variable;
        Pattern scope;

        variable = "${scope}";
        if (withPrefix) {
            variable = XDomainConstants.DELTAV_STORE_PREFIX + "_" + variable;
        }
        scope = config.getScopePattern(scopeParameter);
        return add(new XStoreType(name, scope, null, variable, XParentStore.class.getName(),
                                          XStoreAspects.TAMINO_ASPECTS, NO_PARAS,
                                          XStore.DEFAULT_OBJECT_NODE_CLASS, new ArrayList()));
    }
    private XStoreType sec(String scope, String storeNamePattern, String nodeAspectClass) {
        // TODO: name is not unique
        return add(new XStoreType("security",
                                          new Pattern("/administration/security/" + scope),
                                          XNamespace.SECURITY_GROUP_NAME,
                                          storeNamePattern,
                                          XAdministrationStore.class.getName(),
                                          new XStoreAspects(nodeAspectClass),
                                          NO_PARAS,
                                          XStore.DEFAULT_OBJECT_NODE_CLASS, new ArrayList()));
    }
    
    private XStoreType xdav(String scope, String slideStoreNamePattern, String nodeAspectClass) {
        return xdav(scope, slideStoreNamePattern, new XStoreAspects(nodeAspectClass), NO_PARAS, XStore.DEFAULT_OBJECT_NODE_CLASS, null);
    }
    
    private XStoreType xdav(String scope, String slideStoreNamePattern, XStoreAspects aspects, String objectNodeClass) {
        return xdav(scope, slideStoreNamePattern, aspects, NO_PARAS, objectNodeClass, null);
    }
    
    private XStoreType xdav(String scope, String storeNamePattern, String nodeAspectClass, Parameter[] paras) {
        return xdav(scope, storeNamePattern, new XStoreAspects(nodeAspectClass), paras, XStore.DEFAULT_OBJECT_NODE_CLASS, null);
    }

    private XStoreType xdav(String scope, String storeNamePattern, XStoreAspects aspects, Parameter[] paras,
                                           String objectNodeClass, String xmlData) {
        Element ele;
        List lst;
        Iterator iter;
        
        lst = new ArrayList();
        if (xmlData != null) {
            try {
                ele = JDom.forString(xmlData).getRootElement();
            } catch (IOException e) {
                throw new XAssertionFailed(e);
            } catch (JDOMException e) {
                throw new XAssertionFailed(e);
            }
            iter = ele.getChildren().iterator();
            while (iter.hasNext()) {
                // note that clone also detaches the child element
                lst.add(((Element) iter.next()).clone());
            }
        }
        // TODO: paras
        // TODO: only default-part of parameter is used
        // TODO: name is not unique
        return add(new XStoreType("xdav",
                                          new Pattern(scope),
                                          XNamespace.XDAV_GROUP_NAME, storeNamePattern,
                                          XAdministrationStore.class.getName(),
                                          aspects, paras, objectNodeClass, lst));
    }

    //--
    
    public static final String XDAV_DEFAULT_NAME = "$xdav_default";
    public static final String XDAV_USERS_NAME = "$xdav_users";

    public static final String NORMAL_NAME = "normal";
    public static final String HISTORY_NAME = "history";
    public static final String WORKSPACE_NAME = "workspace";
    public static final String WORKINGRESOURCE_NAME = "workingresource";
    
    private static final Parameter[] NO_PARAS = new Parameter[] {};
    private static final Parameter BASIC_QUERY_PARA = new Parameter("basicQueryClass", DummyBasicQuery.class.getName());
}

