/*
 * $Header: /home/cvspublic/jakarta-slide/proposals/tamino/src/store/org/apache/slide/store/tamino/tools/repairer/ContentSchemaCheck.java,v 1.5 2004/12/15 10:38:27 pnever Exp $
 * $Revision: 1.5 $
 * $Date: 2004/12/15 10:38:27 $
 *
 * ====================================================================
 *
 * 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 com.softwareag.tamino.db.api.objectModel.TXMLObject;
import java.util.Iterator;
import java.util.List;
import org.apache.slide.store.tamino.common.XGlobals;
import org.apache.slide.store.tamino.datastore.XUtilDBAccessor;
import org.apache.slide.util.JDom;
import org.apache.slide.util.XException;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.Namespace;
import org.jdom.output.XMLOutputter;

/**
 ** Check metadata version.
 **
 ** @author    Peter.Nevermann@softwareag.com
 ** @version   $Revision: 1.5 $
 **
 ** @see       AbstractCheck
 **/
public class ContentSchemaCheck extends AbstractCheck implements RepairConstants {
    // constants
    private static final String
        E_SCHEMA = "schema",
        E_ANNOTATION = "annotation",
        E_APPINFO = "appinfo",
        E_SCHEMAINFO = "schemaInfo",
        E_DOCTYPE = "doctype",
        E_ELEMENT = "element",
        E_COMPLEXTTYPE = "complexType",
        E_SEQUENCE = "sequence",
        E_ANY = "any",
        E_ANYATTRIBUTE = "anyAttribute",
        A_PROCESSCONTENTS = "processContents",
        V_SKIP = "skip",
        DUMMY = "@";


    private static Namespace xsNsp = Namespace.getNamespace(
        XGlobals.XML_SCHEMA_NAMESPACE_PREFIX, XGlobals.XML_SCHEMA_NAMESPACE_URI );
    private static Namespace tsdNsp = Namespace.getNamespace(
        XGlobals.TAMINO_TSD_3_NAMESPACE_PREFIX, XGlobals.TAMINO_TSD_3_NAMESPACE_URI );


    /**
     ** Default constructor.
     **
     ** @pre        (taminoClient != null)
     **
     ** @param      taminoClient       the current database session
     **/
    protected ContentSchemaCheck(XTaminoClient taminoClient) throws XException {
        super( taminoClient, MSG_START_INVALID_CONTENTSCHEMA, MSG_DESCR_INVALID_CONTENTSCHEMA);
    }

    // Inherited from AbstractCheck
    public void check() throws XException {
        // check for TSD3
        String slang = taminoClient.getSchemaLanguage( taminoCollection );
        if( !XGlobals.TSD3_SCHEMA_VERSION.equals(slang) )
            return;

        XUtilDBAccessor schemaAccessor = taminoClient.getUtilAccessor();
        Iterator i = schemaAccessor.getSchemaNames(taminoCollection).iterator();
        while( i.hasNext() ) {
            String sname = (String)i.next();
            Element selm = schemaAccessor.getSchemaElement( taminoCollection, sname );
            if( doRepair(selm) ) {
                logAndApplyPatch(new UpdateSchema(sname, selm, schemaAccessor, taminoCollection));
            }
        }
    }

    /**
     * Add "skip" processing info.
     *
     * @param    selm                an Element
     *
     * @return   if true, the schema was changed.
     *
     */
    private boolean doRepair( Element selm ) {
        Element annelm = selm.getChild( E_ANNOTATION, xsNsp );
        if( annelm == null )
            return false;

        Element ainfoelm = annelm.getChild( E_APPINFO, xsNsp );
        if( ainfoelm == null )
            return false;

        Element sinfoelm = ainfoelm.getChild( E_SCHEMAINFO, tsdNsp );
        if( sinfoelm == null )
            return false;

        String sname = sinfoelm.getAttributeValue( "name" );

        List dts = sinfoelm.getChildren(E_DOCTYPE, tsdNsp);
        if( dts == null || dts.size() != 1 )
            return false;

        Element dtelm = (Element)dts.get(0);
        if( dtelm == null )
            return false;

        String dtname = dtelm.getAttributeValue( "name" );
        if( dtname == null || !dtname.equals(sname) )
            return false;

        List elms = selm.getChildren(E_ELEMENT, xsNsp);
        if( elms == null || elms.size() != 1 )
            return false;

        Element eelm = (Element)elms.get(0);
        if( eelm == null )
            return false;

        String ename = eelm.getAttributeValue( "name" );
        if( ename == null || !ename.equals(sname) )
            return false;

        Element ctypeelm = eelm.getChild( E_COMPLEXTTYPE, xsNsp );
        if( ctypeelm == null )
            return false;
        String mixed = ctypeelm.getAttributeValue( "mixed" );
        if( mixed == null || !mixed.equals("true") )
            return false;

        Element seqelm = ctypeelm.getChild( E_SEQUENCE, xsNsp );
        if( seqelm == null )
            return false;

        List seqchilds = seqelm.getChildren();
        if( seqchilds == null || seqchilds.size() != 1 )
            return false;

        Element anyelm = (Element)seqchilds.get(0);
        if( !E_ANY.equals(anyelm.getName()) )
            return false;

        String proccont = anyelm.getAttributeValue( A_PROCESSCONTENTS );
        if( !V_SKIP.equals(proccont) )
            return false;

        Element anyattelm = ctypeelm.getChild( E_ANYATTRIBUTE, xsNsp );
        if( anyattelm == null )
            return false;

        proccont = anyattelm.getAttributeValue( A_PROCESSCONTENTS );
        if( V_SKIP.equals(proccont) ) {
            // nothing to repair
            return false;
        }

        anyattelm.setAttribute( A_PROCESSCONTENTS, V_SKIP );

        return true;
    }

    // TODO: to much repeated state;
    // TODO: doesn't operator on descriptors ...
    public static class UpdateSchema extends Patch {
        private final String sname;
        private final Element selm;
        private final XUtilDBAccessor schemaAccessor;
        private final String taminoCollection;

        public UpdateSchema(String sname, Element selm, XUtilDBAccessor schemaAccessor, String taminoCollection) {
            this.sname = sname;
            this.selm = selm;
            this.schemaAccessor = schemaAccessor;
            this.taminoCollection = taminoCollection;
        }

        public void apply(XTaminoClient notUsed) throws XException {
            XMLOutputter out = JDom.outputter();
            Document schemadoc = new Document( selm );
            String schemaStr = out.outputString( schemadoc );
            TXMLObject schemaObj = TXMLObject.newInstance( schemaStr );
            schemaAccessor.createSchema( taminoCollection, schemaObj );
        }

        public void log(XRepairLogWriter logWriter) {
            logWriter.println(TC_CHECK_DETAILS, MSG_FOUND_INVALID_CONTENTSCHEMA, sname);
        }
    }
}



