/*
 * Copyright 2001-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.axis.encoding;

import org.apache.axis.Constants;
import org.apache.axis.Part;
import org.apache.axis.components.logger.LogFactory;
import org.apache.axis.message.EnvelopeHandler;
import org.apache.axis.message.MessageElement;
import org.apache.axis.message.SAX2EventRecorder;
import org.apache.axis.message.SAXOutputter;
import org.apache.axis.message.SOAPHandler;
import org.apache.axis.utils.Messages;
import org.apache.axis.soap.SOAPConstants;
import org.apache.commons.logging.Log;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;

import javax.xml.namespace.QName;
import java.io.StringWriter;
import java.util.HashSet;
import java.util.Vector;

/** The Deserializer base class.
 * 
 * @author Glen Daniels (gdaniels@allaire.com)
 * Re-architected for JAX-RPC Compliance by
 * @author Rich Scheuerle (sche@us.ibm.com)
 */

public class DeserializerImpl extends SOAPHandler
        implements javax.xml.rpc.encoding.Deserializer, Deserializer, Callback
{
    protected static Log log =
            LogFactory.getLog(DeserializerImpl.class.getName());

    protected Object value = null;

    // invariant member variable to track low-level logging requirements
    // we cache this once per instance lifecycle to avoid repeated lookups
    // in heavily used code.
    private final boolean debugEnabled = log.isDebugEnabled();

    // isEnded is set when the endElement is called
    protected boolean isEnded = false;

    protected Vector targets = null;

    protected QName defaultType = null;

    protected boolean componentsReadyFlag = false;

    /**
     * A set of sub-deserializers whose values must complete before our
     * value is complete.
     */ 
    private HashSet activeDeserializers = new HashSet();

    protected boolean isHref = false;
    protected boolean isNil = false;  // xsd:nil attribute is set to true
    protected String id = null;  // Set to the id of the element

    public DeserializerImpl() {
    }

    /** 
     * JAX-RPC compliant method which returns mechanism type.
     */
    public String getMechanismType() {
        return Constants.AXIS_SAX;
    }
    
    /** 
     * Get the deserialized value.
     * @return Object representing deserialized value or null
     */
    public Object getValue()
    {
        return value;
    }
    /** 
     * Set the deserialized value.
     * @param value Object representing deserialized value
     */
    public void setValue(Object value)
    {
        this.value = value;
    }

    /** 
     * If the deserializer has component values (like ArrayDeserializer)
     * this method gets the specific component via the hint.
     * The default implementation returns null.
     * @return Object representing deserialized value or null
     */
    public Object getValue(Object hint)
    {
        return null;  
    }

    /** 
     * If the deserializer has component values (like ArrayDeserializer)
     * this method sets the specific component via the hint.
     * The default implementation does nothing.
     * @param hint Object representing deserialized value or null
     */
    public void setChildValue(Object value, Object hint) throws SAXException
    {
    }

    public void setValue(Object value, Object hint) throws SAXException {
        if (hint instanceof Deserializer) {
            // This one's done
            activeDeserializers.remove(hint);
            
            // If we're past the end of our XML, and this is the last one,
            // our value has been assembled completely.
            if (componentsReady()) {
                // Got everything we need, call valueComplete()
                valueComplete();
            }
        }        
    }

    /**
     * In some circumstances an element may not have 
     * a type attribute, but a default type qname is known from
     * information in the container.  For example,
     * an element of an array may not have a type= attribute, 
     * so the default qname is the component type of the array.
     * This method is used to communicate the default type information 
     * to the deserializer.
     */
    public void setDefaultType(QName qName) {
        defaultType = qName;
    }
    public QName getDefaultType() {
        return defaultType;
    }

    /**
     * For deserializers of non-primitives, the value may not be
     * known until later (due to multi-referencing).  In such
     * cases the deserializer registers Target object(s).  When
     * the value is known, the set(value) will be invoked for
     * each Target registered with the Deserializer.  The Target
     * object abstracts the function of setting a target with a
     * value.  See the Target interface for more info.
     * @param target
     */
    public void registerValueTarget(Target target)
    {
        if (targets == null) {
            targets = new Vector();
        }
        
        targets.addElement(target);
    }
    
    /**
     * Get the Value Targets of the Deserializer.
     * @return Vector of Target objects or null
     */
    public Vector getValueTargets() {
        return targets;
    }
    
    /**
     * Remove the Value Targets of the Deserializer.
     */
    public void removeValueTargets() {
        if (targets != null) {
            targets = null;
        }
    }

    /**
     * Move someone else's targets to our own (see DeserializationContext)
     *
     * The DeserializationContext only allows one Deserializer to  
     * wait for a unknown multi-ref'ed value.  So to ensure
     * that all of the targets are updated, this method is invoked
     * to copy the Target objects to the waiting Deserializer.
     * @param other is the Deserializer to copy targets from.
     */
    public void moveValueTargets(Deserializer other)
    {
        if ((other == null) || (other.getValueTargets() == null)) {
            return;
        }
        
        if (targets == null) {
            targets = new Vector();
        }
        
        targets.addAll(other.getValueTargets());
        other.removeValueTargets();
    }
    
    /**
     * Some deserializers (ArrayDeserializer) require
     * all of the component values to be known before the
     * value is complete.
     * (For the ArrayDeserializer this is important because
     * the elements are stored in an ArrayList, and all values
     * must be known before the ArrayList is converted into the
     * expected array.
     *
     * This routine is used to indicate when the components are ready.
     * The default (true) is useful for most Deserializers.
     */
    public boolean componentsReady() {
        return (componentsReadyFlag ||
                (!isHref && isEnded && activeDeserializers.isEmpty()));
    }

    /** 
     * The valueComplete() method is invoked when the
     * end tag of the element is read.  This results
     * in the setting of all registered Targets (see
     * registerValueTarget).
     * Note that the valueComplete() only processes
     * the Targets if componentReady() returns true.
     * So if you override componentReady(), then your
     * specific Deserializer will need to call valueComplete()
     * when your components are ready (See ArrayDeserializer)
     */
    public void valueComplete() throws SAXException
    {
        if (componentsReady()) {            
            if (targets != null) {
                for (int i = 0; i < targets.size(); i++) {
                    Target target = (Target) targets.get(i);
                    target.set(value);
                    if (debugEnabled) {
                        log.debug(Messages.getMessage("setValueInTarget00",
                                                            "" + value, "" + target));
                    }
                }
                // Don't need targets any more, so clear them
                removeValueTargets();
            }
        }
    }
    
    public void addChildDeserializer(Deserializer dSer) {
        // Keep track of our active deserializers.  This enables us to figure
        // out whether or not we're really done in the case where we get to
        // our end tag, but still have open hrefs for members.
    	if (activeDeserializers != null) {
    		activeDeserializers.add(dSer);
    	}        
        // In concert with the above, we make sure each field deserializer
        // lets us know when it's done so we can take it off our list.
        dSer.registerValueTarget(new CallbackTarget(this, dSer));
    }


    /** 
     * Subclasses may override these
     */

    /**
     * This method is invoked when an element start tag is encountered.
     * DeserializerImpl provides default behavior, which involves the following:
     *   - directly handling the deserialization of a nill value
     *   - handling the registration of the id value.
     *   - handling the registration of a fixup if this element is an href.
     *   - calling onStartElement to do the actual deserialization if not nill or href cases.
     * @param namespace is the namespace of the element
     * @param localName is the name of the element
     * @param prefix is the prefix of the element
     * @param attributes are the attributes on the element...used to get the type
     * @param context is the DeserializationContext
     *
     * Normally a specific Deserializer (FooDeserializer) should extend DeserializerImpl.
     * Here is the flow that will occur in such cases:
     *   1) DeserializerImpl.startElement(...) will be called and do the id/href/nill stuff.
     *   2) If real deserialization needs to take place DeserializerImpl.onStartElement will be
     *      invoked, which will attempt to install the specific Deserializer (FooDeserializer)
     *   3) The FooDeserializer.startElement(...) will be called to do the Foo specific stuff.
     *      This results in a call to FooDeserializer.onStartElement(...) if startElement was
     *      not overridden.
     *   4) The onChildElement(...) method is called for each child element.  Nothing occurs
     *      if not overridden.  The FooDeserializer.onStartChild(...) method should return 
     *      the deserializer for the child element.
     *   5) When the end tag is reached, the endElement(..) method is invoked.  The default 
     *      behavior is to handle hrefs/ids, call onEndElement and then call the Deserializer
     *      valueComplete method.
     * 
     * So the methods that you potentially want to override are:
     *   onStartElement, onStartChild, componentsReady, setValue(object, hint)
     * You probably should not override startElement or endElement.
     * If you need specific behaviour at the end of the element consider overriding
     * onEndElement.
     *
     * See the pre-existing Deserializers for more information.
     */
    public void startElement(String namespace, String localName,
                             String prefix, Attributes attributes,
                             DeserializationContext context)
        throws SAXException
    {
        super.startElement(namespace, localName, prefix, attributes, context);

        // If the nil attribute is present and true, set the value to null
        // and return since there is nothing to deserialize.
        if (context.isNil(attributes)) {
            value = null;
            isNil = true;
            return;
        }

        SOAPConstants soapConstants = context.getSOAPConstants();

        // If this element has an id, then associate the value with the id.
        // (Prior to this association, the MessageElement of the element is
        // associated with the id. Failure to replace the MessageElement at this
        // point will cause an infinite loop during deserialization if the 
        // current element contains child elements that cause an href back to this id.)
        // Also note that that endElement() method is responsible for the final
        // association of this id with the completed value.
        id = attributes.getValue("id");
        if (id != null) {
            context.addObjectById(id, value);
            if (debugEnabled) {
                log.debug(Messages.getMessage("deserInitPutValueDebug00", "" + value, id));
            }
            context.registerFixup("#" + id, this);
        }

        String href = attributes.getValue(soapConstants.getAttrHref());
        if (href != null) {
            isHref = true;

            Object ref = context.getObjectByRef(href);            
            if (debugEnabled) {
                log.debug(Messages.getMessage(
                        "gotForID00",
                        new String[] {"" + ref, href, (ref == null ? "*null*" : ref.getClass().toString())}));
            }
            
            if (ref == null) {
                // Nothing yet... register for later interest.
                context.registerFixup(href, this);
                return;
            }
            
            if (ref instanceof MessageElement) {
                context.replaceElementHandler(new EnvelopeHandler(this));

                SAX2EventRecorder r = context.getRecorder();
                context.setRecorder(null);
                ((MessageElement)ref).publishToHandler((DefaultHandler) context);
                context.setRecorder(r);
            } else {

                if( !href.startsWith("#") && defaultType != null && ref instanceof Part ){
                    //For attachments this is the end of the road-- invoke deserializer
                    Deserializer dser = context.getDeserializerForType(defaultType );
                    if(null != dser){          
                      dser.startElement(namespace, localName,
                             prefix, attributes,
                             context);
                      ref = dser.getValue();       
                    }
               }
                
                // If the ref is not a MessageElement, then it must be an
                // element that has already been deserialized.  Use it directly.
                value = ref;
                componentsReadyFlag = true;
                valueComplete();
            }
            
        } else {
            isHref = false;
            onStartElement(namespace, localName, prefix, attributes,
                           context);
        }
    }

    /**
     * This method is invoked after startElement when the element requires
     * deserialization (i.e. the element is not an href and the value is not nil.)
     * DeserializerImpl provides default behavior, which simply
     * involves obtaining a correct Deserializer and plugging its handler.
     * @param namespace is the namespace of the element
     * @param localName is the name of the element
     * @param prefix is the prefix of the element
     * @param attributes are the attributes on the element...used to get the type
     * @param context is the DeserializationContext
     */
    public void onStartElement(String namespace, String localName,
                             String prefix, Attributes attributes,
                             DeserializationContext context)
        throws SAXException
    {
        // If I'm the base class, try replacing myself with an
        // appropriate deserializer gleaned from type info.
        if (this.getClass().equals(DeserializerImpl.class)) {
            QName type = context.getTypeFromAttributes(namespace,
                                                       localName,
                                                       attributes);

            // If no type is specified, use the defaultType if available.
            // xsd:string is used if no type is provided.
            if (type == null) {
                type = defaultType;
                if (type == null) {
                    type = Constants.XSD_STRING;
                }
            }
            
            if (debugEnabled) {
                log.debug(Messages.getMessage("gotType00", "Deser", "" + type));
            }
            
            // We know we're deserializing, but we don't have
            // a specific deserializer.  So create one using the
            // attribute type qname.
            if (type != null) {
                Deserializer dser = context.getDeserializerForType(type);
                if (dser == null) {
                    dser = context.getDeserializerForClass(null);
                }
                if (dser != null) {
                    // Move the value targets to the new deserializer
                    dser.moveValueTargets(this);
                    context.replaceElementHandler((SOAPHandler) dser);
                    // And don't forget to give it the start event...
                    boolean isRef = context.isProcessingRef();
                    context.setProcessingRef(true);
                    dser.startElement(namespace, localName, prefix,
                                      attributes, context);
                    context.setProcessingRef(isRef);
                } else {
                    throw new SAXException(
                                           Messages.getMessage("noDeser00", "" + type));
                }
            }
        }
    }
    
    /**
     * onStartChild is called on each child element.
     * The default behavior supplied by DeserializationImpl is to do nothing.
     * A specific deserializer may perform other tasks.  For example a 
     * BeanDeserializer will construct a deserializer for the indicated 
     * property and return it.
     * @param namespace is the namespace of the child element
     * @param localName is the local name of the child element
     * @param prefix is the prefix used on the name of the child element
     * @param attributes are the attributes of the child element
     * @param context is the deserialization context.
     * @return is a Deserializer to use to deserialize a child (must be
     * a derived class of SOAPHandler) or null if no deserialization should
     * be performed.
     */
    public SOAPHandler onStartChild(String namespace, String localName,
                             String prefix, Attributes attributes,
                             DeserializationContext context)
        throws SAXException
    {
        return null;
    }
    
    

    /** 
     * endElement is called when the end element tag is reached.
     * It handles href/id information for multi-ref processing
     * and invokes the valueComplete() method of the deserializer
     * which sets the targets with the deserialized value.
     * @param namespace is the namespace of the child element
     * @param localName is the local name of the child element
     * @param context is the deserialization context
     */
    public final void endElement(String namespace, String localName,
                           DeserializationContext context)
        throws SAXException
    {
        super.endElement(namespace, localName, context);

        isEnded = true;
        if (!isHref) {
            onEndElement(namespace, localName, context);
        }
        
        // Time to call valueComplete to copy the value to 
        // the targets.  First a call is made to componentsReady
        // to ensure that all components are ready.
        if (componentsReady()) {
            valueComplete();
        }

        // If this element has an id, then associate the value with the id.
        // Subsequent hrefs to the id will obtain the value directly.
        // This is necessary for proper multi-reference deserialization.
        if (id != null) {
            context.addObjectById(id, value);
            if (debugEnabled) {
                log.debug(Messages.getMessage("deserPutValueDebug00", "" + value, id));
            }     
        }
    }

   /**
     * onEndElement is called by endElement.  It is not called
     * if the element has an href.
     * @param namespace is the namespace of the child element
     * @param localName is the local name of the child element
     * @param context is the deserialization context
     */
    public void onEndElement(String namespace, String localName,
                           DeserializationContext context)
        throws SAXException
    {
        // If we only have SAX events, but someone really wanted a
        // value, try sending them the contents of this element
        // as a String...
        // ??? Is this the right thing to do here?
        
        if (this.getClass().equals(DeserializerImpl.class) &&
            targets != null &&
            !targets.isEmpty()) {
            StringWriter writer = new StringWriter();
            SerializationContext serContext =
                        new SerializationContext(writer,
                                                 context.getMessageContext());
            serContext.setSendDecl(false);
            
            SAXOutputter so = null;
            so = new SAXOutputter(serContext);
            context.getCurElement().publishContents(so);
            if (!isNil) {
                value = writer.getBuffer().toString();
            }
        }
    }
    
}
