| JavaDoq: Context.java |
001
002 /*
003 * Descripter 1.0 - Java Script Engines
004 * Copyright (C) 2010-2015 Jianjun Liu (J.J.Liu)
005 *
006 * This program is free software: you can redistribute it and/or modify
007 * it under the terms of the GNU Affero General Public License as published by
008 * the Free Software Foundation, either version 3 of the License, or
009 * (at your option) any later version.
010 *
011 * This program is distributed in the hope that it will be useful,
012 * but WITHOUT ANY WARRANTY; without even the implied warranty of
013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
014 * GNU Affero General Public License for more details.
015 *
016 * You should have received a copy of the GNU Affero General Public License
017 * along with this program. If not, see <http://www.gnu.org/licenses/>.
018 */
019
020 package org.descripter.js.api;
021
022 import java.util.HashMap;
023 import java.util.HashSet;
024 import java.util.Set;
025
026 /**
027 * <p>A base class for representing various related contexts in JavaScript.</p>
028 *
029 * @author <a href="mailto:jianjunliu@126.com">J.J.Liu (Jianjun Liu)</a> at <a href="http://www.descripter.org" target="_blank">http://www.descripter.org</a>
030 * @since Descripter 1.0
031 */
032 public class Context<S, T, W extends Context<S, T, ?>>
033 {
034 private final HashMap<S, T> map = new HashMap<S, T>();
035 private boolean readOnly = false;
036 /**
037 * <p>The container of the current context.</p>
038 * @since Descripter 1.0
039 */
040 public final W with;
041
042 /**
043 * <p>Constructs a context of this type.</p>
044 * @param with The containing context.
045 * @since Descripter 1.0
046 */
047 public Context(W with) {
048 this.with = with;
049 }
050
051 /**
052 * <p>Tells if the current context is read-only.</p>
053 * @return <tt>true</tt> if the current context is read-only; <tt>false</tt>, otherwise.
054 * @since Descripter 1.0
055 */
056 public boolean readOnly() {
057 return readOnly;
058 }
059
060 /**
061 * <p>Sets the current context to <tt>readOnly</tt>.</p>
062 * @param readOnly <tt>true</tt> to set the current context read-only; <tt>false</tt>, otherwise.
063 * @since Descripter 1.0
064 */
065 public void readOnly(boolean readOnly) {
066 if (this.readOnly ^ readOnly) {
067 this.readOnly = readOnly;
068 for (T t : map.values()) {
069 if (t instanceof Context) {
070 ((Context<?, ?, ?>)t).readOnly(readOnly);
071 }
072 }
073 }
074 }
075
076 /**
077 * <p>Finds the most inner context that owns the specified key.</p>
078 * @param key A key to lookup
079 * @return The most inner context that owns the specified key or <tt>null</tt> if no such containers.
080 * @since Descripter 1.0
081 */
082 public Context<S, T, ?> in(S key) {
083 if (map.containsKey(key) || with == null) {
084 return this;
085 } else {
086 return with.in(key);
087 }
088 }
089
090 /**
091 * <p>Tells if a specified context is one of the containers of the current one.</p>
092 * @param ctx A context to test
093 * @return <tt>true</tt> if <tt>ctx</tt> contains the current context; <tt>false</tt>, otherwise.
094 * @since Descripter 1.0
095 */
096 public boolean with(Context<S, T, ?> ctx) {
097 return with != null && (with == ctx || with.with(ctx));
098 }
099
100 /**
101 * <p>Tells if the current context owns the specified key.</p>
102 * @param key A key to test
103 * @return <tt>true</tt> if the current context owns the <tt>key</tt>; <tt>false</tt>, otherwise.
104 * @since Descripter 1.0
105 */
106 public boolean owns(S key) {
107 return map.containsKey(key) && map.get(key) != null;
108 }
109
110 /**
111 * <p>Tells if the specified key is visible in the current context.</p>
112 * @param key A key to test
113 * @return <tt>true</tt> if the <tt>key</tt> is visible in the current context; <tt>false</tt>, otherwise.
114 * @since Descripter 1.0
115 */
116 public boolean has(S key) {
117 return map.containsKey(key) || with != null && with.has(key);
118 }
119
120 /**
121 * <p>Returns the {@link Set} of keys that are visible to the current context.</p>
122 * @return The {@link Set} of keys that are visible to the current context.
123 * @since Descripter 1.0
124 */
125 public Set<S> keys() {
126 Set<S> keys = new HashSet<S>(map.keySet());
127 if (with != null) {
128 keys.addAll(with.keys());
129 }
130 return keys;
131 }
132
133 /**
134 * <p>Returns the value associated with the specified key.</p>
135 * @param key A key to lookup
136 * @return The value associated with the specified key or <tt>null</tt> for none.
137 * @since Descripter 1.0
138 */
139 public T get(S key) {
140 if (!map.containsKey(key) && with != null) {
141 return with.get(key);
142 }
143 return map.get(key);
144 }
145
146 /**
147 * <p>Updates the value associated with the specified key if it is visible.</p>
148 * <p>Note that this method does nothing if the key is not visible.</p>
149 * @param key A key to update
150 * @throws RuntimeException if the current context is read-only.
151 * @since Descripter 1.0
152 */
153 public void update(S key, T val) {
154 if (map.containsKey(key)) {
155 put(key, val);
156 } else if (with != null) {
157 with.update(key, val);
158 }
159 }
160
161 /**
162 * <p>Hides the specified key from the current context if it is visible.</p>
163 * <p>Note that this method does nothing if the key is not visible.</p>
164 * @param key A key to remove
165 * @throws RuntimeException if the current context is read-only.
166 * @since Descripter 1.0
167 */
168 public void hide(S key) {
169 if (has(key)) {
170 put(key, null);
171 }
172 }
173
174 /**
175 * <p>Sets the value associated with the specified key.</p>
176 * @param key A key to set
177 * @param val The value to set the value
178 * @throws RuntimeException if the current context is read-only.
179 * @since Descripter 1.0
180 */
181 public void put(S key, T val) {
182 if (readOnly) {
183 throw new RuntimeException();
184 }
185 map.put(key, val);
186 }
187 }
| JavaDoq: Context.java |