001// *************************************************************************************************************************** 002// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file * 003// * distributed with this work for additional information regarding copyright ownership. The ASF licenses this file * 004// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance * 005// * with the License. You may obtain a copy of the License at * 006// * * 007// * http://www.apache.org/licenses/LICENSE-2.0 * 008// * * 009// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an * 010// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the * 011// * specific language governing permissions and limitations under the License. * 012// *************************************************************************************************************************** 013package org.apache.juneau; 014 015import static org.apache.juneau.internal.StringUtils.*; 016 017import java.lang.annotation.*; 018import java.util.*; 019 020import org.apache.juneau.annotation.*; 021import org.apache.juneau.collections.*; 022import org.apache.juneau.internal.*; 023import org.apache.juneau.reflect.*; 024import org.apache.juneau.svl.*; 025 026/** 027 * Class used to add properties to a {@link PropertyStore} from an annotation (e.g. {@link BeanConfig}). 028 * 029 * @param <T> The annotation that this <c>ConfigApply</c> reads from. 030 */ 031public abstract class ConfigApply<T extends Annotation> { 032 033 private final VarResolverSession r; 034 private final Class<T> c; 035 036 /** 037 * Constructor. 038 * 039 * @param c The annotation class. 040 * @param r The string resolver to use for resolving strings. 041 */ 042 protected ConfigApply(Class<T> c, VarResolverSession r) { 043 this.r = r == null ? VarResolver.DEFAULT.createSession() : r; 044 this.c = c; 045 } 046 047 /** 048 * Apply the specified annotation to the specified property store builder. 049 * 050 * @param a The annotation. 051 * @param ps The property store builder. 052 */ 053 public abstract void apply(AnnotationInfo<T> a, PropertyStoreBuilder ps); 054 055 056 /** 057 * Resolves the specified string. 058 * 059 * @param in The string containing variables to resolve. 060 * @return The resolved string. 061 */ 062 protected String string(String in) { 063 return r.resolve(in); 064 } 065 066 /** 067 * Resolves the specified strings in the string array. 068 * 069 * @param in The string array containing variables to resolve. 070 * @return An array with resolved strings. 071 */ 072 protected String[] strings(String[] in) { 073 String[] out = new String[in.length]; 074 for (int i = 0; i < in.length; i++) 075 out[i] = r.resolve(in[i]); 076 return out; 077 } 078 079 /** 080 * Resolves the specified string as a comma-delimited list of strings. 081 * 082 * @param in The CDL string containing variables to resolve. 083 * @return An array with resolved strings. 084 */ 085 protected String[] strings(String in) { 086 in = r.resolve(in); 087 return StringUtils.split(in); 088 } 089 090 /** 091 * Resolves the specified strings as a maps of strings-to-strings. 092 * 093 * @param in The string array containing variables to resolve. 094 * @param loc The annotation field name. 095 * @return A map of strings-to-strings. 096 */ 097 protected Map<String,String> stringsMap(String[] in, String loc) { 098 Map<String,String> m = new LinkedHashMap<>(); 099 for (String s : strings(in)) { 100 for (String s2 : split(s, ';')) { 101 int i = s2.indexOf(':'); 102 if (i == -1) 103 throw new ConfigException("Invalid syntax for key/value pair on annotation @{0}({1}): {2}", c.getSimpleName(), loc, s2); 104 m.put(s2.substring(0, i).trim(), s2.substring(i+1).trim()); 105 } 106 } 107 return m; 108 } 109 110 /** 111 * Resolves the specified string and converts it to a boolean. 112 * 113 * @param in The string containing variables to resolve. 114 * @return The resolved boolean. 115 */ 116 public boolean bool(String in) { 117 return Boolean.parseBoolean(r.resolve(in)); 118 } 119 120 /** 121 * Resolves the specified string and converts it to an int. 122 * 123 * @param in The string containing variables to resolve. 124 * @param loc The annotation field name. 125 * @return The resolved int. 126 */ 127 protected int integer(String in, String loc) { 128 try { 129 return Integer.parseInt(r.resolve(in)); 130 } catch (NumberFormatException e) { 131 throw new ConfigException("Invalid syntax for integer on annotation @{0}({1}): {2}", c.getSimpleName(), loc, in); 132 } 133 } 134 135 /** 136 * Resolves the specified string and converts it to a Visibility. 137 * 138 * @param in The string containing variables to resolve. 139 * @param loc The annotation field name. 140 * @return The resolved Visibility. 141 */ 142 protected Visibility visibility(String in, String loc) { 143 try { 144 return Visibility.valueOf(r.resolve(in)); 145 } catch (IllegalArgumentException e) { 146 throw new ConfigException("Invalid syntax for visibility on annotation @{0}({1}): {2}", c.getSimpleName(), loc, in); 147 } 148 } 149 150 /** 151 * Resolves the specified strings and converts it to an OMap. 152 * 153 * @param in The strings to be concatenated and parsed into an OMap. 154 * @param loc The annotation field name. 155 * @return The resolved OMap. 156 */ 157 protected OMap omap(String[] in, String loc) { 158 return omap(joinnl(strings(in)), loc); 159 } 160 161 /** 162 * Resolves the specified string and converts it to an OMap. 163 * 164 * @param in The string to be parsed into an OMap. 165 * @param loc The annotation field name. 166 * @return The resolved OMap. 167 */ 168 protected OMap omap(String in, String loc) { 169 try { 170 if (! isJsonObject(in, true)) 171 in = "{" + in + "}"; 172 return OMap.ofJson(in); 173 } catch (Exception e) { 174 throw new ConfigException("Invalid syntax for Simple-JSON on annotation @{0}({1}): {2}", c.getSimpleName(), loc, in); 175 } 176 } 177 178 /** 179 * Represents a no-op configuration apply. 180 */ 181 public static class NoOp extends ConfigApply<Annotation> { 182 183 /** 184 * Constructor. 185 * 186 * @param c The annotation class. 187 * @param r The string resolver to use for resolving strings. 188 */ 189 public NoOp(Class<Annotation> c, VarResolverSession r) { 190 super(c, r); 191 } 192 193 @Override /* ConfigApply */ 194 public void apply(AnnotationInfo<Annotation> a, PropertyStoreBuilder ps) {} 195 } 196}