/*
 * $Header: /home/cvspublic/jakarta-slide/proposals/tamino/src/store/org/apache/slide/store/tamino/jdomobjects/XNodeProperty.java,v 1.3 2004/07/30 06:52:00 ozeigermann Exp $
 * $Revision: 1.3 $
 * $Date: 2004/07/30 06:52:00 $
 *
 * ====================================================================
 *
 * 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.Date;
import org.apache.slide.content.NodeProperty;
import org.apache.slide.store.tamino.common.XGlobals;
import org.apache.slide.store.tamino.datastore.schema.KnownPropertyList;
import org.apache.slide.store.tamino.datastore.schema.XKnownPropertyHelper;
import org.apache.slide.util.XAssertionFailed;
import org.jdom.Element;
import org.jdom.Namespace;

/**
 * Serialize NodeProperty objects to and from XML.
 *
 * @author martin.wallmer@softwareag.com
 *
 * @version $Revision: 1.3 $
 */
public class XNodeProperty implements XJdom {
    
    /**
     ** Serializes to Xml. Get an element.
     **
     ** @return an element
     **/
    public static Element getElement (NodeProperty nodeProperty, String tsdLanguage) {
        if (nodeProperty == null) {
            throw new XAssertionFailed();
        }
        
        Element elem;
        
        KnownPropertyList kpl = XKnownPropertyHelper.getKnownPropertyList (tsdLanguage);
        
        if (kpl.isKnown (nodeProperty)) {
            elem = new Element (nodeProperty.getName());
            elem.setNamespace (Namespace.getNamespace (nodeProperty.getNamespace()));
        }
        else {
            elem = new Element(E_NODE_PROPERTY);
            elem.setAttribute (A_NAMESPACE, nodeProperty.getNamespace());
        }
        
        String dataType = null;
        
        if (!kpl.isKnown (nodeProperty))
            elem.setAttribute (A_NAME, nodeProperty.getName());
        
        elem.setAttribute (A_TYPE, nodeProperty.getType());
        elem.setAttribute (A_PROTECTED, nodeProperty.isProtected() ? TRUE : FALSE);
        
        Object value = nodeProperty.getValue();
        String textVal = null;
        // Element xmlValue = null;
        
        if (value instanceof String){
            
            textVal = value.toString();
            dataType = STRING;
            
            // try to make XML of it (for XML valued properties
            //            try {
            //                xmlValue = (Element)JDom.forString (textVal).getRootElement().clone();
            //                dataType = XML;
            //            }
            //            catch (Exception e) {
            //                dataType = STRING;
            //            }
        }
        else if (value instanceof Integer) {
            dataType = INT;
            textVal = value.toString();
        }
        else if (value instanceof Long) {
            dataType = LONG;
            textVal = value.toString();
        }
        else if (value instanceof Boolean) {
            dataType = BOOLEAN;
            textVal = value.toString();
        }
        else if (value instanceof Date) {
            dataType = DATE;
            synchronized (DATE_FORMATTER) {
                textVal = DATE_FORMATTER.format ((Date)value);
            }
        }
        else
            throw new IllegalArgumentException();
        
        
        elem.setAttribute (A_DATATYPE, dataType);
        
        //        if (dataType.equals(XML))
        //            elem.addContent(xmlValue);
        //        else
        elem.setText (textVal);
        
        int shadowSize = Math.min (textVal.length(), XGlobals.MAX_SHADOW_SIZE);
        
        Element eShadow = new Element (E_SHADOW);
        
        eShadow.setText (textVal.substring (0, shadowSize));
        elem.addContent (eShadow);
        
        return elem;
    }
    
