/* * Copyright 2015 Couchbase, 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. */ package org.couchbase.mock.subdoc; import com.google.gson.*; import java.util.ArrayList; import java.util.List; /** * This class is responsible for actually matching the path against the JSON document * and determining if */ public class Match { private final static Gson gs = new Gson(); // Deepest index (in path) that was found // Chain of JSON elements leading up to the deepest match; private List<JsonElement> chain = new ArrayList<JsonElement>(); // Document to search private final JsonElement root; // Path to search for private final Path path; public Match(JsonElement root, Path path) { this.root = root; this.path = path; chain.add(root); } public static Match match(String json, String path) throws SubdocException { JsonElement e; try { e = gs.fromJson(json, JsonElement.class); } catch (JsonSyntaxException ex) { throw new DocNotJsonException(ex); } return match(e, new Path(path)); } public static Match match(JsonElement root, Path path) throws SubdocException { Match m = new Match(root, path); m.execute(); return m; } public void execute() throws SubdocException { JsonElement parent = root; for (int i = 0; i < path.size(); i++) { path.validateComponentType(i, parent); Component component = path.get(i); if (component.isIndex()) { int index = component.getIndex(); JsonArray array = parent.getAsJsonArray(); if (array.size() == 0) { // Empty array break; } if (index == -1) { index = array.size() - 1; } else if (index > array.size()-1) { break; // Not found! } parent = array.get(index); } else { JsonObject object = parent.getAsJsonObject(); parent = object.get(component.getString()); } if (parent == null) { // Match not found here! break; } chain.add(parent); } } public boolean isFound() { if (path.size() == 0) { return true; } return chain.size() - 1 == path.size(); } public boolean hasImmediateParent() { if (path.size() == 0) { return true; } return (chain.size() - 1) >= path.size()-1; } public JsonElement getRoot() { return root; } List<JsonElement> getChain() { return chain; } JsonElement getDeepest() { return chain.get(chain.size()-1); } JsonElement getMatchParent() { if (!isFound()) { throw new IllegalStateException("No match found. Cannot get parent"); } return chain.get(chain.size()-2); } JsonElement getImmediateParent() { if (isFound()) { return getMatchParent(); } else if (hasImmediateParent()) { return getDeepest(); } else { throw new IllegalStateException("No match or immediate parent!"); } } JsonElement getMatch() { if (!isFound()) { throw new IllegalStateException("No match found!"); } return getDeepest(); } }