/*
 * $Header: /home/cvspublic/jakarta-slide/proposals/tamino/testsuite/junit/store/org/apache/slide/store/tamino/tools/repairer/RepairHelper.java,v 1.3 2004/07/30 06:52:19 ozeigermann Exp $
 * $Revision: 1.3 $
 * $Date: 2004/07/30 06:52:19 $
 *
 * ====================================================================
 *
 * 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.repairer;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.apache.slide.store.tamino.Configuration;
import org.apache.slide.store.tamino.common.IDescriptors;
import org.apache.slide.store.tamino.jdomobjects.XDescriptors;
import org.apache.slide.store.tamino.jdomobjects.XDescriptorsUtil;
import org.apache.slide.store.tamino.jdomobjects.XFactory;
import org.apache.slide.store.tamino.jdomobjects.XUuri;
import org.apache.slide.store.tamino.tools.repairer.OnOpenTaToken;
import org.apache.slide.store.tamino.tools.repairer.RepairHandler;
import org.apache.slide.store.tamino.tools.repairer.XHttpClient;
import org.apache.slide.store.tamino.tools.repairer.XTaminoClient;
import org.apache.slide.store.tamino.tools.stores.XDomainFileHandler;
import org.apache.slide.store.tamino.tools.stores.XNamespace;
import org.apache.slide.store.tamino.tools.stores.XNamespaceConfig;
import org.apache.slide.store.tamino.tools.stores.XStore;
import org.apache.slide.store.tamino.tools.stores.XStoreGroup;
import org.apache.slide.util.XAssertionFailed;
import org.apache.slide.util.XException;
import org.apache.slide.util.XUri;

/**
 * TODO: base class for test cases?
 *
 * @author          christopher.harding@softwareag.com
 */
public class RepairHelper {
    private final Configuration testConfig;
    
    private final XHttpClient http;
    
    // resolved main, history, workspace and workingresource paths (in that order!!)
    private final String[] resolvedPaths;
    
    public final XTaminoClient taminoClient;
    
    private final boolean useBinding;
    private final RepairHandler repairer;
    
    public RepairHelper(String namespace) throws Exception {
        this.testConfig = Configuration.get();
        this.repairer = new RepairHandler(namespace, testConfig.catalina, testConfig.getTwsUrl(), testConfig.twsUser, testConfig.twsPassword, true,
                                          RepairHandler.DEFAULT_NAMING_CLASS, null);
        this.useBinding = RepairHandler.useBinding( testConfig.taminoCollection );
        this.http = new XHttpClient(getClass(), XUri.SEP+testConfig.catalina.getContext()+XUri.SEP+testConfig.taminoCollection+XUri.SEP,
                                    testConfig.twsHost, testConfig.twsPort, testConfig.twsUser, testConfig.twsPassword);
        XNamespace ns = XDomainFileHandler.get().getNamespace(namespace);
        XStoreGroup group = ns.getStoreGroup(testConfig.taminoCollection);
        resolvedPaths = group.getScopes();
        XNamespaceConfig nsConfig = ns.getConfig();
        XStore store = ns.getStore(testConfig.taminoCollection);
        taminoClient = XTaminoClient.create(store, nsConfig.getAdminUser(), nsConfig.getAdminPwd());
    }
    
    public void wipeDatabase() throws Exception {
        taminoClient.wipeDatabase();
        // create the initial paths
        for (int i = 0; i < 4; i++) {
            XDescriptors defaultEntry = XFactory.createCollectionDescriptor(
                useBinding, taminoClient.getContentCollection(), resolvedPaths[i]);
            taminoClient.getDescriptorsAccessor().insert(defaultEntry);
        }
        invalidateCache();
        
    }
    
    // call this method after modifying descriptors on the server
    public void invalidateCache() throws XException {
        repairer.lockStore(testConfig.taminoCollection, OnOpenTaToken.DEFAULT);
        repairer.unLockStore(testConfig.taminoCollection);
    }
    
    public void testRepairer(List problems) throws Exception {
        testRepairer(problems, new ArrayList(problems));
    }

    public void testRepairer(List patchClassesReadOnly, List patchClasses) throws Exception {
        testRepairer(patchClassesReadOnly, patchClasses, new ArrayList());
    }
    
    public void testRepairer(List patchClassesReadOnly, List patchClasses, List afterRepair) throws Exception {
        runRepair(true, patchClassesReadOnly);
        runRepair(false, patchClasses);
        runRepair(true, afterRepair);
    }
    
