📄 logictransformer.java
字号:
package org.drools.rule;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
/**
* LogicTransformation is reponsible for removing redundant nodes and move Or
* nodes upwards.
*
* This class does not turn Exists into two Nots at this stage, that role is
* delegated to the Builder.
*
* @author mproctor
*
*/
class LogicTransformer
{
private final Map duplicateTransformations = new HashMap( );
private final Map orTransformations = new HashMap( );
private static LogicTransformer INSTANCE = null;
static LogicTransformer getInstance()
{
if ( INSTANCE == null )
{
INSTANCE = new LogicTransformer( );
}
return INSTANCE;
}
LogicTransformer()
{
initialize( );
}
/**
* sets up the parent->child transformations map
*
*/
private void initialize()
{
// these pairs will have their duplciates removed
addTransformationPair( And.class,
And.class );
addTransformationPair( Or.class,
Or.class );
addTransformationPair( Exist.class,
Exist.class );
// these pairs will be transformed
addTransformationPair( Not.class,
Or.class,
new NotOrTransformation( ) );
addTransformationPair( Exist.class,
Or.class,
new ExistOrTransformation( ) );
addTransformationPair( And.class,
Or.class,
new AndOrTransformation( ) );
}
private void addTransformationPair(Class parent,
Class child)
{
Map map = duplicateTransformations;
Set childSet = (Set) map.get( child );
if ( childSet == null )
{
childSet = new HashSet( );
map.put( parent,
childSet );
}
childSet.add( child );
}
private void addTransformationPair(Class parent,
Class child,
Object method)
{
Map map = orTransformations;
Map childMap = (Map) map.get( parent );
if ( childMap == null )
{
childMap = new HashMap( );
map.put( parent,
childMap );
}
childMap.put( child,
method );
}
And[] transform(And and)
{
And cloned = (And) and.clone();
processTree( cloned );
// Scan for any Child Ors, if found we need apply the AndOrTransformation
// And assign the result to the null declared or
Or or = null;
for ( Iterator it = cloned.getChildren( ).iterator( ); it.hasNext(); )
{
Object object = it.next( );
if ( object instanceof Or )
{
or = (Or) applyOrTransformation( cloned,
(ConditionalElement) object );
break;
}
}
And[] ands = null;
// Or will be null if there are no Ors in our tree
if ( or == null )
{
// No or so just assign
ands = new And[] { cloned };
}
else
{
ands = new And[ or.getChildren().size() ];
int i = 0;
for (Iterator it = or.getChildren().iterator(); it.hasNext(); )
{
ands[i] = (And) it.next();
i++;
}
}
return ands;
}
/**
* Traverses a Tree, during the process it transforms Or nodes moving the
* upwards and it removes duplicate logic statement, this does not include
* Not nodes.
*
* Traversal involves three levels the graph for each iteration. The first
* level is the current node, this node will not be transformed, instead
* what we are interested in are the children of the current node (called
* the parent nodes) and the children of those parents (call the child
* nodes).
*
* @param ce
*/
void processTree(ConditionalElement ce)
{
List newChildren = new ArrayList( );
for ( Iterator it = ce.getChildren( ).iterator( ); it.hasNext( ); )
{
Object object = it.next( );
if ( object instanceof ConditionalElement )
{
ConditionalElement parent = (ConditionalElement) object;
processTree( parent );
checkForAndRemoveDuplicates( parent );
// Scan for any Child Ors, if found we need to move the Or
// upwards
for ( Iterator orIter = parent.getChildren( ).iterator( ); orIter.hasNext( ); )
{
Object object2 = orIter.next( );
if ( object2 instanceof Or )
{
newChildren.add( applyOrTransformation( parent,
(ConditionalElement) object2 ) );
it.remove( );
break;
}
}
}
}
// Add all the transformed children
ce.getChildren( ).addAll( newChildren );
}
/**
* Given a parent and child checks if they are duplicates and that they set
* to have duplicates removed
*
* @param parent
* @param child
* @return
*/
boolean removeDuplicate(ConditionalElement parent,
ConditionalElement child)
{
if ( this.duplicateTransformations.get( parent.getClass( ) ) != null )
{
return ((HashSet) this.duplicateTransformations.get( parent.getClass( ) )).contains( child.getClass( ) );
}
return false;
}
/**
* Removes duplicates, children of the duplicate added to the parent and the
* duplicate child is removed by the parent method.
*
*/
void checkForAndRemoveDuplicates(ConditionalElement parent)
{
List newChildren = new ArrayList( );
for ( Iterator it = parent.getChildren( ).iterator( ); it.hasNext( ); )
{
Object object = it.next( );
// Remove the duplicate if the classes are the same and
// removeDuplicate method returns true
if ( parent.getClass( ).isInstance( object ) && removeDuplicate( parent,
(ConditionalElement) object ) )
{
ConditionalElement child = (ConditionalElement) object;
for ( Iterator childIter = child.getChildren( ).iterator( ); childIter.hasNext( ); )
{
newChildren.add( childIter.next( ) );
}
it.remove( );
}
}
parent.getChildren( ).addAll( newChildren );
}
ConditionalElement applyOrTransformation(ConditionalElement parent,
ConditionalElement child)
{
OrTransformation transformation = null;
Map map = (HashMap) this.orTransformations.get( parent.getClass( ) );
if ( map != null )
{
transformation = (OrTransformation) map.get( child.getClass( ) );
}
if ( transformation == null )
{
throw new RuntimeException( "applyOrTransformation could not find transformation for parent '" + parent.getClass( ).getName( ) + "' and child '" + child.getClass( ).getName( ) + "'" );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -