if (subnodesRel == null) subnodesRel = new Relation (subnodeMapping, "_children", this, props); subnodesRel.update (subnodeMapping, props); if (subnodesRel.accessor != null) propertiesRel = subnodesRel;
if (subRelation == null) subRelation = new Relation (subnodeMapping, "_children", this, props); subRelation.update (subnodeMapping, props);   if (subRelation.accessor != null || subRelation.groupby != null) propRelation = subRelation;
    public synchronized void update () {	// read in properties	table = props.getProperty ("_table");	idgen = props.getProperty ("_idgen");	// see if there is a field which specifies the prototype of objects, if different prototypes	// can be stored in this table	prototypeField = props.getProperty ("_prototypefield");	// see if this prototype extends (inherits from) any other prototype	extendsProto = props.getProperty ("_extends");	sourceName = props.getProperty ("_db");	if (sourceName != null) {	    source = app.getDbSource (sourceName);	    if (source == null) {	        app.logEvent ("*** Data Source for prototype "+typename+" does not exist: "+sourceName);	        app.logEvent ("*** accessing or storing a "+typename+" object will cause an error.");	    } else if (table == null) {	        app.logEvent ("*** No table name specified for prototype "+typename);	        app.logEvent ("*** accessing or storing a "+typename+" object will cause an error.");	        // mark mapping as invalid by nulling the source field	        source = null;	    }	}	// if id field is null, we assume "ID" as default. We don't set it	// however, so that if null we check the parent prototype first.	idField = props.getProperty ("_id");	nameField = props.getProperty ("_name");	protoField = props.getProperty ("_prototype");	String parentSpec = props.getProperty ("_parent");	if (parentSpec != null) {	    // comma-separated list of properties to be used as parent	    StringTokenizer st = new StringTokenizer (parentSpec, ",;");	    parent = new ParentInfo[st.countTokens()];	    for (int i=0; i<parent.length; i++)	        parent[i] = new ParentInfo (st.nextToken().trim());	} else {	    parent = null;	}	lastTypeChange = props.lastModified ();	// null the cached schema & keydef so it's rebuilt the next time around	schema = null;	keydef = null;	// same with columns and select string	columns = null;	select = null;	if (extendsProto != null) {	    parentMapping = app.getDbMapping (extendsProto);	}	// if (table != null && source != null) {	// app.logEvent ("set data source for "+typename+" to "+source);	HashMap p2d = new HashMap ();	HashMap d2p = new HashMap ();	for (Enumeration e=props.keys(); e.hasMoreElements(); ) {	    String propName = (String) e.nextElement ();	    try {	        // ignore internal properties (starting with "_") and sub-options (containing a ".")	        if (!propName.startsWith ("_") && propName.indexOf (".") < 0) {	            String dbField = props.getProperty (propName);	            // check if a relation for this propery already exists. If so, reuse it	            Relation rel = propertyToRelation (propName);	            if (rel == null)	                rel = new Relation (dbField, propName, this, props);	            rel.update (dbField, props);	            p2d.put (propName, rel);	            if (rel.columnName != null &&	            		(rel.reftype == Relation.PRIMITIVE ||	            		rel.reftype == Relation.REFERENCE))	                d2p.put (rel.columnName.toUpperCase (), rel);	            // app.logEvent ("Mapping "+propName+" -> "+dbField);	        }	    } catch (Exception x) {	        app.logEvent ("Error in type.properties: "+x.getMessage ());	    }	}	prop2db = p2d;	db2prop = d2p;	String subnodeMapping = props.getProperty ("_children");	if (subnodeMapping != null) {	    try {	        // check if subnode relation already exists. If so, reuse it	        if (subnodesRel == null)	            subnodesRel = new Relation (subnodeMapping, "_children", this, props);	        subnodesRel.update (subnodeMapping, props);	        if (subnodesRel.accessor != null)	            propertiesRel = subnodesRel;	    } catch (Exception x) {	        app.logEvent ("Error reading _subnodes relation for "+typename+": "+x.getMessage ());	        // subnodesRel = null;	    }	} else {	    subnodesRel = propertiesRel = null;	}	if (groupbyMapping != null) {	    initGroupbyMapping ();	    groupbyMapping.lastTypeChange = this.lastTypeChange;	}    }