1 /*
   2  * Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package javax.script;
  27 
  28 import java.util.Map;
  29 import java.util.HashMap;
  30 import java.util.Collection;
  31 import java.util.Set;
  32 
  33 /**
  34  * A simple implementation of Bindings backed by
  35  * a {@code HashMap} or some other specified {@code Map}.
  36  *
  37  * @author Mike Grogan
  38  * @since 1.6
  39  */
  40 public class SimpleBindings implements Bindings {
  41 
  42     /**
  43      * The {@code Map} field stores the attributes.
  44      */
  45     private Map<String,Object> map;
  46 
  47     /**
  48      * Constructor uses an existing {@code Map} to store the values.
  49      * @param m The {@code Map} backing this {@code SimpleBindings}.
  50      * @throws NullPointerException if m is null
  51      */
  52     public SimpleBindings(Map<String,Object> m) {
  53         if (m == null) {
  54             throw new NullPointerException();
  55         }
  56         this.map = m;
  57     }
  58 
  59     /**
  60      * Default constructor uses a {@code HashMap}.
  61      */
  62     public SimpleBindings() {
  63         this(new HashMap<String,Object>());
  64     }
  65 
  66     /**
  67      * Sets the specified key/value in the underlying {@code map} field.
  68      *
  69      * @param name Name of value
  70      * @param value Value to set.
  71      *
  72      * @return Previous value for the specified key.  Returns null if key was previously
  73      * unset.
  74      *
  75      * @throws NullPointerException if the name is null.
  76      * @throws IllegalArgumentException if the name is empty.
  77      */
  78     public Object put(String name, Object value) {
  79         checkKey(name);
  80         return map.put(name,value);
  81     }
  82 
  83     /**
  84      * {@code putAll} is implemented using {@code Map.putAll}.
  85      *
  86      * @param toMerge The {@code Map} of values to add.
  87      *
  88      * @throws NullPointerException
  89      *         if toMerge map is null or if some key in the map is null.
  90      * @throws IllegalArgumentException
  91      *         if some key in the map is an empty String.
  92      */
  93     public void putAll(Map<? extends String, ? extends Object> toMerge) {
  94         if (toMerge == null) {
  95             throw new NullPointerException("toMerge map is null");
  96         }
  97         for (Map.Entry<? extends String, ? extends Object> entry : toMerge.entrySet()) {
  98             String key = entry.getKey();
  99             checkKey(key);
 100             put(key, entry.getValue());
 101         }
 102     }
 103 
 104     /** {@inheritDoc} */
 105     public void clear() {
 106         map.clear();
 107     }
 108 
 109     /**
 110      * Returns {@code true} if this map contains a mapping for the specified
 111      * key.  More formally, returns {@code true} if and only if
 112      * this map contains a mapping for a key {@code k} such that
 113      * {@code (key==null ? k==null : key.equals(k))}.  (There can be
 114      * at most one such mapping.)
 115      *
 116      * @param key key whose presence in this map is to be tested.
 117      * @return {@code true} if this map contains a mapping for the specified
 118      *         key.
 119      *
 120      * @throws NullPointerException if key is null
 121      * @throws ClassCastException if key is not String
 122      * @throws IllegalArgumentException if key is empty String
 123      */
 124     public boolean containsKey(Object key) {
 125         checkKey(key);
 126         return map.containsKey(key);
 127     }
 128 
 129     /** {@inheritDoc} */
 130     public boolean containsValue(Object value) {
 131         return map.containsValue(value);
 132     }
 133 
 134     /** {@inheritDoc} */
 135     public Set<Map.Entry<String, Object>> entrySet() {
 136         return map.entrySet();
 137     }
 138 
 139     /**
 140      * Returns the value to which this map maps the specified key.  Returns
 141      * {@code null} if the map contains no mapping for this key.  A return
 142      * value of {@code null} does not <i>necessarily</i> indicate that the
 143      * map contains no mapping for the key; it's also possible that the map
 144      * explicitly maps the key to {@code null}.  The {@code containsKey}
 145      * operation may be used to distinguish these two cases.
 146      *
 147      * <p>More formally, if this map contains a mapping from a key
 148      * {@code k} to a value {@code v} such that
 149      * {@code (key==null ? k==null : key.equals(k))},
 150      * then this method returns {@code v}; otherwise
 151      * it returns {@code null}.  (There can be at most one such mapping.)
 152      *
 153      * @param key key whose associated value is to be returned.
 154      * @return the value to which this map maps the specified key, or
 155      *         {@code null} if the map contains no mapping for this key.
 156      *
 157      * @throws NullPointerException if key is null
 158      * @throws ClassCastException if key is not String
 159      * @throws IllegalArgumentException if key is empty String
 160      */
 161     public Object get(Object key) {
 162         checkKey(key);
 163         return map.get(key);
 164     }
 165 
 166     /** {@inheritDoc} */
 167     public boolean isEmpty() {
 168         return map.isEmpty();
 169     }
 170 
 171     /** {@inheritDoc} */
 172     public Set<String> keySet() {
 173         return map.keySet();
 174     }
 175 
 176     /**
 177      * Removes the mapping for this key from this map if it is present
 178      * (optional operation).   More formally, if this map contains a mapping
 179      * from key {@code k} to value {@code v} such that
 180      * {@code (key==null ?  k==null : key.equals(k))}, that mapping
 181      * is removed.  (The map can contain at most one such mapping.)
 182      *
 183      * <p>Returns the value to which the map previously associated the key, or
 184      * {@code null} if the map contained no mapping for this key.  (A
 185      * {@code null} return can also indicate that the map previously
 186      * associated {@code null} with the specified key if the implementation
 187      * supports {@code null} values.)  The map will not contain a mapping for
 188      * the specified  key once the call returns.
 189      *
 190      * @param key key whose mapping is to be removed from the map.
 191      * @return previous value associated with specified key, or {@code null}
 192      *         if there was no mapping for key.
 193      *
 194      * @throws NullPointerException if key is null
 195      * @throws ClassCastException if key is not String
 196      * @throws IllegalArgumentException if key is empty String
 197      */
 198     public Object remove(Object key) {
 199         checkKey(key);
 200         return map.remove(key);
 201     }
 202 
 203     /** {@inheritDoc} */
 204     public int size() {
 205         return map.size();
 206     }
 207 
 208     /** {@inheritDoc} */
 209     public Collection<Object> values() {
 210         return map.values();
 211     }
 212 
 213     private void checkKey(Object key) {
 214         if (key == null) {
 215             throw new NullPointerException("key can not be null");
 216         }
 217         if (!(key instanceof String)) {
 218             throw new ClassCastException("key should be a String");
 219         }
 220         if (key.equals("")) {
 221             throw new IllegalArgumentException("key can not be empty");
 222         }
 223     }
 224 }