/*
 * $Header: /home/cvspublic/jakarta-slide/proposals/tamino/src/store/org/apache/slide/store/tamino/jdomobjects/XDescriptorsUtil.java,v 1.1 2004/03/25 16:18:02 juergen Exp $
 * $Revision: 1.1 $
 * $Date: 2004/03/25 16:18:02 $
 *
 * ====================================================================
 *
 * 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.jdomobjects;

import java.util.Enumeration;
import java.util.Vector;
import org.apache.slide.content.NodeRevisionDescriptors;
import org.apache.slide.content.NodeRevisionNumber;
import org.apache.slide.store.tamino.common.IDescriptors;
import org.apache.slide.store.tamino.common.XGlobals;
import org.apache.slide.structure.ObjectNode;
import org.apache.slide.structure.SubjectNode;
import org.apache.slide.util.XAssertionFailed;
import org.apache.slide.util.XException;

/**
 ** TODO: merge into XDescriptors? But thats already huge
 ** TODO: remove dbSession dependency
 **/
public class XDescriptorsUtil {
    /** parentBindings of the child remain untouched **/
    public static void addChildBinding(XDescriptors parent, XDescriptors child, String segment) {
        ObjectNode node;
        
        node = parent.getUuriObjectNode();
        node.addBinding(segment, child.getUuriObjectNode());
        parent.removeObjectNode();
        parent.setObjectNode( node );
    }
    
    /** childBindings of the child remain untouched **/
    public static void addParentBinding(XDescriptors child, XDescriptors parent, String segment) {
        ObjectNode node;
        
        node = child.getUuriObjectNode();
        node.addParentBinding(segment, parent.getUuriObjectNode());
        child.removeObjectNode();
        child.setObjectNode( node );
    }
    
    public static Enumeration getBindings(XDescriptors desc, boolean parent) {
        ObjectNode obj;
        
        obj = desc.getUuriObjectNode();
        return parent? obj.enumerateParentBindings() : obj.enumerateBindings();
    }
    
    /** @return null or binding name **/
    public static String refersTo(XDescriptors desc, String uuri, boolean parent) {
        Enumeration bindings;
        ObjectNode.Binding b;
        
        bindings = getBindings(desc, parent);
        while (bindings.hasMoreElements()) {
            b = (ObjectNode.Binding) bindings.nextElement();
            if (b.getUuri().equals(uuri)) {
                return b.getName();
            }
        }
        return null;
    }
    
    public static ObjectNode.Binding cloneBinding(ObjectNode.Binding orig) {
        if (orig instanceof ObjectNode.ParentBinding) {
            return new ObjectNode.ParentBinding(orig.getName(), orig.getUuri());
        } else {
            return new ObjectNode.Binding(orig.getName(), orig.getUuri());
        }
    }
    
    private static Vector cloneBindings(XDescriptors desc, String except, boolean parent) {
        Enumeration en;
        Vector lst;
        ObjectNode.Binding b;
        
        en = getBindings(desc, parent);
        lst = new Vector();
        while (en.hasMoreElements()) {
            b = (ObjectNode.Binding) en.nextElement();
            if (!b.getUuri().equals(except)) {
                lst.add(cloneBinding(b));
            }
        }
        return lst;
    }
    
    /** parentBindings of the child remain untouched */
    public static void removeReference(XDescriptors desc, String refUuri, boolean parent) throws XException {
        Vector modified = cloneBindings(desc, refUuri, parent);
        Vector same = cloneBindings(desc, null, !parent);
        
        SubjectNode newNode;
        
        if (parent) {
            newNode = new SubjectNode("willBeIgnored", same, modified, new Vector());
        } else {
            newNode = new SubjectNode("willBeIgnored", modified, same, new Vector());
        }
        desc.removeObjectNode();
        desc.setObjectNode( newNode );
    }
    
    
    /**
     ** Throws runtime exception is parent is not unique
     **/
    public static String getParentUuri(IDescriptors desc) {
        ObjectNode objectNode;
        Enumeration en;
        ObjectNode.ParentBinding binding;
        
        objectNode = desc.getUuriObjectNode();
        en = objectNode.enumerateParentBindings();
        binding = (ObjectNode.ParentBinding) en.nextElement();
        if (en.hasMoreElements()) {
            throw new XAssertionFailed();
        }
        return binding.getUuri();
    }
    
    public static String newSegmentName(XDescriptors parent, XDescriptors child, String base) {
        ObjectNode parentNode;
        ObjectNode childNode;
        int i;
        String name;
        
        parentNode = parent.getUuriObjectNode();
        childNode = child.getUuriObjectNode();
        for (i = 0; true; i++) {
            name = base + i;
            if (!parentNode.hasBinding(name) && !childNode.hasParentBinding(name)) {
                return name;
            }
        }
    }
    
    /**
     * TODO: also stored in NodeRevision?!
     *
     * @return -1 for invalid content length
     */
    public static long getContentLength(XDescriptors desc, NodeRevisionNumber nrn) {
        Object obj;
        
        obj = desc.getPropertyValue(nrn, "getcontentlength", "DAV:");
        if (obj instanceof Long) {
            return ((Long) obj).longValue();
        } else {
            return -1;
        }
    }

    public static String getContentId(XDescriptors desc) {
        NodeRevisionDescriptors nrds = desc.getUuriRevisionDescriptors();
        return getContentId(desc, nrds.getLatestRevision());
    }
    
    /**
     * @return null for collections
     */
    public static String getContentId(XDescriptors desc, NodeRevisionNumber nrn) {
        Object obj;
        
        obj = desc.getPropertyValue(nrn, XGlobals.CONTENT_ID, XGlobals.TAMINO_NAMESPACE_URI);
        if (obj instanceof String) {
            return (String) obj;
        } else {
            // TODO: exception if not a string?
            return null;
        }
    }

    public static void setContentId(XDescriptors desc, String value) {
        desc.setPropertyValue(XGlobals.CONTENT_ID, XGlobals.TAMINO_NAMESPACE_URI, value);
    }
}

