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

📄 extendedbaserules.java

📁 JAVA 文章管理系统源码
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
/* $Id: ExtendedBaseRules.java,v 1.15 2004/05/10 06:30:06 skitching Exp $
 *
 * Copyright 2001-2004 The Apache Software Foundation.
 * 
 * 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.
 */ 


package org.apache.commons.digester;


import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;


/**
 * <p>Extension of {@link RulesBase} for complex schema.</p>
 *
 * <p>This is an extension of the basic pattern matching scheme
 * intended to improve support for mapping complex xml-schema.
 * It is intended to be a minimal extension of the standard rules
 * big enough to support complex schema but without the full generality
 * offered by more exotic matching pattern rules.</p>
 *
 * <h4>When should you use this rather than the original?</h4>
 *
 * <p>These rules are complex and slower but offer more functionality.
 * The <code>RulesBase</code> matching set allows interaction between patterns.
 * This allows sophisticated matching schema to be created
 * but it also means that it can be hard to create and debug mappings
 * for complex schema.
 * This extension introduces <em>universal</em> versions of these patterns
 * that always act independently.</p>
 *
 * <p>Another three kinds of matching pattern are also introduced.
 * The parent matchs allow common method to be easily called for children.
 * The wildcard match allows rules to be specified for all elements.</p>
 *
 * <h4>The additional matching patterns:</h4>
 *
 * <ul>
 * <li><em>Parent Match </em> - Will match child elements of a particular
 *     kind of parent.  This is useful if a parent has a particular method
 *     to call.
 *     <ul>
 *     <li><code>"a/b/c/?"</code> matches any child whose parent matches
 *         <code>"a/b/c"</code>.  Exact parent rules take precedence over
 *         standard wildcard tail endings.</li>
 *     <li><code>"*&#47;a/b/c/?"</code> matches any child whose parent matches
 *         "*&#47;a/b/c"</code>.  The longest matching still applies to parent
 *         matches but the length excludes the '?', which effectively means
 *         that standard wildcard matches with the same level of depth are
 *         chosen in preference.</li>
 *     </ul></li>
 * <li><em>Ancester Match</em> - Will match elements who parentage includes 
 * 	a particular sequence of elements.
 * 	<ul>
 *      <li><code>"a/b/*"</code> matches any element whose parentage path starts with
 *	    'a' then 'b'. Exact parent and parent match rules take precedence. The longest
 *           ancester match will take precedence.</li>
 *	<li><code>"*&#47;a/b/*"</code> matches any elements whose parentage path contains
 *           an element 'a' followed by an element 'b'. The longest matching still applies
 *           but the length excludes the '*' at the end.</li>
 *      </ul>
 * </li>
 * <li><em>Universal Wildcard Match</em> -  Any pattern prefixed with '!'
 *     bypasses the longest matching rule.  Even if there is an exact match
 *     or a longer wildcard match,  patterns prefixed by '!' will still be
 *     tested to see if they match.  This can be used for example to specify
 *     universal construction rules.
 *     <ul>
 *     <li>Pattern <code>"!*&#47;a/b"</code> matches whenever an 'b' element
 *         is inside an 'a'.</li>
 *     <li>Pattern <code>"!a/b/?"</code> matches any child of a parent
 *         matching <code>"a/b"</code>.</li>
 *     <li>Pattern <code>"!*&#47;a/b/?"</code> matches any child of a parent
 *         matching <code>"!*&#47;a/b"</code></li>
 *     <li>Pattern <code>"!a/b/*"</code> matches any element whose parentage path starts with
 *	    "a" then "b".</li>
 *     <li>Pattern <code>"!*&#47;a/b/*"</code> matches any elements whose parentage path contains
 *          'a/b'</li>
 *    </ul></li>
 * <li><em>Wild Match</em>
 *     <ul>
 *     <li>Pattern <code>"*"</code> matches every pattern that isn't matched
 *         by any other basic rule.</li>
 *     <li>Pattern <code>"!*"</code> matches every pattern.</li>
 *     </ul></li>
 * </ul>
 *
 * <h4>Using The Extended Rules</h4>
 *
 * <p>The most important thing to remember
 * when using the extended rules is that universal
 * and non-universal patterns are completely independent.
 * Universal patterns are never effected by the addition of new patterns
 * or the removal of existing ones.
 * Non-universal patterns are never effected
 * by the addition of new <em>universal</em> patterns
 * or the removal of existing <em>universal</em> patterns.
 * As in the basic matching rules, non-universal (basic) patterns
 * <strong>can</strong> be effected
 * by the addition of new <em>non-universal</em> patterns
 * or the removal of existing <em>non-universal</em> patterns.
 * <p> This means that you can use universal patterns
 * to build up the simple parts of your structure
 * - for example defining universal creation and property setting rules.
 * More sophisticated and complex mapping will require non-universal patterns
 * and this might mean that some of the universal rules will need to be
 * replaced by a series of
 * special cases using non-universal rules.
 * But by using universal rules as your backbone,
 * these additions should not break your existing rules.</p>
 */


public class ExtendedBaseRules extends RulesBase {


    // ----------------------------------------------------- Instance Variables

    /**
     * Counts the entry number for the rules.
     */
    private int counter = 0;


    /**
     * The decision algorithm used (unfortunately) doesn't preserve the entry
     * order.
     * This map is used by a comparator which orders the list of matches
     * before it's returned.
     * This map stores the entry number keyed by the rule.
     */
    private Map order = new HashMap();


    // --------------------------------------------------------- Public Methods


    /**
     * Register a new Rule instance matching the specified pattern.
     *
     * @param pattern Nesting pattern to be matched for this Rule
     * @param rule Rule instance to be registered
     */
    public void add(String pattern, Rule rule) {
        super.add(pattern, rule);
        counter++;
        order.put(rule, new Integer(counter));
    }


    /**
     * Return a List of all registered Rule instances that match the specified
     * nesting pattern, or a zero-length List if there are no matches.  If more
     * than one Rule instance matches, they <strong>must</strong> be returned
     * in the order originally registered through the <code>add()</code>
     * method.
     *
     * @param pattern Nesting pattern to be matched
     */
    public List match(String namespace, String pattern) {
        // calculate the pattern of the parent
        // (if the element has one)
        String parentPattern = "";
        int lastIndex = pattern.lastIndexOf('/');

        boolean hasParent = true;
        if (lastIndex == -1) {
            // element has no parent
            hasParent = false;

        } else {
            // calculate the pattern of the parent
            parentPattern = pattern.substring(0, lastIndex);

        }


        // we keep the list of universal matches separate
        List universalList = new ArrayList(counter);

        // Universal all wildards ('!*')
        // These are always matched so always add them
        List tempList = (List) this.cache.get("!*");
        if (tempList != null) {
            universalList.addAll(tempList);
        }

        // Universal exact parent match
        // need to get this now since only wildcards are considered later
        tempList = (List) this.cache.get("!" + parentPattern + "/?");
        if (tempList != null) {
            universalList.addAll(tempList);
        }


        // base behaviour means that if we certain matches, we don't continue
        // but we just have a single combined loop and so we have to set
        // a variable
        boolean ignoreBasicMatches = false;


        // see if we have an exact basic pattern match
        List rulesList = (List) this.cache.get(pattern);
        if (rulesList != null) {
            // we have a match!
            // so ignore all basic matches from now on

⌨️ 快捷键说明

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