Hello Stan,
Dont know whether the code will fit here but sincere attempt to put whatsoever is done by me. Will post the other parts in next post.
package sisl.project.rulesparser;
import sisl.project.rule.Rule;
import sisl.project.rule.RuleSet;
import sisl.project.rule.Declaration;
import sisl.project.rule.Extraction;
import sisl.project.rule.RuleConstructionException;
import sisl.project.spi.ObjectType;
import sisl.project.spi.Extractor;
import sisl.project.spi.Condition;
import sisl.project.spi.Consequence;
import sisl.project.spi.Duration;
import sisl.project.smf.Configuration;
import sisl.project.smf.SemanticModule;
import sisl.project.smf.SemanticsRepository;
import sisl.project.smf.RuleFactory;
import sisl.project.smf.ObjectTypeFactory;
import sisl.project.smf.ConditionFactory;
import sisl.project.smf.ExtractorFactory;
import sisl.project.smf.ConsequenceFactory;
import sisl.project.smf.DurationFactory;
import sisl.project.smf.FactoryException;
import sisl.project.smf.DefaultSemanticsRepository;
import sisl.project.smf.NoSuchSemanticModuleException;
import org.xml.sax.Attributes;
import org.xml.sax.Locator;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;
import org.xml.sax.SAXNotRecognizedException;
import org.xml.sax.helpers.DefaultHandler;
import java.io.Reader;
import java.io.InputStream;
import java.net.URL;
import java.util.Map;
import java.util.HashMap;
import java.util.LinkedList;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import javax.xml.parsers.ParserConfigurationException;
import java.text.MessageFormat;
public class RuleJavaSetReader extends DefaultHandler
{
// ----------------------------------------------------------------------
// Constants
// ----------------------------------------------------------------------
/** Namespace URI for the general tags. */
public static final
String RULES_NAMESPACE_URI = "http://drools.org/rules";
private static final String JAXP_SCHEMA_LANGUAGE =
"http://java.sun.com/xml/jaxp/properties/schemaLanguage";
static final String W3C_XML_SCHEMA =
"http://www.w3.org/2001/XMLSchema";
private static String SCHEMA_SOURCE =
"http://java.sun.com/xml/jaxp/properties/schemaSource";
private static final int STATE_NONE = 0;
private static final int STATE_OBJECT_TYPE = 2;
private static final int STATE_CONDITION = 3;
private static final int STATE_EXTRACTION = 4;
private static final int STATE_CONSEQUENCE = 5;
private static final int STATE_DURATION = 6;
// ----------------------------------------------------------------------
// Instance members
// ----------------------------------------------------------------------
private int state;
/** SAX parser. */
private SAXParser parser;
/** Locator for errors. */
private Locator locator;
/** Current rule-set being built. */
private RuleSet ruleSet;
/** Current rule. */
private Rule rule;
/** Current declaration. */
private Declaration declaration;
/** Current extraction. */
private Extraction extraction;
/** Stack of configurations. */
private LinkedList configurationStack;
/** Current configuration text. */
private StringBuffer characters;
/** Start-tag functors. */
private Map starters;
/** End-tag functors. */
private Map enders;
/** Repository of semantic modules. */
private SemanticsRepository repo;
// ----------------------------------------------------------------------
// Constructors
// ----------------------------------------------------------------------
/** Construct.
*
* Uses the default JAXP SAX parser and the default classpath-based
* code DefaultSemanticModule /code .
*/
public RuleSetReader()
{
this.state = STATE_NONE;
this.starters = new HashMap();
this.enders = new HashMap();
this.configurationStack = new LinkedList();
// - - - - - - - - - - - - - - - - - - - -
// - - - - - - - - - - - - - - - - - - - -
bindStarter( RULES_NAMESPACE_URI,"rule-set",
new Starter()
{
void start(Attributes attrs) throws SAXException
{
startRuleSet( attrs );
}
} );
bindEnder( RULES_NAMESPACE_URI,"rule-set",
new Ender()
{
void end() throws SAXException
{
endRuleSet();
}
} );
bindStarter( RULES_NAMESPACE_URI,"parameter",
new Starter()
{
void start(Attributes attrs)
throws SAXException
{
startParameter( attrs );
}
} );
bindEnder( RULES_NAMESPACE_URI,
"parameter",
new Ender()
{
void end()
throws SAXException
{
endParameter();
}
} );
bindStarter( RULES_NAMESPACE_URI,
"declaration",
new Starter()
{
void start(Attributes attrs)
throws SAXException
{
startDeclaration( attrs );
}
} );
bindEnder( RULES_NAMESPACE_URI,
"declaration",
new Ender()
{
void end()
throws SAXException
{
endDeclaration();
}
} );
}
/** Construct.
*
* Uses the default classpath-based code DefaultSemanticModule /code .
*
* @param parser The SAX parser.
*/
public RuleSetReader(SAXParser parser)
{
this();
this.parser = parser;
}
/** Construct.
*
* @param repo The semantics repository.
* @param parser The SAX parser.
*/
public RuleSetReader(SemanticsRepository repo,SAXParser parser)
{
this( parser );
this.repo = repo;
}
/** Construct.
*
* @param repo The semantics repository.
*/
public RuleSetReader(SemanticsRepository repo)
{
this();
this.repo = repo;
}
// ----------------------------------------------------------------------
// Instance methods
// ----------------------------------------------------------------------
/** Read a RuleSet from a URL
* @param url The rule-set URL.
* @return The rule-set.
* @throws Exception If an error occurs during the parse.
*/
public RuleSet read(URL url) throws Exception
{
return read( new InputSource( url.toExternalForm() ) );
}
public RuleSet read(Reader reader) throws Exception
{
return read( new InputSource( reader ) );
}
public RuleSet read(InputStream inputStream) throws Exception
{
return read( new InputSource( inputStream ) );
}
public RuleSet read(String url) throws Exception
{
return read( new InputSource( url ) );
}
public RuleSet read(InputSource in) throws Exception
{
SAXParser parser = null;
ClassLoader cl = Thread.currentThread().getContextClassLoader();
if ( cl == null )
{
cl = RuleSetReader.class.getClassLoader();
}
if ( this.parser == null )
{
SAXParserFactory factory = SAXParserFactory.newInstance();
factory.setNamespaceAware(true);
String isValidating = System.getProperty("drools.schema.validating");
if (isValidating == null) isValidating = "true";
factory.setValidating(Boolean.valueOf(isValidating).booleanValue());
parser = factory.newSAXParser();
try
{
InputStream java = cl.getResourceAsStream("META-INF/java.xsd");
InputStream python = cl.getResourceAsStream("META-INF/python.xsd");
InputStream groovy = cl.getResourceAsStream("META-INF/groovy.xsd");
InputStream rules = cl.getResourceAsStream("META-INF/rules.xsd");
java.util.List schemaList = new java.util.ArrayList();
if (java != null) schemaList.add(java);
if (python != null) schemaList.add(python);
if (groovy != null) schemaList.add(groovy);
if (rules != null) schemaList.add(rules);
parser.setProperty(JAXP_SCHEMA_LANGUAGE, W3C_XML_SCHEMA);
//parser.setProperty(SCHEMA_SOURCE, (InputStream[]) schemaList.toArray(new InputStream[0]));
parser.setProperty(SCHEMA_SOURCE, new InputStream[] {java, rules});
}
catch(SAXNotRecognizedException e)
{
e.printStackTrace();
System.err.println("Your SAX parser is not JAXP 1.2 compliant.");
}
}
else
{
parser = this.parser;
}
if ( ! parser.isNamespaceAware() )
{
throw new ParserConfigurationException( "parser must be namespace-aware" );
}
if ( this.repo == null )
{
try
{
this.repo = DefaultSemanticsRepository.getInstance();
}
catch (Exception e)
{
e.printStackTrace();
}
}
parser.parse( in,this );
return this.ruleSet;
}
public RuleSet getRuleSet()
{
return this.ruleSet;
}
/** @see org.xml.sax.ContentHandler
*/
public void setLocator(Locator locator)
{
this.locator = locator;
}
public Locator getLocator()
{
return this.locator;
}
/** @see org.xml.sax.ContentHandler
*/
public void startElement(String uri,String localName,String qname,Attributes attrs) throws SAXException
{
Starter starter = lookupStarter( uri,localName );
if ( starter != null )
{
starter.start( attrs );
}
else
{
try
{
SemanticModule module = this.repo.lookupSemanticModule( uri );
if ( this.rule == null )
{
if ( module.getRuleFactoryNames().contains( localName ) )
{
startRule( module,
localName,
attrs );
}
else
{
throw new SAXParseException( "unknown tag '" + localName + "' in namespace '" + uri + "'",
getLocator() );
}
}
else if ( this.declaration != null )
{
if ( module.getObjectTypeFactoryNames().contains( localName ) )
{
startObjectType( module,
localName,
attrs );
}
else
{
throw new SAXParseException( "unknown tag '" + localName + "' in namespace '" + uri + "'",
getLocator() );
}
}
else
{
if ( module.getDurationFactoryNames().contains( localName ) )
{
startDuration( module,
localName,
attrs );
} else if ( module.getConditionFactoryNames().contains( localName ) )
{
startCondition( module,
localName,
attrs );
}
else if ( module.getExtractorFactoryNames().contains( localName ) )
{
startExtraction( module,
localName,
attrs );
}
else if ( module.getConsequenceFactoryNames().contains( localName ) )
{
startConsequence( module,
localName,
attrs );
}
else
{
throw new SAXParseException( "unknown tag '" + localName + "' in namespace '" + uri + "'",
getLocator() );
}
}
}
catch (NoSuchSemanticModuleException e)
{
throw new SAXParseException( "no semantic module for namespace '" + uri + "' (" + localName + ")",
getLocator() );
}
}
}
/** @see org.xml.sax.ContentHandler
*/
public void endElement(String uri,
String localName,
String qname)
throws SAXException
{
Ender ender = lookupEnder( uri,
localName );
if ( ender != null )
{
ender.end();
}
else
{
if ( this.configurationStack.size() = 1 )
{
try
{
SemanticModule module = this.repo.lookupSemanticModule( uri );
switch ( this.state )
{
case ( STATE_OBJECT_TYPE ):
{
endObjectType( module,
localName );
break;
}
case ( STATE_CONDITION ):
{
endCondition( module,
localName );
break;
}
case ( STATE_DURATION ):
{
endDuration( module,
localName );
break;
}
case ( STATE_EXTRACTION ):
{
endExtraction( module,
localName );
break;
}
case ( STATE_CONSEQUENCE ):
{
endConsequence( module,
localName );
break;
}
default:
{
endRule();
}
}
}
catch (NoSuchSemanticModuleException e)
{
throw new SAXParseException( "no semantic module for namespace '" + uri + "' (" + localName + ")",
getLocator() );
}
}
else
{
endConfiguration();
}
}
}
/** Start a <rule-set>.
*
* @param attrs Tag attributes.
*
* @throws SAXException If an error occurs during parse.
*/
protected void startRuleSet(Attributes attrs)
throws SAXException
{
if ( this.ruleSet != null )
{
throw new SAXParseException( "rule-set may not be nested",
getLocator() );
}
String ruleSetName = attrs.getValue( "name" );
String ruleSetDesc = attrs.getValue( "description" );
if ( ruleSetName == null
||
ruleSetName.trim().equals( "" ) )
{
throw new SAXParseException( "rule-set requires a 'name' attribute",
getLocator() );
}
this.ruleSet = new RuleSet( ruleSetName.trim() );
if ( ruleSetDesc == null
||
ruleSetDesc.trim().equals( "" ) )
{
this.ruleSet.setDocumentation( "" );
}
else
{
this.ruleSet.setDocumentation( ruleSetDesc );
}
}
/** End a <rule-set>.
*
* @throws SAXException If an error occurs during parse.
*/
protected void endRuleSet()
throws SAXException
{
// nothing
}
protected void startRule(SemanticModule module,
String localName,
Attributes attrs)
throws SAXException
{
RuleFactory factory = module.getRuleFactory( localName );
startConfiguration( localName,
attrs );
Configuration config = endConfiguration();
try
{
this.rule = factory.newRule( config );
startRule( rule,
attrs );
}
catch (FactoryException e)
{
throw new SAXParseException( "error constructing rule",
getLocator(),
e );
}
}
protected void startRule(Rule rule,
Attributes attrs )
throws SAXException
{
String salienceStr = attrs.getValue( "salience" );
String ruleDesc = attrs.getValue( "description" );
if ( ! ( salienceStr == null
||
salienceStr.trim().equals( "" ) ) )
{
try
{
int salience = Integer.parseInt( salienceStr.trim() );
rule.setSalience( salience );
}
catch (NumberFormatException e)
{
throw new SAXParseException( "invalid number value for 'salience' attribute: " + salienceStr.trim(),
getLocator() );
}
}
if ( ! ( ruleDesc == null
||
ruleDesc.trim().equals( "" ) ) )
{
rule.setDocumentation( ruleDesc );
}
}
/** End a <rule>.
*
* @throws SAXException If an error occurs during parse.
*/
protected void endRule()
throws SAXException
{
try
{
this.ruleSet.addRule( this.rule );
this.rule = null;
}
catch (RuleConstructionException e)
{
throw new SAXParseException( "error adding rule",
getLocator(),
e );
}
}
/** Start a <parameter>.
*
* @param attrs Tag attributes.
*
* @throws SAXException If an error occurs during parse.
*/
protected void startParameter(Attributes attrs)
throws SAXException
{
startParameterOrDeclaration( "parameter",
attrs );
}
/** End a <parameter>.
*
* @throws SAXException If an error occurs during parse.
*/
protected void endParameter()
throws SAXException
{
if ( this.declaration.getObjectType() == null )
{
throw new SAXParseException( "parameter requires an object-type",
getLocator() );
}
this.rule.addParameterDeclaration( this.declaration );
this.declaration = null;
}
/** Start a <declaration>.
*
* @param attrs Tag attributes.
*
* @throws SAXException If an error occurs during parse.
*/
protected void startDeclaration(Attributes attrs)
throws SAXException
{
startParameterOrDeclaration( "declaration",
attrs );
}
/** End a <declaration>.
*
* @throws SAXException If an error occurs during parse.
*/
protected void endDeclaration()
throws SAXException
{
if ( this.declaration.getObjectType() == null )
{
throw new SAXParseException( "declaration requires an object-type",
getLocator() );
}
this.rule.addDeclaration( this.declaration );
this.declaration = null;
}
/** Start a <parameter> or <declaration>.
*
* @param tagName Tag name.
* @param attrs Tag attributes.
*
* @throws SAXException If an error occurs during parse.
*/
private void startParameterOrDeclaration(String tagName,
Attributes attrs)
throws SAXException
{
if ( this.rule == null )
{
throw new SAXParseException( " " + tagName + " must occur within a rule",
getLocator() );
}
String identifier = attrs.getValue( "identifier" );
if ( identifier == null
||
identifier.trim().equals( "" ) )
{
throw new SAXParseException( "" + tagName + " requires an 'identifier' attribute",
getLocator() );
}
this.declaration = new Declaration( identifier.trim() );
}
/** Start an object-type.
* @param module SemanticModule.
* @param localName Tag name.
* @param attrs Tag attributes.
*
* @throws SAXException If an error occurs during parse.
*/
protected void startObjectType(SemanticModule module,
String localName,
Attributes attrs)
throws SAXException
{
this.state = STATE_OBJECT_TYPE;
startConfiguration( localName,
attrs );
}
/** End object-type.
*
* @throws SAXException If an error occurs during parse.
*/
protected void endObjectType(SemanticModule module,
String localName)
throws SAXException
{
Configuration config = endConfiguration();
ObjectTypeFactory factory = module.getObjectTypeFactory( localName );
try
{
ObjectType objectType = factory.newObjectType( config );
this.declaration.setObjectType( objectType );
}
catch (FactoryException e)
{
throw new SAXParseException( "error constructing object type",
getLocator(),
e );
}
finally
{
this.state = STATE_NONE;
}
}
/** Start an extraction.
*
* @param module Semantic module.
* @param localName Tag name.
* @param attrs Tag attributes.
*
* @throws SAXException If an error occurs during parse.
*/
protected void startExtraction(SemanticModule module,
String localName,
Attributes attrs)
throws SAXException
{
this.state = STATE_EXTRACTION;
String targetDeclName = attrs.getValue( "target" );
if ( targetDeclName == null
||
targetDeclName.trim().equals( "" ) )
{
throw new SAXParseException( "extraction requires a 'target' attribute",
getLocator() );
}
Declaration targetDecl = this.rule.getDeclaration( targetDeclName.trim() );
if ( targetDecl == null )
{
throw new SAXParseException( "'" + targetDeclName + "' is not a valid declaration",
getLocator() );
}
this.extraction = new Extraction( targetDecl );
startConfiguration( localName,
attrs );
}
/** End an extraction.
*
* @throws SAXException If an error occurs during parse.
*/
protected void endExtraction(SemanticModule module,
String localName)
throws SAXException
{
Configuration config = endConfiguration();
ExtractorFactory factory = module.getExtractorFactory( localName );
try
{
Extractor extractor = factory.newExtractor( config,
this.rule.getAllDeclarations() );
this.extraction.setExtractor( extractor );
this.rule.addExtraction( this.extraction );
this.extraction = null;
}
catch (FactoryException e)
{
throw new SAXParseException( "error constructing extractor",
getLocator(),
e );
}
finally
{
this.state = STATE_NONE;
}
}
protected void startDuration(SemanticModule module,
String name,
Attributes attrs)
throws SAXException
{
this.state = STATE_DURATION;
startConfiguration( name,
attrs );
}
/** End a condition.
*
* @throws SAXException If an error occurs during parse.
*/
protected void endDuration( SemanticModule module,
String localName)
throws SAXException
{
Configuration config = endConfiguration();
DurationFactory factory = module.getDurationFactory( localName );
try
{
Duration duration = factory.newDuration( config,
this.rule.getAllDeclarations() );
this.rule.setDuration( duration );
}
catch (FactoryException e)
{
throw new SAXParseException( "error constructing duration",
getLocator(),
e );
}
finally
{
this.state = STATE_NONE;
}
}
/** Start a condition.
*
* @param module Semantic module.
* @param name Tag name.
* @param attrs Tag attributes.
*
* @throws SAXException If an error occurs during parse.
*/
protected void startCondition(SemanticModule module,
String name,
Attributes attrs)
throws SAXException
{
this.state = STATE_CONDITION;
startConfiguration( name,
attrs );
}
/** End a condition.
*
* @throws SAXException If an error occurs during parse.
*/
protected void endCondition(SemanticModule module,
String localName)
throws SAXException
{
Configuration config = endConfiguration();
ConditionFactory factory = module.getConditionFactory( localName );
try
{
Condition condition = factory.newCondition( config,
this.rule.getAllDeclarations() );
this.rule.addCondition( condition );
}
catch (FactoryException e)
{
throw new SAXParseException( "error constructing condition",
getLocator(),
e );
}
finally
{
this.state = STATE_NONE;
}
}
/** Start a consequence.
*
* @param module Semantic module.
* @param name Tag name.
* @param attrs Tag attributes.
*
* @throws SAXException If an error occurs during parse.
*/
protected void startConsequence(SemanticModule module,
String name,
Attributes attrs)
throws SAXException
{
this.state = STATE_CONSEQUENCE;
startConfiguration( name,
attrs );
}
/** End a consequence.
*
* @throws SAXException If an error occurs during parse.
*/
protected void endConsequence(SemanticModule module,
String localName)
throws SAXException
{
Configuration config = endConfiguration();
ConsequenceFactory factory = module.getConsequenceFactory( localName );
try
{
Consequence consequence = factory.newConsequence( config,
this.rule.getAllDeclarations() );
this.rule.setConsequence( consequence );
}
catch (FactoryException e)
{
throw new SAXParseException( "error constructing consequence",
getLocator(),
e );
}
finally
{
this.state = STATE_NONE;
}
}
/** Start a configuration node.
*
* @param name Tag name.
* @param attrs Tag attributes.
*
* @throws SAXException If an error occurs during parse.
*/
protected void startConfiguration(String name,
Attributes attrs)
throws SAXException
{
this.characters = new StringBuffer();
DefaultConfiguration config = new DefaultConfiguration( name );
int numAttrs = attrs.getLength();
for ( int i = 0 ; i numAttrs ; ++i )
{
config.setAttribute( attrs.getLocalName( i ),
attrs.getValue( i ) );
}
if ( this.configurationStack.isEmpty() )
{
this.configurationStack.addLast( config );
}
else
{
((DefaultConfiguration)this.configurationStack.getLast()).addChild( config );
}
}
/** @see org.xml.sax.ContentHandler
*/
public void characters(char[] chars,
int start,
int len)
throws SAXException
{
if ( this.characters != null )
{
this.characters.append( chars,
start,
len );
}
}
/** End a configuration node.
*
* @return The configuration.
*/
protected Configuration endConfiguration()
{
DefaultConfiguration config = (DefaultConfiguration) this.configurationStack.removeLast();
config.setText( this.characters.toString() );
this.characters = null;
return config;
}
/** Lookup a code Starter /code functor.
*
* @param uri Tag uri.
* @param name Tag name.
*
* @return The starter.
*/
Starter lookupStarter(String uri,
String name)
{
return (Starter) this.starters.get( uri + " " + name );
}
/** Bind a code Starter /code functor.
*
* @param uri Tag uri.
* @param name Tag name.
* @param starter Starter.
*/
void bindStarter(String uri,
String name,
Starter starter)
{
this.starters.put( uri + " " + name,
starter );
}
/** Lookup an code Ender /code functor.
*
* @param uri Tag uri.
* @param name Tag name.
*
* @return The starter.
*/
Ender lookupEnder(String uri,
String name)
{
return (Ender) this.enders.get( uri + " " + name );
}
/** Bind a code Ender /code functor.
*
* @param uri Tag uri.
* @param name Tag name.
* @param ender Ender.
*/
void bindEnder(String uri,
String name,
Ender ender)
{
this.enders.put( uri + " " + name,
ender );
}
private MessageFormat message =
new MessageFormat("({0}: {1}, {2}): {3}");
private void print(SAXParseException x)
{
String msg = message.format(new Object[]
{
x.getSystemId(),
new Integer(x.getLineNumber()),
new Integer(x.getColumnNumber()),
x.getMessage()
});
System.out.println(msg);
}
public void warning(SAXParseException x)
{
print(x);
}
public void error(SAXParseException x)
{
print(x);
}
public void fatalError(SAXParseException x)
throws SAXParseException
{
print(x);
throw x;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
/** Starter functor.
*/
abstract static class Starter
{
/** Start tag.
*
* @param attrs Tag attributes.
*
* @throws SAXException If an error occurs during parse.
*/
abstract void start(Attributes attrs)
throws SAXException;
}
/** Starter functor.
*/
abstract static class Ender
{
/** End tag.
*
* @throws SAXException If an error occurs during parse.
*/
abstract void end()
throws SAXException;
}
}