📄 abstractrulebase.java
字号:
* @throws RuleIntegrationException
* if an error prevents complete construction of the network for
* the <code>Rule</code>.
* @throws FactException
* @throws InvalidPatternException
*/
public void addPackage(final Package newPkg) throws PackageIntegrationException {
newPkg.checkValidity();
final Package pkg = (Package) this.pkgs.get( newPkg.getName() );
// Iterate each workingMemory and lock it
// This is so we don't update the Rete network during propagation
for ( final Iterator it = this.workingMemories.keySet().iterator(); it.hasNext(); ) {
final AbstractWorkingMemory workingMemory = (AbstractWorkingMemory) it.next();
workingMemory.getLock().lock();
}
if ( pkg != null ) {
mergePackage( pkg,
newPkg );
} else {
this.pkgs.put( newPkg.getName(),
newPkg );
}
final Map newGlobals = newPkg.getGlobals();
// Check that the global data is valid, we cannot change the type
// of an already declared global variable
for ( final Iterator it = newGlobals.keySet().iterator(); it.hasNext(); ) {
final String identifier = (String) it.next();
final Class type = (Class) newGlobals.get( identifier );
if ( this.globals.containsKey( identifier ) && !this.globals.get( identifier ).equals( type ) ) {
throw new PackageIntegrationException( pkg );
}
}
this.globals.putAll( newGlobals );
final Rule[] rules = newPkg.getRules();
for ( int i = 0; i < rules.length; ++i ) {
addRule( rules[i] );
}
this.packageClassLoader.addClassLoader( newPkg.getPackageCompilationData().getClassLoader() );
// Iterate each workingMemory and attempt to fire any rules, that were activated as a result
// of the new rule addition. Unlock after fireAllRules();
for ( final Iterator it = this.workingMemories.keySet().iterator(); it.hasNext(); ) {
final AbstractWorkingMemory workingMemory = (AbstractWorkingMemory) it.next();
workingMemory.fireAllRules();
workingMemory.getLock().unlock();
}
}
/**
* Merge a new package with an existing package.
* Most of the work is done by the concrete implementations,
* but this class does some work (including combining imports, compilation data, globals,
* and the actual Rule objects into the package).
*/
private void mergePackage(final Package pkg,
final Package newPkg) throws PackageIntegrationException {
final Map globals = pkg.getGlobals();
final List imports = pkg.getImports();
// First update the binary files
// @todo: this probably has issues if you add classes in the incorrect order - functions, rules, invokers.
final PackageCompilationData compilationData = pkg.getPackageCompilationData();
final PackageCompilationData newCompilationData = newPkg.getPackageCompilationData();
final String[] files = newCompilationData.list();
for ( int i = 0, length = files.length; i < length; i++ ) {
compilationData.write( files[i],
newCompilationData.read( files[i] ) );
}
// Merge imports
imports.addAll( newPkg.getImports() );
// Add invokers
compilationData.putAllInvokers( newCompilationData.getInvokers() );
// Add globals
for ( final Iterator it = newPkg.getGlobals().keySet().iterator(); it.hasNext(); ) {
final String identifier = (String) it.next();
final Class type = (Class) globals.get( identifier );
if ( globals.containsKey( identifier ) && !globals.get( identifier ).equals( type ) ) {
throw new PackageIntegrationException( "Unable to merge new Package",
newPkg );
}
}
globals.putAll( newPkg.getGlobals() );
//Add rules into the RuleBase package
//as this is needed for individual rule removal later on
Rule[] newRules = newPkg.getRules();
for ( int i = 0; i < newRules.length; i++ ) {
Rule newRule = newRules[i];
if (pkg.getRule( newRule.getName() ) == null) {
pkg.addRule( newRule );
}
}
}
protected void addRule(final Rule rule) throws InvalidPatternException {
if ( !rule.isValid() ) {
throw new IllegalArgumentException( "The rule called " + rule.getName() + " is not valid. Check for compile errors reported." );
}
}
public void removePackage(final String packageName) {
final Package pkg = (Package) this.pkgs.get( packageName );
// Iterate each workingMemory and lock it
// This is so we don't update the Rete network during propagation
for ( final Iterator it = this.workingMemories.keySet().iterator(); it.hasNext(); ) {
final AbstractWorkingMemory workingMemory = (AbstractWorkingMemory) it.next();
workingMemory.getLock().lock();
}
final Rule[] rules = pkg.getRules();
for ( int i = 0; i < rules.length; ++i ) {
removeRule( rules[i] );
}
this.packageClassLoader.removeClassLoader( pkg.getPackageCompilationData().getClassLoader() );
pkg.clear();
// getting the list of referenced globals
final Set referencedGlobals = new HashSet();
for ( final Iterator it = this.pkgs.values().iterator(); it.hasNext(); ) {
final org.drools.rule.Package pkgref = (org.drools.rule.Package) it.next();
if ( pkgref != pkg ) {
referencedGlobals.addAll( pkgref.getGlobals().keySet() );
}
}
// removing globals declared inside the package that are not shared
for ( final Iterator it = pkg.getGlobals().keySet().iterator(); it.hasNext(); ) {
final String globalName = (String) it.next();
if ( !referencedGlobals.contains( globalName ) ) {
this.globals.remove( globalName );
}
}
// removing the package itself from the list
this.pkgs.remove( pkg.getName() );
// Iterate and unlock
for ( final Iterator it = this.workingMemories.keySet().iterator(); it.hasNext(); ) {
final AbstractWorkingMemory workingMemory = (AbstractWorkingMemory) it.next();
workingMemory.getLock().unlock();
}
}
public void removeRule(final String packageName,
final String ruleName) {
final Package pkg = (Package) this.pkgs.get( packageName );
final Rule rule = pkg.getRule( ruleName );
// Iterate each workingMemory and lock it
// This is so we don't update the Rete network during propagation
for ( final Iterator it = this.workingMemories.keySet().iterator(); it.hasNext(); ) {
final AbstractWorkingMemory workingMemory = (AbstractWorkingMemory) it.next();
workingMemory.getLock().lock();
}
removeRule( rule );
pkg.removeRule( rule );
// Iterate and unlock
for ( final Iterator it = this.workingMemories.keySet().iterator(); it.hasNext(); ) {
final AbstractWorkingMemory workingMemory = (AbstractWorkingMemory) it.next();
workingMemory.getLock().unlock();
}
}
protected abstract void removeRule(Rule rule);
protected void addWorkingMemory(final WorkingMemory workingMemory,
final boolean keepReference) {
if ( keepReference ) {
this.workingMemories.put( workingMemory,
AbstractRuleBase.PRESENT );
}
}
public Set getWorkingMemories() {
return this.workingMemories.keySet();
}
public RuleBaseConfiguration getConfiguration() {
return this.config;
}
public WorkingMemory newWorkingMemory(InputStream stream) throws IOException, ClassNotFoundException {
return newWorkingMemory( stream,
true );
}
public WorkingMemory newWorkingMemory(InputStream stream,
boolean keepReference ) throws IOException, ClassNotFoundException {
final ObjectInputStreamWithLoader streamWithLoader = new ObjectInputStreamWithLoader( stream,
this.packageClassLoader );
AbstractWorkingMemory workingMemory = ( AbstractWorkingMemory ) streamWithLoader.readObject();
workingMemory.setRuleBase( this );
return workingMemory;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -