Package de.danet.an.workflow.tools.soapclient

Source Code of de.danet.an.workflow.tools.soapclient.JDOMAxisDeserializer

/*
* This file is part of the WfMOpen project.
* Copyright (C) 2001-2003 Danet GmbH (www.danet.de), GS-AN.
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*
* $Id: JDOMAxisDeserializer.java 1607 2006-09-29 12:32:13Z drmlipp $
*
* $Log$
* Revision 1.1.1.1  2003/06/30 20:05:17  drmlipp
* Initial import
*
* Revision 1.4  2003/06/27 08:51:44  lipp
* Fixed copyright/license information.
*
* Revision 1.3  2003/06/26 22:07:46  lipp
* Fixed deserializer.
*
* Revision 1.2  2003/06/26 15:32:57  lipp
* Improved version.
*
* Revision 1.1  2003/06/25 15:50:29  lipp
* New SOAP client that makes wsif obsolete.
*
*/
package de.danet.an.workflow.tools.soapclient;


import java.util.Enumeration;
import java.util.Iterator;
import java.util.Vector;

import javax.xml.namespace.QName;

import org.apache.axis.Constants;
import org.apache.axis.Part;
import org.apache.axis.encoding.DeserializationContext;
import org.apache.axis.encoding.Deserializer;
import org.apache.axis.encoding.DeserializerTarget;
import org.apache.axis.encoding.Target;
import org.apache.axis.message.EnvelopeHandler;
import org.apache.axis.message.MessageElement;
import org.apache.axis.message.SAX2EventRecorder;
import org.apache.axis.message.SOAPHandler;
import org.apache.axis.soap.SOAPConstants;

import org.jdom.Element;
import org.jdom.Namespace;
import org.jdom.Text;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;

