/*
 * $Header: /home/cvspublic/jakarta-slide/proposals/tamino/src/store/org/apache/slide/store/tamino/datastore/XContentId.java,v 1.3 2004/07/30 06:51:54 ozeigermann Exp $
 * $Revision: 1.3 $
 * $Date: 2004/07/30 06:51:54 $
 *
 * ====================================================================
 *
 * 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.datastore;
import java.util.StringTokenizer;

/**
 * Represents the content ID of one content object. The string representation
 * of the content ID is stored in XDescriptors. It is used to uniquely identify
 * the content object and find it within Tamino (or on the filesystem, if faked)
 * <p>
 * The information stored in an XContentId is:
 * <li> if it is empty content </li>
 * <li> if it is XML or nonXML content </li>
 * <li> schema </li>
 * <li> id, which is the ino:id within Tamino </li>
 * </ul>
 * @author martin.wallmer@softwareag.com
 * @version $Revision: 1.3 $
 */
public class XContentId {
    private String id;
    private String stringRepresentation;
    private String schema;
    
    private boolean isEmptyContent = false;
    private boolean isXml = true;
    
    // should be in a global constants file, but to keep
    // component structure handy :-)
    /** name of non-xml content collection */
    private static final String NONXML_CONTENT      = "xdav_nonXML";

    private static final String DELIM = "@";
    private static final String EMPTY_CONTENT = "*empty*";
    private static final String NON_XML = "*nonXML*";
    
    /**
     * Constructs a contentId from schema and id
     *
     * @pre        (id != null)
     * @post
     *
     * @param      id ino:id or filename of the content
     * @param      schema if null or empty string, content is NonXML
     *
     * TODO: rename 'schema' to 'doctype'
     */
    public XContentId (String id, String schema) {
        stringRepresentation = createStringRepresentation (id, schema).toString();
        isXml = !schema.equals (NONXML_CONTENT);
        isEmptyContent = false;
    }
    
    /**
     * creates a contentId from schema, id and an XML indicator. Allows to enable
     * non XML schemas with name other than xdav_nonXML
     *
     * @pre        true
     * @post       true
     *
     * @param      id ino:id or filename of the content
     * @param      schema if null or empty string, content is NonXML
     * @param      isXml true if it is xml
     *
     */
    public XContentId (String id, String schema, boolean isXml) {
        StringBuffer sb = createStringRepresentation (id, schema);
        isEmptyContent = false;
        
        if (schema.equals (NONXML_CONTENT)) {
            this.isXml = false;
        }
        else if (isXml == false) {
            sb.append (DELIM).append (NON_XML);
            this.isXml = false;
        }
        else {
            isXml = true;
        }
        
        stringRepresentation = sb.toString();
    }

    private StringBuffer createStringRepresentation (String id, String schema) {
        this.id = id;
        this.schema = schema;
        
        StringBuffer sb = new StringBuffer ();
        sb.append (id);
        if (schema != null) {
            sb.append (DELIM).append (schema);
        }
        
        return sb;
    }
    
    /**
     * Constructs a contentId from its string representation
     *
     * @pre        (stringRepresentation != null)
     * @post
     *
     * @param      stringRepresentation  string representation of the content id
     */
    public XContentId (String stringRepresentation) {
        if (stringRepresentation.equals (EMPTY_CONTENT)) {
            id = null;
            schema = null;
            this.stringRepresentation = stringRepresentation;
            isEmptyContent = true;
            isXml = false;
        }
        else {
            
            StringTokenizer st = new StringTokenizer (stringRepresentation, DELIM);
            
            this.stringRepresentation = stringRepresentation;
            id = st.nextToken();
            if (st.hasMoreTokens())
                schema = st.nextToken ();
            
            isEmptyContent = false;
            
            if (st.hasMoreTokens()) {
                if (st.nextToken().equals (NON_XML)) {
                    isXml = false;
                }
                else {
                    isXml = true;
                }
            }
            else {
                isXml = !schema.equals (NONXML_CONTENT);
            }
            
        }
    }
    
    /**
     * Constructs a contentId for an empty content
     */
    public XContentId () {
        id = null;
        schema = null;
        stringRepresentation = EMPTY_CONTENT;
        isEmptyContent = true;
        isXml = false;
    }
    
    /**
     * id accessor
     *
     * @return     the id (ino:id in case of XML content)
     */
    public String getId () {
        return id;
    }
    
    /**
     * schema accessor
     *
     * @return     the schema
     */
    public String getSchema () {
        return schema;
    }
    
    /**
     * checks, if this contentId represents an XML or nonXML content
     *
     * @return     true if content is valid XML
     */
    public boolean isXml () {
        return isXml;
    }
    
    /**
     * returns the string representation of this contentId.
     *
     * @return     the string representation of this contentId.
     */
    public String toString () {
        return stringRepresentation;
    }
    
    /**
     * indicates empty content.
     *
     * @return     true if this contentId represents an empty content
     *
     */
    public boolean isEmptyContent () {
        return isEmptyContent;
    }
    
    /**
     * Method hashCode
     *
     * @return   an int
     *
     */
    public int hashCode () {
        return stringRepresentation.hashCode();
    }
    
    /**
     * Method equals
     *
     * @param    other               an Object
     *
     * @return   a boolean
     *
     */
    public boolean equals (Object other) {
        if (! (other instanceof XContentId))
            return false;
        
        return ((XContentId)other).toString().equals (stringRepresentation);
    }
}

