QueryResult.java

  1. /*
  2.  * Licensed to the Apache Software Foundation (ASF) under one or more
  3.  * contributor license agreements.  See the NOTICE file distributed with
  4.  * this work for additional information regarding copyright ownership.
  5.  * The ASF licenses this file to You under the Apache License, Version 2.0
  6.  * (the "License"); you may not use this file except in compliance with
  7.  * the License.  You may obtain a copy of the License at
  8.  *
  9.  *     http://www.apache.org/licenses/LICENSE-2.0
  10.  *
  11.  * Unless required by applicable law or agreed to in writing, software
  12.  * distributed under the License is distributed on an "AS IS" BASIS,
  13.  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14.  * See the License for the specific language governing permissions and
  15.  * limitations under the License.
  16.  */
  17. package org.apache.commons.configuration2.tree;

  18. import org.apache.commons.lang3.StringUtils;
  19. import org.apache.commons.lang3.builder.EqualsBuilder;
  20. import org.apache.commons.lang3.builder.HashCodeBuilder;
  21. import org.apache.commons.lang3.builder.ToStringBuilder;

  22. /**
  23.  * <p>
  24.  * A data class representing a single query result produced by an {@link ExpressionEngine}.
  25.  * </p>
  26.  * <p>
  27.  * When passing a key to the {@code query()} method of {@code ExpressionEngine} the result can be a set of nodes or
  28.  * attributes - depending on the key. This class can represent both types of results. The aim is to give a user of
  29.  * {@code ExpressionEngine} all information needed for evaluating the results returned.
  30.  * </p>
  31.  * <p>
  32.  * Implementation note: Instances are immutable. They are created using the static factory methods.
  33.  * </p>
  34.  *
  35.  * @param <T> the type of the result nodes
  36.  * @since 2.0
  37.  */
  38. public final class QueryResult<T> {
  39.     /**
  40.      * Creates a {@code QueryResult} instance representing an attribute result. An attribute result consists of the node the
  41.      * attribute belongs to and the attribute name. (The value can be obtained based on this information.)
  42.      *
  43.      * @param parentNode the node which owns the attribute
  44.      * @param attrName the attribute name
  45.      * @param <T> the type of the parent node
  46.      * @return the newly created instance
  47.      */
  48.     public static <T> QueryResult<T> createAttributeResult(final T parentNode, final String attrName) {
  49.         return new QueryResult<>(parentNode, attrName);
  50.     }

  51.     /**
  52.      * Creates a {@code QueryResult} instance representing the specified result node.
  53.      *
  54.      * @param <T> the type of the result node
  55.      * @param resultNode the result node
  56.      * @return the newly created instance
  57.      */
  58.     public static <T> QueryResult<T> createNodeResult(final T resultNode) {
  59.         return new QueryResult<>(resultNode, null);
  60.     }

  61.     /** The node result. */
  62.     private final T node;

  63.     /** The name of the result attribute. */
  64.     private final String attributeName;

  65.     /**
  66.      * Creates a new instance of {@code QueryResult}.
  67.      *
  68.      * @param nd the node
  69.      * @param attr the attribute name
  70.      */
  71.     private QueryResult(final T nd, final String attr) {
  72.         node = nd;
  73.         attributeName = attr;
  74.     }

  75.     /**
  76.      * Compares this object with another one. Two instances of {@code QueryResult} are considered equal if they are of the
  77.      * same result type and have the same properties.
  78.      *
  79.      * @param obj the object to compare to
  80.      * @return a flag whether these objects are equal
  81.      */
  82.     @Override
  83.     public boolean equals(final Object obj) {
  84.         if (this == obj) {
  85.             return true;
  86.         }
  87.         if (!(obj instanceof QueryResult)) {
  88.             return false;
  89.         }

  90.         final QueryResult<?> c = (QueryResult<?>) obj;
  91.         return new EqualsBuilder().append(getNode(), c.getNode()).append(getAttributeName(), c.getAttributeName()).isEquals();
  92.     }

  93.     /**
  94.      * Gets the name of the attribute. This method is defined only for results of type attribute.
  95.      *
  96.      * @return the attribute name
  97.      */
  98.     public String getAttributeName() {
  99.         return attributeName;
  100.     }

  101.     /**
  102.      * Gets the attribute value if this is an attribute result. If this is not an attribute result, an exception is
  103.      * thrown.
  104.      *
  105.      * @param handler the {@code NodeHandler}
  106.      * @return the attribute value
  107.      * @throws IllegalStateException if this is not an attribute result
  108.      */
  109.     public Object getAttributeValue(final NodeHandler<T> handler) {
  110.         if (!isAttributeResult()) {
  111.             throw new IllegalStateException("This is not an attribute result! " + "Attribute value cannot be fetched.");
  112.         }
  113.         return handler.getAttributeValue(getNode(), getAttributeName());
  114.     }

  115.     /**
  116.      * Gets the node referenced by this object. Depending on the result type, this is either the result node or the
  117.      * parent node of the represented attribute.
  118.      *
  119.      * @return the referenced node
  120.      */
  121.     public T getNode() {
  122.         return node;
  123.     }

  124.     @Override
  125.     public int hashCode() {
  126.         return new HashCodeBuilder().append(getNode()).append(getAttributeName()).toHashCode();
  127.     }

  128.     /**
  129.      * Returns a flag whether this is a result of type attribute. If result is <strong>true</strong>, the attribute name and value can
  130.      * be queried. Otherwise, only the result node is available.
  131.      *
  132.      * @return <strong>true</strong> for an attribute result, <strong>false</strong> otherwise
  133.      */
  134.     public boolean isAttributeResult() {
  135.         return StringUtils.isNotEmpty(getAttributeName());
  136.     }

  137.     /**
  138.      * Returns a string representation of this object. Depending on the result type either the result node or the parent
  139.      * node and the attribute name are contained in this string.
  140.      *
  141.      * @return a string for this object
  142.      */
  143.     @Override
  144.     public String toString() {
  145.         final ToStringBuilder sb = new ToStringBuilder(this);
  146.         if (isAttributeResult()) {
  147.             sb.append("parentNode", getNode()).append("attribute", getAttributeName());
  148.         } else {
  149.             sb.append("resultNode", getNode());
  150.         }
  151.         return sb.toString();
  152.     }
  153. }