/drools-core/src/main/java/org/drools/core/util/AbstractBitwiseHierarchyImpl.java
https://github.com/esteban-aliverti/drools · Java · 549 lines · 400 code · 104 blank · 45 comment · 92 complexity · 240eaf35a74848625642415f8f47bc86 MD5 · raw file
- package org.drools.core.util;
- import org.drools.core.factmodel.traits.LatticeElement;
- import java.io.Externalizable;
- import java.io.IOException;
- import java.io.ObjectInput;
- import java.io.ObjectOutput;
- import java.util.ArrayList;
- import java.util.BitSet;
- import java.util.Collection;
- import java.util.Comparator;
- import java.util.LinkedHashMap;
- import java.util.List;
- import java.util.LinkedList;
- import java.util.Map;
- import java.util.SortedMap;
- import java.util.TreeMap;
- public abstract class AbstractBitwiseHierarchyImpl<H ,J extends LatticeElement<H>> implements Externalizable, CodedHierarchy<H> {
- protected SortedMap<BitSet,J> line = new TreeMap<BitSet,J>( new HierCodeComparator() );
- protected boolean fixedRoot = false;
- public int size() {
- return fixedRoot ? line.size() - 1 : line.size();
- }
- protected J getNodeByKey( BitSet key ) {
- return line.get( key );
- }
- protected abstract J getNode( H name );
- protected void remove( J node ) {
- line.remove( node.getBitMask() );
- }
- protected boolean contains( J node ) {
- return line.containsKey( node.getBitMask() );
- }
- public BitSet getCode( H val ) {
- if ( val == null ) {
- return null;
- }
- J node = getNode( val );
- return node != null ? node.getBitMask() : null;
- }
- public BitSet metMembersCode( Collection<H> vals ) {
- BitSet x = new BitSet( this.size() );
- for ( H val : vals ) {
- x.or( getNode( val ).getBitMask() );
- }
- return x;
- }
- public BitSet jointMembersCode( Collection<H> vals ) {
- BitSet x = new BitSet( this.size() );
- boolean first = true;
- for ( H val : vals ) {
- if ( first ) {
- first = false;
- x.or( getNode( val ).getBitMask() );
- } else {
- x.and( getNode( val ).getBitMask() );
- }
- }
- return x;
- }
- public BitSet meetCode( Collection<BitSet> codes ) {
- BitSet x = new BitSet( this.size() );
- for ( BitSet code : codes ) {
- x.or( code );
- }
- return x;
- }
- public BitSet joinCode( Collection<BitSet> codes ) {
- BitSet x = new BitSet( this.size() );
- boolean first = true;
- for ( BitSet code : codes ) {
- if ( first ) {
- first = false;
- x.or( code );
- } else {
- x.and( code );
- }
- }
- return x;
- }
- public List<H> getSortedMembers() {
- List<H> anx = new ArrayList<H>( size() );
- for ( J node : getNodes() ) {
- if ( node.getValue() != null ) {
- anx.add( node.getValue() );
- }
- }
- return anx;
- }
- public Collection<H> upperAncestors( BitSet key ) {
- List<H> vals = new LinkedList<H>();
- int l = key.length();
- //System.out.println( key );
- BitSet start = new BitSet( l );
- BitSet end = new BitSet( l );
- int index = 0;
- H rootVal = getMember( new BitSet() );
- if ( rootVal != null ) {
- vals.add( rootVal );
- }
- while ( index >= 0 ) {
- int s = index;
- int t = key.nextClearBit( s );
- start.clear();
- start.set( s, true );
- end.set( s, t, true );
- // System.out.println( "X >> " + s + " << " + t );
- // System.out.println( "S >> " + start );
- // System.out.println( "E >> " + end );
- // System.out.println( "E+1>> " + nextKey( end ) );
- if ( t > 0 ) {
- for ( J val : line.subMap( start, nextKey( end ) ).values() ) {
- // System.out.println( "\t " + val.getValue() );
- vals.add( val.getValue() );
- }
- }
- index = key.nextSetBit( t );
- }
- return vals;
- }
- /**
- * @param key a key, possibly the meet of a number of member keys
- * @return
- */
- public Collection<H> lowerBorder( BitSet key ) {
- return gcs( key, true );
- }
- /**
- * @param key a key, possibly the meet of a number of member keys
- * @return
- */
- public Collection<H> immediateChildren( BitSet key ) {
- return gcs( key, false );
- }
- /**
- * @param key a key, possibly the meet of a number of member keys
- * @return
- */
- Collection<H> gcs( BitSet key, boolean includeEquals ) {
- List<H> vals = new LinkedList<H>();
- List<J> border = gcsBorderNodes( key, includeEquals );
- for ( int j = 0; j < border.size(); j++ ) {
- J node = border.get( j );
- if ( node != null ) {
- vals.add( node.getValue() );
- }
- }
- return vals;
- }
- List<J> gcsBorderNodes( BitSet key, boolean includeEquals ) {
- List<J> border = new LinkedList<J>();
- int l = key.length();
- int n = line.size() != 0 ? line.lastKey().length() : 0;
- BitSet start = new BitSet( n );
- BitSet end = new BitSet( n );
- start.or( key );
- // for ( int j = l; j <= n; j++ ) {
- if ( l > n ) { return border; }
- if ( l > 0 ) {
- start.set( l - 1 );
- }
- end.set( n );
- // end.set( j );
- for ( J val : line.subMap( start, end ).values() ) {
- BitSet candidate = val.getBitMask();
- boolean minimal = true;
- int check = superset( candidate, key );
- if ( ( includeEquals && check >= 0 ) || ( ! includeEquals && check > 0 ) ) {
- // it is a descendant of the probe key
- for ( int k = 0; k < border.size(); k++ ) {
- // current border
- J ex = border.get( k );
- if ( ex != null ) {
- if ( superset( candidate, ex.getBitMask() ) >= 0 ) {
- // System.out.println( "Skipping " + val + " due to " + ex );
- minimal = false;
- break;
- } else if ( superset( ex.getBitMask(), candidate ) > 0 ) {
- // System.out.println( "Clearing " + ex + " due to " + val );
- border.set( k, null );
- }
- } // else cleared border member, continue
- }
- if ( minimal ) {
- border.add( val );
- }
- } // else no desc, ignore
- }
- // if ( j > 0 ) {
- // start.clear( j - 1 );
- // }
- // end.clear( j );
- //
- // }
- return border;
- }
- /**
- * @param key a key, possibly the meet of a number of member keys
- * @return
- */
- Collection<H> lcs( BitSet key, boolean includeEquals ) {
- List<H> vals = new LinkedList<H>();
- List<J> border = lcsBorderNodes( key, includeEquals );
- for ( int j = 0; j < border.size(); j++ ) {
- J node = border.get( j );
- if ( node != null ) {
- vals.add( node.getValue() );
- }
- }
- return vals;
- }
- List<J> lcsBorderNodes( BitSet key, boolean includeEquals ) {
- List<J> border = new ArrayList<J>();
- if ( key == null ) { return border; }
- // System.out.println( key );
- int l = key.length();
- BitSet start = new BitSet( l + 1 );
- BitSet end = new BitSet( l + 1 );
- int index = 0;
- J root = line.get( new BitSet() );
- if ( root != null ) {
- border.add( root );
- }
- while ( index >= 0 ) {
- int s = index;
- int t = key.nextClearBit( s );
- start.clear();
- start.set( s, true );
- end.set( s, t, true );
- for ( J val : line.subMap( start, nextKey( end ) ).values() ) {
- BitSet candidate = val.getBitMask();
- int comp = superset( key, candidate );
- if ( ( includeEquals && comp >= 0 ) || ( ! includeEquals && comp > 0 ) ) {
- border.add( val );
- for ( int j = 0; j < border.size(); j++ ) {
- J ex = border.get( j );
- if ( ex != null ) {
- if ( superset( candidate, ex.getBitMask() ) > 0 ) {
- // System.out.println( "Clearing " + ex + " due to " + val );
- border.set( j, null );
- }
- }
- }
- }
- // System.out.println( "\t\t " + border );
- }
- index = key.nextSetBit( t );
- }
- return border;
- }
- //------------------------------
- protected String toBinaryString( BitSet mask ) {
- return toBinaryString(mask, mask.length());
- }
- protected String toBinaryString( BitSet mask, int len ) {
- StringBuilder sb = new StringBuilder();
- for ( int j = len - 1; j >= 0; j-- ) {
- sb.append( mask.get( j ) ? "1 " : "0 " );
- }
- return sb.toString();
- }
- BitSet prevKey( BitSet key ) {
- BitSet b = new BitSet( key.length() );
- b.or( key );
- int x = key.nextSetBit( 0 );
- if ( x == 0 ) {
- b.clear( 0 );
- } else {
- b.set( 0, x, true );
- b.clear( x );
- }
- return b;
- }
- BitSet nextKey( BitSet key ) {
- int l = key.length();
- if ( l == 0 ) {
- BitSet b = new BitSet( 1 );
- b.set( 0 );
- return b;
- }
- BitSet b = new BitSet( l + 1 );
- b.or( key );
- int x = key.nextSetBit( 0 );
- if ( x == 0 ) {
- int y = b.nextClearBit( 0 );
- b.set( x, y, false );
- b.set(y);
- } else {
- b.set(0);
- }
- return b;
- }
- public static boolean supersetOrEqualset( BitSet n1, BitSet n2 ) {
- BitSet x;
- int l1 = n1.length();
- int l2 = n2.length();
- if ( l1 > l2 ) {
- x = new BitSet( l2 );
- x.or( n2 );
- x.and( n1 );
- } else {
- x = new BitSet( l1 );
- x.or( n1 );
- x.and( n2 );
- }
- return x.equals( n2 );
- }
- int superset( J n1, J n2 ) {
- return superset( n1.getBitMask(), n2.getBitMask() );
- }
- public int superset( BitSet n1, BitSet n2 ) {
- if ( n1.equals( n2 ) ) {
- return 0;
- }
- return supersetOrEqualset(n1, n2) ? 1 : -1;
- }
- protected int numBit( BitSet x ) {
- return x.length();
- }
- public void writeExternal( ObjectOutput objectOutput ) throws IOException {
- objectOutput.writeBoolean( this.fixedRoot );
- objectOutput.writeObject( this.line );
- }
- public void readExternal( ObjectInput objectInput ) throws IOException, ClassNotFoundException {
- this.fixedRoot = objectInput.readBoolean();
- this.line = (SortedMap<BitSet, J>) objectInput.readObject();
- }
- protected static class HierCodeComparator implements Comparator<BitSet>, Externalizable {
- public HierCodeComparator() {
- }
- public int compare( BitSet bitMask, BitSet yset ) {
- int lx = bitMask.length();
- int ly = yset.length();
- if ( lx == 0 && ly == 0 ) { return 0; }
- if ( lx > ly ) { return 1; }
- if ( ly > lx ) { return -1; }
- BitSet x;
- x = new BitSet( ly );
- x.or( yset );
- x.xor( bitMask );
- if ( x.isEmpty() ) { return 0; }
- int ix = x.length() - 1;
- if ( bitMask.get( ix ) ) {
- return 1;
- } else if ( yset.get( ix ) ) {
- return -1;
- } else {
- return 0;
- }
- }
- public void writeExternal(ObjectOutput objectOutput) throws IOException {
- }
- public void readExternal(ObjectInput objectInput) throws IOException, ClassNotFoundException {
- }
- }
- public static BitSet stringToBitSet( String s ) {
- BitSet b = new BitSet();
- int n = s.length();
- for( int j = 0; j < s.length(); j++ ) {
- if ( s.charAt( j ) == '1' ) {
- b.set( n - j - 1 );
- } else if ( s.charAt( j ) != '0' ) {
- throw new IllegalStateException( "The string " + s + " is not a valid bitset encoding" );
- }
- }
- return b;
- }
- //---------------needed by sub classes of TypeHierarchy---------------
- // public void addMember(LatticeElement<H> val, BitSet key) {
- // System.out.println(">>>>>>************* it should not happen");
- // }
- public void removeMember( H val ) {
- System.out.println(">>>>>>************* it should not happen");
- }
- public void removeMember(BitSet key) {
- J node = line.get(key);
- remove(node);
- }
- public Map<H, BitSet> getSortedMap() {
- Map<H,BitSet> anx = new LinkedHashMap<H, BitSet>( size() );
- for ( J node : getNodes() ) {
- if ( node.getValue() != null ) {
- anx.put( node.getValue(), node.getBitMask() );
- }
- }
- return anx;
- }
- public boolean hasKey(BitSet key) {
- return line.containsKey( key );
- }
- // public Collection<J> children(BitSet key) {
- // return null; //To change body of implemented methods use File | Settings | File Templates.
- // }
- public Collection<H> lowerDescendants( BitSet key ) {
- List<H> vals = new LinkedList<H>();
- int l = key.length();
- if ( l == 0 || line.isEmpty() ) {
- return new ArrayList( getSortedMembers() );
- }
- int n = line.lastKey().length();
- if ( l > n ) { return vals; }
- BitSet start = new BitSet( n );
- BitSet end = new BitSet( n );
- start.or( key );
- start.set( l - 1 );
- end.set( n );
- for ( J val : line.subMap( start, end ).values() ) {
- BitSet x = val.getBitMask();
- if ( superset( x, key ) >= 0 ) {
- vals.add( val.getValue() );
- }
- }
- start.clear( l - 1 );
- return vals;
- }
- protected abstract Collection<H> parentValues( J node );
- public Collection<H> parents(H x) {
- J node = getNode( x );
- return parentValues(node);
- }
- public Collection<H> parents(BitSet x) {
- J node = getNodeByKey( x );
- return parentValues( node );
- }
- public Collection<H> upperBorder(BitSet key) {
- return lcs( key, true );
- }
- public Collection<H> immediateParents(BitSet key) {
- return lcs( key, false );
- }
- public boolean isEmpty() {
- return line.isEmpty();
- }
- public void clear() {
- line.clear();
- }
- protected void add( J node ) {
- line.put(node.getBitMask(), node);
- }
- protected Collection<J> getNodes() {
- return line.values();
- }
- public H getMember( BitSet key ) {
- return line.containsKey( key ) ? line.get( key ).getValue() : null;
- }
- }