/**
* General purpose serializer/deserializerFactory for JDOM in the AXIS
* implementation of the JAX-RPC interface.
* Creates a simple org.jdom.Element for the parsed xml content,
* preserving the stucture and text content.
* This class uses a stack to notice the created nodes. So we do not
* need to generate new instances of this class for every recursive
* descent (initialized by the onStartChild() call).
*/
public class JDOMAxisDeserializer
    extends SOAPHandler implements Deserializer {

    private static final org.apache.commons.logging.Log logger
  = org.apache.commons.logging.LogFactory.getLog
  (JDOMAxisDeserializer.class);

    private Element value = null;
    private QName defaultType;
    private Vector targets = null;

    private StringBuffer textBuffer = null;
   
    /**
     * Default constructor.
     */
    public JDOMAxisDeserializer() {
  super();
    }
   
    /**
     * This method is invoked when an element start tag is encountered.
     * @param namespace is the namespace of the element
     * @param localName is the name of the element
     * @param prefix is the prefix
     * @param attributes are the attributes on the element
     * @param context is the DeserializationContext
     * @throws SAXException not thrown
     */
    public void startElement(String namespace, String localName,
                             String prefix, Attributes attributes,
                             DeserializationContext context)
        throws SAXException {
  if (logger.isDebugEnabled ()) {
      logger.debug ("startElement: {" + namespace + "}" + localName);
  }
        super.startElement(namespace, localName, prefix, attributes, context);

  // axis sometimes resends the start event, ignore
  if (value != null) {
      return;
  }

  value = new Element (localName, prefix, namespace);
  if (attributes != null) {
      for (int i = 0; i < attributes.getLength(); i++) {
    String aName = attributes.getLocalName(i); // Attr name
    if ("".equals(aName)) {
        aName = attributes.getQName(i);
    }
    String aValue = attributes.getValue(i);
    value.setAttribute(aName, aValue);
      }
  }

        String id = attributes.getValue("id");
        if (id != null) {
            context.addObjectById(id, value);
        }

        SOAPConstants soapConstants
      = context.getMessageContext().getSOAPConstants();
        String href = attributes.getValue(soapConstants.getAttrHref());
        if (href == null) {
            onStartElement(namespace, localName, prefix, attributes, context);
  } else {
            Object ref = context.getObjectByRef(href);           
            if (ref == null) {
                // Nothing yet... register for later interest.
                context.registerFixup(href, this);
            } else 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 = (Element)ref;
    return;
            }
        }
    }

    /**
     * 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
     * @param context is the DeserializationContext
     * @throws SAXException not thrown
     */
    public void onStartElement(String namespace, String localName,
                             String prefix, Attributes attributes,
                             DeserializationContext context)
        throws SAXException {
  if (logger.isDebugEnabled ()) {
      logger.debug ("onStartElement: {" + namespace + "}" + localName);
  }
    }

    /**
     * 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.
     * @throws SAXException not thrown
     */
    public SOAPHandler onStartChild(String namespace, String localName,
                             String prefix, Attributes attributes,
                             DeserializationContext context)
        throws SAXException {
  if (logger.isDebugEnabled ()) {
      logger.debug ("onStartChild: {" + namespace + "}" + localName);
  }
  SOAPHandler hdlr = new JDOMAxisDeserializer ();
        ((Deserializer)hdlr).registerValueTarget
      (new DeserializerTarget(this, value));
  return hdlr;
    }

    /**
     * Gets called when the text of an XML element handled by this
     * deserializer is reached. 
     * We simply add the current text to a text buffer. The completed
     * buffer will be evaluated in the onEndElement() method.
     * @param chars characters
     * @param start start
     * @param end end
     * @throws SAXException SAXException
     */
    public void characters(char [] chars, int start, int end)
  throws SAXException {
  String s = new String(chars, start, (end-start));
  if (textBuffer == null) {
      textBuffer = new StringBuffer(s);
  } else {
      textBuffer.append(s);
  }
    }
   
    /**
     * 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
     * @throws SAXException not thrown
     */
    public void endElement(String namespace, String localName,
                           DeserializationContext context)
        throws SAXException {
  if (logger.isDebugEnabled ()) {
      logger.debug ("endElement: {" + namespace + "}" + localName);
  }
        super.endElement(namespace, localName, context);

  if (textBuffer!=null) {
      value.addContent(new Text(textBuffer.toString()));
      textBuffer=null;
  }
  valueComplete();
    }

   /**
    * 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
    * @throws SAXException not thrown
    */
    public void onEndElement(String namespace, String localName,
           DeserializationContext context)
        throws SAXException {
  if (logger.isDebugEnabled ()) {
      logger.debug ("onEndElement: {" + namespace + "}" + localName);
  }
    }

    /**
     * Get the deserialized value.
     * @return Object representing deserialized value or null
     */
    public Object getValue() {
  if (logger.isDebugEnabled ()) {
      logger.debug ("getValue returns: " + value);
  }
  return value;
    }

    /**
     * Set the deserialized value.
     * @param value Object representing deserialized value
     */
    public void setValue(Object value) {
  if (logger.isDebugEnabled ()) {
      logger.debug ("setValue to: " + value);
  }
  this.value = (Element)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
     * @param hint a hint
     */
    public Object getValue(Object hint) {
  if (logger.isDebugEnabled ()) {
      logger.debug ("getValue with hint returns: null");
  }
  return null;
    }

    /**
     * From axis callback interface.
     * @param value the value
     * @param hint the hint
     * @throws SAXException not thrown
     */
    public void setValue(Object value, Object hint) throws SAXException {
    }

    /**
     * If the deserializer has component values (like ArrayDeserializer)
     * this method sets the specific component via the hint.
     * The default implementation does nothing.
     * @param value Object representing deserialized value or null
     * @throws SAXException if an error occurs
     * @param hint a hint
     */
    public void setChildValue(Object value, Object hint) throws SAXException {
  if (logger.isDebugEnabled ()) {
      logger.debug ("setChildValue with hint " + hint + " to: " + value);
  }
  Element child = (Element)value;
  if (!child.getNamespace().equals (Namespace.NO_NAMESPACE)
      || !child.getName().equals("multiRef")) {
      this.value.addContent (child);
  } else {
      for (Iterator i = child.getChildren().iterator(); i.hasNext();) {
    this.value.addContent ((Element)((Element)i.next()).clone());
      }
      if (child.getText () != null) {
    this.value.addContent (child.getText ());
      }
  }
    }

   /**
     * 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.
     * @param qName default type
     */
    public void setDefaultType(QName qName) {
  defaultType = qName;
    }

    /**
     * Return the default type.
     * @return default type
     * @see #setDefaultType
     */
    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 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.clear();
            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();
        }
        Enumeration e = other.getValueTargets().elements();
        while (e.hasMoreElements()) {
            targets.addElement(e.nextElement());
        }
        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.
     * @return <code>true</code> if component ready
     */
    public boolean componentsReady() {
  return true;
    }

    /**
     * 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)
     * @throws SAXException not thrown
     */
    public void valueComplete() throws SAXException {
        if (componentsReady()) {           
            if (targets != null) {
                Enumeration e = targets.elements();
                while (e.hasMoreElements()) {
                    Target target = (Target)e.nextElement();
                    target.set(value);
                }
                // Don't need targets any more, so clear them
                removeValueTargets();
            }
        }
    }

    /**
     * JAX-RPC compliant method which returns mechanism type.
     * @return the mechanism
     */
    public String getMechanismType() {
        return Constants.AXIS_SAX;
    }


}
TOP

Related Classes of de.danet.an.workflow.tools.soapclient.JDOMAxisDeserializer

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.