src.openwfe.org.engine.expressions.ChildrenTracker Maven / Gradle / Ivy
/*
* Copyright (c) 2001-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: ChildrenTracker.java 2835 2006-06-18 20:20:30Z jmettraux $
*/
//
// ChildrenTracker.java
//
// [email protected]
//
// generated with
// jtmpl 1.1.01 2004/05/19 ([email protected])
//
package openwfe.org.engine.expressions;
import openwfe.org.xml.XmlUtils;
import openwfe.org.engine.Definitions;
import openwfe.org.engine.launch.Launcher;
import openwfe.org.engine.workitem.InFlowWorkItem;
import openwfe.org.engine.expressions.raw.RawExpression;
/**
* This class is used by SubProcessRefExpression to keep track of nested
* children evaluation and results.
* Currently, the implementation is XML only, maybe later, the tracker will
* be cut into an interface and its [XML] implementation.
*
* CVS Info :
*
$Author: jmettraux $
*
$Id: ChildrenTracker.java 2835 2006-06-18 20:20:30Z jmettraux $
*
* @author [email protected]
*/
public class ChildrenTracker
{
private final static org.apache.log4j.Logger log = org.apache.log4j.Logger
.getLogger(ChildrenTracker.class.getName());
//
// CONSTANTS & co
//
// FIELDS
private String[] childrenToMap = null;
private String remainingContent = null;
private InFlowWorkItem workitem = null;
private /*transient*/ org.jdom.Element xmlContent = null;
private int position = -1;
private java.util.Map results = null;
//
// CONSTRUCTORS
/**
* As it's a serializable bean, this class has an empty constructor.
*/
public ChildrenTracker ()
{
super();
}
/**
* The '2nd step constructor' used by SubProcessRefExpression when
* creating the ChildrenTracker.
*/
public void init
(final String initialContent,
final String[] childrenToMap,
final InFlowWorkItem wi)
throws
ApplyException
{
//
// given elements
this.remainingContent = initialContent;
this.childrenToMap = childrenToMap;
this.workitem = (InFlowWorkItem)wi.clone();
//
// determined elements
try
{
initializeXmlContent(true);
}
catch (final Exception e)
{
log.warn
("failed to parse children out of \n"+this.remainingContent, e);
throw new ApplyException
("failed to parse children", e);
}
this.position = 0;
this.results = new java.util.HashMap();
}
protected void initializeXmlContent (final boolean force)
throws Exception
{
if (force || this.xmlContent == null)
{
this.xmlContent = XmlUtils.extractXmlElement(this.remainingContent);
if (this.xmlContent == null) return;
this.xmlContent = cleanElement(this.xmlContent);
this.remainingContent = XmlUtils.xmlToString(this.xmlContent);
}
}
//
// BEAN METHODS
public String[] getChildrenToMap ()
{
return this.childrenToMap;
}
public void setChildrenToMap (final String[] s)
{
this.childrenToMap = s;
}
public String getRemainingContent ()
{
return this.remainingContent;
}
public void setRemainingContent (final String s)
{
this.remainingContent = s;
}
/**
* The SubProcessRefExpression when initting an instance of ChildrenTracker
* gives it the applied workitem, a copy of it is stored here an will be
* used to apply each child.
* After the children got evaluated and applied, the SubProcessRefExpression
* will also use the workitem stored here to launch the subprocess itself.
*/
public InFlowWorkItem getWorkitem ()
{
return this.workitem;
}
public void setWorkitem (final InFlowWorkItem wi)
{
this.workitem = wi;
}
public int getPosition ()
{
return this.position;
}
public void setPosition (final int i)
{
this.position = i;
}
public java.util.Map getResults ()
{
return this.results;
}
public void setResults (final java.util.Map m)
{
this.results = m;
}
//
// METHODS from ChildrenTracker
/**
* Returns true if there are more children to eval.
*/
public boolean hasNext ()
{
//log.debug
// ("hasNext() ? "+(this.position < this.childrenToMap.length));
return (this.position < this.childrenToMap.length);
}
/**
* Applies the next child.
*
* @param owner the SubProcessRefExpression using this tracker
*/
public void applyNext (final FlowExpression owner)
throws ReplyException
{
final InFlowWorkItem wi = (InFlowWorkItem)this.workitem.clone();
final org.jdom.Content c = fetchFirstChild();
if (c == null)
{
//log.debug("applyNext() no child");
ValueUtils.setResult(wi, "");
owner.reply(wi);
return;
}
//log.debug("applyNext() child is \n"+XmlUtils.xmlToString(c));
try
{
final Launcher launcher = Definitions.getLauncher(owner.context());
//log.debug("applyNext() owner is "+owner.getId());
final RawExpression next = launcher.eval(owner, c, wi);
//log.debug("applyNext() next is "+next.getId());
owner.storeItself();
next.apply(wi);
//final ExpressionPool pool = (ExpressionPool)Definitions
// .getExpressionPool(owner.context());
//pool.apply(next.getId(), wi);
}
catch (final Throwable t)
{
throw new ReplyException
("failed to apply next [nested] child", t);
}
}
/**
* This method is called by the SubProcessRefExpression upon receiving
* a reply from a child.
* The next step for SubProcessRefExpression is to
*/
public void reply (final InFlowWorkItem wi)
{
//log.debug("reply() "+this+" this.position is "+this.position);
final String childName = this.childrenToMap[this.position];
//final Object childValue = ValueUtils.getResult(wi).clone();
final Object childValue = ValueUtils.getResult(wi);
//log.debug
// ("reply() childName >"+childName+"< --> value ["+childValue+"]");
this.results.put(childName, childValue);
this.position++;
}
//
// METHODS
/*
* fetches the first child of the current xmlContent (makes sure it's
* removed from the xmlContent too).
*/
private org.jdom.Content fetchFirstChild ()
throws ReplyException
{
try
{
initializeXmlContent(false);
}
catch (final Exception e)
{
throw new ReplyException
("failed to prepare xml content", e);
}
if (this.xmlContent == null ||
this.xmlContent.getContent().size() < 1)
{
return null;
}
//return (org.jdom.Content)this.xmlContent.getContent().get(0);
final org.jdom.Content c = this.xmlContent.removeContent(0);
this.remainingContent = XmlUtils.toString(this.xmlContent);
return c;
}
//
// STATIC METHODS
private static org.jdom.Element cleanElement
(final org.jdom.Element elt)
{
final org.jdom.Element result = new org.jdom.Element(elt.getName());
final java.util.Iterator it = elt.getContent().iterator();
while (it.hasNext())
{
final org.jdom.Content c = (org.jdom.Content)it.next();
if (c instanceof org.jdom.Text)
if (((org.jdom.Text)c).getTextTrim().length() < 1) continue;
//log.debug("cleanElement() adding "+XmlUtils.xmlToString(c));
result.addContent((org.jdom.Content)c.clone());
}
return result;
}
}