Constructor: |
public SimpleHash() {
this((ObjectWrapper)null);
}
|
public SimpleHash(Map map) {
this(map, null);
}
Parameters:
map - The Map to use for the key/value pairs. It makes a copy for
internal use. If the map implements the SortedMap interface, the
internal copy will be a TreeMap , otherwise it will be a
HashMap .
|
public SimpleHash(ObjectWrapper wrapper) {
super(wrapper);
map = new HashMap();
}
Creates an empty simple hash using the specified object wrapper. |
public SimpleHash(Map map,
ObjectWrapper wrapper) {
super(wrapper);
try {
this.map = copyMap(map);
} catch (ConcurrentModificationException cme) {
//This will occur extremely rarely.
//If it does, we just wait 5 ms and try again. If
// the ConcurrentModificationException
// is thrown again, we just let it bubble up this time.
// TODO: Maybe we should log here.
try {
Thread.sleep(5);
} catch (InterruptedException ie) {
}
synchronized (map) {
this.map = copyMap(map);
}
}
}
|
Method from freemarker.template.SimpleHash Detail: |
protected Map copyMap(Map map) {
if (map instanceof HashMap) {
return (Map) ((HashMap) map).clone();
}
if (map instanceof SortedMap) {
if (map instanceof TreeMap) {
return (Map) ((TreeMap) map).clone();
}
else {
return new TreeMap((SortedMap) map);
}
}
return new HashMap(map);
}
|
public TemplateModel get(String key) throws TemplateModelException {
Object result = map.get(key);
if (result == null && key.length() == 1) {
// just check for Character key if this is a single-character string
try {
result = map.get(new Character(key.charAt(0)));
} catch (Exception e) {}
}
if (result instanceof TemplateModel) {
return (TemplateModel) result;
}
TemplateModel tm = wrap(result);
// result != null || map.containsKey(key) criteria is to get around
// ConcurrentModificationException when the map is accessed in a loop,
// see bug #1939742 in SourceForge tracker.
if (!putFailed && (result != null || map.containsKey(key))) {
try {
map.put(key, tm);
} catch (Exception e) {
// If it's immutable or something, we just keep going.
putFailed = true;
}
}
return tm;
}
|
public boolean isEmpty() {
return map == null || map.isEmpty();
}
|
public TemplateCollectionModel keys() {
return new SimpleCollection(map.keySet(), getObjectWrapper());
}
|
public void put(String key,
Object obj) {
map.put(key, obj);
unwrappedMap = null;
}
Adds a key-value entry to the map. |
public void put(String key,
boolean b) {
put(key, b ? TemplateBooleanModel.TRUE : TemplateBooleanModel.FALSE);
}
Puts a boolean in the map |
public void putAll(Map m) {
for (Iterator it = m.entrySet().iterator(); it.hasNext();) {
Map.Entry entry = (Map.Entry) it.next();
this.put((String) entry.getKey(), entry.getValue());
}
}
Adds all the key/value entries in the map |
public void remove(String key) {
map.remove(key);
}
Removes the given key from the underlying map. |
public int size() {
return map.size();
}
|
public SimpleHash synchronizedWrapper() {
return new SynchronizedHash();
}
|
public Map toMap() throws TemplateModelException {
if (unwrappedMap == null) {
Class mapClass = this.map.getClass();
Map m = null;
try {
m = (Map) mapClass.newInstance();
} catch (Exception e) {
throw new TemplateModelException("Error instantiating map of type " + mapClass.getName() + "\n" + e.getMessage());
}
// Create a copy to maintain immutability semantics and
// Do nested unwrapping of elements if necessary.
BeansWrapper bw = BeansWrapper.getDefaultInstance();
for (Iterator it = map.entrySet().iterator(); it.hasNext();) {
Map.Entry entry = (Map.Entry) it.next();
Object key = entry.getKey();
Object value = entry.getValue();
if (value instanceof TemplateModel) {
value = bw.unwrap((TemplateModel) value);
}
m.put(key, value);
}
unwrappedMap=m;
}
return unwrappedMap;
}
Note that this method creates and returns a deep-copy of the underlying hash used
internally. This could be a gotcha for some people
at some point who want to alter something in the data model,
but we should maintain our immutability semantics (at least using default SimpleXXX wrappers)
for the data model. It will recursively unwrap the stuff in the underlying container. |
public String toString() {
return map.toString();
}
Convenience method for returning the String value of the
underlying map. |
public TemplateCollectionModel values() {
return new SimpleCollection(map.values(), getObjectWrapper());
}
|