org.xchain.framework.util.AttributesUtil.java Source code

Java tutorial

Introduction

Here is the source code for org.xchain.framework.util.AttributesUtil.java

Source

/**
 *    Copyright 2011 meltmedia
 *
 *    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.xchain.framework.util;

import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.apache.commons.jxpath.JXPathContext;
import org.apache.commons.jxpath.JXPathException;
import java.util.List;
import java.util.ArrayList;
import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;
import java.util.regex.Matcher;
import org.xchain.framework.jxpath.JXPathValidator;
import javax.xml.namespace.NamespaceContext;

/**
 * Utility class for Attribute related methods.
 * 
 * @author Christian Trimble
 * @author Devon Tackett
 * @author Josh Kennedy
 *
 * @see org.xml.sax.Attributes
 */
public class AttributesUtil {
    private static Logger log = LoggerFactory.getLogger(AttributesUtil.class);

    /** A regex that matches the fixed part of an attribute value template. */
    public static final String FIXED_PART_REGEX = "((?:[^{}]+|\\{\\{|\\}\\})+)";
    /** A regex that matches the dynamic part of an attribute value template. */
    public static final String DYNAMIC_PART_REGEX = "(?:\\{((?:[^\\}\'\"]*|\"[^\"]*\"|\'[^\']*\')*)\\})";

    /**
     * The pattern for attribute value templates.  The first group of this pattern is a fixed part, the second group is a dynamic part.  This
     * pattern will match one part at a time.
     */
    private static Pattern attributeValueTemplatePattern = null;

    static {
        try {
            attributeValueTemplatePattern = Pattern.compile(FIXED_PART_REGEX + "|" + DYNAMIC_PART_REGEX);
        } catch (PatternSyntaxException pse) {
            log.error("Could not compile attribute value template pattern.", pse);
        }
    }

    /**
     * Get the attribute value.
     * 
     * @param attributes The list of attributes to check.
     * @param namespaceUri The namespace of the attribute.
     * @param localName The local name of the attribute.
     * 
     * @return The value of the attribute if found.  Null if not found.
     */
    public static String getAttribute(Attributes attributes, String namespaceUri, String localName) {
        return getAttribute(attributes, namespaceUri, localName, null);
    }

    /**
     * Get the attribute value.
     * 
     * @param attributes The list of attributes to check.
     * @param namespaceUri The namespace of the attribute.
     * @param localName The local name of the attribute.
     * @param defaultValue The default value to use if the attribute could not be found.
     * 
     * @return The value of the attribute if found.  The given defaultValue if not found.
     */
    public static String getAttribute(Attributes attributes, String namespaceUri, String localName,
            String defaultValue) {
        String value = defaultValue;

        // get the index of the target attribute.
        int index = attributes.getIndex(namespaceUri, localName);

        // if the index is 0 or greater, then return the value.
        if (index >= 0) {
            value = attributes.getValue(index);
        }

        return value;
    }

    /**
     * Parses an attribute value template into fixed and dynamic parts.  This list will always start with a fixed part and
     * then include alternating dynamic and fixed parts.
     */
    public static List<String> parseAttributeValueTemplate(String attributeValueTemplate) throws SAXException {
        // the result.
        ArrayList<String> result = new ArrayList<String>();

        // create the matcher.
        Matcher matcher = attributeValueTemplatePattern.matcher(attributeValueTemplate);

        while (matcher.lookingAt()) {
            String fixedPart = matcher.group(1);
            String dynamicPart = matcher.group(2);

            if (result.isEmpty() && fixedPart == null) {
                result.add("");
            }

            if (fixedPart != null) {
                result.add(fixedPart.replaceAll("\\{\\{", "{").replaceAll("\\}\\}", "}"));
            }
            if (dynamicPart != null) {
                result.add(dynamicPart);
            }
            matcher.region(matcher.regionStart() + matcher.group().length(), matcher.regionEnd());
        }

        if (!matcher.hitEnd()) {
            throw new SAXException(
                    "The attribute value template '" + attributeValueTemplate + "' has an error between characters "
                            + matcher.regionStart() + " and " + matcher.regionEnd() + ".");
        }

        return result;
    }

    /**
     * Evaluates an attribute value template using the provided JXPathContext object.
     */
    public static String evaluateAttributeValueTemplate(JXPathContext context, String attributeValueTemplate)
            throws SAXException, Exception {
        List<String> parsedAvt = parseAttributeValueTemplate(attributeValueTemplate);

        // if there is just one part, then return the string.
        if (parsedAvt.size() == 1) {
            return parsedAvt.get(0);
        }

        // build a string buffer and start building the result in it.
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < parsedAvt.size(); i += 2) {
            sb.append(parsedAvt.get(i));
            if ((i + 1) < parsedAvt.size()) {
                sb.append((String) context.getValue(parsedAvt.get(i + 1), String.class));
            }
        }
        return sb.toString();
    }

    public static void validateAttributeValueTemplate(String attributeValueTemplate,
            NamespaceContext namespaceContext) throws JXPathException {
        List<String> parsedAvt = null;
        try {
            parsedAvt = parseAttributeValueTemplate(attributeValueTemplate);
        } catch (SAXException saxe) {
            throw new JXPathException(saxe.getMessage());
        }

        // validate the xpaths nested in the attribute value template.
        for (int i = 1; i < parsedAvt.size(); i += 2) {
            JXPathValidator.validate(parsedAvt.get(i), namespaceContext);
        }
    }
}