src.openwfe.org.engine.expressions.xeme.XemeUtils Maven / Gradle / Ivy
/*
* Copyright (c) 2005-2006, John Mettraux, OpenWFE.org
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* . Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* . Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* . Neither the name of the "OpenWFE" nor the names of its contributors may be
* used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* $Id: XemeUtils.java 2670 2006-05-26 19:06:15Z jmettraux $
*/
//
// XemeUtils.java
//
// [email protected]
//
// generated with
// jtmpl 1.1.01 2004/05/19 ([email protected])
//
package openwfe.org.engine.expressions.xeme;
import org.jdom.Text;
import org.jdom.CDATA;
import org.jdom.Content;
import org.jdom.Element;
import org.jdom.Document;
import org.jdom.Attribute;
import openwfe.org.xml.XmlUtils;
import openwfe.org.engine.Definitions;
import openwfe.org.engine.workitem.XmlAttribute;
import openwfe.org.engine.workitem.StringAttribute;
import openwfe.org.engine.workitem.InFlowWorkItem;
import openwfe.org.engine.expressions.ValueUtils;
import openwfe.org.engine.expressions.FlowExpression;
import openwfe.org.engine.expressions.FlowExpressionId;
import openwfe.org.engine.expressions.raw.RawExpression;
import openwfe.org.engine.impl.workitem.xml.XmlWorkItemCoder;
/**
* A utility class about Xeme, there aren't much comments here as it's just
* Lisp translation to XML.
*
* CVS Info :
*
$Author: jmettraux $
*
$Id: XemeUtils.java 2670 2006-05-26 19:06:15Z jmettraux $
*
* @author [email protected]
*/
public abstract class XemeUtils
{
private final static org.apache.log4j.Logger log = org.apache.log4j.Logger
.getLogger(XemeUtils.class.getName());
//
// CONSTANTS & co
/**
* The representation of null / nada / nil for Xeme.
*/
public final static org.jdom.Content NULL_RESULT
= new org.jdom.Text("");
//
// STATIC METHODS
/**
* Returns the size of the given content (will not count empty Text
* content).
*/
public static int size (final Content c)
{
if (c instanceof Text)
{
if (isNotEmptyText(c)) return 1;
return 0;
}
int result = 0;
final Element elt = (Element)c;
final java.util.Iterator it = elt.getContent().iterator();
while (it.hasNext())
{
final Content cc = (Content)it.next();
if (cc instanceof Element)
{
result++;
continue;
}
if (cc instanceof Text)
{
if (isNotEmptyText(cc)) result++;
}
}
return result;
}
/**
* Returns the element at nth position (index) in the given content.
*/
public static Content nth (int index, final Content c)
{
//log.debug("nth() i : "+index+" c : \n"+XmlUtils.xmlToString(c));
if (c instanceof Text)
{
final String s = ((Text)c).getTextTrim();
while (index < 0) index = s.length() + index;
if (log.isDebugEnabled())
log.debug("nth() 0 index : "+index);
if (index >= s.length()) return NULL_RESULT;
return new Text(""+s.charAt(index));
//
// wouldn't an indexation on s.split(" ") (or white-space split)
// better suit the philosophy of this method ?
}
final int size = size(c);
//log.debug("nth() list size : "+size);
while (index < 0) index = size + index;
//log.debug("nth() 1 index : "+index);
final Element elt = (Element)c;
int i = 0;
final java.util.Iterator it = elt.getContent().iterator();
while (it.hasNext())
{
final Content cc = (Content)it.next();
//log.debug("nth() i:"+i+" is \n"+XmlUtils.xmlToString(cc));
if (isNotEmptyText(cc) && (i == index)) return cc;
if (isNotEmptyText(cc)) i++;
}
return NULL_RESULT;
}
private static boolean isNotEmptyText (final Content c)
{
if ( ! (c instanceof Text)) return true;
return ((Text)c).getTextTrim().length() > 0;
}
public static Content car (final Content c)
{
if (log.isDebugEnabled())
log.debug("car() input is of class "+c.getClass().getName());
final Element elt = toElement(c);
if (elt.getContent().size() < 1)
throw new IllegalArgumentException("cannot car an empty element");
for (int i=0; i"+result.toString()+"<");
if (result instanceof Text)
{
if (((Text)result).getTextTrim().length() < 1) continue;
}
if (log.isDebugEnabled())
log.debug("car() returning >"+XmlUtils.xmlToString(result)+"<");
return (Content)result.clone();
}
return null;
}
public static Element cdr (final Content c)
{
final Element elt = toElement(c);
if (elt.getContent().size() < 1)
throw new IllegalArgumentException("cannot cdr an empty element");
Element result = (Element)elt.clone();
//log.debug("cdr() before \n"+XmlUtils.toString(result));
result = removeFirstChild(result);
//log.debug("cdr() after \n"+XmlUtils.toString(result));
return result;
}
private static Element removeFirstChild (final Element e)
{
final Content c = e.removeContent(0);
if (c == null)
return e;
if (c instanceof Element)
return e;
if (c instanceof Text && ((Text)c).getTextTrim().length() > 0)
return e;
return removeFirstChild(e);
}
/**
* Returns the tag name of the given element (null if the parameter
* is not an element).
*/
public static Text xar (final Content c)
{
final Element elt = toElement(c);
return new Text(elt.getName());
}
/**
* Given an element (c0) and another element (c1), will insert
* c0 as the first child of element c1.
*/
public static Element cons (final Content c0, final Content c1)
{
//log.debug("cons() c0 : "+c0);
//log.debug("cons() c1 : "+c1);
final Element result = toElement(c1);
result.addContent(0, (Content)c0.clone());
//log.debug("cons() result : "+result);
//log.debug("cons() result children : "+result.getChildren().size());
return result;
}
/**
* Appends two elements (two XML lists).
*/
public static Element append (final Content c0, final Content c1)
{
final Element result = toElement(c0);
final Element l1 = toElement(c1);
final java.util.Iterator it = l1.getContent().iterator();
while (it.hasNext())
{
org.jdom.Content c = (org.jdom.Content)it.next();
c = (org.jdom.Content)c.clone();
c.detach();
result.addContent(c);
}
return result;
}
/**
* Given an element (c0) and another element (c1), will change the
* name and attributes of c1 for the ones of c0.
*/
public static Element xons (final Content c0, final Content c1)
{
//
// toto
// -->
//
final org.jdom.Element eResult = toElement(c1);
if (c0 instanceof org.jdom.Text)
{
eResult.setName(((org.jdom.Text)c0).getTextTrim());
return eResult;
}
//
// regular cases
final org.jdom.Element e0 = toElement(c0);
if (e0.getChildren().size() < 1)
//
// toto
// -->
//
//
{
final String aName = e0.getName();
final String aValue = e0.getTextTrim();
eResult.setAttribute(aName, aValue);
return eResult;
}
eResult.setName(e0.getName());
final java.util.Iterator it = e0.getChildren().iterator();
while (it.hasNext())
{
final org.jdom.Element eChild = (org.jdom.Element)it.next();
final String aName = eChild.getName();
final String aValue = eChild.getTextTrim();
eResult.setAttribute(aName, aValue);
}
return eResult;
}
/**
* Returns the given element's attributes as an Element with as
* children each attribute :
*
*
* <truc a1="x" a2="y">
* <nada/>
* </truc>
* -->
* <truc>
* <a1>x<a1>
* <a2>y<a2>
* </truc>
*
*/
public static Element xdr (final Content c)
{
final Element elt = toElement(c);
final Element result = new org.jdom.Element(elt.getName());
final java.util.Iterator it = elt.getAttributes().iterator();
while (it.hasNext())
{
final Attribute a = (Attribute)it.next();
final Element e = new Element(a.getName());
e.addContent(new Text(a.getValue()));
result.addContent(e);
}
return result;
}
//
// IS METHODS ?
//
// (are ?)
public static boolean isEmpty (final Content c)
{
if ( ! (c instanceof Element)) return true;
//return ((Element)c).getContent().size() < 1;
return ((Element)c).getChildren().size() < 1;
}
public static boolean isNull (final Content c)
{
if (c == null) return true;
if (log.isDebugEnabled())
log.debug("isNull() c is \n"+XmlUtils.xmlToString(c));
if (c instanceof Element)
return (((Element)c).getContent().size() < 1);
if (c instanceof Text)
return c.equals(NULL_RESULT);
if (log.isDebugEnabled())
log.debug("isNull() returning false (default).");
return false;
}
public static boolean isAtom (final Content c)
{
return ( ! (c instanceof Element));
}
public static boolean isList (final Content c)
{
return (c instanceof Element);
}
//
// MISC
/**
* Turns an expression result (see ValueUtils) into some XML.
*/
public static Content fetchWorkitemResult
(final FlowExpression expression, final InFlowWorkItem wi)
{
final openwfe.org.engine.workitem.Attribute aResult =
ValueUtils.getResult(wi);
//return attributeToJdom(expression, aResult);
return toXemeResult(expression, aResult);
}
/**
* Turns an object into some XML content (for a given expression).
*/
public static Content toXemeResult
(final FlowExpression expression,
final Object o)
{
if (o == null)
return NULL_RESULT;
if (log.isDebugEnabled())
log.debug("toXemeResult() o.class is "+o.getClass().getName());
if (o instanceof Content)
//return (Content)((Content)o).clone();
return (Content)o;
if (o instanceof XmlAttribute)
//return (Content)((XmlAttribute)o).getContent().clone();
return ((XmlAttribute)o).getContent();
if (o instanceof String ||
o instanceof StringAttribute)
{
final String s = o.toString();
if (s.equals(""))
return NULL_RESULT;
try
{
return XmlUtils.extractXmlElement(s);
}
catch (final Throwable t)
{
log.debug
("toXemeResult() String[Attribute] doesn't contain XML");
}
}
if (o instanceof openwfe.org.engine.workitem.Attribute)
{
final XmlWorkItemCoder coder =
Definitions.getXmlCoder(expression.context());
try
{
return coder.encodeAttribute
((openwfe.org.engine.workitem.Attribute)o);
}
catch (final Exception e)
{
log.debug("toXemeResult() couldn't code attribute", e);
return NULL_RESULT;
}
}
if (o instanceof FlowExpressionId)
return new org.jdom.Text("subprocess '"+o+"'");
if (o instanceof RawExpression)
return new org.jdom.Text("process '"+o+"'");
//
// default solution
return new org.jdom.Text(o.toString());
//
// wouldn't CDATA be better ?
// or is JDOM able to determine CDATA over Text ?
}
/**
* Makes sure the passed content is an element.
* If not, an IllegalArgumentException will get thrown. If the content
* is a Text instance, this method will attempt to parse an Element
* out of it.
*/
public static Element toElement (final Content c)
{
if (c instanceof Element) return (Element)c.clone();
if (c instanceof Text)
{
final String s = ((Text)c).getText();
if (log.isDebugEnabled())
log.debug("toElement() text is >"+s+"<");
try
{
return XmlUtils.extractXmlElement(s);
}
catch (final Exception e)
{
log.debug("toElement() couldn't fetch XML");
}
}
throw new IllegalArgumentException("Not an element : "+c);
}
}