Example 2: Finding rows in an array
This example shows how to implement a function to find rows in an array.
arrays.4gl
source:
IMPORT reflect
PUBLIC CONSTANT FC_EQUALS = "="
PUBLIC CONSTANT FC_BEGINS_WITH = "b"
PUBLIC CONSTANT FC_ENDS_WITH = "e"
PUBLIC CONSTANT FC_LESS_THAN = "<"
PUBLIC CONSTANT FC_GREATER_THAN = ">"
PUBLIC CONSTANT FC_CONTAINS = "c"
PUBLIC CONSTANT FC_NOT_CONTAINS = "!c"
PUBLIC TYPE FindCondition RECORD
field STRING,
type STRING,
value STRING,
ignoreCase BOOLEAN
END RECORD
PUBLIC TYPE FindConditionList DYNAMIC ARRAY OF FindCondition
PRIVATE FUNCTION _conditionMatches(
value reflect.Value, condition FindCondition INOUT)
RETURNS BOOLEAN
DEFINE s, v STRING
IF value.getType().getKind() != "PRIMITIVE" THEN
DISPLAY "ERROR: The record members must be of primitive types"
EXIT PROGRAM 1
END IF
LET s = value.toString()
LET v = condition.value
IF condition.ignoreCase THEN
LET s = s.toLowerCase()
LET v = condition.value.toLowerCase()
END IF
CASE condition.type
WHEN FC_EQUALS
RETURN s == v
WHEN FC_BEGINS_WITH
RETURN s MATCHES (v || "*")
WHEN FC_ENDS_WITH
RETURN s MATCHES ("*" || v)
WHEN FC_CONTAINS
RETURN s MATCHES ("*" || v || "*")
WHEN FC_NOT_CONTAINS
RETURN s NOT MATCHES ("*" || v || "*")
WHEN FC_LESS_THAN
RETURN s < v
WHEN FC_GREATER_THAN
RETURN s > v
OTHERWISE
DISPLAY "ERROR: Invalid condition type"
EXIT PROGRAM 1
END CASE
RETURN FALSE
END FUNCTION
PRIVATE FUNCTION _checkArray( a reflect.Value ) RETURNS ()
IF a.getType().getKind() != "ARRAY" THEN
DISPLAY "ERROR: Expecting an array to search in"
EXIT PROGRAM 1
END IF
IF a.getType().getElementType().getKind() != "RECORD" THEN
DISPLAY "ERROR: The element type of the array must be a record"
EXIT PROGRAM 1
END IF
END FUNCTION
PRIVATE FUNCTION _getFieldIndex(t reflect.Type, n STRING) RETURNS INT
DEFINE x, c INT
LET c = t.getFieldCount()
FOR x = 1 TO c
IF t.getFieldName(x) == n THEN
EXIT FOR
END IF
END FOR
IF x > c THEN
DISPLAY "ERROR: Illegal field name: ", n
EXIT PROGRAM 1
END IF
RETURN x
END FUNCTION
FUNCTION search(a reflect.Value, condition FindCondition INOUT, fromIndex INT)
RETURNS INT
DEFINE fx, x, n INT
CALL _checkArray(a)
LET fx = _getFieldIndex(a.getType().getElementType(), condition.field)
LET n = a.getLength()
FOR x = fromIndex TO n
IF _conditionMatches(a.getArrayElement(x).getField(fx), condition) THEN
RETURN x
END IF
END FOR
RETURN 0
END FUNCTION
FUNCTION searchMultiCond( a reflect.Value, conditions FindConditionList,
all BOOLEAN, fromIndex INT)
RETURNS INT
DEFINE fx DYNAMIC ARRAY OF INT
DEFINE m, x, c, n INT
DEFINE element reflect.Value
DEFINE r BOOLEAN
CALL _checkArray(a)
LET m = conditions.getLength()
FOR x = 1 TO m
LET fx[x] = _getFieldIndex(a.getType().getElementType(), conditions[x].field)
END FOR
LET n = a.getLength()
FOR x = fromIndex TO n
LET element = a.getArrayElement(x)
LET r = TRUE
FOR c = 1 TO m
IF _conditionMatches(element.getField(fx[c]), conditions[c]) THEN
IF NOT all THEN RETURN x END IF
ELSE
LET r = FALSE
IF all THEN EXIT FOR END IF
END IF
END FOR
IF r THEN RETURN x END IF
END FOR
RETURN 0
END FUNCTION
main.4gl
source:
IMPORT util
IMPORT reflect
IMPORT FGL arrays
TYPE Customer RECORD
pkey INTEGER,
name VARCHAR(50),
address VARCHAR(200)
END RECORD
TYPE CustomerList DYNAMIC ARRAY OF Customer
MAIN
DEFINE custlist CustomerList = [
(pkey:101, name:"Mike"),
(pkey:102, name:"Scott"),
(pkey:103, name:"Peter"),
(pkey:155, name:"Bruce"),
(pkey:299, name:"Phil"),
(pkey:302, name:"Scott")
]
DEFINE c arrays.FindCondition
DEFINE cl arrays.FindConditionList
DEFINE x INT
LET c.field="name"
LET c.type=FC_EQUALS
LET c.value="Scott"
LET c.ignoreCase=TRUE
DISPLAY "search 1:", util.JSON.stringify(c)
LET x = 1
WHILE x>0
LET x = arrays.search(reflect.Value.valueOf(custlist), c, x)
IF x>0 THEN
DISPLAY " ",util.JSON.stringify(custlist[x])
LET x = x + 1
END IF
END WHILE
LET cl[1].field="pkey"
LET cl[1].type=FC_GREATER_THAN
LET cl[1].value=100
LET cl[2].field="name"
LET cl[2].type=FC_CONTAINS
LET cl[2].value="e"
DISPLAY "search 2:", util.JSON.stringify(cl)
LET x = 1
WHILE x>0
LET x = arrays.searchMultiCond(reflect.Value.valueOf(custlist), cl, TRUE, x)
IF x>0 THEN
DISPLAY " ",util.JSON.stringify(custlist[x])
LET x = x + 1
END IF
END WHILE
END MAIN
Output:
search 1:{"field":"name","type":"=","value":"Scott","ignoreCase":true}
{"pkey":102,"name":"Scott"}
{"pkey":302,"name":"Scott"}
search 2:[{"field":"pkey","type":">","value":"100"},{"field":"name","type":"c","value":"e"}]
{"pkey":101,"name":"Mike"}
{"pkey":103,"name":"Peter"}
{"pkey":155,"name":"Bruce"}