    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     */
    017    package org.apache.commons.lang.text;
    018
    019    import java.util.Map;
    020
    021    /**
    022     * Lookup a String key to a String value.
    023     * <p>
    024     * This class represents the simplest form of a string to string map.
    025     * It has a benefit over a map in that it can create the result on
    026     * demand based on the key.
    027     * <p>
    028     * This class comes complete with various factory methods.
    029     * If these do not suffice, you can subclass and implement your own matcher.
    030     * <p>
    031     * For example, it would be possible to implement a lookup that used the
    032     * key as a primary key, and looked up the value on demand from the database
    033     *
    034     * @author Apache Software Foundation
    035     * @since 2.2
    036     * @version $Id: StrLookup.java 905636 2010-02-02 14:03:32Z niallp $
    037     */
    038    public abstract class StrLookup {
    039
    040        /**
    041         * Lookup that always returns null.
    042         */
    043        private static final StrLookup NONE_LOOKUP;
    044        /**
    045         * Lookup that uses System properties.
    046         */
    047        private static final StrLookup SYSTEM_PROPERTIES_LOOKUP;
    048        static {
    049            NONE_LOOKUP = new MapStrLookup(null);
    050            StrLookup lookup = null;
    051            try {
    052                lookup = new MapStrLookup(System.getProperties());
    053            } catch (SecurityException ex) {
    054                lookup = NONE_LOOKUP;
    055            }
    056            SYSTEM_PROPERTIES_LOOKUP = lookup;
    057        }
    058
    059        //-----------------------------------------------------------------------
    060        /**
    061         * Returns a lookup which always returns null.
    062         *
    063         * @return a lookup that always returns null, not null
    064         */
    065        public static StrLookup noneLookup() {
    066            return NONE_LOOKUP;
    067        }
    068
    069        /**
    070         * Returns a lookup which uses {@link System#getProperties() System properties}
    071         * to lookup the key to value.
    072         * <p>
    073         * If a security manager blocked access to system properties, then null will
    074         * be returned from every lookup.
    075         * <p>
    076         * If a null key is used, this lookup will throw a NullPointerException.
    077         *
    078         * @return a lookup using system properties, not null
    079         */
    080        public static StrLookup systemPropertiesLookup() {
    081            return SYSTEM_PROPERTIES_LOOKUP;
    082        }
    083
    084        /**
    085         * Returns a lookup which looks up values using a map.
    086         * <p>
    087         * If the map is null, then null will be returned from every lookup.
    088         * The map result object is converted to a string using toString().
    089         *
    090         * @param map  the map of keys to values, may be null
    091         * @return a lookup using the map, not null
    092         */
    093        public static StrLookup mapLookup(Map map) {
    094            return new MapStrLookup(map);
    095        }
    096
    097        //-----------------------------------------------------------------------
    098        /**
    099         * Constructor.
    100         */
    101        protected StrLookup() {
    102            super();
    103        }
    104
    105        /**
    106         * Looks up a String key to a String value.
    107         * <p>
    108         * The internal implementation may use any mechanism to return the value.
    109         * The simplest implementation is to use a Map. However, virtually any
    110         * implementation is possible.
    111         * <p>
    112         * For example, it would be possible to implement a lookup that used the
    113         * key as a primary key, and looked up the value on demand from the database
    114         * Or, a numeric based implementation could be created that treats the key
    115         * as an integer, increments the value and return the result as a string -
    116         * converting 1 to 2, 15 to 16 etc.
    117         * <p>
    118         * The {@link #lookup(String)} method always returns a String, regardless of
    119         * the underlying data, by converting it as necessary. For example:
    120         * <pre>
    121         * Map map = new HashMap();
    122         * map.put("number", new Integer(2));
    123         * assertEquals("2", StrLookup.mapLookup(map).lookup("number"));
    124         * </pre>
    125         * @param key  the key to be looked up, may be null
    126         * @return the matching value, null if no match
    127         */
    128        public abstract String lookup(String key);
    129
    130        //-----------------------------------------------------------------------
    131        /**
    132         * Lookup implementation that uses a Map.
    133         */
    134        static class MapStrLookup extends StrLookup {
    135
    136            /** Map keys are variable names and value. */
    137            private final Map map;
    138
    139            /**
    140             * Creates a new instance backed by a Map.
    141             *
    142             * @param map  the map of keys to values, may be null
    143             */
    144            MapStrLookup(Map map) {
    145                this.map = map;
    146            }
    147
    148            /**
    149             * Looks up a String key to a String value using the map.
    150             * <p>
    151             * If the map is null, then null is returned.
    152             * The map result object is converted to a string using toString().
    153             *
    154             * @param key  the key to be looked up, may be null
    155             * @return the matching value, null if no match
    156             */
    157            public String lookup(String key) {
    158                if (map == null) {
    159                    return null;
    160                }
    161                Object obj = map.get(key);
    162                if (obj == null) {
    163                    return null;
    164                }
    165                return obj.toString();
    166            }
    167        }
    168    }