RapidACE software uses MVC (loosely). In that, I have a generic “data holder” for all data elements. This data containter is called ITEM. It is not inherited, nor abstracted. All properties are assigned dynamically, and therefore the code abstraction “of what you can do with the data” is endless, without modification to the core set.
Furthermore, any “abstraction” happens in the controller layers – again, without Inheritance of the physical object. This makes RapidACE core engine infinitely scalable, and easy to alter/update. The core element or data holder is exposed here.
It’s called: “ITEM”.
[java]
/**
*
*/
package model.generic;
import java.util.ArrayList;
import java.util.List;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;
import freemarker.template.SimpleNumber;
import freemarker.template.SimpleCollection;
import freemarker.template.SimpleHash;
/**
* @author Dan Linstedt
* (C) Dan Linstedt, 2011-2012, All Rights Reserved
* Written for RapidACE
*
* Purpose: to hold ALL data elements, and to be a recursive container
* for additional data elements. This way, an Item can represent a FIELD
* or a CONSTRAINT, or a TABLE with fields, or anything else I want it
* to be. All “attributes” are programmatically added as objects,
* so they are NEVER private, but can be manipulated at run-time.
*
*/
public class Item extends LinkedHashMap<String,Object> {
/**
*
*/
private static final long serialVersionUID = 1597929376529169667L;
private Item parentMap;
private String XMLTag = “”;
private boolean vHasChildren = false;
// hold a COPY of array pointers to children objects
// this allows freemarker access direct through recursive hash
// and allows Java easy “function” reference to children
private LinkedHashMap<String,Item> private_children;
// hold a COPY of array pointers to PROPERTIES types objects
// for the same reasons as CHILDREN are private
//private LinkedHashMap<String,Object> private_properties;
// these are variables that are INTERNAL ONLY
// they are NOT added to the children, therefore are
// hidden from the view of FreeMarker
private LinkedHashMap<String,Item> internals;
/**
*
*/
public Item() {
internalInit();
}
/**
* @param initialCapacity
*/
public Item(int initialCapacity) {
super(initialCapacity);
internalInit();
}
/**
* @param m
*/
@SuppressWarnings({ “unchecked”, “rawtypes” })
public Item(Map m) {
super(m);
internalInit();
}
/**
* @param initialCapacity
* @param loadFactor
*/
public Item(int initialCapacity, float loadFactor) {
super(initialCapacity, loadFactor);
internalInit();
}
/**
* @param initialCapacity
* @param loadFactor
* @param accessOrder
*/
public Item(int initialCapacity, float loadFactor, boolean accessOrder) {
super(initialCapacity, loadFactor, accessOrder);
internalInit();
}
private void internalInit() {
private_children = new LinkedHashMap<String,Item>();
// private_properties = new LinkedHashMap<String,Object>();
internals = new LinkedHashMap<String,Item>();
hasChildren(false);
}
public void hasChildren(boolean setchildren) {
vHasChildren = setchildren;
}
public void XMLType(String xType) {
XMLTag = xType;
}
public String XMLType() {
return(XMLTag);
}
public void name(String name) {
this.put(“name”, name);
}
public String name() {
return(this.getProperty(“name”));
}
public void destroy() {
// destroyLinkedMap(private_properties);
destroyLinkedMap(private_children);
ArrayList<Object> vals = new ArrayList<Object>();
for(Object child:this.values())
vals.add(child);
for(Object child:vals) {
this.remove(child);
if (child instanceof Item)
((Item)child).destroy();
}
vals.clear();
// private_properties.clear();
private_children.clear(); // clear the COPY of the objects
internals.clear(); // YOU are responsible for destroying other objects
this.clear();
}
/**
* DEEP COPY OF MYSELF TO ANOTHER OBJECT
* @return
*/
public Item copy() {
Item newCopy = new Item();
for(String prop:this.keySet()) {
Object val = this.get(prop);
if (val instanceof Item)
newCopy.put(prop, ((Item) val).copy());
else
newCopy.put(prop, val);
}
return(newCopy);
}
public void setCDATA(String cdata) {
this.put(“#CDATA”, cdata);
}
public boolean ignoreInLoop(String key) {
return(key.toUpperCase().matches(“XMLATTRS|#CDATA|HASDUPLICATENAMES”));
}
@SuppressWarnings({ “unchecked”, “rawtypes” })
private void destroyLinkedMap(LinkedHashMap myMap) {
ArrayList<String> keyList = new ArrayList<String>();
Set<String> props = myMap.keySet();
for(String key:props)
keyList.add(key);
for(String key:keyList) {
Object val = (Object)myMap.get(key);
myMap.remove(key);
if (val instanceof Item)
((Item)val).destroy();
}
}
public void put(String key,String value) {
// private_properties.put(key, value);
super.put(key, value);
}
public void put(String key, Integer value) {
SimpleNumber myval = new SimpleNumber(value);
// private_properties.put(key, myval);
super.put(key, myval);
}
public void put(String key, Float value) {
SimpleNumber myval = new SimpleNumber(value);
// private_properties.put(key, myval);
super.put(key, myval);
}
public void put(String key, Double value) {
SimpleNumber myval = new SimpleNumber(value);
// private_properties.put(key, myval);
super.put(key, myval);
}
public void put(String key, Long value) {
SimpleNumber myval = new SimpleNumber(value);
// private_properties.put(key, myval);
super.put(key, myval);
}
public void put(String key, boolean value) {
Boolean myval = new Boolean(value);
// private_properties.put(key, myval);
super.put(key, myval);
}
public void put(String key, List<Object> value) {
super.put(key, new SimpleCollection(value));
}
public void put(String key, HashMap<Object,Object> value) {
super.put(key, new SimpleHash(value));
}
public void put(String key, Item child) {
super.put(key, child);
private_children.put(key, child);
child.setParent(this);
hasChildren(true);
}
public void putDontChangeParent(String key, Item child) {
super.put(key, child);
private_children.put(key, child);
hasChildren(true);
}
public void setParent(Item parent) {
parentMap = parent;
}
public Item createChild(String key) {
if (this.childContainsKey(key))
return(this.getChild(key));
Item child = new Item();
this.put(key,child);
child.XMLType(key);
return(child);
}
public Item createChildMap(String childName) {
Item newItem = createChild(childName);
newItem.XMLType(childName);
return(newItem);
}
public String getAttribute(String key) {
Item child = this.getChild(“XMLAttrs”);
if (child==null) return(“”);
return(child.getProperty(key));
}
/* ————————————–
*
* These are routines used for interfacing with this
* hash array
*
*/
public void putProperty(String key, String value) {
this.put(key, value);
}
public String removeProperty(String key) {
return((String)this.remove(key));
}
public String getProperty(String key) {
Object itm = this.get(key);
if (itm instanceof String)
return((String)itm);
if (itm instanceof SimpleNumber)
return(((SimpleNumber)itm).toString());
return(“”);
}
public String getString(String key) {
return(getProperty(key));
}
public Integer getInteger(String key) {
Object itm = this.get(key);
try {
Integer newInt = Integer.parseInt((String)itm.toString());
return(newInt);
} catch (Exception e) {
return(0);
}
}
public Item getParent() {
return(parentMap);
}
public void putChild(String key, Item value) {
this.put(key, value);
}
public boolean childContainsKey(String key) {
return(private_children.containsKey(key));
}
public Item getChild(String key) {
return(private_children.get(key));
}
public Item removeChild(String key) {
Item itm = private_children.remove(key.toUpperCase());
if (private_children.size()==0)
this.hasChildren(false);
this.remove(key.toUpperCase());
return(itm);
}
public LinkedHashMap<String,Item> children() {
return(private_children);
}
public boolean hasProperties() {
if (this.size()>=1)
return(true);
return(false);
}
public boolean hasChildren() {
if (private_children.size()>=1)
return(true);
return(false);
}
public LinkedHashMap<String,Object> properties() {
return(this);
}
/**
* Drill into a path (dot notation) to get a CHILD item
* @param path – String (dot notation path)
* @return Item – child item
*/
public Item getPath(String path) {
if (path.equals(“”)) return(null);
Item match = this;
String[] keys = path.split(“\\.”);
if (match.containsKey(keys[0])) {
match = match.getChild(keys[0]);
int count = 1;
while(count < keys.length) {
String key = keys[count];
if (match.childContainsKey(key))
match = match.getChild(key);
if (match == null) return(null);
count++;
}
}
return(match);
}
public Item getInternal(String key) {
return(internals.get(key));
}
public void putInternal(String key, Item ptr) {
internals.put(key, ptr);
}
}
[/java]