001/* 002 * The contents of this file are subject to the terms of the Common Development and 003 * Distribution License (the License). You may not use this file except in compliance with the 004 * License. 005 * 006 * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the 007 * specific language governing permission and limitations under the License. 008 * 009 * When distributing Covered Software, include this CDDL Header Notice in each file and include 010 * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL 011 * Header, with the fields enclosed by brackets [] replaced by your own identifying 012 * information: "Portions Copyrighted [year] [name of copyright owner]". 013 * 014 * Copyright 2016 ForgeRock AS. 015 */ 016package org.forgerock.json; 017 018import static org.forgerock.json.JsonValue.array; 019import static org.forgerock.json.JsonValue.object; 020 021import java.util.ArrayList; 022import java.util.LinkedHashMap; 023import java.util.List; 024import java.util.Map; 025 026import org.forgerock.util.Function; 027 028/** 029 * An implementation of {@link Function} that recursively traverses the {@link JsonValue} and applies some 030 * transformation if needed. This class may be subclassed to override needed methods to perform the 031 * expected transformation(s). 032 */ 033public class JsonValueTraverseFunction implements Function<JsonValue, JsonValue, JsonValueException> { 034 035 /** the transformation function to be applied to each value. */ 036 private Function<JsonValue, ?, JsonValueException> transform; 037 038 /** 039 * Construct the traversal function with a transformation function to apply to each array element 040 * nested object attribute value element, or primitive element. 041 * 042 * @param transform a transformation function 043 */ 044 public JsonValueTraverseFunction(Function<JsonValue, ?, JsonValueException> transform) { 045 this.transform = transform; 046 } 047 048 @Override 049 public final JsonValue apply(JsonValue value) { 050 return new JsonValue(traverse(value), value.getPointer()); 051 } 052 053 private Object traverse(JsonValue value) { 054 if (value.isList()) { 055 return traverseList(value); 056 } 057 if (value.isMap()) { 058 return traverseMap(value); 059 } 060 return value.as(transform); 061 } 062 063 /** 064 * Transform a JsonValue List into another object. Default implementation is to return a new 065 * {@link ArrayList} filled with the elements on which we applied the transformations. 066 * 067 * @param value the value to transform 068 * @return the transformed value 069 */ 070 protected Object traverseList(JsonValue value) { 071 List<Object> result = array(); 072 for (JsonValue elem : value) { 073 result.add(apply(elem).getObject()); 074 } 075 return result; 076 } 077 078 /** 079 * Transform a JsonValue Map into another object. Default implementation is to return a new 080 * {@link LinkedHashMap} filled with the elements on which we applied the transformations. 081 * 082 * @param value the value to transform 083 * @return the transformed value 084 */ 085 protected Object traverseMap(JsonValue value) { 086 Map<String, Object> result = object(value.size()); 087 for (String key : value.keys()) { 088 result.put(key, apply(value.get(key)).getObject()); 089 } 090 return result; 091 } 092 093}