From 0e485cbafdfa9b2d16f505f41ef52c58c0531862 Mon Sep 17 00:00:00 2001 From: erickson Date: Thu, 30 Apr 2009 14:42:40 +0000 Subject: [PATCH] field array position is determined by position in the IDL. dynamically generate isnew/ischanged/isdeleted fields and push them onto the end of the list of fields. For now, if isnew/ischanged/isdeleted fields exist in the IDL, they are ignored git-svn-id: svn://svn.open-ils.org/ILS/trunk@13022 dcc99617-32d9-48b4-a31d-7c20da2025e4 --- Open-ILS/src/c-apps/oils_idl-core.c | 57 ++++++++++++++++------ Open-ILS/src/extras/org_tree_js.pl | 2 +- Open-ILS/src/perlmods/OpenILS/Utils/Fieldmapper.pm | 17 ++++--- Open-ILS/src/python/oils/utils/idl.py | 41 +++++++++------- Open-ILS/web/js/dojo/fieldmapper/Fieldmapper.js | 4 +- Open-ILS/web/js/dojo/fieldmapper/IDL.js | 28 ++++++----- Open-ILS/web/opac/common/js/fmgen.js | 10 ++-- 7 files changed, 103 insertions(+), 56 deletions(-) diff --git a/Open-ILS/src/c-apps/oils_idl-core.c b/Open-ILS/src/c-apps/oils_idl-core.c index b0cce8dd26..471435c7f1 100644 --- a/Open-ILS/src/c-apps/oils_idl-core.c +++ b/Open-ILS/src/c-apps/oils_idl-core.c @@ -23,6 +23,7 @@ static xmlDocPtr idlDoc = NULL; // parse and store the IDL here /* parse and store the IDL here */ static osrfHash* idlHash; +static void add_std_fld( osrfHash* fields_hash, const char* field_name, unsigned pos ); osrfHash* oilsIDL(void) { return idlHash; } osrfHash* oilsIDLInit( const char* idl_filename ) { @@ -121,14 +122,34 @@ osrfHash* oilsIDLInit( const char* idl_filename ) { unsigned int array_pos = 0; char array_pos_buf[ 7 ]; // For up to 1,000,000 fields per class - xmlNodePtr _f = _cur->children; + xmlNodePtr _f = _cur->children; while(_f) { if (strcmp( (char*)_f->name, "field" )) { _f = _f->next; continue; } + // Get the field name. If it's one of the three standard + // fields that we always generate, ignore it. + char* field_name = (char*)xmlGetProp(_f, BAD_CAST "name"); + if( field_name ) { + osrfLogDebug(OSRF_LOG_MARK, + "Found field %s for class %s", field_name, current_class_name ); + if( !strcmp( field_name, "isnew" ) + || !strcmp( field_name, "ischanged" ) + || !strcmp( field_name, "isdeleted" ) ) { + free( field_name ); + _f = _f->next; + continue; + } + } else { + osrfLogDebug(OSRF_LOG_MARK, + "Found field with no name for class %s", current_class_name ); + _f = _f->next; + continue; + } + osrfHash* field_def_hash = osrfNewHash(); // Insert array_position @@ -165,25 +186,20 @@ osrfHash* oilsIDLInit( const char* idl_filename ) { ); } - if( (prop_str = (char*)xmlGetProp(_f, BAD_CAST "name")) ) { - osrfHashSet( - field_def_hash, - prop_str, - "name" - ); - osrfLogDebug(OSRF_LOG_MARK, - "Found field %s for class %s", prop_str, current_class_name ); - } else - osrfLogDebug(OSRF_LOG_MARK, - "Found field with no name for class %s", current_class_name ); - + osrfHashSet( field_def_hash, field_name, "name" ); osrfHashSet( current_fields_hash, field_def_hash, - prop_str + field_name ); _f = _f->next; } + + // Create three standard, stereotyped virtual fields for every class + add_std_fld( current_fields_hash, "isnew", array_pos++ ); + add_std_fld( current_fields_hash, "ischanged", array_pos++ ); + add_std_fld( current_fields_hash, "isdeleted", array_pos ); + } if (!strcmp( (char*)_cur->name, "links" )) { @@ -419,6 +435,19 @@ osrfHash* oilsIDLInit( const char* idl_filename ) { return idlHash; } +// Adds a standard virtual field to a fields hash +static void add_std_fld( osrfHash* fields_hash, const char* field_name, unsigned pos ) { + char array_pos_buf[ 7 ]; + osrfHash* std_fld_hash = osrfNewHash(); + + snprintf( array_pos_buf, sizeof( array_pos_buf ), "%u", pos ); + osrfHashSet( std_fld_hash, strdup( array_pos_buf ), "array_position" ); + osrfHashSet( std_fld_hash, "true", "virtual" ); + osrfHashSet( std_fld_hash, strdup( field_name ), "name" ); + osrfHashSet( fields_hash, std_fld_hash, field_name ); +} + + osrfHash* oilsIDLFindPath( const char* path, ... ) { if(!path || strlen(path) < 1) return NULL; diff --git a/Open-ILS/src/extras/org_tree_js.pl b/Open-ILS/src/extras/org_tree_js.pl index cac77fc70c..50f34cb246 100644 --- a/Open-ILS/src/extras/org_tree_js.pl +++ b/Open-ILS/src/extras/org_tree_js.pl @@ -86,7 +86,7 @@ sub build_tree_js { for my $t (@$types) { my ($u,$v,$d,$i,$n,$o,$p) = (val($t->can_have_users),val($t->can_have_vols),$t->depth,$t->id,val($t->name),val($t->opac_label),$t->parent); $p ||= 'null'; - $pile .= "new aout([null,null,null,null,$u,$v,$d,$i,$n,$o,$p]), "; + $pile .= "new aout([null,$u,$v,$d,$i,$n,$o,$p]), "; } $pile =~ s/, $//; # remove trailing comma $pile .= ']; /* OU Types */'; diff --git a/Open-ILS/src/perlmods/OpenILS/Utils/Fieldmapper.pm b/Open-ILS/src/perlmods/OpenILS/Utils/Fieldmapper.pm index 308976bd4b..ea782f7075 100644 --- a/Open-ILS/src/perlmods/OpenILS/Utils/Fieldmapper.pm +++ b/Open-ILS/src/perlmods/OpenILS/Utils/Fieldmapper.pm @@ -78,6 +78,7 @@ sub load_fields { my $attribute_list = $field->attributes(); my $name = get_attribute( $attribute_list, 'name' ); + next if( $name eq 'isnew' || $name eq 'ischanged' || $name eq 'isdeleted' ); my $virtual = get_attribute( $attribute_list, 'oils_persist:virtual' ); if( ! defined( $virtual ) ) { $virtual = "false"; @@ -100,6 +101,16 @@ sub load_fields { ++$array_position; } } + + # Load the standard 3 virtual fields ------------------------ + + for my $vfield ( qw/isnew ischanged isdeleted/ ) { + $$fieldmap{$fm}{fields}{ $vfield } = + { position => $array_position, + virtual => 1 + }; + ++$array_position; + } } sub load_links { @@ -199,12 +210,6 @@ sub import { use base 'Fieldmapper'; PERL - my $pos = 0; - for my $vfield ( qw/isnew ischanged isdeleted/ ) { - $$fieldmap{$pkg}{fields}{$vfield} = { position => $pos, virtual => 1 }; - $pos++; - } - if (exists $$fieldmap{$pkg}{proto_fields}) { for my $pfield ( sort keys %{ $$fieldmap{$pkg}{proto_fields} } ) { $$fieldmap{$pkg}{fields}{$pfield} = { position => $pos, virtual => $$fieldmap{$pkg}{proto_fields}{$pfield} }; diff --git a/Open-ILS/src/python/oils/utils/idl.py b/Open-ILS/src/python/oils/utils/idl.py index 32da172f2b..e8345584bf 100644 --- a/Open-ILS/src/python/oils/utils/idl.py +++ b/Open-ILS/src/python/oils/utils/idl.py @@ -78,6 +78,10 @@ class IDLParser(object): def parse_IDL(self): """Parses the IDL file and builds class, field, and link objects""" + # in case we're calling parse_IDL directly + if not IDLParser._global_parser: + IDLParser._global_parser = self + doc = xml.dom.minidom.parse(self.idlFile) root = doc.documentElement @@ -105,11 +109,11 @@ class IDLParser(object): fields = [f for f in child.childNodes if f.nodeName == 'fields'] links = [f for f in child.childNodes if f.nodeName == 'links'] - keys = self.parse_fields(obj, fields[0]) + fields = self.parse_fields(obj, fields[0]) if len(links) > 0: self.parse_links(obj, links[0]) - osrf.net_obj.register_hint(obj.name, keys, 'array') + osrf.net_obj.register_hint(obj.name, [f.name for f in fields], 'array') doc.unlink() @@ -129,22 +133,21 @@ class IDLParser(object): def parse_fields(self, idlobj, fields): """Takes the fields node and parses the included field elements""" - keys = [] - idlobj.primary = self._get_attr(fields, 'oils_persist:primary', OILS_NS_PERSIST) idlobj.sequence = self._get_attr(fields, 'oils_persist:sequence', OILS_NS_PERSIST) - # pre-flesh the array of keys to accomodate random index insertions - for field in fields.childNodes: - if field.nodeType == field.ELEMENT_NODE: - keys.append(None) - + position = 0 for field in [l for l in fields.childNodes if l.nodeName == 'field']: + name = self._get_attr(field, 'name') + + if name in ['isnew', 'ischanged', 'isdeleted']: + continue + obj = IDLField( idlobj, - name = self._get_attr(field, 'name'), - position = int(self._get_attr(field, 'oils_obj:array_position', OILS_NS_OBJ)), + name = name, + position = position, virtual = self._get_attr(field, 'oils_persist:virtual', OILS_NS_PERSIST), label = self._get_attr(field, 'reporter:label', OILS_NS_REPORTER), rpt_datatype = self._get_attr(field, 'reporter:datatype', OILS_NS_REPORTER), @@ -152,15 +155,19 @@ class IDLParser(object): primitive = self._get_attr(field, 'oils_persist:primitive', OILS_NS_PERSIST) ) - try: - keys[obj.position] = obj.name - except Exception, e: - osrf.log.log_error("parse_fields(): position out of range. pos=%d : key-size=%d" % (obj.position, len(keys))) - raise e + idlobj.fields.append(obj) + position += 1 + for name in ['isnew', 'ischanged', 'isdeleted']: + obj = IDLField(idlobj, + name = name, + position = position, + virtual = 'true' + ) idlobj.fields.append(obj) + position += 1 - return keys + return idlobj.fields diff --git a/Open-ILS/web/js/dojo/fieldmapper/Fieldmapper.js b/Open-ILS/web/js/dojo/fieldmapper/Fieldmapper.js index ec9066efac..901d87d084 100644 --- a/Open-ILS/web/js/dojo/fieldmapper/Fieldmapper.js +++ b/Open-ILS/web/js/dojo/fieldmapper/Fieldmapper.js @@ -150,8 +150,6 @@ if(!dojo._hasResource["fieldmapper.Fieldmapper"]){ for (var f in fieldmapper.IDL.fmclasses[this.classname].fields) { var field = fieldmapper.IDL.fmclasses[this.classname].fields[f]; var p = field.array_position; - if (p <= 2) continue; - this._fields.push( field.name ); this[field.name]=new Function('n', 'if(arguments.length==1)this.a['+p+']=n;return this.a['+p+'];'); } @@ -174,7 +172,7 @@ if(!dojo._hasResource["fieldmapper.Fieldmapper"]){ this.classname = this.declaredClass; this._fields = fmclasses[this.classname]; for( var pos = 0; pos < this._fields.length; pos++ ) { - var p = parseInt(pos) + 3; + var p = parseInt(pos); var f = this._fields[pos]; this[f]=new Function('n', 'if(arguments.length==1)this.a['+p+']=n;return this.a['+p+'];'); } diff --git a/Open-ILS/web/js/dojo/fieldmapper/IDL.js b/Open-ILS/web/js/dojo/fieldmapper/IDL.js index 105e246e8b..87af3e3650 100644 --- a/Open-ILS/web/js/dojo/fieldmapper/IDL.js +++ b/Open-ILS/web/js/dojo/fieldmapper/IDL.js @@ -105,10 +105,14 @@ if(!dojo._hasResource["fieldmapper.IDL"]) { else links = []; + var position = 0; for(var i = 0; i < fields.length; i++) { var field = fields[i]; var name = field.getAttribute('name'); + if(name == 'isnew' || name == 'ischanged' || name == 'isdeleted') + continue; + var obj = { field : field, name : name, @@ -116,7 +120,7 @@ if(!dojo._hasResource["fieldmapper.IDL"]) { datatype : field.getAttributeNS(this.NS_REPORTS,'datatype'), primitive : field.getAttributeNS(this.NS_PERSIST,'primitive'), selector : field.getAttributeNS(this.NS_REPORTS,'selector'), - array_position : parseInt(field.getAttributeNS(this.NS_OBJ,'array_position')), + array_position : position++, type : 'field', virtual : (fields[i].getAttributeNS(this.NS_PERSIST, 'virtual') == 'true') }; @@ -124,8 +128,7 @@ if(!dojo._hasResource["fieldmapper.IDL"]) { obj.label = obj.label || obj.name; obj.datatype = obj.datatype || 'text'; - if (obj.array_position > 2) - window.fmclasses[classname].push(obj.name); + window.fmclasses[classname].push(obj.name); var link = null; for(var l = 0; l < links.length; l++) { @@ -146,16 +149,19 @@ if(!dojo._hasResource["fieldmapper.IDL"]) { map[obj.name] = obj; } - /* - data = data.sort( - function(a,b) { - if( a.label > b.label ) return 1; - if( a.label < b.name ) return -1; - return 0; + dojo.forEach(['isnew', 'ischanged', 'isdeleted'], + function(name) { + var obj = { + name : name, + array_position : position++, + type : 'field', + virtual : true + }; + data.push(obj); + map[obj.name] = obj; } ); - */ - + return { list : data, map : map }; } diff --git a/Open-ILS/web/opac/common/js/fmgen.js b/Open-ILS/web/opac/common/js/fmgen.js index e26d2623eb..bf67355e8a 100644 --- a/Open-ILS/web/opac/common/js/fmgen.js +++ b/Open-ILS/web/opac/common/js/fmgen.js @@ -33,9 +33,7 @@ Fieldmapper.prototype.clone = function() { } return obj; } -Fieldmapper.prototype.isnew = function(n) { if(arguments.length == 1) this.a[0] =n; return this.a[0]; } -Fieldmapper.prototype.ischanged = function(n) { if(arguments.length == 1) this.a[1] =n; return this.a[1]; } -Fieldmapper.prototype.isdeleted = function(n) { if(arguments.length == 1) this.a[2] =n; return this.a[2]; } + function FMEX(message) { this.message = message; } FMEX.toString = function() { return "FieldmapperException: " + this.message + "\n"; } @@ -51,8 +49,12 @@ for( var cl in fmclasses ) { string += cl + "._isfieldmapper=true;"; + fmclasses[cl].push('isnew'); + fmclasses[cl].push('ischanged'); + fmclasses[cl].push('isdeleted'); + for( var pos in fmclasses[cl] ) { - var p = parseInt(pos) + 3; + var p = parseInt(pos); var field = fmclasses[cl][pos]; string += cl + ".prototype." + field + "=function(n){if(arguments.length == 1)this.a[" + -- 2.11.0