Package org.drools.core.util

Source Code of org.drools.core.util.AbstractBitwiseHierarchyImpl$HierCodeComparator

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;
    }

}
TOP

Related Classes of org.drools.core.util.AbstractBitwiseHierarchyImpl$HierCodeComparator

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.