View Javadoc
1   package io.jawk.jrt;
2   
3   /*-
4    * ╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲
5    * Jawk
6    * ჻჻჻჻჻჻
7    * Copyright (C) 2006 - 2026 MetricsHub
8    * ჻჻჻჻჻჻
9    * This program is free software: you can redistribute it and/or modify
10   * it under the terms of the GNU Lesser General Public License as
11   * published by the Free Software Foundation, either version 3 of the
12   * License, or (at your option) any later version.
13   *
14   * This program is distributed in the hope that it will be useful,
15   * but WITHOUT ANY WARRANTY; without even the implied warranty of
16   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17   * GNU General Lesser Public License for more details.
18   *
19   * You should have received a copy of the GNU General Lesser Public
20   * License along with this program.  If not, see
21   * <http://www.gnu.org/licenses/lgpl-3.0.html>.
22   * ╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱
23   */
24  
25  import java.util.HashMap;
26  
27  /**
28   * An AWK associative array backed by a {@link HashMap}.
29   * <p>
30   * Keys are not kept in any particular order. This is the default implementation
31   * used when sorted keys are not required.
32   * </p>
33   *
34   * @author MetricsHub
35   */
36  public class HashAssocArray extends HashMap<Object, Object> implements AssocArray {
37  
38  	private static final long serialVersionUID = 1L;
39  
40  	/**
41  	 * Returns the value to which the specified key is mapped, normalizing the key
42  	 * first. If the key does not exist, a blank ({@link io.jawk.intermediate.UninitializedObject})
43  	 * is inserted and returned, as required by AWK semantics.
44  	 *
45  	 * @param key the key whose associated value is to be returned
46  	 * @return the value associated with the key, or a blank value if not found
47  	 */
48  	@Override
49  	public Object get(Object key) {
50  		key = AssocArray.normalizeKey(key);
51  		Object result = super.get(key);
52  		if (result != null) {
53  			return result;
54  		}
55  		Long lKey = AssocArray.toLongKey(key);
56  		if (lKey != null) {
57  			result = super.get(lKey);
58  			if (result != null) {
59  				return result;
60  			}
61  			key = lKey;
62  		}
63  		result = UNTYPED;
64  		super.put(key, result);
65  		return result;
66  	}
67  
68  	/**
69  	 * Associates the specified value with the specified key, normalizing the key
70  	 * to a {@code Long} when the key is a valid integer string.
71  	 *
72  	 * @param key the key
73  	 * @param value the value
74  	 * @return the previous value associated with the key, or {@code null}
75  	 */
76  	@Override
77  	public Object put(Object key, Object value) {
78  		key = AssocArray.normalizeKey(key);
79  		Long lKey = AssocArray.toLongKey(key);
80  		// null has no meaning in an AWK array: store the untyped marker so
81  		// callers never have to special-case it
82  		return super.put(lKey != null ? lKey : key, value == null ? UNTYPED : value);
83  	}
84  
85  	/**
86  	 * Removes the mapping for the specified key, trying both the original and its
87  	 * {@code Long} equivalent.
88  	 *
89  	 * @param key the key whose mapping is to be removed
90  	 * @return the previous value associated with the key, or {@code null}
91  	 */
92  	@Override
93  	public Object remove(Object key) {
94  		key = AssocArray.normalizeKey(key);
95  		Object result = super.remove(key);
96  		if (result != null) {
97  			return result;
98  		}
99  		Long lKey = AssocArray.toLongKey(key);
100 		return lKey != null ? super.remove(lKey) : null;
101 	}
102 
103 	/**
104 	 * Returns the specification version of the underlying {@link HashMap} class.
105 	 *
106 	 * @return the specification version string, or {@code null} if unavailable
107 	 */
108 	@Override
109 	public String getMapVersion() {
110 		return HashMap.class.getPackage().getSpecificationVersion();
111 	}
112 
113 	/**
114 	 * {@inheritDoc}
115 	 *
116 	 * @throws AwkRuntimeException always, to prevent accidental use of
117 	 *         {@link HashMap#toString()} in an AWK evaluation
118 	 *         context
119 	 */
120 	@Override
121 	public String toString() {
122 		throw new AwkRuntimeException("Attempting to use an array in a scalar context.");
123 	}
124 }