⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 logictransformer.java

📁 jboss规则引擎
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
package org.drools.rule;

/*
 * Copyright 2005 JBoss Inc
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *      http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
import java.util.Map;
import java.util.Set;

/**
 * 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 ( LogicTransformer.INSTANCE == null ) {
            LogicTransformer.INSTANCE = new LogicTransformer();
        }

        return LogicTransformer.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( Exists.class,
                               Exists.class );

        // these pairs will be transformed
        addTransformationPair( Not.class,
                               Or.class,
                               new NotOrTransformation() );
        addTransformationPair( Exists.class,
                               Or.class,
                               new ExistOrTransformation() );
        addTransformationPair( And.class,
                               Or.class,
                               new AndOrTransformation() );
    }

    private void addTransformationPair(final Class parent,
                                       final Class child) {
        final Map map = this.duplicateTransformations;
        Set childSet = (Set) map.get( child );
        if ( childSet == null ) {
            childSet = new HashSet();
            map.put( parent,
                     childSet );
        }
        childSet.add( child );
    }

    private void addTransformationPair(final Class parent,
                                       final Class child,
                                       final Object method) {
        final Map map = this.orTransformations;
        Map childMap = (Map) map.get( parent );
        if ( childMap == null ) {
            childMap = new HashMap();
            map.put( parent,
                     childMap );
        }
        childMap.put( child,
                      method );
    }

    And[] transform(final And and) throws InvalidPatternException {
        final 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 ( final Iterator it = cloned.getChildren().iterator(); it.hasNext(); ) {
            final Object object = it.next();
            if ( object instanceof Or ) {
                or = (Or) applyOrTransformation( cloned,
                                                 (GroupElement) 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};
            checkForAndRemoveDuplicates( ands[0] );            
        } else {
            ands = new And[or.getChildren().size()];
            int i = 0;
            for ( final Iterator it = or.getChildren().iterator(); it.hasNext(); ) {
                final Object object = it.next();
                if ( object.getClass() == And.class ) {
                    ands[i] = (And) object;
                } else {
                    final And newAnd = new And();
                    newAnd.addChild( and );
                    ands[i] = newAnd;
                }

                checkForAndRemoveDuplicates( ands[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(final GroupElement ce) throws InvalidPatternException {

        for ( final ListIterator it = ce.getChildren().listIterator(); it.hasNext(); ) {
            final Object object = it.next();
            if ( object instanceof GroupElement ) {
                final GroupElement parent = (GroupElement) object;

                processTree( parent );

                checkForAndRemoveDuplicates( parent );

                // Scan for any Child Ors, if found we need to move the Or
                // upwards
                for ( final Iterator orIter = parent.getChildren().iterator(); orIter.hasNext(); ) {
                    final Object object2 = orIter.next();
                    if ( object2 instanceof Or ) {
                        it.remove();
                        it.add( applyOrTransformation( parent,
                                                       (GroupElement) object2 ) );
                        break;
                    }
                }

            }
        }
    }

    /**
     * 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(final GroupElement parent,
                            final GroupElement 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(final GroupElement parent) {
        for ( final ListIterator it = parent.getChildren().listIterator(); it.hasNext(); ) {
            final 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,
                                                                            (GroupElement) object ) ) {
                final List newList = new ArrayList();
                final GroupElement child = (GroupElement) object;
                for ( final Iterator childIter = child.getChildren().iterator(); childIter.hasNext(); ) {
                    newList.add( childIter.next() );
                }
                it.remove();
                for ( final Iterator childIter = newList.iterator(); childIter.hasNext(); ) {
                    it.add( childIter.next() );
                }
            }
        }
    }

    GroupElement applyOrTransformation(final GroupElement parent,
                                       final GroupElement child) throws InvalidPatternException {
        Transformation transformation = null;
        final Map map = (HashMap) this.orTransformations.get( parent.getClass() );
        if ( map != null ) {
            transformation = (Transformation) 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() + "'" );
        }

        return transformation.transform( parent );
    }

    interface Transformation {
        GroupElement transform(GroupElement element) throws InvalidPatternException;
    }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -