rexx-things/modules/windows/oodialog/userGuide/exercises/Exercise08/Support/Model.rex
2025-03-12 20:50:48 +00:00

188 lines
9.0 KiB
Rexx
Executable File

/*----------------------------------------------------------------------------*/
/* */
/* Copyright (c) 2011-2014 Rexx Language Association. All rights reserved. */
/* */
/* This program and the accompanying materials are made available under */
/* the terms of the Common Public License v1.0 which accompanies this */
/* distribution. A copy is also available at the following address: */
/* https://www.oorexx.org/license.html */
/* */
/* Redistribution and use in source and binary forms, with or */
/* without modification, are permitted provided that the following */
/* conditions are met: */
/* */
/* Redistributions of source code must retain the above copyright */
/* notice, this list of conditions and the following disclaimer. */
/* Redistributions in binary form must reproduce the above copyright */
/* notice, this list of conditions and the following disclaimer in */
/* the documentation and/or other materials provided with the distribution. */
/* */
/* Neither the name of Rexx Language Association nor the names */
/* of its contributors may be used to endorse or promote products */
/* derived from this software without specific prior written permission. */
/* */
/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */
/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */
/* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS */
/* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */
/* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */
/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED */
/* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, */
/* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY */
/* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING */
/* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS */
/* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
/* */
/*----------------------------------------------------------------------------*/
/* ooDialog User Guide
Exercise08
Support - Model v02-00 24May13
----------------
A superclass for the Model-View framework.
v01-00 09Aug12: First version.
11Jan13: Commented-out "say"s.
31Jan13: Store model's data in 'myData'.
27Feb13: Commented-out some "say" instructions.
v02-00 24May13: Added inherit from the 'Component' mixin.
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */
::REQUIRES "Support\Component.rex"
/*============================================================================*/
::CLASS 'Model' PUBLIC INHERIT Component
::ATTRIBUTE wantList CLASS PUBLIC -- for List subclasses
::ATTRIBUTE myData
/*----------------------------------------------------------------------------
newInstance - must be invoked by subclass.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
::METHOD newInstance CLASS PUBLIC
expose noDataError -- .true if data not found.
use strict arg instanceName
--say ".Model-newInstance-01: instanceName =" instanceName
-- Check that the model's Data object is up and running. If not, then return .false:
if noDataError = .true then return .false
-- Now get the name of the Data component (FredModel or FredListModel --> FredData):
-- Get my root name (i.e. the root name of the subclass):
className = self~objectName -- objectName for a class Foo is "The Foo class"
className = className~upper() -- When class name is in quotes, then it's mixed case.
-- Upper here to make everthing upper case for parse var.
-- Handling Forms:
-- If this is a "Form" then there's no data to get (the user will provide
-- the data). So just create the Form Model (e.g. Order Form) and return.
-- Assume that the instance name is the Form Number (e.g. for an OrderForm,
-- the Form Number will be the new Order Number).
p = className~pos("FORM")
if p > 0 then do -- if this is a "Form" component.
instData = .Directory~new
instData[formNumber] = instanceName
formObject = self~new(instData)
formObject~myData = instData -- store instance data for subclasses to access.
--say ".Model-newInstance-011: formObj, instanceName =" formObject||"," instanceName
return formObject
end
-- End of Handling Forms.
-- If there's "LIST" in the name, then set "get all" for the file access
-- (as opposed to the default of "get 1 record")
getAllRecords = .false
p = className~pos("LIST")
if p > 0 then getAllRecords = .true
-- if there's a "LIST" in the name, strip it out 'cos an xListModel gets data from xData
parse var className . root1 "MODEL" .
parse var root1 root "LIST"
dataClassName = root||"Data"
--say ".Model-newInstance-02, dataClassName =" dataClassName
-- Get the id of Data component:
objMgr = .local~my.ObjectMgr
--say ".Model-newInstance-03: objMgr =" objMgr
myDataId = objMgr~getComponentId(dataClassName, "The")
if myDataId = .false then do -- if instantiation failed
say ".Model-newInstance-04: getting ID of Data Class failed."
noDataError = .true
return .false
end
-- Got my data id, now get data for this model instance.
-- But distinguish between Entity Models and List Models - the former needs
-- a single record, the latter a group of records.
-- say ".Model-newInstance-05a: getAllRecords =" getAllRecords
if getAllRecords then instData = myDataId~getFile() -- returns a 2D array
else instData = myDataId~getRecord(instanceName) -- a directory
-- say ".Model-newInstance-05b: array dimensions: =" instData~dimension
if instData = .false then return .false -- if ID (key) not found
-- All is well, then make new instance:
--say ".Model-newInstance-06: instData =" instData
id = self~new(instData)
id~myData = instData
--say ".Model-newInstance-07: instData =" id
return id
/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
/*----------------------------------------------------------------------------
getInstanceName - For an "anonymous" instance only (e.g. CustomerList)
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
::METHOD getInstanceName CLASS PUBLIC
expose anonInstanceName
if anonInstanceName = "ANONINSTANCENAME" then anonInstanceName = 1
else anonInstanceName = anonInstanceName + 1
return anonInstanceName
/*----------------------------------------------------------------------------
query - returns a Model's data.
Standard protocol:
Accept a .nil, directory, array, or string of names (case-sensitive).
if .nil then return all fields; else return values for the names in
the directory, array, or string. String is assumed to be data
names separated by one or more spaces.
All returns are a Directory containing names and values.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
::METHOD query PUBLIC
use arg dataNames
--say "Model-query-01: dataNames:" dataNames
dirReturn = .Directory~new
select
when dataNames = .nil | dataNames = "" then return self~myData
when dataNames = "DATANAMES" then return self~myData
-- Caller is requesting specific data items:
when dataNames~isa(.Directory) then do
--say "Model-query-02; dataNames =" dataNames
do i over dataNames
dirReturn[i] = self~myData[i]
end
end
when dataNames~isa(.Array) then do
do i over dataNames
dirReturn[i] = self~myData[i]
end
end
when dataNames~isa(.String) then do
dataNames = dataNames~strip
n = dataNames~countStr(" ")+1
do i = 1 to n
parse var dataNames name " " dataNames
if name = " " then iterate -- ignore extraneous leading spaces.
dirReturn[name] = self~myData[name]
end
end
otherwise return .false
end
return dirReturn
/*============================================================================*/
/*============================================================================*/