/*
* Copyright 2001-2008 Geert Bevin <gbevin[remove] at uwyn dot com>
* Licensed under the Apache License, Version 2.0 (the "License")
* $Id: Xml2Site.java 3928 2008-04-22 16:25:18Z gbevin $
*/
package com.uwyn.rife.engine;
import com.uwyn.rife.config.Config;
import com.uwyn.rife.config.RifeConfig;
import com.uwyn.rife.database.Datasources;
import com.uwyn.rife.engine.exceptions.EngineException;
import com.uwyn.rife.engine.exceptions.FlowLinkSpecificDataLinkDestIdSpecifiedException;
import com.uwyn.rife.engine.exceptions.NotFoundProcessingErrorException;
import com.uwyn.rife.engine.exceptions.ParsingErrorException;
import com.uwyn.rife.engine.exceptions.ProcessingErrorException;
import com.uwyn.rife.ioc.PropertyValue;
import com.uwyn.rife.ioc.PropertyValueList;
import com.uwyn.rife.ioc.PropertyValueObject;
import com.uwyn.rife.ioc.PropertyValueParticipant;
import com.uwyn.rife.ioc.PropertyValueTemplate;
import com.uwyn.rife.ioc.exceptions.PropertyConstructionException;
import com.uwyn.rife.ioc.exceptions.PropertyValueException;
import com.uwyn.rife.resources.ResourceFinder;
import com.uwyn.rife.resources.exceptions.ResourceFinderErrorException;
import com.uwyn.rife.xml.Xml2Data;
import com.uwyn.rife.xml.exceptions.CantFindResourceException;
import com.uwyn.rife.xml.exceptions.XmlErrorException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Stack;
import java.util.List;
import org.xml.sax.Attributes;
class Xml2Site implements SiteProcessor
{
Xml2Site()
{
}
public void processSite(SiteBuilder builder, String declarationName, ResourceFinder resourceFinder)
throws EngineException
{
XmlProcessor processor = new XmlProcessor(builder);
String processed_path = null;
try
{
// process the site xml file
try
{
processed_path = declarationName;
processor.processXml(processed_path, resourceFinder);
}
catch (CantFindResourceException e)
{
processed_path = SiteProcessor.DEFAULT_SITES_PATH+declarationName;
processor.processXml(processed_path, resourceFinder);
}
}
catch (XmlErrorException e)
{
throw new ProcessingErrorException("site", declarationName, e);
}
// obtain the modification time
if (RifeConfig.Engine.getSiteAutoReload())
{
URL resource = resourceFinder.getResource(processed_path);
if (null == resource)
{
throw new NotFoundProcessingErrorException("site", processed_path, null);
}
try
{
builder.addResourceModificationTime(new UrlResource(resource, processed_path), resourceFinder.getModificationTime(resource));
}
catch (ResourceFinderErrorException e)
{
throw new ProcessingErrorException("site", declarationName, "Error while retrieving the modification time.", e);
}
}
}
private class XmlProcessor extends Xml2Data
{
private SiteBuilder mSiteBuilder = null;
private ElementInfoBuilder mCurrentElementInfoBuilder = null;
private XmlElementInfoProcessor mCurrentElementInfoProcessor = null;
private FlowLinkBuilder mCurrentFlowLinkBuilder = null;
private String mCurrentPropertyName = null;
private String mCurrentGlobalVar = null;
private ArrayList<String> mCurrentGlobalVarDefaults = null;
private String mCurrentGlobalCookie = null;
private String mCurrentGlobalCookieDefault = null;
private StringBuilder mCharacterData = null;
private Stack<String> mParticipantNameStack = null;
private Stack<PropertyValueList> mPropertyValuesStack = null;
private String mCurrentTemplateType = null;
private String mCurrentErrorDestId = null;
private List<Class> mCurrentTypes = null;
private XmlProcessor(SiteBuilder builder)
{
mSiteBuilder = builder;
}
public void startDocument()
{
mCurrentPropertyName = null;
mCurrentGlobalVar = null;
mCurrentGlobalVarDefaults = null;
mCurrentGlobalCookie = null;
mCurrentGlobalCookieDefault = null;
mParticipantNameStack = null;
mPropertyValuesStack = null;
mCharacterData = null;
mCurrentErrorDestId = null;
mCurrentTypes = null;
}
public void endDocument()
{
mCurrentGlobalVarDefaults = null;
mCharacterData = null;
mParticipantNameStack = null;
mPropertyValuesStack = null;
}
public void startElement(String namespaceURI, String localName, String qName, Attributes atts)
{
if (qName.equals("site"))
{
mSiteBuilder.setFallback(atts.getValue("fallbackid"));
}
else if (qName.equals("subsite"))
{
mSiteBuilder = mSiteBuilder
.enterSubsiteDeclaration(atts.getValue("file"))
.setId(atts.getValue("id"))
.setUrlPrefix(atts.getValue("urlprefix"))
.enterSubsite()
.setInherits(atts.getValue("inherits"))
.setPre(atts.getValue("pre"));
}
else if (qName.equals("group"))
{
String inherits = atts.getValue("inherits");
String pre = atts.getValue("pre");
mSiteBuilder.enterGroup()
.setInherits(inherits)
.setPre(pre);
}
else if (qName.equals("globalvar"))
{
mCurrentGlobalVar = atts.getValue("name");
mCurrentGlobalVarDefaults = new ArrayList<String>();
}
else if (qName.equals("globalcookie"))
{
mCurrentGlobalCookie = atts.getValue("name");
mCurrentGlobalCookieDefault = null;
}
else if (qName.equals("globalbean"))
{
String classname = atts.getValue("classname");
String prefix = atts.getValue("prefix");
String name = atts.getValue("name");
String group = atts.getValue("group");
mSiteBuilder.addGlobalBean(classname, prefix, name, group);
}
else if (qName.equals("globalexit"))
{
String name = atts.getValue("name");
String destid = atts.getValue("destid");
boolean reflective = false;
boolean snapback = false;
boolean cancel_inheritance = false;
boolean cancel_embedding = false;
boolean redirect = false;
boolean cancel_continuations = false;
if (atts.getValue("reflect") != null &&
(atts.getValue("reflect").equals("1") ||
atts.getValue("reflect").equals("t") ||
atts.getValue("reflect").equals("true")))
{
reflective = true;
}
if (atts.getValue("snapback") != null &&
(atts.getValue("snapback").equals("1") ||
atts.getValue("snapback").equals("t") ||
atts.getValue("snapback").equals("true")))
{
snapback = true;
}
if (atts.getValue("redirect") != null &&
(atts.getValue("redirect").equals("1") ||
atts.getValue("redirect").equals("t") ||
atts.getValue("redirect").equals("true")))
{
redirect = true;
}
String inheritance = atts.getValue("inheritance");
if (inheritance != null &&
inheritance.equals("cancel"))
{
cancel_inheritance = true;
}
String embedding = atts.getValue("embedding");
if (embedding != null &&
embedding.equals("cancel"))
{
cancel_embedding = true;
}
String continuations = atts.getValue("continuations");
if (continuations != null &&
continuations.equals("cancel"))
{
cancel_continuations = true;
}
mSiteBuilder.addGlobalExit(name, destid, reflective, snapback, cancel_inheritance, cancel_embedding, redirect, cancel_continuations);
}
else if (qName.equals("arrival"))
{
boolean redirect = false;
if (atts.getValue("redirect") != null &&
(atts.getValue("redirect").equals("1") ||
atts.getValue("redirect").equals("t") ||
atts.getValue("redirect").equals("true")))
{
redirect = true;
}
mSiteBuilder.setArrival(atts.getValue("destid"), redirect);
}
else if (qName.equals("departure"))
{
mSiteBuilder.addDeparture(atts.getValue("srcid"));
}
else if (qName.equals("state"))
{
String state = atts.getValue("store");
if (null == state)
{
state = StateStoreQuery.IDENTIFIER;
}
mSiteBuilder.enterState(state);
}
else if (qName.equals("element"))
{
mCurrentElementInfoBuilder = mSiteBuilder.enterElement(atts.getValue("file"))
.setId(atts.getValue("id"))
.setUrl(atts.getValue("url"))
.setInherits(atts.getValue("inherits"))
.setPre(atts.getValue("pre"));
mCurrentElementInfoProcessor = new XmlElementInfoProcessor(mCurrentElementInfoBuilder);
mCurrentElementInfoProcessor.startElement(namespaceURI, localName, qName, atts);
String pathinfo = atts.getValue("pathinfo");
if (pathinfo != null)
{
mCurrentElementInfoBuilder.setPathInfoMode(PathInfoMode.getMode(atts.getValue("pathinfo")));
}
}
else if (qName.equals("datalink"))
{
String srcoutput = atts.getValue("srcoutput");
String srcoutbean = atts.getValue("srcoutbean");
String dest_id = atts.getValue("destid");
boolean snapback = false;
String destinput = atts.getValue("destinput");
String destinbean = atts.getValue("destinbean");
if (atts.getValue("snapback") != null &&
(atts.getValue("snapback").equals("1") ||
atts.getValue("snapback").equals("t") ||
atts.getValue("snapback").equals("true")))
{
snapback = true;
}
if (mCurrentFlowLinkBuilder != null)
{
if (dest_id != null)
{
throw new FlowLinkSpecificDataLinkDestIdSpecifiedException(getXmlPath(), mCurrentFlowLinkBuilder.getElementInfoBuilder().getElementDeclaration().getId(), mCurrentFlowLinkBuilder.getSrcExit());
}
mCurrentFlowLinkBuilder.addDataLink(srcoutput, srcoutbean, snapback, destinput, destinbean);
}
else
{
mCurrentElementInfoBuilder.addDataLink(srcoutput, srcoutbean, dest_id, snapback, destinput, destinbean);
}
}
else if (qName.equals("flowlink"))
{
String srcexit = atts.getValue("srcexit");
String destid = atts.getValue("destid");
boolean snapback = false;
boolean cancel_inheritance = false;
boolean cancel_embedding = false;
boolean redirect = false;
boolean cancel_continuations = false;
if (atts.getValue("snapback") != null &&
(atts.getValue("snapback").equals("1") ||
atts.getValue("snapback").equals("t") ||
atts.getValue("snapback").equals("true")))
{
snapback = true;
}
if (atts.getValue("redirect") != null &&
(atts.getValue("redirect").equals("1") ||
atts.getValue("redirect").equals("t") ||
atts.getValue("redirect").equals("true")))
{
redirect = true;
}
String inheritance = atts.getValue("inheritance");
if (inheritance != null &&
inheritance.equals("cancel"))
{
cancel_inheritance = true;
}
String embedding = atts.getValue("embedding");
if (embedding != null &&
embedding.equals("cancel"))
{
cancel_embedding = true;
}
String continuations = atts.getValue("continuations");
if (continuations != null &&
continuations.equals("cancel"))
{
cancel_continuations = true;
}
mCurrentFlowLinkBuilder = mCurrentElementInfoBuilder.enterFlowLink(srcexit)
.destId(destid)
.snapback(snapback)
.cancelInheritance(cancel_inheritance)
.cancelEmbedding(cancel_embedding)
.redirect(redirect)
.cancelContinuations(cancel_continuations);
}
else if (qName.equals("autolink"))
{
String srcexit = atts.getValue("srcexit");
String destid = atts.getValue("destid");
boolean cancel_inheritance = false;
boolean cancel_embedding = false;
boolean redirect = false;
boolean cancel_continuations = false;
if (atts.getValue("redirect") != null &&
(atts.getValue("redirect").equals("1") ||
atts.getValue("redirect").equals("t") ||
atts.getValue("redirect").equals("true")))
{
redirect = true;
}
String inheritance = atts.getValue("inheritance");
if (inheritance != null &&
inheritance.equals("cancel"))
{
cancel_inheritance = true;
}
String embedding = atts.getValue("embedding");
if (embedding != null &&
embedding.equals("cancel"))
{
cancel_embedding = true;
}
String continuations = atts.getValue("continuations");
if (continuations != null &&
continuations.equals("cancel"))
{
cancel_continuations = true;
}
mCurrentElementInfoBuilder.addAutoLink(srcexit, destid, cancel_inheritance, cancel_embedding, redirect, cancel_continuations);
}
else if (qName.equals("property"))
{
mCurrentPropertyName = atts.getValue("name");
mCharacterData = new StringBuilder();
mPropertyValuesStack = new Stack<PropertyValueList>();
mPropertyValuesStack.push(new PropertyValueList());
}
else if (qName.equals("participant") ||
qName.equals("datasource"))
{
// store the character data of the previous property value series
mPropertyValuesStack.peek().add(new PropertyValueObject(mCharacterData.toString()));
// initialize the new nested participant
if (null == mParticipantNameStack)
{
mParticipantNameStack = new Stack<String>();
}
mCharacterData = new StringBuilder();
String name;
if (qName.equals("datasource"))
{
name = Datasources.DEFAULT_PARTICIPANT_NAME;
}
else
{
name = atts.getValue("name");
}
mParticipantNameStack.push(name);
mPropertyValuesStack.push(new PropertyValueList());
}
else if (qName.equals("template"))
{
// store the character data of the previous property value series
mPropertyValuesStack.peek().add(new PropertyValueObject(mCharacterData.toString()));
mCurrentTemplateType = atts.getValue("type");
mCharacterData = new StringBuilder();
mPropertyValuesStack.push(new PropertyValueList());
}
else if (qName.equals("config"))
{
if (mCurrentElementInfoProcessor != null &&
mCurrentElementInfoProcessor.getDefaults() != null)
{
mCurrentElementInfoProcessor.startElement(namespaceURI, localName, qName, atts);
}
else
{
if (mCharacterData != null &&
Config.hasRepInstance())
{
mCharacterData.append(Config.getRepInstance().getString(atts.getValue("param"), ""));
}
}
}
else if (qName.equals("default"))
{
if (mCurrentElementInfoProcessor != null)
{
mCurrentElementInfoProcessor.startElement(namespaceURI, localName, qName, atts);
}
else
{
mCharacterData = new StringBuilder();
}
}
else if (qName.equals("errorhandler"))
{
mCurrentErrorDestId = atts.getValue("destid");
mCurrentTypes = new ArrayList<Class>();
}
else if (qName.equals("type"))
{
String classname = atts.getValue("classname");
try
{
mCurrentTypes.add(Class.forName(classname));
}
catch (ClassNotFoundException e)
{
throw new ParsingErrorException("site", getXmlPath(), "Can't find the type class '"+classname+"' for the error handler that targets the element '"+mCurrentErrorDestId+"'", e);
}
}
else
{
if (mCurrentElementInfoProcessor != null)
{
mCurrentElementInfoProcessor.startElement(namespaceURI, localName, qName, atts);
}
else
{
throw new ParsingErrorException("site", getXmlPath(), "Unsupport element name '"+qName+"'.", null);
}
}
}
public void endElement(String namespaceURI, String localName, String qName)
{
if (qName.equals("element"))
{
mCurrentElementInfoProcessor = null;
mCurrentElementInfoBuilder.leaveElement();
mCurrentElementInfoBuilder = null;
}
else if (qName.equals("flowlink"))
{
mCurrentFlowLinkBuilder.leaveFlowLink();
mCurrentFlowLinkBuilder = null;
}
else if (qName.equals("subsite"))
{
mSiteBuilder = mSiteBuilder.leaveSubsite().leaveSubsiteDeclaration();
}
else if (qName.equals("state"))
{
mSiteBuilder.leaveState();
}
else if (qName.equals("group"))
{
mSiteBuilder.leaveGroup();
}
else if (qName.equals("globalvar"))
{
String[] defaults = null;
if (mCurrentGlobalVarDefaults.size() > 0)
{
defaults = new String[mCurrentGlobalVarDefaults.size()];
defaults = mCurrentGlobalVarDefaults.toArray(defaults);
}
mSiteBuilder.addGlobalVar(mCurrentGlobalVar, defaults);
mCurrentGlobalVar = null;
mCurrentGlobalVarDefaults = null;
}
else if (qName.equals("globalcookie"))
{
mSiteBuilder.addGlobalCookie(mCurrentGlobalCookie, mCurrentGlobalCookieDefault);
mCurrentGlobalCookie = null;
mCurrentGlobalCookieDefault = null;
}
else if (qName.equals("property"))
{
PropertyValueList propvals = mPropertyValuesStack.pop();
// store the character data to the current property value series
propvals.add(new PropertyValueObject(mCharacterData.toString()));
try
{
if (mCurrentElementInfoBuilder != null)
{
mCurrentElementInfoBuilder.addProperty(mCurrentPropertyName, propvals.makePropertyValue());
}
else if (mSiteBuilder.getSubsiteDeclaration() != null)
{
mSiteBuilder.getSubsiteDeclaration().addProperty(mCurrentPropertyName, propvals.makePropertyValue());
}
else
{
mSiteBuilder.addProperty(mCurrentPropertyName, propvals.makePropertyValue());
}
}
catch (PropertyValueException e)
{
throw new PropertyConstructionException("site", getXmlPath(), mCurrentPropertyName, e);
}
mCharacterData = null;
mCurrentPropertyName = null;
mPropertyValuesStack = null;
}
else if (qName.equals("participant") ||
qName.equals("datasource"))
{
PropertyValueList propvals = mPropertyValuesStack.pop();
// store the character data to the current property value series
propvals.add(new PropertyValueObject(mCharacterData.toString()));
try
{
PropertyValue propval = new PropertyValueParticipant(mParticipantNameStack.pop(), propvals.makePropertyValue());
ArrayList<PropertyValue> containing_propval_series = mPropertyValuesStack.peek();
containing_propval_series.add(propval);
}
catch (PropertyValueException e)
{
throw new PropertyConstructionException("site", getXmlPath(), mCurrentPropertyName, e);
}
mCharacterData = new StringBuilder();
}
else if (qName.equals("template"))
{
PropertyValueList propvals = mPropertyValuesStack.pop();
// store the character data to the current property value series
propvals.add(new PropertyValueObject(mCharacterData.toString()));
try
{
PropertyValue propval = new PropertyValueTemplate(mCurrentTemplateType, propvals.makePropertyValue().getValueString());
ArrayList<PropertyValue> containing_propval_series = mPropertyValuesStack.peek();
containing_propval_series.add(propval);
}
catch (PropertyValueException e)
{
throw new PropertyConstructionException("site", getXmlPath(), mCurrentPropertyName, e);
}
mCharacterData = new StringBuilder();
}
else if (qName.equals("default"))
{
if (mCurrentElementInfoProcessor != null)
{
mCurrentElementInfoProcessor.endElement(namespaceURI, localName, qName);
}
else
{
if (null != mCurrentGlobalCookie)
{
mCurrentGlobalCookieDefault = mCharacterData.toString();
}
else if( null != mCurrentGlobalVar )
{
mCurrentGlobalVarDefaults.add(mCharacterData.toString());
}
mCharacterData = null;
}
}
else if (qName.equals("errorhandler"))
{
mSiteBuilder.addErrorHandler(mCurrentErrorDestId, mCurrentTypes);
mCurrentErrorDestId = null;
mCurrentTypes = null;
}
else
{
if (mCurrentElementInfoProcessor != null)
{
mCurrentElementInfoProcessor.endElement(namespaceURI, localName, qName);
}
}
}
public void characters(char[] ch, int start, int length)
{
if (mCurrentElementInfoProcessor != null &&
mCurrentElementInfoProcessor.getDefaults() != null)
{
mCurrentElementInfoProcessor.characters(ch, start, length);
}
else
{
if (length > 0 &&
mCharacterData != null)
{
mCharacterData.append(String.copyValueOf(ch, start, length));
}
}
}
}
}