package org.apache.solr.search.xjoin; /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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. */ import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.HashSet; import java.util.Map; import java.util.Set; import org.apache.solr.common.util.NamedList; import org.apache.solr.common.util.SimpleOrderedMap; /** * Class for adding properties from an object to a NamedList. */ public class FieldAppender { // selected properties (or null for all) private Set<String> fieldNames; /** * Create a FieldAppender for adding the fields specified by the given * SOLR formatted field list (i.e. command or space delimited). */ public FieldAppender(String fl) { this(); for (String field : fl.split("[, ]")) { field = field.trim(); if (field.length() == 0) { continue; } if ("*".equals(field)) { fieldNames = null; return; } fieldNames.add(field); } } /** * Create a FieldAppender for adding all fields (if the parameter is true) * or for no fields (but fields may be added via getFieldNames()). */ public FieldAppender(boolean all) { fieldNames = all ? null : new HashSet<String>(); } /** * Create a FieldAppeneder for adding fields, which may be added via * getFieldNames(). */ public FieldAppender() { this(false); } /** * Returns the (modifiable) set of field names to be added. A value of null * indicates all fields are to be added. */ public Set<String> getFieldNames() { return fieldNames; } /** * Indicate that all fields should be added. Once this method is called, fields * can not be added using the set returned by getFieldNames() (since it is null). */ public void appendAllFields() { fieldNames = null; } /** * Add a NamedList (with given name) with properties from the given object. * Returns the new NamedList. */ @SuppressWarnings({ "rawtypes", "unchecked" }) public NamedList addNamedList(NamedList target, String name, Object object) { NamedList<Object> list = new SimpleOrderedMap<>(); target.add(name, list); if (object instanceof Map) { Map map = (Map)object; for (Object field : map.keySet()) { String fieldName = field.toString(); if (! includeField(fieldName)) continue; list.add(fieldName, map.get(field)); } } else { for (Method method : object.getClass().getMethods()) { if (method.getParameterTypes().length > 0) continue; String fieldName = NameConverter.getFieldName(method.getName()); if (! includeField(fieldName)) continue; try { list.add(fieldName, method.invoke(object)); } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) { throw new RuntimeException(e.getClass().getName() + " (" + fieldName + ": " + e.getMessage() + ")", e.getCause()); } } } return list; } // whether to include a particular object field based on fieldNames private boolean includeField(String fieldName) { if (fieldName == null) return false; if (fieldNames == null) { // return all get methods except getClass() if (fieldName.equals("class")) return false; } else { // return named methods only if (! fieldNames.contains(fieldName)) return false; } return true; } }