001 /*
002 * Copyright 2012 Mark Slater
003 *
004 * 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
005 *
006 * http://www.apache.org/licenses/LICENSE-2.0
007 *
008 * 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.
009 */
010
011 package argo.jdom;
012
013 /**
014 * Instances of {@code JsonNodeSelector} extract values from {@code Object}s of a specified type.
015 * <p/>
016 * <p>For example, given a {@code JsonNode} representing {@code {"Fee":{"fi":"fo"}}},
017 * <pre>
018 * anObjectNodeWithField("Fee")
019 * .withChild(anObjectNodeWithField("fi"))
020 * .withChild(aStringNode())
021 * .getValue(jsonNode)
022 * </pre> will return the {@code String} "fo".</p>
023 *
024 * @param <T> The type of Object worked on.
025 * @param <U> The type of Object returned.
026 */
027 public final class JsonNodeSelector<T, U> {
028
029 private final Functor<T, U> valueGetter;
030
031 JsonNodeSelector(final Functor<T, U> valueGetter) {
032 this.valueGetter = valueGetter;
033 }
034
035 /**
036 * Determines whether this {@code JsonNodeSelector} can extract a value from the given {@code JsonNode}.
037 *
038 * @param jsonNode the {@code JsonNode} to test.
039 * @return true if a value can be extracted from the given {@code JsonNode}, false otherwise.
040 */
041 public boolean matches(final T jsonNode) {
042 return valueGetter.matchesNode(jsonNode);
043 }
044
045 /**
046 * Extracts a value from the give {@code JsonNode}.
047 *
048 * @param argument the {@code JsonNode} to extract a value from.
049 * @return the extracted value.
050 * @throws IllegalArgumentException if calling {@code matches{@code with the given {@code JsonNode} would return false, indicating no value can be extracted from it.
051 */
052 public U getValue(final T argument) {
053 return valueGetter.applyTo(argument);
054 }
055
056 /**
057 * <p>Constructs a JsonNodeSelector consisting of this chained with the given {@code JsonNodeSelector}.</p>
058 * <p/>
059 * <p>For example, if we have {@code JsonNodeSelectors} for the first element of an array, and another that
060 * selects the second element of an array, and we chain them together in that order, we will get a selector that
061 * works on nested arrays, selecting the second element from an array stored in the first element of a parent
062 * array.</p>
063 *
064 * @param childJsonNodeSelector the {@code JsonNodeSelector} to chain onto this.
065 * @param <V> the type the chained {@code JsonNodeSelector} will return.
066 * @return a new {@code JsonNodeSelector} representing this, and the given selector applied in sequence.
067 */
068 public <V> JsonNodeSelector<T, V> with(final JsonNodeSelector<U, V> childJsonNodeSelector) {
069 return new JsonNodeSelector<T, V>(new ChainedFunctor<T, U, V>(this, childJsonNodeSelector));
070 }
071
072 String shortForm() {
073 return valueGetter.shortForm();
074 }
075
076 @Override
077 public String toString() {
078 return valueGetter.toString();
079 }
080
081 }