/*
* Copyright 2001-2008 Geert Bevin <gbevin[remove] at uwyn dot com>
* Licensed under the Apache License, Version 2.0 (the "License")
* $Id: Xml2BlockingRepository.java 3918 2008-04-14 17:35:35Z gbevin $
*/
package com.uwyn.rife.rep;
import com.uwyn.rife.config.Config;
import com.uwyn.rife.database.Datasources;
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.rep.exceptions.ParticipantNotFoundException;
import com.uwyn.rife.resources.ResourceFinder;
import com.uwyn.rife.tools.StringUtils;
import com.uwyn.rife.xml.Xml2Data;
import com.uwyn.rife.xml.exceptions.XmlErrorException;
import java.util.ArrayList;
import java.util.Stack;
import org.xml.sax.Attributes;
/**
* Processes a <code>Rep</code> XML document and add all the declared
* participants to a <code>BlockingRepository</code>.
*
* @author Geert Bevin (gbevin[remove] at uwyn dot com)
* @version $Revision: 3918 $
* @see BlockingRepository
* @since 1.0
*/
public class Xml2BlockingRepository extends Xml2Data
{
private BlockingRepository mRepository = null;
private String mName = null;
private boolean mBlocking = false;
private String mParameter = null;
private StringBuilder mCharacterData = null;
private String mCurrentPropertyName = null;
private Stack<String> mParticipantNameStack = null;
private Stack<PropertyValueList> mPropertyValuesStack = null;
private String mCurrentTemplateType = null;
Xml2BlockingRepository(BlockingRepository repository)
{
mRepository = repository;
}
/**
* Adds all the participants of a provided resource to the repository.
*
* @param resource the name of the resource that contains the declaration
* of the participants.
* @param resourcefinder a <code>ResourceFinder</code> that will be used
* to retrieve the resource
* @exception XmlErrorException if an error occurs during the processing
* of the document
*/
public void addRepParticipants(String resource, ResourceFinder resourcefinder)
throws XmlErrorException
{
processXml(resource, resourcefinder);
}
public void startElement(String namespaceURI, String localName, String qName, Attributes atts)
{
if (qName.equals("participant") &&
null == mCurrentPropertyName)
{
mCharacterData = new StringBuilder();
mName = atts.getValue("name");
mBlocking = false;
String blocking = atts.getValue("blocking");
if (blocking != null &&
(blocking.equals("1") ||
blocking.equals("t") ||
blocking.equals("true")))
{
mBlocking = true;
}
mParameter = atts.getValue("param");
}
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"))
{
// check if inappropriate attributes aren't used
if (qName.equals("participant"))
{
if (null == atts.getValue("name"))
{
throw new XmlErrorException("The repository 'participant' tag requires the 'name' attribute when it's used as a property value.");
}
if (atts.getValue("param") != null)
{
throw new XmlErrorException("The repository 'participant' tag can't have the 'param' attribute when it's used as a property value.");
}
}
// 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"))
{
// store the character data of the previous property value series
mPropertyValuesStack.peek().add(new PropertyValueObject(mCharacterData.toString()));
// add the property value for the configuration
mPropertyValuesStack.peek().add(new PropertyValueParticipant(Config.DEFAULT_PARTICIPANT_NAME, new PropertyValueObject(atts.getValue("param"))));
mCharacterData = new StringBuilder();
}
else if (qName.equals("rep"))
{
// do nothing
}
else
{
throw new XmlErrorException("Unsupport element name '"+qName+"'.");
}
}
public void endElement(String namespaceURI, String localName, String qName)
{
if (qName.equals("participant") &&
null == mCurrentPropertyName)
{
if (!mRepository.addParticipant(StringUtils.trim(mCharacterData.toString()), mName, mBlocking, mParameter))
{
throw new ParticipantNotFoundException(mCharacterData.toString());
}
}
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
{
mRepository.getProperties().put(mCurrentPropertyName, propvals.makePropertyValue());
}
catch (PropertyValueException e)
{
throw new PropertyConstructionException("repository", 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("repository", 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("repository", getXmlPath(), mCurrentPropertyName, e);
}
mCharacterData = new StringBuilder();
}
}
public void characters(char[] ch, int start, int length)
{
if (length > 0)
{
mCharacterData.append(String.copyValueOf(ch, start, length));
}
}
}