Struct.java
/***************************************************************************
Copyright 2013 Emily Estes
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
***************************************************************************/
package net.metanotion.scripting;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import net.metanotion.util.Dictionary;
import net.metanotion.util.reflect.GetInitializer;
import net.metanotion.util.reflect.Initializer;
/** This class represents a dynamically created "struct" or "value object". */
public final class Struct implements GetInitializer, Initializer, Dictionary<String,Object> {
private String type;
/** This map stores the list of fields(the keys) and their types(the values). */
private final Map<String,String> struct;
private final Map<String,Object> values = new HashMap<>();
/** Create a new struct, whose type is 't' and with fields in the map keys, to types in the map values.
@param t The canonical type name of the struct.
@param s The keys of the map are the names of the fields, and the values are the cannonical names of the field types.
*/
public Struct(final String t, final Map<String,String> s) {
this.type = t;
this.struct = s;
}
/** Clone this structure without the values associated with it.
@return a copy of this structure with no values set.
*/
public Struct newInstance() { return new Struct(type, struct); }
// GetInitializer
@Override public Initializer initializer() { return new Struct(type, struct); }
@Override public Iterator<String> iterator() { return struct.keySet().iterator(); }
@Override public Dictionary<String,Object> struct(final Object instance) {
if(instance instanceof Struct) { return (Struct) instance; }
throw new RuntimeException("Bad instance type");
}
@Override public String type(final String field) { return struct.get(field); }
// Initializer
@Override public Struct instance() { return this; }
/** Provide a list of the field names of this structure in array form.
@return A set of strings containing the fields.
*/
public Set<String> listProperties() { return struct.keySet(); }
// Dictionary
@Override public Object get(final String property) {
if(struct.containsKey(property)) { return values.get(property); }
throw new RuntimeException("Property '" + property + "' does not exist on Struct:" + type);
}
/** Lookup the type for a given field/property.
@param property The name of the field to look up.
@return The name of the type of the field.
*/
public String getType(final String property) { return struct.get(property); }
/** Set the value of a property.
@param property The name of the field to set the value of.
@param val The new value of the field.
*/
public void put(final String property, final Object val) {
if(!(struct.containsKey(property))) {
throw new RuntimeException("Invalid property '" + property + "' on Struct '" + type + "'");
}
values.put(property, val);
}
/* This should return a JSON representation of the struct.
At the moment, however, it does not exactly do that.
To fix later. */
@Override public String toString() {
final StringBuilder b = new StringBuilder("{ ");
String sep = "";
for(final Map.Entry<String,Object> e: values.entrySet()) {
b.append(sep);
sep = ", \"";
b.append(e.getKey());
b.append("\":");
final Object v = e.getValue();
b.append((v!=null) ? (" \"" + v.toString() + "\""): " null");
}
b.append("}");
return b.toString();
}
}