| 
001 /*002  * Copyright 2008-2015 the original author or authors.
 003  *
 004  * Licensed under the Apache License, Version 2.0 (the "License");
 005  * you may not use this file except in compliance with the License.
 006  * You may obtain a copy of the License at
 007  *
 008  *     http://www.apache.org/licenses/LICENSE-2.0
 009  *
 010  * Unless required by applicable law or agreed to in writing, software
 011  * distributed under the License is distributed on an "AS IS" BASIS,
 012  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 013  * See the License for the specific language governing permissions and
 014  * limitations under the License.
 015  */
 016 package org.codehaus.griffon.runtime.core.resources;
 017
 018 import griffon.core.CallableWithArgs;
 019 import griffon.core.resources.NoSuchResourceException;
 020 import griffon.core.resources.ResourceResolver;
 021
 022 import javax.annotation.Nonnull;
 023 import javax.annotation.Nullable;
 024 import java.text.MessageFormat;
 025 import java.util.List;
 026 import java.util.Locale;
 027 import java.util.Map;
 028 import java.util.MissingResourceException;
 029
 030 import static griffon.util.GriffonNameUtils.requireNonBlank;
 031 import static java.util.Objects.requireNonNull;
 032
 033 /**
 034  * @author Andres Almiray
 035  * @since 2.0.0
 036  */
 037 public abstract class AbstractResourceResolver implements ResourceResolver {
 038     protected static final String ERROR_KEY_BLANK = "Argument 'key' must not be blank";
 039     protected static final String ERROR_LOCALE_NULL = "Argument 'locale' must not be null";
 040     protected static final String ERROR_ARGS_NULL = "Argument 'args' must not be null";
 041     protected static final String ERROR_RESOURCE_BLANK = "Argument 'resource' must not be blank";
 042
 043     protected static final Object[] EMPTY_OBJECT_ARGS = new Object[0];
 044
 045     @Nonnull
 046     @Override
 047     public Object resolveResource(@Nonnull String key) throws NoSuchResourceException {
 048         return resolveResource(key, EMPTY_OBJECT_ARGS, Locale.getDefault());
 049     }
 050
 051     @Nonnull
 052     @Override
 053     public Object resolveResource(@Nonnull String key, @Nonnull Locale locale) throws NoSuchResourceException {
 054         return resolveResource(key, EMPTY_OBJECT_ARGS, locale);
 055     }
 056
 057     @Nonnull
 058     @Override
 059     public Object resolveResource(@Nonnull String key, @Nonnull Object[] args) throws NoSuchResourceException {
 060         return resolveResource(key, args, Locale.getDefault());
 061     }
 062
 063     @Nonnull
 064     @Override
 065     public Object resolveResource(@Nonnull String key, @Nonnull Object[] args, @Nonnull Locale locale) throws NoSuchResourceException {
 066         requireNonBlank(key, ERROR_KEY_BLANK);
 067         requireNonNull(args, ERROR_ARGS_NULL);
 068         requireNonNull(locale, ERROR_LOCALE_NULL);
 069         Object resource = resolveResourceValue(key, locale);
 070         Object result = evalResourceWithArguments(resource, args);
 071         if (result != null) return result;
 072         throw new NoSuchResourceException(key, locale);
 073     }
 074
 075     @Nonnull
 076     @Override
 077     public Object resolveResource(@Nonnull String key, @Nonnull List<?> args) throws NoSuchResourceException {
 078         return resolveResource(key, toObjectArray(args), Locale.getDefault());
 079     }
 080
 081     @Nonnull
 082     @Override
 083     public Object resolveResource(@Nonnull String key, @Nonnull List<?> args, @Nonnull Locale locale) throws NoSuchResourceException {
 084         return resolveResource(key, toObjectArray(args), locale);
 085     }
 086
 087     @Nullable
 088     @Override
 089     public Object resolveResource(@Nonnull String key, @Nullable Object defaultValue) {
 090         return resolveResource(key, EMPTY_OBJECT_ARGS, Locale.getDefault(), defaultValue);
 091     }
 092
 093     @Nullable
 094     @Override
 095     public Object resolveResource(@Nonnull String key, @Nonnull Locale locale, @Nullable Object defaultValue) {
 096         return resolveResource(key, EMPTY_OBJECT_ARGS, locale, defaultValue);
 097     }
 098
 099     @Nullable
 100     @Override
 101     public Object resolveResource(@Nonnull String key, @Nonnull Object[] args, @Nullable Object defaultValue) {
 102         return resolveResource(key, args, Locale.getDefault(), defaultValue);
 103     }
 104
 105     @Nullable
 106     @Override
 107     public Object resolveResource(@Nonnull String key, @Nonnull Object[] args, @Nonnull Locale locale, @Nullable Object defaultValue) {
 108         try {
 109             return resolveResource(key, args, locale);
 110         } catch (NoSuchResourceException nsre) {
 111             return null == defaultValue ? key : defaultValue;
 112         }
 113     }
 114
 115     @Nullable
 116     @Override
 117     public Object resolveResource(@Nonnull String key, @Nonnull List<?> args, @Nullable Object defaultValue) {
 118         return resolveResource(key, toObjectArray(args), Locale.getDefault(), defaultValue);
 119     }
 120
 121     @Nullable
 122     @Override
 123     public Object resolveResource(@Nonnull String key, @Nonnull List<?> args, @Nonnull Locale locale, @Nullable Object defaultValue) {
 124         return resolveResource(key, toObjectArray(args), locale, defaultValue);
 125     }
 126
 127     @Nonnull
 128     @Override
 129     public Object resolveResource(@Nonnull String key, @Nonnull Map<String, Object> args) throws NoSuchResourceException {
 130         return resolveResource(key, args, Locale.getDefault());
 131     }
 132
 133     @Nonnull
 134     @Override
 135     public Object resolveResource(@Nonnull String key, @Nonnull Map<String, Object> args, @Nonnull Locale locale) throws NoSuchResourceException {
 136         requireNonBlank(key, ERROR_KEY_BLANK);
 137         requireNonNull(args, ERROR_ARGS_NULL);
 138         requireNonNull(locale, ERROR_LOCALE_NULL);
 139         Object resource = resolveResourceValue(key, locale);
 140         Object result = evalResourceWithArguments(resource, args);
 141         if (result != null) return result;
 142         throw new NoSuchResourceException(key, locale);
 143     }
 144
 145     @Nullable
 146     @Override
 147     public Object resolveResource(@Nonnull String key, @Nonnull Map<String, Object> args, @Nullable Object defaultValue) {
 148         return resolveResource(key, args, Locale.getDefault(), defaultValue);
 149     }
 150
 151     @Nullable
 152     @Override
 153     public Object resolveResource(@Nonnull String key, @Nonnull Map<String, Object> args, @Nonnull Locale locale, @Nullable Object defaultValue) {
 154         try {
 155             return resolveResource(key, args, locale);
 156         } catch (NoSuchResourceException nsre) {
 157             return null == defaultValue ? key : defaultValue;
 158         }
 159     }
 160
 161     @Nonnull
 162     @Override
 163     public Object resolveResourceValue(@Nonnull String key, @Nonnull Locale locale) throws NoSuchResourceException {
 164         requireNonBlank(key, ERROR_KEY_BLANK);
 165         requireNonNull(locale, ERROR_LOCALE_NULL);
 166         try {
 167             Object resource = doResolveResourceValue(key, locale);
 168             if (resource instanceof CharSequence) {
 169                 String msg = resource.toString();
 170                 if (msg.length() >= 4 && msg.startsWith(REF_KEY_START) && msg.endsWith(REF_KEY_END)) {
 171                     String refKey = msg.substring(2, msg.length() - 1);
 172                     resource = resolveResourceValue(refKey, locale);
 173                 }
 174             }
 175             return resource;
 176         } catch (MissingResourceException mre) {
 177             throw new NoSuchResourceException(key, locale);
 178         }
 179     }
 180
 181     @Nonnull
 182     @Override
 183     public String formatResource(@Nonnull String resource, @Nonnull List<?> args) {
 184         requireNonBlank(resource, ERROR_RESOURCE_BLANK);
 185         requireNonNull(args, ERROR_ARGS_NULL);
 186         return formatResource(resource, args.toArray(new Object[args.size()]));
 187     }
 188
 189     @Nonnull
 190     @Override
 191     public String formatResource(@Nonnull String resource, @Nonnull Object[] args) {
 192         requireNonBlank(resource, ERROR_RESOURCE_BLANK);
 193         requireNonNull(args, ERROR_ARGS_NULL);
 194         if (args.length == 0) return resource;
 195         return MessageFormat.format(resource, args);
 196     }
 197
 198     @Nonnull
 199     @Override
 200     public String formatResource(@Nonnull String resource, @Nonnull Map<String, Object> args) {
 201         requireNonBlank(resource, ERROR_RESOURCE_BLANK);
 202         requireNonNull(args, ERROR_ARGS_NULL);
 203         for (Map.Entry<String, Object> variable : args.entrySet()) {
 204             String var = variable.getKey();
 205             String value = variable.getValue() != null ? variable.getValue().toString() : null;
 206             if (value != null) {
 207                 resource = resource.replace("{:" + var + "}", value);
 208             }
 209         }
 210         return resource;
 211     }
 212
 213     @Nonnull
 214     protected abstract Object doResolveResourceValue(@Nonnull String key, @Nonnull Locale locale) throws NoSuchResourceException;
 215
 216     @Nullable
 217     protected Object evalResourceWithArguments(@Nonnull Object resource, @Nonnull Object[] args) {
 218         if (resource instanceof CallableWithArgs) {
 219             CallableWithArgs<?> callable = (CallableWithArgs<?>) resource;
 220             return callable.call(args);
 221         } else if (resource instanceof CharSequence) {
 222             return formatResource(String.valueOf(resource), args);
 223         }
 224         return resource;
 225     }
 226
 227     @Nullable
 228     protected Object evalResourceWithArguments(@Nonnull Object resource, @Nonnull Map<String, Object> args) {
 229         if (resource instanceof CallableWithArgs) {
 230             CallableWithArgs<?> callable = (CallableWithArgs<?>) resource;
 231             return callable.call(args);
 232         } else if (resource instanceof CharSequence) {
 233             return formatResource(String.valueOf(resource), args);
 234         }
 235         return resource;
 236     }
 237
 238     @Nonnull
 239     protected Object[] toObjectArray(@Nonnull List<?> args) {
 240         if (args.isEmpty()) {
 241             return EMPTY_OBJECT_ARGS;
 242         }
 243         return args.toArray(new Object[args.size()]);
 244     }
 245 }
 |