PageRenderTime 68ms CodeModel.GetById 18ms RepoModel.GetById 1ms app.codeStats 0ms

/jboss-as-7.1.1.Final/controller/src/main/java/org/jboss/as/controller/descriptions/StandardResourceDescriptionResolver.java

#
Java | 246 lines | 116 code | 22 blank | 108 comment | 11 complexity | 101ba157cd0f725d685f7aab6b24647a MD5 | raw file
Possible License(s): LGPL-2.1, Apache-2.0
  1. /*
  2. * JBoss, Home of Professional Open Source.
  3. * Copyright 2011, Red Hat, Inc., and individual contributors
  4. * as indicated by the @author tags. See the copyright.txt file in the
  5. * distribution for a full listing of individual contributors.
  6. *
  7. * This is free software; you can redistribute it and/or modify it
  8. * under the terms of the GNU Lesser General Public License as
  9. * published by the Free Software Foundation; either version 2.1 of
  10. * the License, or (at your option) any later version.
  11. *
  12. * This software is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  15. * Lesser General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU Lesser General Public
  18. * License along with this software; if not, write to the Free
  19. * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
  20. * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
  21. */
  22. package org.jboss.as.controller.descriptions;
  23. import java.lang.ref.WeakReference;
  24. import java.util.Locale;
  25. import java.util.MissingResourceException;
  26. import java.util.ResourceBundle;
  27. /**
  28. * {@link ResourceBundle} based {@link ResourceDescriptionResolver} that builds resource bundle
  29. * keys by taking a "key prefix" provided to the constructor and dot-appending the string params to the
  30. * various {@code getXXXDescription} methods. The "key prefix" is associated with a particular resource and serves
  31. * to provide a namespace for the resource's key's in the set of keys used by a {@link ResourceBundle}.
  32. * <p>
  33. * Code that uses this class to localize text descriptions should store their text description in a properties
  34. * file whose keys follow the following format, where "prefix" is the {@code keyPrefix} param passed to the constructor,
  35. * "attribute-name" is the name of an attribute, "operation-name" is the name of an operation, "param-name" is the
  36. * name of a parameter to an operation, "child-type" is the name of one of the resource's valid child types, and
  37. * "value-type-suffix" is the name of some detail element in a parameter, attribute or operation reply value that has a
  38. * complex type.
  39. * </p>
  40. * <p>
  41. * prefix=The description of the resource
  42. * prefix.attribute-name=The description of one of the resource's attributes.
  43. * prefix.attribute-name.value-type-suffix=The description of an element in a complex attribute's {@link ModelDescriptionConstants#VALUE_TYPE}.
  44. * prefix.operation-name=The description of one of the resource's operations.
  45. * prefix.operation-name.param-name=The description of one of an operation's parameters.
  46. * prefix.operation-name.param-name.value-type-suffix=The description of an element in a complex operation parameter's {@link ModelDescriptionConstants#VALUE_TYPE}.
  47. * prefix.operation-name.reply=The description of an operation's reply value.
  48. * prefix.operation-name.reply.value-type-suffix=The description of an element in a complex operation reply value's {@link ModelDescriptionConstants#VALUE_TYPE}.
  49. * prefix.child-type=The description of one of the resource's child resource types.
  50. * </p>
  51. * <p>
  52. * The constructor supports two settings designed to help minimize the need for redundant entries in the properties file:
  53. * <ol>
  54. * <li>{@code reuseAttributesForAdd} affects how the {@code getOperationParameter...} methods work. If {@code true},
  55. * the assumption is that for an operation named "add" the text description of a parameter will be the same as
  56. * the description of an attribute of the same name. This would allow the properties for this example resource:
  57. * <p>
  58. * pool.min-size=The minimum pool size.
  59. * pool.max-size=The maximum pool size.
  60. * pool.add.min-size=The minimum pool size.
  61. * pool.add.max-size=The maximum pool size.
  62. * </p>
  63. * <p>To be reduced to:</p>
  64. * <p>
  65. * pool.min-size=The minimum pool size.
  66. * pool.max-size=The maximum pool size.
  67. * </p>
  68. *
  69. * </li>
  70. *
  71. * <li>{@code useUnprefixedChildTypes} affects how the {@link #getChildTypeDescription(String, Locale, ResourceBundle)}
  72. * method works. The descriptions of a set of related resources need to include a description in the parent resource
  73. * of its relationship to the child resource, as well as the description of the child resource itself. These two
  74. * descriptions are often included in the same properties file and may be the exact same text. If {@code useUnprefixedChildTypes}
  75. * is {@code true}, {@code getChildTypeDescription(...)} will assume there is an entry in the properties file
  76. * that exactly matches the name of the child type. This would allow the properties for this example set of resources:
  77. * <p>
  78. * subsystem=The foo subsystem.
  79. * ... attributes and operations of the "subsystem" resource
  80. * subsystem.connector=A connector that can be used to access the foo.
  81. * connector=A connector that can be used to access the foo.
  82. * ... attributes and operations of the "connector" resource
  83. * </p>
  84. * <p>To be reduced to:</p>
  85. * <p>
  86. * subsystem=The foo subsystem.
  87. * ... attributes and operations of the "subsystem" resource
  88. * connector=A connector that can be used to access the foo.
  89. * connector=A connector that can be used to access the foo.
  90. * ... attributes and operations of the "connector" resource
  91. * </p>
  92. * <p>Note that while this kind of usage is convenient, it often results in slightly lower quality descriptions. For example,
  93. * in the example above, a better description for "subsystem.connector" is "The connectors that can be used to access the foo."</p>
  94. * </li>
  95. * </ol>
  96. * </p>
  97. *
  98. * @author Brian Stansberry (c) 2011 Red Hat Inc.
  99. */
  100. public class StandardResourceDescriptionResolver implements ResourceDescriptionResolver {
  101. /**
  102. * Additional string dot-appended to the key by the
  103. * {@link StandardResourceDescriptionResolver#getOperationReplyDescription(String, Locale, ResourceBundle)} method.
  104. */
  105. public static final String REPLY = "reply";
  106. private final String keyPrefix;
  107. private final String bundleBaseName;
  108. private final WeakReference<ClassLoader> bundleLoader;
  109. private final boolean reuseAttributesForAdd;
  110. private final boolean useUnprefixedChildTypes;
  111. public StandardResourceDescriptionResolver(final String keyPrefix,
  112. final String bundleBaseName,
  113. final ClassLoader bundleLoader) {
  114. this(keyPrefix, bundleBaseName, bundleLoader, false, false);
  115. }
  116. public StandardResourceDescriptionResolver(final String keyPrefix,
  117. final String bundleBaseName,
  118. final ClassLoader bundleLoader,
  119. final boolean reuseAttributesForAdd,
  120. final boolean useUnprefixedChildTypes) {
  121. this.keyPrefix = keyPrefix;
  122. this.bundleBaseName = bundleBaseName;
  123. this.bundleLoader = new WeakReference<ClassLoader>(bundleLoader);
  124. this.reuseAttributesForAdd = reuseAttributesForAdd;
  125. this.useUnprefixedChildTypes = useUnprefixedChildTypes;
  126. }
  127. public String getKeyPrefix() {
  128. return keyPrefix;
  129. }
  130. public boolean isReuseAttributesForAdd() {
  131. return reuseAttributesForAdd;
  132. }
  133. public boolean isUseUnprefixedChildTypes() {
  134. return useUnprefixedChildTypes;
  135. }
  136. /** {@inheritDoc} */
  137. @Override
  138. public ResourceBundle getResourceBundle(Locale locale) {
  139. if (locale == null) {
  140. locale = Locale.getDefault();
  141. }
  142. return ResourceBundle.getBundle(bundleBaseName, locale, bundleLoader.get());
  143. }
  144. /** {@inheritDoc} */
  145. @Override
  146. public String getResourceDescription(Locale locale, ResourceBundle bundle) {
  147. return bundle.getString(getBundleKey());
  148. }
  149. /** {@inheritDoc} */
  150. @Override
  151. public String getResourceAttributeDescription(String attributeName, Locale locale, ResourceBundle bundle) {
  152. return bundle.getString(getBundleKey(attributeName));
  153. }
  154. /** {@inheritDoc} */
  155. @Override
  156. public String getResourceAttributeValueTypeDescription(String attributeName, Locale locale, ResourceBundle bundle, String... suffixes) {
  157. return bundle.getString(getVariableBundleKey(new String[]{attributeName}, suffixes));
  158. }
  159. /** {@inheritDoc} */
  160. @Override
  161. public String getOperationDescription(String operationName, Locale locale, ResourceBundle bundle) {
  162. return bundle.getString(getBundleKey(operationName));
  163. }
  164. /** {@inheritDoc} */
  165. @Override
  166. public String getOperationParameterDescription(String operationName, String paramName, Locale locale, ResourceBundle bundle) {
  167. if (reuseAttributesForAdd && ModelDescriptionConstants.ADD.equals(operationName)) {
  168. return bundle.getString(getBundleKey(paramName));
  169. }
  170. return bundle.getString(getBundleKey(operationName, paramName));
  171. }
  172. /** {@inheritDoc} */
  173. @Override
  174. public String getOperationParameterValueTypeDescription(String operationName, String paramName, Locale locale, ResourceBundle bundle, String... suffixes) {
  175. String[] fixed;
  176. if (reuseAttributesForAdd && ModelDescriptionConstants.ADD.equals(operationName)) {
  177. fixed = new String[]{paramName};
  178. } else {
  179. fixed = new String[]{operationName, paramName};
  180. }
  181. return bundle.getString(getVariableBundleKey(fixed, suffixes));
  182. }
  183. /** {@inheritDoc} */
  184. @Override
  185. public String getOperationReplyDescription(String operationName, Locale locale, ResourceBundle bundle) {
  186. try {
  187. return bundle.getString(getBundleKey(operationName, REPLY));
  188. } catch (MissingResourceException e) {
  189. return null;
  190. }
  191. }
  192. /** {@inheritDoc} */
  193. @Override
  194. public String getOperationReplyValueTypeDescription(String operationName, Locale locale, ResourceBundle bundle, String... suffixes) {
  195. try {
  196. return bundle.getString(getVariableBundleKey(new String[] {operationName, REPLY}, suffixes));
  197. } catch (MissingResourceException e) {
  198. return null;
  199. }
  200. }
  201. /** {@inheritDoc} */
  202. @Override
  203. public String getChildTypeDescription(String childType, Locale locale, ResourceBundle bundle) {
  204. final String bundleKey = useUnprefixedChildTypes ? childType : getBundleKey(childType);
  205. return bundle.getString(bundleKey);
  206. }
  207. private String getBundleKey(String... args) {
  208. return getVariableBundleKey(args);
  209. }
  210. private String getVariableBundleKey(String[] fixed, String... variable) {
  211. StringBuilder sb = new StringBuilder(keyPrefix);
  212. for (String arg : fixed) {
  213. sb.append('.');
  214. sb.append(arg);
  215. }
  216. if (variable != null) {
  217. for (String arg : variable) {
  218. sb.append('.');
  219. sb.append(arg);
  220. }
  221. }
  222. return sb.toString();
  223. }
  224. }