001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.apache.juneau.objecttools; 018 019import static org.apache.juneau.commons.utils.CollectionUtils.*; 020 021import java.lang.reflect.*; 022import java.util.*; 023 024import org.apache.juneau.*; 025import org.apache.juneau.internal.*; 026 027/** 028 * POJO model viewer. 029 * 030 * <p> 031 * This class is designed to extract properties from collections of maps or beans. 032 * </p> 033 * 034 * <h5 class='section'>Example:</h5> 035 * <p class='bjava'> 036 * MyBean[] <jv>arrayOfBeans</jv> = ...; 037 * ObjectViewer <jv>viewer</jv> = ObjectViewer.<jsm>create</jsm>(); 038 * 039 * <jc>// Returns the 'foo' and 'bar' properties extracted into a list of maps.</jc> 040 * List<Map> <jv>result</jv> = <jv>viewer</jv>.run(<jv>arrayOfBeans</jv>, <js>"foo,bar"</js>); 041 * </p> 042 * <p> 043 * The tool can be used against the following data types: 044 * </p> 045 * <ul> 046 * <li>Arrays/collections of maps or beans. 047 * <li>Singular maps or beans. 048 * </ul> 049 * 050 * <h5 class='section'>See Also:</h5><ul> 051 * <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/ObjectTools">Object Tools</a> 052 053 * </ul> 054 */ 055@SuppressWarnings({ "unchecked", "rawtypes" }) 056public class ObjectViewer implements ObjectTool<ViewArgs> { 057 /** 058 * Default reusable searcher. 059 */ 060 public static final ObjectViewer DEFAULT = new ObjectViewer(); 061 062 /** 063 * Static creator. 064 * 065 * @return A new {@link ObjectViewer} object. 066 */ 067 public static ObjectViewer create() { 068 return new ObjectViewer(); 069 } 070 071 @Override /* Overridden from ObjectTool */ 072 public Object run(BeanSession session, Object input, ViewArgs args) { 073 074 if (input == null) 075 return null; 076 077 List<String> view = args.getView(); 078 ClassMeta type = session.getClassMetaForObject(input); 079 080 if (type.isBeanMap()) 081 return new DelegateBeanMap(((BeanMap)input).getBean(), session).filterKeys(view); 082 if (type.isMap()) 083 return new DelegateMap((Map)input, session).filterKeys(view); 084 if (type.isBean()) 085 return new DelegateBeanMap(input, session).filterKeys(view); 086 087 var l = (ArrayList<Object>)null; 088 089 if (type.isArray()) { 090 var size = Array.getLength(input); 091 l = listOfSize(size); 092 for (var i = 0; i < size; i++) 093 l.add(Array.get(input, i)); 094 } else if (type.isCollection()) { 095 var c = (Collection)input; 096 l = listOfSize(c.size()); 097 List<Object> l2 = l; 098 c.forEach(x -> l2.add(x)); 099 } else { 100 return input; 101 } 102 103 for (ListIterator li = l.listIterator(); li.hasNext();) { 104 Object o = li.next(); 105 ClassMeta cm2 = session.getClassMetaForObject(o); 106 107 if (cm2 == null) 108 o = null; 109 else if (cm2.isBeanMap()) 110 o = new DelegateBeanMap(((BeanMap)o).getBean(), session).filterKeys(view); 111 else if (cm2.isMap()) 112 o = new DelegateMap((Map)o, session).filterKeys(view); 113 else if (cm2.isBean()) 114 o = new DelegateBeanMap(o, session).filterKeys(view); 115 116 li.set(o); 117 } 118 119 return l; 120 } 121 122 /** 123 * Runs this viewer on the specified collection or array of objects. 124 * 125 * @param input The input. Must be an array or collection. 126 * @param args The view args. See {@link ViewArgs} for format. 127 * @return The extracted properties from the collection of objects. 128 */ 129 public List<Map> run(Object input, String args) { 130 return (List<Map>)run(BeanContext.DEFAULT_SESSION, input, ViewArgs.create(args)); 131 } 132 133 /** 134 * Runs this viewer on a singleton object. 135 * 136 * @param input The input. Must be a singleton object. 137 * @param args The view args. See {@link ViewArgs} for format. 138 * @return The extracted properties from the object. 139 */ 140 public Map runSingle(Object input, String args) { 141 return (Map)run(BeanContext.DEFAULT_SESSION, input, ViewArgs.create(args)); 142 } 143}