    public static void toStream(XmlStream xs, NodeProperty nodeProperty, String tsdLanguage) {
        if (nodeProperty == null) {
            throw new XAssertionFailed();
        }
        String propName;
        
        KnownPropertyList kpl = XKnownPropertyHelper.getKnownPropertyList (tsdLanguage);
        
        if (kpl.isKnown (nodeProperty)) {
            Namespace ns = Namespace.getNamespace (nodeProperty.getNamespace());
            xs.addStartElement(nodeProperty.getName(),ns.getURI(),ns.getPrefix());
            propName=nodeProperty.getName();
        }
        else {
            xs.addStartElement(E_NODE_PROPERTY);
            xs.addAttribute(A_NAMESPACE, nodeProperty.getNamespace());
            propName = E_NODE_PROPERTY;
        }
        
        String dataType = null;
        
        if (!kpl.isKnown (nodeProperty))
            xs.addAttribute(A_NAME, nodeProperty.getName());
        
        xs.addAttribute(A_TYPE, nodeProperty.getType());
        xs.addAttribute(A_PROTECTED, nodeProperty.isProtected());
        
        Object value = nodeProperty.getValue();
        String textVal = null;
        
        if (value instanceof String){
            
            textVal = value.toString();
            dataType = STRING;
            
        }
        else if (value instanceof Integer) {
            dataType = INT;
            textVal = value.toString();
        }
        else if (value instanceof Long) {
            dataType = LONG;
            textVal = value.toString();
        }
        else if (value instanceof Boolean) {
            dataType = BOOLEAN;
            textVal = value.toString();
        }
        else if (value instanceof Date) {
            dataType = DATE;
            synchronized (DATE_FORMATTER) {
                textVal = DATE_FORMATTER.format ((Date)value);
            }
        }
        else
            throw new IllegalArgumentException();
        
        
        xs.addAttribute(A_DATATYPE, dataType);
        
        xs.addEndElement();
        xs.addText(textVal);
        
        int shadowSize = Math.min (textVal.length(), XGlobals.MAX_SHADOW_SIZE);
        
        xs.addStartElement(E_SHADOW,"","");
        xs.addEndElement();
        xs.addText(textVal.substring (0, shadowSize));
        xs.addCloseElement(E_SHADOW);
        
        xs.addCloseElement(propName);
    }

    /**
     * Method toSlide
     *
     * @param    jdomAspect          an Element describing a NodeProperty
     *
     * @return   a NodeProperty
     *
     */
    public static NodeProperty toSlide (Element jdomAspect) {
        if (jdomAspect == null) {
            throw new XAssertionFailed();
        }
        
        String name;
        
        Namespace ns = jdomAspect.getNamespace();
        String elementName = jdomAspect.getName();
        NodeProperty nodeProperty;
        String namespace;
        
        if (elementName.equals (E_NODE_PROPERTY)) {
            name = jdomAspect.getAttributeValue (A_NAME);
            namespace = jdomAspect.getAttributeValue (A_NAMESPACE);
        }
        else {
            name = elementName;
            namespace = ns.getURI();
        }
        
        String type = jdomAspect.getAttributeValue (A_TYPE);
        boolean isProtected = jdomAspect.getAttributeValue
            (A_PROTECTED).equals (TRUE) ? true : false;
        
        String dataType = jdomAspect.getAttributeValue (A_DATATYPE);
        String sVal = jdomAspect.getText();
        Object value = null;
        
        if (dataType.equals(STRING))
            value = sVal;
            
        else if (dataType.equals (INT))
            value = new Integer (sVal);
            
            //        else if (dataType.equals (XML)) {
            //            value = JDom.toString ((Element)value);
            //        }
            
        else if (dataType.equals (LONG))
            value = new Long (sVal);
            
        else if (dataType.equals (BOOLEAN))
            value = new Boolean (sVal);
            
        else if (dataType.equals (DATE)) {
            try {
                synchronized (DATE_FORMATTER) {
                    value = DATE_FORMATTER.parse (sVal);
                }
            }
            catch (java.text.ParseException e) {
                e.printStackTrace();
                throw new IllegalStateException ();
            }
        }
        else {
            throw new IllegalStateException("unkown type: " + dataType);
        }
        
        nodeProperty = new NodeProperty (name, value, namespace, type);
        if( isProtected && !NodeProperty.allLiveProperties.contains(name) ) {
            // this is a proprietary (non-standard; shouldn't be DAV:) protected (live) property;
            // for the standard live properties, the kind is set automatically
            nodeProperty.setKind( NodeProperty.Kind.PROTECTED );
        }
        return nodeProperty;
    }
}