    private void runRepair( boolean checkOnly, List patchClasses ) {
        List lst;
        Class cl;
        Object obj;

        repairer.repair(testConfig.taminoCollection, OnOpenTaToken.DEFAULT, checkOnly );
        lst = repairer.getPatches();
        if (lst.size() != patchClasses.size()) {
            throw new XAssertionFailed("wrong size:\n" + msg(patchClasses, lst));
        }
        for (int i = 0; i < lst.size(); i++) {
            cl = (Class) patchClasses.get(i);
            obj = lst.get(i);
            if (!cl.isInstance(obj)) {
                throw new XAssertionFailed(obj + " not instance of " + cl.getName() + ":\n" + msg(patchClasses, lst));
            }
        }
    }
    
    private static String msg(List expected, List got) {
        StringBuffer buffer;
        Iterator iter;
        
        buffer = new StringBuffer();
        iter = expected.iterator();
        buffer.append("expected:");
        while (iter.hasNext()) {
            buffer.append(' ');
            buffer.append(((Class) iter.next()).getName());
        }
        buffer.append("\ngot:");
        iter = got.iterator();
        while (iter.hasNext()) {
            buffer.append(' ');
            buffer.append(iter.next().getClass().getName());
        }
        return buffer.toString();
    }
    
    /**
     * Set the second uri to the first one but there are 2 different contentids
     *
     * @throws      Exception
     **/
    public void createDuplicateDescriptors() throws Exception {
        System.out.println("Create multiple descriptors.");
        String inoId1;
        String inoId2;
        String contentId2;
        XDescriptors desc1;
        XDescriptors desc2;
        
        try {
            // lock store before modifying:
            repairer.lockStore( testConfig.taminoCollection, OnOpenTaToken.DEFAULT );
            
            // get the uris of both content descriptors:
            Map inoIdContentIdPairs = taminoClient.getDescriptorsAccessor().queryAllContentIds(taminoClient.getContentCollection());
            Iterator pairIt = inoIdContentIdPairs.entrySet().iterator();
            Map.Entry pair = (Map.Entry)pairIt.next();
            inoId1 = (String)pair.getKey();
            pair = (Map.Entry)pairIt.next();
            inoId2 = (String)pair.getKey();
            contentId2 = (String)(pair.getValue());
            
            deleteChildUuri(taminoClient.getDescriptorsAccessor().readDescriptorsByIno(inoId2).getUuri());
            
            desc1 = taminoClient.getDescriptorsAccessor().readDescriptorsByIno(inoId1);
            desc2 = taminoClient.getDescriptorsAccessor().readDescriptorsByIno(inoId2);
            
            desc2 = (XDescriptors) desc2.getClone(desc1.getUuri());
            taminoClient.getDescriptorsAccessor().update(desc2);
            
            taminoClient.commit();
            System.out.println("Node " + desc1.getUuri() + " created with contentId " + contentId2);
        } finally {
            repairer.unLockStore( testConfig.taminoCollection);
        }
    }

    public void deleteChildUuri(String childUuri) throws Exception {
        IDescriptors desc = taminoClient.getDescriptorsAccessor().readOneRwDescriptorsByUuri(childUuri);
        String parentUuri = XDescriptorsUtil.getParentUuri(desc);
        XDescriptors parent = taminoClient.getDescriptorsAccessor().readOneRwDescriptorsByUuri(parentUuri);
        XDescriptorsUtil.removeReference(parent, childUuri, false);
        taminoClient.getDescriptorsAccessor().update(parent);
        taminoClient.commit();
    }
    
    /**
     ** @return uuri of the created descriptor
     **/
    public String doCreate(String uri) throws IOException {
        String uuri;
        
        http.create(uri);
        uuri = http.getResourceId(uri);
        
        if (!XUuri.isUuri(uuri)) { // TODO: get rid of this special case
            String pathPrefix = XUri.SEP+testConfig.catalina.getContext()+XUri.SEP+testConfig.taminoCollection+XUri.SEP;  // TODO: duplicated
            if (uuri.startsWith(pathPrefix)) {
                uuri = XUri.SEP + testConfig.taminoCollection + XUri.SEP + uuri.substring(pathPrefix.length());
            } else {
                throw new IllegalStateException(uuri + " doesnt start with " + pathPrefix);
            }
        }
        return uuri;
    }
}

