Examples: invoking EDMmapMethod

EDMmapMethods are executable EDMmethods written in EDMexpressX and wrapped in an EDMmapSchema that may be compiled by the EDMexpressXcompiler. EDMmapMethods are executed by the EDMvirtualMachine.

EDMmapMethods are implemented as SCHEMA_MAP in EDMmapSchemas. Unlike EDMruleMethods and EDMqueryMethods, only one EDMmapMethod may be implemented in each EDMmapSchema. The EDMmapSchema below shows how the EDMmapMethod "CheckPropertySet" is implemented in an EDMmapSchema.

CheckPropertySet
SCHEMA_MAP CheckPropertySet;
  -- ---------------------------------------------------------------
  -- Method: CheckPropertySet
  -- ---------------------------------------------------------------
  GLOBAL
    DECLARE src INSTANCE OF SOURCE_SCHEMA IFC2X3;
    DECLARE trg INSTANCE OF TARGET_SCHEMA IFC2X3;
    retVal : INTEGER := 0; -- Global for holding return value.
  END_GLOBAL;
 
  STATEMENTS IdentifyMethod;
    -- Report to the methods stdout.
    xpxPrintf('Method: CheckPropertySet Started.\n');
  END_STATEMENTS;
 
  STATEMENTS ExecuteMethod;
    LOCAL
      found        : BOOLEAN := FALSE;
      str          : STRING := '';
      resultFileId : INTEGER := 0;
      entityId     : GENERIC;
      ifcObjId     : GENERIC;
      isSubtype    : BOOLEAN;
      nPar         : INTEGER := 0;
      parType      : GENERIC;
      par          : GENERIC;
      entityName   : STRING := '';     -- Parameter #1
      pSetName     : STRING := '';     -- Parameter #2
      fileMapping  : BOOLEAN := FALSE; -- Parameter #3
    END_LOCAL;
 
    -- ------------------------------------------------
    -- Uncomment this line to have the method terminate
    -- with a value -999 returned as UserDefinedStatus.
    -- -------------------------------------------------
    -- xpxTerminate(-999);
 
    -- ------------------------------------------------
    -- EXCEPTION HANDLER
    -- ------------------------------------------------
    ON_ERROR_DO
      str := xpfStringPrintf('\nERROR -> %s threw exception at line %d:',
                              xpxExceptionId.functionName,
                              xpxExceptionId.lineNumber);
      str += xpfStringPrintf('\n  EDMI Error: %d - %s',
                              xpxExceptionId.errCode,
                              xpxExceptionId.errMessage);
      str += xpfStringPrintf('\n  User Error: %d - %s',
                              xpxExceptionId.userCode,
                              xpxExceptionId.userMessage);
      -- Write a detailed exception report to the methods
      -- stdout. May be picked up on the client side as
      -- the user output file.
      xpxPrintf(str);

      -- Close the mapped result file if open
      IF (resultFileId > 0) THEN
        xpxCloseFile(resultFileId);
      END_IF;

      -- Send the error code to the calling client to inform
      -- that an exception was thrown within the method.
      -- The string goes to the exception log file.
      xpxTerminate(xpxExceptionId.errCode, str);
    END_ON_ERROR_DO;
 
    -- Check number of parameters (Accepts either three or none)
    npar := xpxGetNumberOfUserParameters();
    IF (NOT(nPar = 0)) THEN
      -- Check number of parameters
      IF (NOT(nPar = 3)) THEN
        xpxExceptionId.errCode := xpxE_ACTUAL_FORMAL_ARGS;
        str := 'Wrong number of parameters. Expected 3, ';
        str += xpfStringPrintf('Actual %d', nPar);
        xpxExceptionId.userMessage := str;
        xpxThrow;
      END_IF;

      -- Check Parameter #1
      xpxGetUserParameter(1,par);
      xpxGetDataType(par,parType);
      IF (parType <> xpxSTRING) THEN
        xpxExceptionId.errCode := xpxE_ARG2_DATATYPE;
        str := 'Wrong type of Par #1, entityName. Expected STRING';
        xpxExceptionId.userMessage := str;
        xpxThrow;
      ELSE
        entityName := par;
      END_IF;

      -- Check Parameter #2
      xpxGetUserParameter(2,par);
      xpxGetDataType(par,parType);
      IF (parType <> xpxSTRING) THEN
        xpxExceptionId.errCode := xpxE_ACTUAL_FORMAL_ARGS;
        str := 'Wrong type of Par #2, propertySet. Expected STRING';
        xpxExceptionId.userMessage := str;
        xpxThrow;
      ELSE
        pSetName := par;
      END_IF;

      -- Check Parameter #3
      xpxGetUserParameter(3,par);
      xpxGetDataType(par,parType);
      IF (parType <> xpxBOOLEAN) THEN
        xpxExceptionId.errCode := xpxE_ACTUAL_FORMAL_ARGS;
        str := 'Wrong type of Par #3, propertySet. Expected BOOLEAN';
        xpxExceptionId.userMessage := str;
        xpxThrow;
      ELSE
        fileMapping := par;
        IF (fileMapping = TRUE) THEN
          resultFileId := xpfOpenFile('result', 'wt');
        END_IF;
      END_IF;

      -- Check if the Entity is a subtype of ifcObject in IFC2x3
      entityId := xpfGetEntityInSchema(xpxSOURCESCHEMAID, entityName);
      ifcObjId := xpfGetEntityInSchema(xpxSOURCESCHEMAID, 'ifcObject');
      xpxIsSubtypeOf(entityId , ifcObjId, isSubtype);
      IF (NOT(isSubtype)) THEN
        xpxExceptionId.errCode := xpxE_ARG1_DATATYPE;
        str := xpfStringPrintf('The entity %s', entityName);
        str += 'is not a subtype of ifcObject';
        xpxExceptionId.userMessage := str;
        xpxThrow;
      END_IF;

      -- Loop over all instances of entityName.
      FROM (SUBTYPE obj:src::ifcObject)
      WHEN(entityId :=: xpfGetInstanceType(obj));
      BEGIN
        -- Loop over all ifcreldefines objects pointing at this ifcObject
        found := FALSE;
        REPEAT i := 1 TO SIZEOF(obj.IsDefinedBy);
          IF (obj.IsDefinedBy[i].relatingpropertydefinition.Name = pSetName) THEN
            found := TRUE;
            ESCAPE;
          END_IF;
        END_REPEAT;
 
        IF (NOT(found)) THEN
          retVal += 1;
          IF (resultFileId > 0) THEN
            str := xpfStringPrintf('\n%s,%s,%d', obj.GlobalId,
                      entityName, obj);
            xpxWriteFile(resultFileId, str, 100);
          END_IF;
        END_IF;
      END;
      -- Close the resultFile if open.
      IF (resultFileId > 0) THEN
        xpxCloseFile(resultFileId);
      END_IF;
    ELSE
      -- No input parameters: Count property sets.
      FROM (SUBTYPE obj:src::ifcObject)
      WHEN(TRUE);
      BEGIN
        retVal += SIZEOF(obj.IsDefinedBy);
      END;
    END_IF;
  END_STATEMENTS;
 
  STATEMENTS TerminateAndReturnStatusToCaller;
    -- Report to the methods stdout.
    xpxPrintf('  * Returning with value %d\n', -retVal);
    xpxPrintf('Method: CheckPropertySet: Completed\n');
    xpxTerminate(-retVal);
  END_STATEMENTS;
 
END_SCHEMA_MAP;