[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
enhanced container object
- Subject: enhanced container object
- From: Martin Schultz <martin.schultz(at)dkrz.de>
- Date: Fri, 21 Jul 2000 17:05:23 +0200
- Newsgroups: comp.lang.idl-pvwave
- Organization: MPI fuer Meteorologie
- Xref: news.doit.wisc.edu comp.lang.idl-pvwave:20362
Hi, everybody out there,
as always, progress is much slower than anticipated, but to keep my
spirits
up and to take the chance of valuable feedback from you gurus, I'd like
to present
a new object of mine, MGS_Container, which enhances the IDL_Container
object by
allowing child-object access via the child objects' "name" attribute (if
they have
one). Thus, to retrieve all objects which are called "Hugo", you can
write:
theContainer->Get(name='Hugo')
It even goes beyond that and allows a simple wildcard search with a
trailing
'*'. To find all objects whose name starts with 'A' (or 'a') type:
theContainer->Get(name='A*')
Objects without a name attribute (or without a GetProperty method
which returns
the name via a "name" keyword), are recognized as name=''.
The other small enhancement with respect to IDL_Container is that you
can
remove several objects at once, i.e. it is now allowed to type e.g.
theContainer->Remove,position=[0,2,4,6]
(and, of course, also : theContainer->Remove,name=['A*','H*'] )
Two new methods allow to retrieve all objects' names (GetName()), and
the
index position of objects (GetPosition(objlist), where objlist is an
object
reference array or a string list with names).
Hope you find this useful,
Regards,
Martin
--
[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[
[[ Dr. Martin Schultz Max-Planck-Institut fuer Meteorologie [[
[[ Bundesstr. 55, 20146 Hamburg [[
[[ phone: +49 40 41173-308 [[
[[ fax: +49 40 41173-298 [[
[[ martin.schultz@dkrz.de [[
[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[
;+
; NAME:
; MGS_Container (Object)
;
; PURPOSE:
; This object extends the IDL_Container object (see online help)
; by allowing access to objects by name. If all objects stored in
; the container possess a structure element called 'name' and allow
; access to this element via a GetProperty method, MGS_Container
; allows the following in excess of IDL_Container's functionality:
; 1. retrieve the container position objects via their name attributes
; 2. retrieve object references via the objects' name attributes
; 3. remove objects via their name attributes
; Objects without a name attribute (or without a GetProperty
; method) are internally handled as objects with an empty name string.
; The Get, and Remove methods accept a single string or a string
; vector with the 'name' keyword. Each name may end with a '*' which
; is interpreted as "and any other characters including none". Note,
; however, that '*' alone will not return empty names ('').
; A new method GetPosition accepts an object list as
; argument. This can either be a list of object references or a
; string (or string vector). This method returns an index vector
; which can be used as 'position' value in other methods.
;
; AUTHOR:
; Dr. Martin Schultz
; Max-Planck-Institut fuer Meteorologie
; Bundesstr. 55, D-20146 Hamburg
; email: martin.schultz@dkrz.de
;
; CATEGORY:
; Objects, General Programming
;
; CALLING SEQUENCE:
; theContainer = Obj_New( 'MGS_Container' )
; theContainer->Add, objectref
; objectref = theContainer->Get( [keywords] )
; Obj_Destroy, theContainer
;
; KEYWORDS TO THE INITIALIZATION ROUTINE:
; None.
;
; PROCEDURES AND METHODS:
; For a more detailed explanation on individual methods or
; procedures, see the comments in the respective code sections.
; The following list contains only "public" procedures and methods.
; Methods marked with '*' are changed or new with respect to the
; parent IDL_Container object.
;
; NON-OBJECT PROCEDURES:
; None
;
; PROCEDURE METHODS:
; MGS_Container::Add, objref [Position=index]
; Add an object to the container.
; MGS_Container::Move, source, dest
; Move the position of an object within the container.
; * MGS_Container::Remove, [ objectref | Position=index | /All |
; Name=string ]
; Delete an object from the container. NEW: can specify
; objects by name.
;
; FUNCTION METHODS:
; MGS_Container::Count()
; Return number of objects stored in container.
; * MGS_Container::Get( /All | IsA=classname | Position=index |
; Name=string [, Count=variable] )
; Return references to selected objects from the
; container. If no object matches the search criteria, a
; long value of -1 is returned (as in IDL_Container).
; NEW: can specify objects by name.
; MGS_Container::IsContained( objref [, Position=index] )
; Test if object(s) is stored in container.
; * MGS_Container::GetNames( [Position=index] )
; NEW method. Return the names of the objects stored in the
; container. Objects without a name field yield an empty string.
; * MGS_Container::GetPosition( objlist )
; NEW method. Returns the index values of objects specified
; by object reference or name. Objlist can be a string vector
; where each string can have a trailing '*' as wildcard.
;
; MODIFICATION HISTORY:
;
; mgs, 19 Jul 2000 : VERSION 1.00
;
;-
;
;###########################################################################
;
; LICENSE
;
; This software is OSI Certified Open Source Software.
; OSI Certified is a certification mark of the Open Source Initiative.
;
; Copyright © 2000 Martin Schultz
;
; This software is provided "as-is", without any express or
; implied warranty. In no event will the authors be held liable
; for any damages arising from the use of this software.
;
; Permission is granted to anyone to use this software for any
; purpose, including commercial applications, and to alter it and
; redistribute it freely, subject to the following restrictions:
;
; 1. The origin of this software must not be misrepresented; you must
; not claim you wrote the original software. If you use this software
; in a product, an acknowledgment in the product documentation
; would be appreciated, but is not required.
;
; 2. Altered source versions must be plainly marked as such, and must
; not be misrepresented as being the original software.
;
; 3. This notice may not be removed or altered from any source distribution.
;
; For more information on Open Source Software, visit the Open Source
; web site: http://www.opensource.org.
;
;###########################################################################
;---------------------------------------------------------------------------
; GetOneName (*private*):
; This method returns the NAME field of the object stored at the
; position given as argument. If the object contains no NAME field or
; has no GetProperty method, an empty string is returned.
; Note: position must be a scalar!
FUNCTION MGS_Container::GetOneName, Position
;; Establish error handler in case object has no GetProperty method
CATCH, theError
IF theError NE 0 THEN BEGIN
CATCH, /Cancel
RETURN, ''
ENDIF
;; Get the object reference of the specified object
theObject = self->Get(Position=position)
IF not Obj_Valid(theObject) THEN RETURN, ''
;; Atempt to call the object's GetProperty method to retrieve the
;; name
theObject->GetProperty, name=name
;; If successful, return object name. Otherwise, error handler
;; should return empty string.
RETURN, name
END
;---------------------------------------------------------------------------
; GetNames:
; This method returns the NAME fields of all objects stored in the
; container. If the optional POSITION keyword is used, only the names
; of the objects at the indices given by POSITION will be returned.
; Invalid position indices yield empty strings as names.
FUNCTION MGS_Container::GetNames, Position=position
;; If no position vector was passed, get number of objects stored
;; in container and create index list
IF N_Elements(position) GT 0 THEN BEGIN
index = position
ENDIF ELSE BEGIN
objcount = self->Count()
IF objcount GT 0 THEN $
index = lindgen(objcount) $
ELSE $
RETURN, ''
ENDELSE
;; Create result array
result = StrArr(N_Elements(index))
;; Get individual object names
FOR i=0L, N_Elements(index)-1 DO $
result[i] = self->GetOneName(index[i])
RETURN, result
END
;---------------------------------------------------------------------------
; GetPosition:
; This method returns the position indices of the objects specified as
; object reference (in this case the IDL_Container method IsContained
; is used) or specified by names. A -1 is returned if no object in the
; container matches the search or if OBJLIST is neither of type string
; nor objref. Note that objects without name (i.e. empty strings) are
; not found with '*' as search mask but are found if an empty
; string is specified as objlist.
FUNCTION MGS_Container::GetPosition, objlist
;; Establish error handler to be safe
CATCH, theError
IF theError NE 0 THEN BEGIN
CATCH, /Cancel
RETURN, -1L
ENDIF
;; If no objlist is given, return immediately
IF N_Elements(objlist) EQ 0 THEN RETURN, -1L
;; Check if objlist is of type object reference or string
type = Size(objlist, /TNAME)
;; For object references use the inherited IsContained method
IF type EQ 'OBJREF' THEN BEGIN
dummy = self->IsContained(objlist, Position=index)
RETURN, index
ENDIF
;; For strings, interpret them as object names. Get the names of
;; all objects and apply primitive pattern matching.
;; The search is always case-insensitive.
IF type EQ 'STRING' THEN BEGIN
names = self->GetNames()
names = StrTrim( StrUpCase(names), 2)
index = -1L
;; Loop through objlist and find matching indices
FOR i=0L, N_Elements(objlist)-1 DO BEGIN
testname = StrTrim( StrUpCase(objlist[i]), 2)
;; Check if wildcard is used in name
sloppy = 0
IF (( p = StrPos(testname,'*') )) GE 0 THEN BEGIN
l = StrLen(testname)
IF l-p NE 1 THEN BEGIN ; wildcard must be last character
Message, 'Invalid name specification '+objlist[i]+'!', /Continue
GOTO, skip_it
ENDIF
testname = StrMid(testname, 0, l-1)
sloppy = 1
ENDIF
;; Look for matching object names
IF sloppy THEN BEGIN
w = Where(StrPos(names,testname) EQ 0, wcnt)
ENDIF ELSE BEGIN
w = Where(names EQ testname, wcnt)
ENDELSE
;; Add indices to list
IF wcnt GT 0 THEN index = [ index, w ]
skip_it:
ENDFOR
;; Remove first dummy index if any names have been found
IF N_Elements(index) GT 1 THEN index = index[1:*]
RETURN, index
ENDIF
;; Reaching this portion of the routine means invalid type for
;; objlist. Simply return -1.
RETURN, -1L
END
;---------------------------------------------------------------------------
; Get:
; This method returns object references for objects that match
; specified criteria - or all objects if the All keyword is set.
; The IDL_Container method Get is extended to include a Name
; keyword. All and Position take precedence over name. As in the
; original, count can be used to return the number of objects
; retrieved.
FUNCTION MGS_Container::Get, All=all, Position=position, $
Name=name, Count=count, _Ref_Extra=e
;; If All or Position keywords are used, call inherited method
IF Keyword_Set(all) THEN $
RETURN, self->IDL_Container::Get(/All, count=count)
IF N_Elements(Position) GT 0 THEN $
RETURN, self->IDL_Container::Get(Position=position, count=count)
;; Look for named objects ?
IF N_Elements(name) GT 0 THEN BEGIN
;; Find object positions
namepos = self->GetPosition(name)
;; Return objects
RETURN, self->IDL_Container::Get(Position=namepos, count=count)
ENDIF
;; Otherwise call inherited method with extra keywords
RETURN, self->IDL_Container::Get(_extra=e, count=count)
END
;---------------------------------------------------------------------------
; Remove:
; This method removes objects from the container. Similarily to the
; Get method, this method extends the IDL_Container::Remove method to
; allow object specification by name.
; Note: Unlike the original method of IDL_Container, the child_object
; argument, or the position or name keywords can contain more than one
; element. The unique position values are sorted and reversed before
; removing objects.
PRO MGS_Container::Remove, child_object, name=name, position=position, $
All=all, _Ref_Extra=e
;; If all keyword is set, call parent method accordingly
IF Keyword_Set(all) THEN BEGIN
self->IDL_Container::Remove, /All
RETURN
ENDIF
;; If object references are given, loop over them and call the
;; parent object's remove method for each of them
IF N_Elements(child_object) GT 0 THEN BEGIN
FOR i=0L, N_Elements(child_object)-1 DO $
self->IDL_Container::Remove, child_object[i]
RETURN
ENDIF
;; If names are provided, convert them to position indices
IF N_Elements(name) GT 0 THEN $
index = self->GetPosition(name)
;; If position indices are provided, make local copy
IF N_Elements(position) GT 0 THEN $
index = long(position)
;; Handle name and position cases: find unique position values,
;; sort and reverse them and loop
maxindex = self->Count()
IF N_Elements(index) GT 0 THEN BEGIN
;; Need to sort index array and remove items from the end
index = Reverse( index[ Uniq( index, Sort(index) ) ] )
ok = where(index GE 0 AND index LT maxindex, cnt)
IF cnt EQ 0 THEN RETURN ;; no valid index values
index = index[ok]
FOR i=0L, N_Elements(index)-1 DO $
self->IDL_Container::Remove, Position=index[i]
RETURN
ENDIF
;; Handle other (future extensions) cases
self->IDL_Container::Remove, _extra=e
END
;---------------------------------------------------------------------------
; Cleanup:
; This method frees all object values and destroys all objects stored
; in the container. This is already handled in IDL_Container, so
; Cleanup only needs to call the inherited object's method.
PRO MGS_Container::Cleanup
self->IDL_Container::Cleanup
END
;---------------------------------------------------------------------------
; Init:
; This method initializes the object values. There are no arguments,
; so the only action is to call the parent's Init method
FUNCTION MGS_Container::INIT
RETURN, self->IDL_Container::Init()
END
;---------------------------------------------------------------------------
; MGS_Container__Define:
; This is the object definition for the container object. It inherits
; everything from IDL_Container.
PRO MGS_Container__Define
object_class = { MGS_Container, $
INHERITS IDL_Container $
}
END