---
policy: /ce/ca/google/logging/iam-permission-changes-monitoring
logic: /ce/ca/google/logging/iam-permission-changes-monitoring/prod.logic.yaml
executionTime: 2025-04-24T23:47:10.450532051Z
rows:
  - id: aB9P1
    match: true
    status:
      expected: COMPLIANT
      actual: COMPLIANT
    conditionIndex:
      expected: 199
      actual: 199
    conditionText:
      expected: CA10__Google_Logging_Log_Metrics__r.has(COMPLIANT)
      actual: CA10__Google_Logging_Log_Metrics__r.has(COMPLIANT)
    runtimeError: {}
  - id: aB9P12
    match: true
    status:
      expected: INCOMPLIANT
      actual: INCOMPLIANT
    conditionIndex:
      expected: 200
      actual: 200
    conditionText:
      expected: otherwise
      actual: otherwise
    runtimeError: {}
  - id: aB9P13
    match: true
    status:
      expected: INCOMPLIANT
      actual: INCOMPLIANT
    conditionIndex:
      expected: 200
      actual: 200
    conditionText:
      expected: otherwise
      actual: otherwise
    runtimeError: {}
  - id: aB222
    match: true
    status:
      expected: INCOMPLIANT
      actual: INCOMPLIANT
    conditionIndex:
      expected: 200
      actual: 200
    conditionText:
      expected: otherwise
      actual: otherwise
    runtimeError: {}
usedFiles:
  - path: /ce/ca/google/logging/iam-permission-changes-monitoring/policy.yaml
    md5Hash: 25BAB4EDD3FF4847B1DA965FB6232ACD
    content: "---\nnames: \n  full: \"Google Logging Log Metric Filter and Alerts\
      \ Cloud Storage IAM Permission Changes do not exist\"\n  contextual: \"Log Metric\
      \ Filter and Alerts Cloud Storage IAM Permission Changes do not exist\"\ndescription:\
      \ \"It is recommended that a metric filter and alarm be established for Cloud\
      \ Storage Bucket IAM changes.\"\ntype: COMPLIANCE_POLICY\ncategories:\n  - \"\
      SECURITY\"\nframeworkMappings:\n  - /frameworks/cis-gcp-v3.0.0/02/10\n  - /frameworks/cloudaware/logging-and-monitoring/logging-and-monitoring-configuration\n\
      similarPolicies:\n  cloudConformity:\n    - url: \"https://www.trendmicro.com/cloudoneconformity-staging/knowledge-base/gcp/CloudLogging/enable-bucket-permission-changes-monitoring.html\"\
      \n      name: \"Enable Monitoring for Bucket Permission Changes\"\n"
  - path: /ce/ca/google/logging/iam-permission-changes-monitoring/prod.logic.yaml
    md5Hash: 6C067980D0EC51CB82DF2919B287A2FE
    content: "---\n\ninputType: \"CA10__CaGoogleProject__c\"\ntestData:\n  - file:\
      \ test-data.json\nimportExtracts:\n  - file: /types/CA10__CaGoogleProject__c/object.extracts.yaml\n\
      conditions:\n  - status: \"COMPLIANT\"\n    currentStateMessage: \"Log metric\
      \ filter and alerts exist for Project Ownership Assignments/Changes.\"\n   \
      \ check:\n      RELATED_LIST_HAS:\n        relationshipName: \"CA10__Google_Logging_Log_Metrics__r\"\
      \n        status: \"COMPLIANT\"\notherwise:\n  status: \"INCOMPLIANT\"\n  currentStateMessage:\
      \ \"No log metric filter or alerts exist for Project Ownership Assignments/Changes.\"\
      \n  remediationMessage: \"Create log metric and alert policy.\"\nrelatedLists:\n\
      \  - relationshipName: \"CA10__Google_Logging_Log_Metrics__r\"\n    importExtracts:\n\
      \      - file: /types/CA10__CaGoogleLoggingLogMetric__c/object.extracts.yaml\n\
      \      - file: /types/CA10__CaGoogleMonitoringAlertPolicy__c/object.extracts.yaml\n\
      \    conditions:\n        - status: \"COMPLIANT\"\n          currentStateMessage:\
      \ \"Corresponding log metric exists.\"\n          check:\n            AND:\n\
      \              args:\n                - GCP_LOGGING_QUERY_MATCH:\n         \
      \           arg: \n                      EXTRACT: CA10__filter__c\n        \
      \            value: 'resource.type=gcs_bucket AND protoPayload.methodName=\"\
      storage.setIamPermissions\"'\n                - RELATED_LIST_HAS:\n        \
      \            relationshipName: \"CA10__Google_Monitoring_Conditions__r\"\n \
      \                   status: \"COMPLIANT\"\n    otherwise:\n      status: \"\
      INCOMPLIANT\"\n      currentStateMessage: \"There is no log metric with such\
      \ filter.\"\n      remediationMessage: \"Create log metric with the appropriate\
      \ filter.\"\n    relatedLists:\n      - relationshipName: \"CA10__Google_Monitoring_Conditions__r\"\
      \n        conditions:\n          - status: \"COMPLIANT\"\n            currentStateMessage:\
      \ \"Alert policy exist and enabled.\"\n            check:\n              IS_EQUAL:\n\
      \                left:\n                  EXTRACT: CA10__alertPolicy__r.CA10__enabledState__c\n\
      \                right:\n                  TEXT: 'on'\n        otherwise:\n\
      \          status: \"INCOMPLIANT\"\n          currentStateMessage: \"No alert\
      \ policy exist or policy not enabled.\"\n          remediationMessage: \"Create\
      \ or enable alert policy.\""
  - path: /types/CA10__CaGoogleLoggingLogMetric__c/object.extracts.yaml
    md5Hash: D10B1CB14CDBBB08D9E3B38F2BB16DD2
    content: "---\nextracts:\n  - name: \"CA10__descriptorType__c\"\n    value: \n\
      \      FIELD:\n        path: \"CA10__descriptorType__c\"\n  - name: \"CA10__filter__c\"\
      \n    value:\n      FIELD:\n          path: \"CA10__filter__c\"\n  - name: \"\
      CA10__name__c\"\n    value: \n      FIELD:\n        path: \"CA10__name__c\""
  - path: /types/CA10__CaGoogleMonitoringAlertPolicy__c/object.extracts.yaml
    md5Hash: FB18542F30919AFFF9B8EC854708DAC7
    content: "---\nextracts:\n  - name: \"CA10__enabledState__c\"\n    value: \n \
      \     FIELD:\n        path: \"CA10__enabledState__c\""
  - path: /ce/ca/google/logging/iam-permission-changes-monitoring/test-data.json
    md5Hash: F8FA51E320256003656EEE5675912B15
    content: "[\n    {\n      \"expectedResult\": {\n        \"status\": \"COMPLIANT\"\
      ,\n        \"conditionIndex\": \"199\",\n        \"conditionText\": \"CA10__Google_Logging_Log_Metrics__r.has(COMPLIANT)\"\
      ,\n        \"runtimeError\": null\n      },\n      \"context\": { \"snapshotTime\"\
      : \"2024-12-16T11:04:54Z\" },\n      \"Id\": \"aB9P1\",\n      \"CA10__Google_Logging_Log_Metrics__r\"\
      : [\n        {\n          \"Id\": \"aAzM1\",\n          \"CA10__disappearanceTime__c\"\
      : null,\n          \"CA10__filter__c\": \"resource.type=gcs_bucket AND protoPayload.methodName=\\\
      \"storage.setIamPermissions\\\"\",\n          \"CA10__project__c\": \"aB9P1\"\
      ,\n          \"CA10__Google_Monitoring_Conditions__r\": [\n            {\n \
      \             \"Id\": \"aBMC1\",\n              \"CA10__disappearanceTime__c\"\
      : null,\n              \"CA10__alertPolicy__c\": \"aBAP1\",\n              \"\
      CA10__alertPolicyId__c\": \"projects/shared-logging-976f\",\n              \"\
      CA10__loggingLogMetric__c\": \"aAzM1\",\n              \"CA10__alertPolicy__r\"\
      : {\n                \"Id\": \"aBAP1\",\n                \"CA10__disappearanceTime__c\"\
      : null,\n                \"CA10__enabledState__c\": \"on\"\n              }\n\
      \            }\n          ]\n        },\n        {\n          \"Id\": \"aAzM2\"\
      ,\n          \"CA10__disappearanceTime__c\": null,\n          \"CA10__filter__c\"\
      : \"(protoPayload.serviceName=\\\"cloudresourcemanager.googleapis.com\\\")\"\
      ,\n          \"CA10__project__c\": \"aB9P1\",\n          \"CA10__Google_Monitoring_Conditions__r\"\
      : [\n            {\n              \"Id\": \"aBMC2\",\n              \"CA10__disappearanceTime__c\"\
      : null,\n              \"CA10__alertPolicy__c\": \"aBAP2\",\n              \"\
      CA10__alertPolicyId__c\": \"projects/shared-logging-976f2\",\n             \
      \ \"CA10__loggingLogMetric__c\": \"aAzM2\",\n              \"CA10__alertPolicy__r\"\
      : {\n                \"Id\": \"aBAP2\",\n                \"CA10__disappearanceTime__c\"\
      : null,\n                \"CA10__enabledState__c\": \"on\"\n              }\n\
      \            }\n          ]\n        }\n      ]\n    },\n    {\n      \"expectedResult\"\
      : {\n        \"status\": \"INCOMPLIANT\",\n        \"conditionIndex\": \"200\"\
      ,\n        \"conditionText\": \"otherwise\",\n        \"runtimeError\": null\n\
      \      },\n      \"context\": { \"snapshotTime\": \"2024-12-16T11:04:54Z\" },\n\
      \      \"Id\": \"aB9P12\",\n      \"CA10__Google_Logging_Log_Metrics__r\": [\n\
      \        {\n          \"Id\": \"aAzM12\",\n          \"CA10__disappearanceTime__c\"\
      : null,\n          \"CA10__filter__c\": \"other filter\",\n          \"CA10__project__c\"\
      : \"aB9P12\",\n          \"CA10__Google_Monitoring_Conditions__r\": [\n    \
      \        {\n              \"Id\": \"aBMC12\",\n              \"CA10__disappearanceTime__c\"\
      : null,\n              \"CA10__alertPolicy__c\": \"aBAP12\",\n             \
      \ \"CA10__alertPolicyId__c\": \"projects/shared-logging-976f3\",\n         \
      \     \"CA10__loggingLogMetric__c\": \"aAzM12\",\n              \"CA10__alertPolicy__r\"\
      : {\n                \"Id\": \"aBAP12\",\n                \"CA10__disappearanceTime__c\"\
      : null,\n                \"CA10__enabledState__c\": \"on\"\n              }\n\
      \            }\n          ]\n        }\n      ]\n    },\n    {\n      \"expectedResult\"\
      : {\n        \"status\": \"INCOMPLIANT\",\n        \"conditionIndex\": \"200\"\
      ,\n        \"conditionText\": \"otherwise\",\n        \"runtimeError\": null\n\
      \      },\n      \"context\": { \"snapshotTime\": \"2024-12-16T11:04:54Z\" },\n\
      \      \"Id\": \"aB9P13\",\n      \"CA10__Google_Logging_Log_Metrics__r\": [\n\
      \        {\n          \"Id\": \"aAzM13\",\n          \"CA10__disappearanceTime__c\"\
      : null,\n          \"CA10__filter__c\": \"resource.type=gcs_bucket AND protoPayload.methodName=\\\
      \"storage.setIamPermissions\\\"\",\n          \"CA10__project__c\": \"aB9P13\"\
      ,\n          \"CA10__Google_Monitoring_Conditions__r\": [\n            {\n \
      \             \"Id\": \"aBMC13\",\n              \"CA10__disappearanceTime__c\"\
      : null,\n              \"CA10__alertPolicy__c\": \"aBAP13\",\n             \
      \ \"CA10__alertPolicyId__c\": \"projects/shared-logging-976f4\",\n         \
      \     \"CA10__loggingLogMetric__c\": \"aAzM13\",\n              \"CA10__alertPolicy__r\"\
      : {\n                \"Id\": \"aBAP13\",\n                \"CA10__disappearanceTime__c\"\
      : null,\n                \"CA10__enabledState__c\": \"off\"\n              }\n\
      \            }\n          ]\n        }\n      ]\n    },\n    {\n      \"expectedResult\"\
      : {\n        \"status\": \"INCOMPLIANT\",\n        \"conditionIndex\": \"200\"\
      ,\n        \"conditionText\": \"otherwise\",\n        \"runtimeError\": null\n\
      \      },\n      \"context\": { \"snapshotTime\": \"2024-12-16T11:04:54Z\" },\n\
      \      \"Id\": \"aB222\",\n      \"CA10__Google_Logging_Log_Metrics__r\": []\n\
      \    }\n  ]\n  "
  - path: /types/CA10__CaGoogleProject__c/object.extracts.yaml
    md5Hash: 8EB422663BF4493D44ABA5FEC0FB9AD4
    content: "---\nextracts:\n  - name: \"CA10__projectId__c\"\n    value: \n    \
      \   FIELD:\n         path: \"CA10__projectId__c\"\n         undeterminedIf:\n\
      \          isEmpty: \"Corrupted data. Project ID cannot be empty.\"\n  - name:\
      \ \"CA10__enabledServices__c\"\n    value: \n      FIELD:\n        path: \"\
      CA10__enabledServices__c\""
script: "CREATE TEMP FUNCTION mock_ExpectedResult()\nRETURNS ARRAY<STRUCT<\n     \
  \   Id STRING,\n        expectedResult STRUCT<status STRING, conditionIndex DECIMAL,\
  \ conditionText STRING, runtimeError STRING>\n    >>\nDETERMINISTIC\nLANGUAGE js\n\
  AS r\"\"\"\n  return [ {\n  \"Id\" : \"aB9P1\",\n  \"expectedResult\" : {\n    \"\
  status\" : \"COMPLIANT\",\n    \"conditionIndex\" : \"199\",\n    \"conditionText\"\
  \ : \"CA10__Google_Logging_Log_Metrics__r.has(COMPLIANT)\",\n    \"runtimeError\"\
  \ : null\n  }\n}, {\n  \"Id\" : \"aB9P12\",\n  \"expectedResult\" : {\n    \"status\"\
  \ : \"INCOMPLIANT\",\n    \"conditionIndex\" : \"200\",\n    \"conditionText\" :\
  \ \"otherwise\",\n    \"runtimeError\" : null\n  }\n}, {\n  \"Id\" : \"aB9P13\"\
  ,\n  \"expectedResult\" : {\n    \"status\" : \"INCOMPLIANT\",\n    \"conditionIndex\"\
  \ : \"200\",\n    \"conditionText\" : \"otherwise\",\n    \"runtimeError\" : null\n\
  \  }\n}, {\n  \"Id\" : \"aB222\",\n  \"expectedResult\" : {\n    \"status\" : \"\
  INCOMPLIANT\",\n    \"conditionIndex\" : \"200\",\n    \"conditionText\" : \"otherwise\"\
  ,\n    \"runtimeError\" : null\n  }\n} ];\n\"\"\";\n\nCREATE TEMP FUNCTION mock_CA10__CaGoogleProject__c()\n\
  RETURNS ARRAY<STRUCT<\n    Id STRING,\n    context STRUCT<\n        snapshotTime\
  \ TIMESTAMP\n    >\n>>\nDETERMINISTIC\nLANGUAGE js\nAS r\"\"\"\n  return [ {\n \
  \ \"context\" : {\n    \"snapshotTime\" : new Date(\"2024-12-16T11:04:54Z\")\n \
  \ },\n  \"Id\" : \"aB9P1\"\n}, {\n  \"context\" : {\n    \"snapshotTime\" : new\
  \ Date(\"2024-12-16T11:04:54Z\")\n  },\n  \"Id\" : \"aB9P12\"\n}, {\n  \"context\"\
  \ : {\n    \"snapshotTime\" : new Date(\"2024-12-16T11:04:54Z\")\n  },\n  \"Id\"\
  \ : \"aB9P13\"\n}, {\n  \"context\" : {\n    \"snapshotTime\" : new Date(\"2024-12-16T11:04:54Z\"\
  )\n  },\n  \"Id\" : \"aB222\"\n} ];\n\"\"\";\n\nCREATE TEMP FUNCTION mock_CA10__CaGoogleLoggingLogMetric__c()\n\
  RETURNS ARRAY<STRUCT<\n    Id STRING,\n    CA10__disappearanceTime__c TIMESTAMP,\n\
  \    CA10__filter__c STRING,\n    CA10__project__c STRING,\n    context STRUCT<\n\
  \        snapshotTime TIMESTAMP\n    >\n>>\nDETERMINISTIC\nLANGUAGE js\nAS r\"\"\
  \"\n  return [ {\n  \"context\" : {\n    \"snapshotTime\" : new Date(\"2024-12-16T11:04:54Z\"\
  )\n  },\n  \"Id\" : \"aAzM1\",\n  \"CA10__filter__c\" : \"resource.type=gcs_bucket\
  \ AND protoPayload.methodName=\\\"storage.setIamPermissions\\\"\",\n  \"CA10__project__c\"\
  \ : \"aB9P1\"\n}, {\n  \"context\" : {\n    \"snapshotTime\" : new Date(\"2024-12-16T11:04:54Z\"\
  )\n  },\n  \"Id\" : \"aAzM2\",\n  \"CA10__filter__c\" : \"(protoPayload.serviceName=\\\
  \"cloudresourcemanager.googleapis.com\\\")\",\n  \"CA10__project__c\" : \"aB9P1\"\
  \n}, {\n  \"context\" : {\n    \"snapshotTime\" : new Date(\"2024-12-16T11:04:54Z\"\
  )\n  },\n  \"Id\" : \"aAzM12\",\n  \"CA10__filter__c\" : \"other filter\",\n  \"\
  CA10__project__c\" : \"aB9P12\"\n}, {\n  \"context\" : {\n    \"snapshotTime\" :\
  \ new Date(\"2024-12-16T11:04:54Z\")\n  },\n  \"Id\" : \"aAzM13\",\n  \"CA10__filter__c\"\
  \ : \"resource.type=gcs_bucket AND protoPayload.methodName=\\\"storage.setIamPermissions\\\
  \"\",\n  \"CA10__project__c\" : \"aB9P13\"\n} ];\n\"\"\";\n\nCREATE TEMP FUNCTION\
  \ mock_CA10__CaGoogleMonitoringCondition__c()\nRETURNS ARRAY<STRUCT<\n    Id STRING,\n\
  \    CA10__disappearanceTime__c TIMESTAMP,\n    CA10__alertPolicy__c STRING,\n \
  \   CA10__alertPolicyId__c STRING,\n    CA10__loggingLogMetric__c STRING,\n    context\
  \ STRUCT<\n        snapshotTime TIMESTAMP\n    >\n>>\nDETERMINISTIC\nLANGUAGE js\n\
  AS r\"\"\"\n  return [ {\n  \"context\" : {\n    \"snapshotTime\" : new Date(\"\
  2024-12-16T11:04:54Z\")\n  },\n  \"Id\" : \"aBMC1\",\n  \"CA10__alertPolicy__c\"\
  \ : \"aBAP1\",\n  \"CA10__alertPolicyId__c\" : \"projects/shared-logging-976f\"\
  ,\n  \"CA10__loggingLogMetric__c\" : \"aAzM1\"\n}, {\n  \"context\" : {\n    \"\
  snapshotTime\" : new Date(\"2024-12-16T11:04:54Z\")\n  },\n  \"Id\" : \"aBMC2\"\
  ,\n  \"CA10__alertPolicy__c\" : \"aBAP2\",\n  \"CA10__alertPolicyId__c\" : \"projects/shared-logging-976f2\"\
  ,\n  \"CA10__loggingLogMetric__c\" : \"aAzM2\"\n}, {\n  \"context\" : {\n    \"\
  snapshotTime\" : new Date(\"2024-12-16T11:04:54Z\")\n  },\n  \"Id\" : \"aBMC12\"\
  ,\n  \"CA10__alertPolicy__c\" : \"aBAP12\",\n  \"CA10__alertPolicyId__c\" : \"projects/shared-logging-976f3\"\
  ,\n  \"CA10__loggingLogMetric__c\" : \"aAzM12\"\n}, {\n  \"context\" : {\n    \"\
  snapshotTime\" : new Date(\"2024-12-16T11:04:54Z\")\n  },\n  \"Id\" : \"aBMC13\"\
  ,\n  \"CA10__alertPolicy__c\" : \"aBAP13\",\n  \"CA10__alertPolicyId__c\" : \"projects/shared-logging-976f4\"\
  ,\n  \"CA10__loggingLogMetric__c\" : \"aAzM13\"\n} ];\n\"\"\";\n\nCREATE TEMP FUNCTION\
  \ mock_CA10__CaGoogleMonitoringAlertPolicy__c()\nRETURNS ARRAY<STRUCT<\n    Id STRING,\n\
  \    CA10__disappearanceTime__c TIMESTAMP,\n    CA10__enabledState__c STRING,\n\
  \    context STRUCT<\n        snapshotTime TIMESTAMP\n    >\n>>\nDETERMINISTIC\n\
  LANGUAGE js\nAS r\"\"\"\n  return [ {\n  \"context\" : {\n    \"snapshotTime\" :\
  \ new Date(\"2024-12-16T11:04:54Z\")\n  },\n  \"Id\" : \"aBAP1\",\n  \"CA10__enabledState__c\"\
  \ : \"on\"\n}, {\n  \"context\" : {\n    \"snapshotTime\" : new Date(\"2024-12-16T11:04:54Z\"\
  )\n  },\n  \"Id\" : \"aBAP2\",\n  \"CA10__enabledState__c\" : \"on\"\n}, {\n  \"\
  context\" : {\n    \"snapshotTime\" : new Date(\"2024-12-16T11:04:54Z\")\n  },\n\
  \  \"Id\" : \"aBAP12\",\n  \"CA10__enabledState__c\" : \"on\"\n}, {\n  \"context\"\
  \ : {\n    \"snapshotTime\" : new Date(\"2024-12-16T11:04:54Z\")\n  },\n  \"Id\"\
  \ : \"aBAP13\",\n  \"CA10__enabledState__c\" : \"off\"\n} ];\n\"\"\";\n\nCREATE\
  \ TEMP FUNCTION process_CA10__CaGoogleProject__c(\n    obj STRUCT<\n        Id STRING,\n\
  \        CA10__Google_Logging_Log_Metrics__r ARRAY<STRUCT<\n            Id STRING,\n\
  \            CA10__disappearanceTime__c TIMESTAMP,\n            CA10__filter__c\
  \ STRING,\n            CA10__project__c STRING,\n            CA10__Google_Monitoring_Conditions__r\
  \ ARRAY<STRUCT<\n                Id STRING,\n                CA10__disappearanceTime__c\
  \ TIMESTAMP,\n                CA10__alertPolicy__c STRING,\n                CA10__alertPolicyId__c\
  \ STRING,\n                CA10__loggingLogMetric__c STRING,\n                CA10__alertPolicy__r\
  \ STRUCT<\n                    Id STRING,\n                    CA10__disappearanceTime__c\
  \ TIMESTAMP,\n                    CA10__enabledState__c STRING\n               \
  \ >,\n                result STRUCT<status STRING, conditionIndex DECIMAL, conditionText\
  \ STRING, currentStateMessage STRING, currentStateReferences STRING, remediation\
  \ STRING, runtimeError STRING>\n            >>,\n            result STRUCT<status\
  \ STRING, conditionIndex DECIMAL, conditionText STRING, currentStateMessage STRING,\
  \ currentStateReferences STRING, remediation STRING, runtimeError STRING>\n    \
  \    >>\n    >,\n    snapshotTime TIMESTAMP\n)\nRETURNS STRUCT<status STRING, conditionIndex\
  \ DECIMAL, conditionText STRING, currentStateMessage STRING, currentStateReferences\
  \ STRING, remediation STRING, runtimeError STRING>\nDETERMINISTIC\nLANGUAGE js\n\
  AS r\"\"\"\n    var references1 = [];\n    // condition[0], conditionIndex:[0..99]\n\
  \    if (false) {\n        return {status: 'DISAPPEARED', conditionIndex: 99, conditionText:\
  \ \"isDisappeared()\", currentStateMessage: \"Object is deleted in the source\"\
  , currentStateReferences: references1.join('\\n'), remediation: null, runtimeError:\
  \ null};\n    }\n    var count_CA10__Google_Logging_Log_Metrics__r_COMPLIANT2 =\
  \ 0;\n    if (obj.CA10__Google_Logging_Log_Metrics__r != null) {\n        for (var\
  \ i3 = 0; i3 < obj.CA10__Google_Logging_Log_Metrics__r.length; i3++) {\n       \
  \     if (obj.CA10__Google_Logging_Log_Metrics__r[i3].result.status == 'COMPLIANT')\
  \ {\n                count_CA10__Google_Logging_Log_Metrics__r_COMPLIANT2 += 1;\n\
  \            }\n        }\n    }\n    // condition[1], conditionIndex:[100..199]\n\
  \    references1.push('Related list [CA10__Google_Logging_Log_Metrics__r] ' + (count_CA10__Google_Logging_Log_Metrics__r_COMPLIANT2\
  \ > 0 ? 'has' : 'does not have') + ' objects in COMPLIANT status');\n    if (count_CA10__Google_Logging_Log_Metrics__r_COMPLIANT2\
  \ > 0) {\n        return {status: 'COMPLIANT', conditionIndex: 199, conditionText:\
  \ \"CA10__Google_Logging_Log_Metrics__r.has(COMPLIANT)\", currentStateMessage: \"\
  Log metric filter and alerts exist for Project Ownership Assignments/Changes.\"\
  , currentStateReferences: references1.join('\\n'), remediation: null, runtimeError:\
  \ null};\n    }\n    return {status: 'INCOMPLIANT', conditionIndex: 200, conditionText:\
  \ \"otherwise\", currentStateMessage: \"No log metric filter or alerts exist for\
  \ Project Ownership Assignments/Changes.\", currentStateReferences: references1.join('\\\
  n'), remediation: \"Create log metric and alert policy.\", runtimeError: null};\n\
  \"\"\";\n\nCREATE TEMP FUNCTION process_CA10__Google_Monitoring_Conditions__r(\n\
  \    obj STRUCT<\n        Id STRING,\n        CA10__disappearanceTime__c TIMESTAMP,\n\
  \        CA10__alertPolicy__c STRING,\n        CA10__alertPolicyId__c STRING,\n\
  \        CA10__loggingLogMetric__c STRING,\n        CA10__alertPolicy__r STRUCT<\n\
  \            Id STRING,\n            CA10__disappearanceTime__c TIMESTAMP,\n   \
  \         CA10__enabledState__c STRING\n        >\n    >,\n    snapshotTime TIMESTAMP\n\
  )\nRETURNS STRUCT<status STRING, conditionIndex DECIMAL, conditionText STRING, currentStateMessage\
  \ STRING, currentStateReferences STRING, remediation STRING, runtimeError STRING>\n\
  DETERMINISTIC\nLANGUAGE js\nAS r\"\"\"\n    var TextLib = new function () {\n  \
  \      this.normalize = function(arg) {\n            return arg == null ? '' : arg.replace(/\\\
  s+/g, ' ').trim().toLowerCase();\n        };\n        this.isEmpty = function(arg)\
  \ {\n            return this.normalize(arg) == '';\n        };\n        this.isNotEmpty\
  \ = function(arg) {\n            return this.normalize(arg) != '';\n        };\n\
  \        this.equal = function(left, right) {\n            return this.normalize(left)\
  \ == this.normalize(right);\n        };\n        this.notEqual = function(left,\
  \ right) {\n            return this.normalize(left) != this.normalize(right);\n\
  \        };\n        this.startsWith = function(arg, substring) {\n            return\
  \ this.normalize(arg).startsWith(this.normalize(substring));\n        };\n     \
  \   this.endsWith = function(arg, substring) {\n            return this.normalize(arg).endsWith(this.normalize(substring));\n\
  \        };\n        this.contains = function(arg, substring) {\n            return\
  \ this.normalize(arg).includes(this.normalize(substring));\n        };\n    }();\n\
  \    var references1 = [];\n    // condition[0], conditionIndex:[0..99]\n    references1.push('Deleted\
  \ From Google [CA10__disappearanceTime__c]: ' + obj.CA10__disappearanceTime__c);\n\
  \    if (obj.CA10__disappearanceTime__c != null) {\n        return {status: 'DISAPPEARED',\
  \ conditionIndex: 99, conditionText: \"isDisappeared(CA10__disappearanceTime__c)\"\
  , currentStateMessage: \"Object is deleted in the source\", currentStateReferences:\
  \ references1.join('\\n'), remediation: null, runtimeError: null};\n    }\n    //\
  \ condition[1], conditionIndex:[100..199]\n    function extractChecked2() {\n  \
  \      if (TextLib.isEmpty(obj.CA10__alertPolicyId__c)) {\n            throw new\
  \ Error(\"UNDETERMINED condition:101\", {cause: {status: 'UNDETERMINED', conditionIndex:\
  \ 101, conditionText: \"extractCheck(obj.CA10__alertPolicyId__c)\", currentStateMessage:\
  \ \"Related object via CA10__alertPolicyId__c has empty ID\", currentStateReferences:\
  \ references1.join('\\n'), remediation: null, runtimeError: null}});\n        }\n\
  \        if (TextLib.isEmpty(obj.CA10__alertPolicy__c)) {\n            throw new\
  \ Error(\"UNDETERMINED condition:102\", {cause: {status: 'UNDETERMINED', conditionIndex:\
  \ 102, conditionText: \"extractCheck(obj.CA10__alertPolicy__c)\", currentStateMessage:\
  \ \"Related object via CA10__alertPolicy__c is not present\", currentStateReferences:\
  \ references1.join('\\n'), remediation: null, runtimeError: null}});\n        }\n\
  \        if (obj.CA10__alertPolicy__r.CA10__disappearanceTime__c != null) {\n  \
  \          throw new Error(\"UNDETERMINED condition:103\", {cause: {status: 'UNDETERMINED',\
  \ conditionIndex: 103, conditionText: \"extractCheck(obj.CA10__alertPolicy__r.CA10__disappearanceTime__c)\"\
  , currentStateMessage: \"Related object via CA10__alertPolicy__c is present, but\
  \ deleted in the source\", currentStateReferences: references1.join('\\n'), remediation:\
  \ null, runtimeError: null}});\n        }\n        return extract3.call(extract3);\n\
  \    }\n    function extract3() { if (!this.out) { this.out = obj.CA10__alertPolicy__r.CA10__enabledState__c;\
  \ } return this.out; };\n    references1.push('Enabled State [obj.CA10__alertPolicy__r.CA10__enabledState__c]:\
  \ ' + obj.CA10__alertPolicy__r.CA10__enabledState__c);\n    try {\n        if (TextLib.equal(extractChecked2(),\
  \ 'on')) {\n            return {status: 'COMPLIANT', conditionIndex: 199, conditionText:\
  \ \"extract('CA10__alertPolicy__r.CA10__enabledState__c') == 'on'\", currentStateMessage:\
  \ \"Alert policy exist and enabled.\", currentStateReferences: references1.join('\\\
  n'), remediation: null, runtimeError: null};\n        }\n    } catch (err) {\n \
  \       if (err.cause && err.cause.status) { return err.cause; } else { throw err;\
  \ }\n    }\n    return {status: 'INCOMPLIANT', conditionIndex: 200, conditionText:\
  \ \"otherwise\", currentStateMessage: \"No alert policy exist or policy not enabled.\"\
  , currentStateReferences: references1.join('\\n'), remediation: \"Create or enable\
  \ alert policy.\", runtimeError: null};\n\"\"\";\n\nCREATE TEMP FUNCTION process_CA10__Google_Logging_Log_Metrics__r(\n\
  \    obj STRUCT<\n        Id STRING,\n        CA10__disappearanceTime__c TIMESTAMP,\n\
  \        CA10__filter__c STRING,\n        CA10__project__c STRING,\n        CA10__Google_Monitoring_Conditions__r\
  \ ARRAY<STRUCT<\n            Id STRING,\n            CA10__disappearanceTime__c\
  \ TIMESTAMP,\n            CA10__alertPolicy__c STRING,\n            CA10__alertPolicyId__c\
  \ STRING,\n            CA10__loggingLogMetric__c STRING,\n            CA10__alertPolicy__r\
  \ STRUCT<\n                Id STRING,\n                CA10__disappearanceTime__c\
  \ TIMESTAMP,\n                CA10__enabledState__c STRING\n            >,\n   \
  \         result STRUCT<status STRING, conditionIndex DECIMAL, conditionText STRING,\
  \ currentStateMessage STRING, currentStateReferences STRING, remediation STRING,\
  \ runtimeError STRING>\n        >>\n    >,\n    snapshotTime TIMESTAMP\n)\nRETURNS\
  \ STRUCT<status STRING, conditionIndex DECIMAL, conditionText STRING, currentStateMessage\
  \ STRING, currentStateReferences STRING, remediation STRING, runtimeError STRING>\n\
  DETERMINISTIC\nLANGUAGE js\nAS r\"\"\"\n    const Comparator = Object.freeze({\n\
  \        EQUALS: { name: \"EQUALS\", value: ['='] },\n        NOT_EQUALS: { name:\
  \ \"NOT_EQUALS\", value: ['!', '='] },\n        LESS_THAN: { name: \"LESS_THAN\"\
  , value: ['<'] },\n        GREATER_THAN: { name: \"GREATER_THAN\", value: ['>']\
  \ },\n        GREATER_THAN_EQUALS: { name: \"GREATER_THAN_EQUALS\", value: ['>',\
  \ '='] },\n        LESS_THAN_EQUALS: { name: \"LESS_THAN_EQUALS\", value: ['<',\
  \ '='] },\n        MATCHES_REGEXP: { name: \"MATCHES_REGEXP\", value: ['=', '~']\
  \ },\n        NOT_MATCHES_REGEXP: { name: \"NOT_MATCHES_REGEXP\", value: ['!', '~']\
  \ },\n        HAS: { name: \"HAS\", value: [':'] },\n        GLOBAL: { name: \"\
  GLOBAL\", value: [] }\n    });\n    const ExpressionType = Object.freeze({\n   \
  \     CONJUNCTION: { name: \"CONJUNCTION\", value: [\"AND\"] },\n        DISJUNCTION:\
  \ { name: \"DISJUNCTION\", value: [\"OR\"] },\n        NEGATION: { name: \"NEGATION\"\
  , value: [\"NOT\", \"-\"] },\n        SINGLE: { name: \"SINGLE\", value: [] }\n\
  \    });\n    const ValueType = Object.freeze({\n        JSON: { name: 'JSON' },\n\
  \        STRING: { name: 'STRING' },\n        BOOLEAN: { name: 'BOOLEAN' },\n  \
  \      NUMBER: { name: 'NUMBER' },\n        ENUM: { name: 'ENUM' },\n        ANY_VALUE:\
  \ { name: 'ANY_VALUE' },\n        FUNCTION: { name: 'FUNCTION' }\n    });\n    const\
  \ FunctionType = Object.freeze({\n        LOG_ID: { name: 'LOG_ID', functionName:\
  \ 'log_id' },\n        CAST: { name: 'CAST', functionName: 'cast' },\n        REGEXP_EXTRACT:\
  \ { name: 'REGEXP_EXTRACT', functionName: 'regexp_extract' },\n        SOURCE: {\
  \ name: 'SOURCE', functionName: 'source' },\n        SAMPLE: { name: 'SAMPLE', functionName:\
  \ 'sample' },\n        IP_IN_NET: { name: 'IP_IN_NET', functionName: 'ip_in_net'\
  \ },\n        SEARCH: { name: 'SEARCH', functionName: 'search' },\n    });\n   \
  \ class Restriction {\n        constructor(comparator, field, value) {\n       \
  \     this.comparator = comparator;\n            this.field = field;\n         \
  \   this.value = value;\n        }\n    \n        static equals(actual, expected)\
  \ {\n            if (!actual && !expected) {\n                return true;\n   \
  \         }\n            if ((!actual && expected) || (actual && !expected)) {\n\
  \                return false;\n            }\n            return actual.comparator\
  \ === expected.comparator\n                && actual.field === expected.field\n\
  \                && Value.equals(actual.value, expected.value);\n        }\n   \
  \ }\n    class Value {\n        constructor(type, value) {\n            this.type\
  \ = type;\n            this.value = value;\n        }\n    \n        static equals(actual,\
  \ expected) {\n            if (!actual && !expected) {\n                return true;\n\
  \            }\n            if ((!actual && expected) || (actual && !expected))\
  \ {\n                return false;\n            }\n            return actual.type\
  \ === expected.type && actual.value === expected.value;\n        }\n    }\n    class\
  \ Expression {\n        constructor(type, restriction, expressions, expVar, condition)\
  \ {\n            this.type = type;\n            this.restriction = restriction;\n\
  \            this.expressions = expressions;\n            this.expVar = expVar;\n\
  \            this.condition = condition;\n        }\n    \n        static typeAndExpressions(type,\
  \ expressions){\n            return new Expression(type, null, expressions, null,\
  \ null)\n        }\n    \n        static typeAndRestriction(type, restriction){\n\
  \            return new Expression(type, restriction, null, null, null)\n      \
  \  }\n    \n        static equals(actual, expected) {\n            if (!actual &&\
  \ !expected) {\n                return true;\n            }\n            if ((!actual\
  \ && expected) || (actual && !expected)) {\n                return false;\n    \
  \        }\n            let equalsType = actual.type === expected.type;\n      \
  \      let equalsRestriction = Restriction.equals(actual.restriction, expected.restriction);\n\
  \            let equalsExpressions = false;\n            if (actual.expressions\
  \ && expected.expressions) {\n                if (actual.expressions.length ===\
  \ expected.expressions.length) {\n                    let successCount = 0;\n  \
  \                  for (const actualKey in actual.expressions) {\n             \
  \           let actualExp = actual.expressions[actualKey];\n                   \
  \     for (const expKey in expected.expressions) {\n                           \
  \ let expectedExp = expected.expressions[expKey];\n                            if\
  \ (Expression.equals(actualExp, expectedExp)) {\n                              \
  \  successCount++\n                                break\n                     \
  \       }\n                        }\n                    }\n                  \
  \  if (successCount === actual.expressions.length) {\n                        equalsExpressions\
  \ = true;\n                    }\n                }\n            } else if (!actual.expressions\
  \ && !expected.expressions) {\n                equalsExpressions = true\n      \
  \      }\n            return equalsType && equalsRestriction && equalsExpressions;\n\
  \        }\n    }\n    const GoogleMetricQueryParser = new function () {\n     \
  \   this.ComparatorGetByChars = function(first, second) {\n            if (first\
  \ === null) {\n                return null;\n            }\n            let with2symbols\
  \ = null;\n            let with1symbol = null;\n            for (const [key, value]\
  \ of Object.entries(Comparator)) {\n                if (key === 'GLOBAL') {\n  \
  \                  continue;\n                }\n                if (value.value.length\
  \ > 1) {\n                    if (value.value[0] === first && value.value[1] ===\
  \ second) {\n                        with2symbols = Comparator[key];\n         \
  \           }\n                } else {\n                    if (value.value[0]\
  \ === first) {\n                        with1symbol = Comparator[key];\n       \
  \             }\n                }\n            }\n            return with2symbols\
  \ || with1symbol;\n        };\n        this.ComparatorIsFirstChar = function(first)\
  \ {\n            for (const [key, value] of Object.entries(Comparator)) {\n    \
  \            if (key === 'GLOBAL') {\n                    continue;\n          \
  \      }\n                if (value.value[0] === first) {\n                    return\
  \ true;\n                }\n            }\n            return false;\n        };\n\
  \        this.ValueTypePredict = function (input) {\n            if (input === \"\
  NULL_VALUE\") {\n                return ValueType.JSON;\n            } else if (input\
  \ === \"*\") {\n                return ValueType.ANY_VALUE;\n            } else\
  \ if (input.charAt(0) === '\"' && input.charAt(input.length - 1) === '\"') {\n \
  \               return ValueType.STRING;\n            } else if (input.toLowerCase()\
  \ === \"true\" || input.toLowerCase() === \"false\") {\n                return ValueType.BOOLEAN;\n\
  \            } else if (!isNaN(input) && input.trim() !== '') {\n              \
  \  return ValueType.NUMBER;\n            } else if (this.isFunction(input)) {\n\
  \                return ValueType.FUNCTION;\n            } else {\n            \
  \    return ValueType.ENUM;\n            }\n        }\n    \n        this.isFunction\
  \ = function (input) {\n            if (input === null || input.length === 0) {\n\
  \                return false;\n            }\n            let normalized = input.trim().toLowerCase();\n\
  \            for (const [key, value] of Object.entries(FunctionType)) {\n      \
  \          if (normalized.startsWith(value.functionName)) {\n                  \
  \  return true;\n                }\n            }\n            return false;\n \
  \       }\n    \n        const OPENED_BRACKET_PLACEHOLDER = \"%OPENED_BRACKET%\"\
  ;\n        const CLOSED_BRACKET_PLACEHOLDER = \"%CLOSED_BRACKET%\";\n        const\
  \ NOT_PLACEHOLDER = \"%NOT_PLACEHOLDER%\";\n        const BRACKET_START = '(';\n\
  \        const BRACKET_END = ')';\n        const SPACE = ' ';\n        const QUOTE\
  \ = '\"';\n        const NOT_SHORT_CHAR = '-';\n        const DECIMAL = 10;\n  \
  \      const EXP_VAR = \"exp\";\n        const OR = ExpressionType.DISJUNCTION.value[0];\n\
  \        const AND = ExpressionType.CONJUNCTION.value[0];\n        const NOT = ExpressionType.NEGATION.value[0];\n\
  \        const NOT_SHORT = ExpressionType.NEGATION.value[1];\n    \n        this.normalize\
  \ = function (query) {\n            const charList = Array.from(query.trim());\n\
  \            let result = [];\n            let element = [];\n            let inQuotes\
  \ = false;\n            let inComments = false;\n            for (let i = 0; i <\
  \ charList.length; i++) {\n                const prev = i === 0 ? null : charList[i\
  \ - 1];\n                const current = charList[i];\n    \n                if\
  \ (inComments) {\n                    if (current === '\\n') {\n               \
  \         inComments = false;\n                    }\n                } else {\n\
  \                    if (!inQuotes && current === '-' && prev != null && prev ===\
  \ '-') {\n                        inComments = true;\n                        element.pop();\n\
  \                        result.push(element.join('').replaceAll(/\\n/g, \" \").replaceAll(/\\\
  s{2,}/g, \" \"));\n                        element = [];\n                     \
  \   continue;\n                    } else if (current === QUOTE && prev !== \"\\\
  \\\") {\n                        if (inQuotes) {\n                            inQuotes\
  \ = false;\n                            element.push(current);\n               \
  \             result.push(element.join(''));\n                            element\
  \ = [];\n                            continue;\n                        } else {\n\
  \                            inQuotes = true;\n                            result.push(element.join('').replaceAll(/\\\
  n/g, \" \").replaceAll(/\\s{2,}/g, \" \"));\n                            element\
  \ = [];\n                        }\n                    }\n    \n              \
  \      element.push(current);\n                }\n            }\n    \n        \
  \    if (!inComments && !inQuotes && element.length > 0) {\n                result.push(element.join('').replaceAll(/\\\
  n/g, \" \").replaceAll(/\\s{2,}/g, \" \"));\n            }\n    \n            return\
  \ result.join('');\n        }\n    \n        this.getExpressions = function (normalized)\
  \ {\n            const result = [];\n            const charList = normalized.split('');\n\
  \            let inQuotes = false;\n            let insideComplexValue = false;\n\
  \            let insideField = true;\n            let insideFunction = false;\n\
  \            let expTypeInsideComplexValue = null;\n            let stageNumber\
  \ = 0;\n            let currentExpressionSb = [];\n            let complexValueSb\
  \ = [];\n            let complexExpressionTypeSb = [];\n            let currentComparatorStr\
  \ = null;\n            let currentComparator = null;\n    \n            for (let\
  \ i = 0; i < charList.length; i++) {\n                const prev = i === 0 ? null\
  \ : charList[i - 1];\n                const current = charList[i];\n           \
  \     const next = i === charList.length - 1 ? null : charList[i + 1];\n       \
  \         const next2 = i >= charList.length - 2 ? null : charList[i + 2];\n   \
  \ \n                currentExpressionSb.push(current);\n    \n                if\
  \ (insideComplexValue) {\n                    complexValueSb.push(current);\n  \
  \              }\n    \n                if (current === QUOTE && (currentExpressionSb.join('').trim().length\
  \ === 1\n                    || (currentExpressionSb.join('').trim().length ===\
  \ 2 && prev !== null && prev === NOT_SHORT_CHAR))\n                ) {\n       \
  \             insideField = false;\n                }\n    \n                if\
  \ (insideFunction && current === QUOTE && prev != null && prev !== '\\\\') {\n \
  \                   inQuotes = !inQuotes;\n                    continue;\n     \
  \           }\n    \n                if (!insideField && current === QUOTE && prev\
  \ !== null && prev !== '\\\\') {\n                    if (inQuotes) {\n        \
  \                stageNumber = 2;\n                    }\n                    inQuotes\
  \ = !inQuotes;\n    \n                    if (insideComplexValue) {\n          \
  \              complexExpressionTypeSb = [];\n                        continue;\n\
  \                    }\n    \n                    if (next !== null && next !==\
  \ BRACKET_END) {\n                        if (inQuotes && stageNumber === 0) {\n\
  \                            currentComparator = this.ComparatorGetByChars(prev,\
  \ current);\n                            if (currentComparator !== null) {\n   \
  \                             currentComparatorStr = currentComparator.value.join('');\n\
  \                                stageNumber = 1;\n                            }\n\
  \                        }\n                        continue;\n                \
  \    }\n                }\n    \n                if (!inQuotes) {\n            \
  \        if (stageNumber === 0) {\n                        if (!insideFunction)\
  \ {\n                            currentComparator = this.ComparatorGetByChars(current,\
  \ next);\n                            let nextComparator = this.ComparatorGetByChars(next,\
  \ next2);\n                            if (currentComparator !== null && (nextComparator\
  \ === null || currentComparator.value.length > nextComparator.value.length)) {\n\
  \                                currentComparatorStr = currentComparator.value.join('');\n\
  \                                stageNumber = 1;\n                            \
  \    insideField = false;\n                                if (next !== null &&\
  \ next !== BRACKET_END) {\n                                    continue;\n     \
  \                           }\n                            }\n                 \
  \       }\n    \n                        let normalizedExp = currentExpressionSb.join('').trim();\n\
  \                        if (OR === normalizedExp && this.isSpaceChar(next)) {\n\
  \                            currentExpressionSb = [];\n                       \
  \     continue;\n                        } else if (AND === normalizedExp && this.isSpaceChar(next))\
  \ {\n                            currentExpressionSb = [];\n                   \
  \         continue;\n                        } else if (NOT === normalizedExp &&\
  \ this.isSpaceChar(next)) {\n                            currentExpressionSb = [];\n\
  \                            continue;\n                        } else if (ExpressionType.NEGATION.value[1]\
  \ === normalizedExp && this.isSpaceChar(next)) {\n                            currentExpressionSb\
  \ = [];\n                            continue;\n                        } else if\
  \ (current === BRACKET_START) {\n                            if (this.isFunction(normalizedExp))\
  \ {\n                                insideFunction = true;\n                  \
  \          } else {\n                                currentExpressionSb = [];\n\
  \                            }\n                            continue;\n        \
  \                } else if (current === BRACKET_END) {\n                       \
  \     if (insideFunction && (next === null || this.isSpaceChar(next) || this.charsEquals(next,\
  \ BRACKET_END))) {\n                                stageNumber = 2;\n         \
  \                       insideFunction = false;\n                            } else\
  \ if (currentExpressionSb.length > 1) {\n                                stageNumber\
  \ = 2;\n                                currentExpressionSb.pop();\n           \
  \                 } else {\n                                currentExpressionSb\
  \ = [];\n                                continue;\n                           \
  \ }\n                        } else if (current === SPACE || next === null) {\n\
  \                            if (insideFunction) {\n                           \
  \     continue;\n                            }\n    \n                         \
  \   if (!this.ComparatorIsFirstChar(next) && currentExpressionSb.length > 1) {\n\
  \                                stageNumber = 2;\n                            }\
  \ else {\n                                continue;\n                          \
  \  }\n                        }\n                    } else if (stageNumber ===\
  \ 1 && !insideComplexValue) {\n                        if (current === BRACKET_START)\
  \ {\n                            insideComplexValue = true;\n                  \
  \          complexExpressionTypeSb = [];\n                            complexValueSb.push(current);\n\
  \                            continue;\n                        }\n            \
  \        } else if (insideComplexValue) {\n                        complexExpressionTypeSb.push(current);\n\
  \                        let normalizedExpType = complexExpressionTypeSb.join('').trim();\n\
  \                        if (current === BRACKET_END) {\n                      \
  \      const normalizedExp = currentExpressionSb.join('').trim();\n            \
  \                const normalizedComplexValue = complexValueSb.join('').trim();\n\
  \                            const expression = this.processComplexValueExpression(\n\
  \                                normalizedExp,\n                              \
  \  normalizedComplexValue,\n                                result.length + 1,\n\
  \                                expTypeInsideComplexValue,\n                  \
  \              currentComparator\n                            );\n             \
  \               result.push(expression);\n    \n                            currentExpressionSb\
  \ = [];\n                            complexValueSb = [];\n                    \
  \        complexExpressionTypeSb = [];\n                            stageNumber\
  \ = 0;\n                            currentComparatorStr = null;\n             \
  \               currentComparator = null;\n                            insideComplexValue\
  \ = false;\n                            insideField = true;\n                  \
  \          expTypeInsideComplexValue = null;\n                        } else if\
  \ (OR === normalizedExpType && this.isSpaceChar(next)) {\n                     \
  \       if (expTypeInsideComplexValue === null) {\n                            \
  \    expTypeInsideComplexValue = ExpressionType.DISJUNCTION;\n                 \
  \           }\n                            complexExpressionTypeSb  = [];\n    \
  \                    } else if (AND === normalizedExpType && this.isSpaceChar(next))\
  \ {\n                            if (expTypeInsideComplexValue === null) {\n   \
  \                             expTypeInsideComplexValue = ExpressionType.CONJUNCTION;\n\
  \                            }\n                            complexExpressionTypeSb\
  \ = [];\n                        } else if (current === SPACE) {\n             \
  \               complexExpressionTypeSb = [];\n                        }\n     \
  \                   continue;\n                    }\n    \n                   \
  \ if (\n                        (this.isSpaceChar(current) || next === null || this.charsEquals(next,\
  \ BRACKET_END))\n                            && !insideComplexValue\n          \
  \                  && this.checkConditionCompleted(currentExpressionSb, currentComparatorStr)\n\
  \                    ) {\n                        let normalizedExp = currentExpressionSb.join('').trim();\n\
  \                        if (normalizedExp.charAt(0) === NOT_SHORT_CHAR) {\n   \
  \                         normalizedExp = normalizedExp.substring(1);\n        \
  \                }\n                        const expression = this.processExpression(normalizedExp,\
  \ result.length + 1, currentComparator);\n                        result.push(expression);\n\
  \                        currentExpressionSb = [];\n                        stageNumber\
  \ = 0;\n                        currentComparatorStr = null;\n                 \
  \       currentComparator = null;\n                        insideField = true;\n\
  \                    } else if (stageNumber === 2 && !insideComplexValue) {\n  \
  \                      const normalizedExp = currentExpressionSb.join('').trim();\n\
  \                        const expression = this.processGlobalExpression(normalizedExp,\
  \ result.length + 1);\n                        result.push(expression);\n      \
  \                  currentExpressionSb = [];\n                        stageNumber\
  \ = 0;\n                        currentComparatorStr = null;\n                 \
  \       currentComparator = null;\n                        insideField = true;\n\
  \                    }\n                }\n            }\n            return result;\n\
  \        };\n    \n        this.checkConditionCompleted = function (currentExpressionSb,\
  \ currentComparatorStr) {\n            if (currentComparatorStr === null) {\n  \
  \              return false;\n            }\n            let condition = currentExpressionSb.join('').trim();\n\
  \            let arr = condition.split(currentComparatorStr);\n            return\
  \ arr.length === 2 && arr[0].length > 0 && arr[1].length > 0;\n        }\n    \n\
  \        this.processComplexValueExpression = function (normalizedExp, normalizedComplexValue,\
  \ order, expType, comparator) {\n            let field;\n            if (comparator\
  \ != null) {\n                const comparatorStr = comparator.value.join('');\n\
  \                field = normalizedExp.split(comparatorStr)[0].trim();\n       \
  \     } else {\n                field = null;\n            }\n    \n           \
  \ const expressionList = this.fillExpressionFromComplexValue(field, normalizedComplexValue,\
  \ expType, comparator);\n    \n            return new Expression(\n            \
  \    expType,\n                null,\n                expressionList,\n        \
  \        EXP_VAR + (order < DECIMAL ? \"0\" + order : order),\n                normalizedExp\n\
  \            );\n        }\n    \n        this.fillExpressionFromComplexValue =\
  \ function (field, normalizedComplexValue, type, comparator) {\n            let\
  \ withoutBracketsInside = normalizedComplexValue;\n            if (this.surroundedByBrackets(normalizedComplexValue))\
  \ {\n                withoutBracketsInside = normalizedComplexValue.substring(1,\
  \ normalizedComplexValue.length - 1);\n            }\n            const values =\
  \ [];\n            if (type === ExpressionType.CONJUNCTION) {\n                values.push(...withoutBracketsInside.split(\"\
  \ \" + AND + \" \"));\n            } else if (type === ExpressionType.DISJUNCTION)\
  \ {\n                values.push(...withoutBracketsInside.split(\" \" + OR + \"\
  \ \"));\n            } else if (type === null) {\n                values.push(withoutBracketsInside);\n\
  \            } else {\n                throw new Error(\"Invalid expression type\
  \ for complex value!\");\n            }\n    \n            const result = [];\n\
  \            for (const value of values) {\n                result.push(new Expression(\n\
  \                    ExpressionType.SINGLE,\n                    new Restriction(\n\
  \                        comparator,\n                        field,\n         \
  \               new Value(\n                            this.ValueTypePredict(value),\n\
  \                            this.surroundedByQuotes(value) ? value.substring(1,\
  \ value.length - 1) : value\n                        )\n                    ),\n\
  \                    null,\n                    null,\n                    null\n\
  \                ));\n            }\n            return result;\n        }\n   \
  \ \n        this.processExpression = function (normalizedExp, order, comparator)\
  \ {\n            let value;\n            let field;\n            if (comparator\
  \ !== null) {\n                const comparatorStr = comparator.value.join('');\n\
  \                field = normalizedExp.split(comparatorStr)[0].trim();\n       \
  \         value = normalizedExp.split(comparatorStr)[1].trim();\n            } else\
  \ {\n                field = null;\n                value = normalizedExp.trim();\n\
  \            }\n            const valueType = this.ValueTypePredict(value);\n  \
  \  \n            if (this.surroundedByQuotes(value)) {\n                value =\
  \ value.substring(1, value.length - 1);\n            }\n    \n            return\
  \ new Expression(\n                ExpressionType.SINGLE,\n                new Restriction(\n\
  \                    comparator,\n                    field,\n                 \
  \   new Value(valueType, value)\n                ),\n                null,\n   \
  \             EXP_VAR + (order < DECIMAL ? \"0\" + order : order),\n           \
  \     normalizedExp\n            );\n        }\n    \n        this.processGlobalExpression\
  \ = function (normalizedExp, order) {\n            let value = normalizedExp.trim();\n\
  \            const valueType = this.ValueTypePredict(value);\n    \n           \
  \ if (this.surroundedByQuotes(value)) {\n                value = value.substring(1,\
  \ value.length - 1);\n            }\n    \n            return new Expression(\n\
  \                ExpressionType.SINGLE,\n                new Restriction(\n    \
  \                Comparator.GLOBAL,\n                    null,\n               \
  \     new Value(valueType, value)\n                ),\n                null,\n \
  \               EXP_VAR + (order < DECIMAL ? \"0\" + order : order),\n         \
  \       normalizedExp\n            );\n        }\n    \n        this.buildPrioritizedQuery\
  \ = function (query, variables) {\n            if (!query.includes(OR) && !query.includes(NOT)\
  \ && !query.includes(BRACKET_START) && !query.includes(BRACKET_END)) {\n       \
  \         if (variables.length === 1) {\n                    return query;\n   \
  \             }\n                return \"AND(\" + query.replaceAll(\" AND \", \"\
  , \") + \")\";\n            }\n    \n            let elements = query.replaceAll(BRACKET_START\
  \ + \"\", BRACKET_START + \" \")\n                .replaceAll(BRACKET_END + \"\"\
  , \" \" + BRACKET_END)\n                .split(\" \");\n    \n            const\
  \ result = this.surroundByBracketsSimpleExpressions(elements);\n            elements\
  \ = result.split(\" \");\n    \n            let resultStr = this.surroundByBracketsSequenceExpressions(elements);\n\
  \    \n            resultStr = this.removeUselessBrackets(resultStr, variables);\n\
  \    \n            resultStr = resultStr.replaceAll(OR, \" \" + OR + \" \")\n  \
  \              .replaceAll(AND, \" \" + AND + \" \")\n                .replaceAll(NOT,\
  \ NOT + \" \")\n                .replaceAll(BRACKET_START + \"\", BRACKET_START\
  \ + \" \")\n                .replaceAll(BRACKET_END + \"\", \" \" + BRACKET_END);\n\
  \    \n            return this.buildPrioritizedQueryByBracketLevel(resultStr);\n\
  \        }\n    \n        this.surroundByBracketsSimpleExpressions = function (elements)\
  \ {\n            let result = [];\n            let isOrSequance = false;\n     \
  \       for (let i = 0; i < elements.length; i++) {\n                const prev\
  \ = i > 0 ? elements[i - 1] : null;\n                current = elements[i];\n  \
  \              const next = i === elements.length - 1 ? null : elements[i + 1];\n\
  \    \n                if (current.startsWith(OR)) {\n                    isOrSequance\
  \ = true;\n                    result.push(current);\n                } else if\
  \ (current.startsWith(AND)) {\n                    if (isOrSequance) {\n       \
  \                 result = Array.from(result.join('')\n                        \
  \        .replaceAll(OPENED_BRACKET_PLACEHOLDER, \"( \")\n                     \
  \           .replaceAll(CLOSED_BRACKET_PLACEHOLDER, \" )\")\n                  \
  \      );\n                    }\n                    result.push(current);\n  \
  \              } else if (current.startsWith(NOT)) {\n                    result.push(NOT_PLACEHOLDER);\n\
  \                } else if (current.startsWith(\"(\")) {\n                    result.push(current);\n\
  \                } else if (current.startsWith(\")\")) {\n                    if\
  \ (isOrSequance) {\n                        result = Array.from(result.join('')\n\
  \                            .replaceAll(OPENED_BRACKET_PLACEHOLDER, \"\")\n   \
  \                         .replaceAll(CLOSED_BRACKET_PLACEHOLDER, \"\")\n      \
  \                  );\n                    }\n                    result.push(current);\n\
  \                } else {\n                    if (prev !== null && prev.startsWith(NOT)\
  \ && (!current.startsWith(\"(\") || !current.startsWith(\")\"))) {\n           \
  \             current = NOT + \" (\" + current + \" )\";\n                     \
  \   result = Array.from(result.join('')\n                            .replaceAll(NOT_PLACEHOLDER,\
  \ \"\")\n                        );\n                    }\n    \n             \
  \       if (next !== null && next.startsWith(OR) && (prev === null || (!prev.startsWith(\"\
  )\") && !prev.startsWith(OR)))) {\n                        result.push(OPENED_BRACKET_PLACEHOLDER);\n\
  \                        result.push(current);\n                    } else if (prev\
  \ !== null && prev.startsWith(OR) && (next === null || (!next.startsWith(\"(\")\
  \ && !next.startsWith(OR)))) {\n                        isOrSequance = true;\n \
  \                       result.push(current);\n                        result.push(CLOSED_BRACKET_PLACEHOLDER);\n\
  \                    } else {\n                        result.push(current);\n \
  \                   }\n                }\n                if (next !== null) {\n\
  \                    result.push(\" \");\n                } else {\n           \
  \         if (isOrSequance) {\n                        result = Array.from(result.join('')\n\
  \                                .replaceAll(OPENED_BRACKET_PLACEHOLDER, \"( \"\
  )\n                                .replaceAll(CLOSED_BRACKET_PLACEHOLDER, \" )\"\
  )\n                        );\n                    }\n                }\n      \
  \      }\n            result = Array.from(result.join('')\n                .replaceAll(NOT_PLACEHOLDER,\
  \ NOT)\n            );\n            return result.join('');\n        }\n    \n \
  \       this.surroundByBracketsSequenceExpressions = function (elements) {\n   \
  \         const replaceWithStartBracket = [];\n            const replaceWithEndBracket\
  \ = [];\n            let buffer = [];\n            let prevBuffer = [];\n      \
  \      let appendToBuffer = false;\n            let prevOr = false;\n          \
  \  let bracketCount = 0;\n            for (let i = 0; i < elements.length; i++)\
  \ {\n                const prev = i > 0 ? elements[i - 1] : null;\n            \
  \    const current = elements[i];\n                const next= i === elements.length\
  \ - 1 ? null : elements[i + 1];\n    \n                if (current.startsWith(OR))\
  \ {\n                    if (prev !== null && prev.startsWith(\")\") && prevBuffer.length\
  \ > 0 && bracketCount === 0) {\n                        replaceWithStartBracket.push(prevBuffer.join(''));\n\
  \                        prevBuffer = [];\n                    }\n             \
  \       if (next !== null && next.startsWith(\"(\")) {\n                       \
  \ prevOr = true;\n                        bracketCount = 0;\n                  \
  \  }\n                } else if (current.startsWith(\"(\")) {\n                \
  \    if (bracketCount === 0) {\n                        appendToBuffer = true;\n\
  \                        prevBuffer = [];\n                    }\n             \
  \       if (appendToBuffer) {\n                        bracketCount++;\n       \
  \             }\n                } else if (current.startsWith(\")\")) {\n     \
  \               if (appendToBuffer) {\n                        bracketCount--;\n\
  \                        if (bracketCount === 0) {\n                           \
  \ buffer.push(current);\n                            if (prevOr) {\n           \
  \                     replaceWithEndBracket.push(buffer.join(''));\n           \
  \                     prevOr = false;\n                            }\n         \
  \                   prevBuffer.push(buffer.join(''));\n                        \
  \    appendToBuffer = false;\n                            buffer = [];\n       \
  \                 }\n                    }\n                }\n    \n          \
  \      if (appendToBuffer) {\n                    buffer.push(current);\n      \
  \          }\n            }\n            let result = elements.join('');\n     \
  \       for (const element of replaceWithStartBracket) {\n                if (this.surroundedByBrackets(element)\
  \ && replaceWithEndBracket.includes(element)) {\n                    continue;\n\
  \                }\n                result = result.replaceAll(element, \"(\" +\
  \ element);\n            }\n            for (const element of replaceWithEndBracket)\
  \ {\n                if (this.surroundedByBrackets(element) && replaceWithStartBracket.includes(element))\
  \ {\n                    continue;\n                }\n                result =\
  \ result.replaceAll(element, element + \")\");\n            }\n            return\
  \ result;\n        }\n    \n        this.removeUselessBrackets = function (query,\
  \ variables) {\n            let result = query;\n            for (const variable\
  \ of variables) {\n                if (!query.includes(NOT + \"(\" + variable +\
  \ \")\") && query.includes(\"(\" + variable + \")\")) {\n                    result\
  \ = result.replaceAll(\"(\" + variable + \")\", variable);\n                }\n\
  \            }\n            return result;\n        }\n    \n        this.buildPrioritizedQueryByBracketLevel\
  \ = function (input) {\n            let query = \"( \" + input + \" )\";\n    \n\
  \            let maxLevel = 0;\n            let bracketCount = 0;\n            for\
  \ (const element of query.split(\" \")) {\n                maxLevel = Math.max(bracketCount,\
  \ maxLevel);\n                if (\"(\" === element) {\n                    bracketCount++;\n\
  \                } else if (\")\" === (element)) {\n                    bracketCount--;\n\
  \                }\n            }\n    \n            const mapping = new Map();\n\
  \    \n            let level = maxLevel;\n            while (level > 0) {\n    \
  \            query = this.normalizeFragmentByBracketLevel(level, query, mapping);\n\
  \                level--;\n            }\n    \n            for (const [key, value]\
  \ of mapping) {\n                query = query.replaceAll(key.trim(), value.trim());\n\
  \            }\n    \n            query = query.replaceAll(\"A_N_D\", AND)\n   \
  \             .replaceAll(\"O_R\", OR)\n                .replaceAll(\"N_O_T\", NOT)\n\
  \                .replaceAll(\" \", \"\")\n                .replaceAll(\",\", \"\
  , \");\n    \n            if (this.surroundedByBrackets(query)) {\n            \
  \    query = query.substring(1, query.length - 1);\n            }\n    \n      \
  \      return query;\n        }\n    \n        this.normalizeFragmentByBracketLevel\
  \ = function (level, input, mapping) {\n            let result = input;\n    \n\
  \            for (const [key, value] of mapping) {\n                result = result.replaceAll(key,\
  \ value);\n            }\n    \n            mapping.clear();\n    \n           \
  \ const fragmentByLevel = this.getFragmentByLevel(level, result);\n    \n      \
  \      for (const res of fragmentByLevel) {\n                if (res.includes(AND))\
  \ {\n                    mapping.set(res, \"A_N_D \" + res.replaceAll(AND, \",\"\
  ));\n                } else if (res.includes(OR)) {\n                    mapping.set(res,\
  \ \"O_R \" + res.replaceAll(OR, \",\"));\n                } else if (res.includes(NOT))\
  \ {\n                    mapping.set(res, res.replaceAll(NOT, \"N_O_T (\") + \"\
  )\");\n                }\n            }\n    \n            return result;\n    \
  \    }\n    \n        this.getFragmentByLevel = function (level, str) {\n      \
  \      const result = [];\n            let buffer = [];\n            let bracketCount\
  \ = 0;\n            let prevElement = null;\n            for (const element of str.split(\"\
  \ \")) {\n                if (\"(\" === element) {\n                    bracketCount++;\n\
  \                } else if (\")\" === element) {\n                    if (buffer.length\
  \ > 0 && bracketCount >= level) {\n                        buffer.push(element);\n\
  \                        buffer.push(\" \");\n                    }\n          \
  \          bracketCount--;\n                    prevElement = element;\n       \
  \             continue;\n                }\n    \n                if (bracketCount\
  \ >= level) {\n                    buffer.push(element);\n                    buffer.push(\"\
  \ \");\n                } else if (buffer.length > 0) {\n                    result.push(buffer.join(''));\n\
  \                    buffer = [];\n                }\n                prevElement\
  \ = element;\n            }\n            if (buffer.length > 0) {\n            \
  \    result.push(buffer.join(''));\n            }\n            return result;\n\
  \        }\n    \n        this.replaceQueryByExpressionVars = function (normalized,\
  \ expressions) {\n            let variableQuery = normalized;\n            for (const\
  \ expression of expressions) {\n                variableQuery = variableQuery.replaceAll(expression.condition,\
  \ expression.expVar);\n                variableQuery = variableQuery.replaceAll(BRACKET_START\
  \ + expression.expVar + BRACKET_END, expression.expVar);\n            }\n    \n\
  \            return variableQuery.replaceAll(NOT_SHORT, NOT + SPACE)\n         \
  \       .replaceAll(SPACE + OR + SPACE + NOT + SPACE, \"_\" + OR + \"_\" + NOT +\
  \ \"_\")\n                .replaceAll(SPACE + AND + SPACE + NOT + SPACE, \"_\" +\
  \ AND + \"_\" + NOT + \"_\")\n                .replaceAll(SPACE + OR + SPACE, \"\
  _\" + OR + \"_\")\n                .replaceAll(SPACE + AND + SPACE, \"_\" + AND\
  \ + \"_\")\n                .replaceAll(NOT + SPACE, NOT + \"_\")\n            \
  \    .replaceAll(BRACKET_START + \" \", BRACKET_START + \"\")\n                .replaceAll(\"\
  \ \" + BRACKET_END, BRACKET_END + \"\")\n                .replaceAll(\" \", \"_\"\
  \ + AND + \"_\")\n                .replaceAll(\"_\", \" \");\n        }\n    \n\
  \        this.buildLogicObject = function (normalizedLogicQuery, varToExpressionMap)\
  \ {\n            let input = normalizedLogicQuery.replaceAll(\"AND(\", \"{\\\"and\\\
  \": [\")\n                .replaceAll(\"OR(\", \"{\\\"or\\\": [\")\n           \
  \     .replaceAll(\"NOT(\", \"{\\\"not\\\": [\")\n                .replaceAll(\"\
  )\", \"]}\");\n    \n            for (const [key, value] of varToExpressionMap)\
  \ {\n                input = input.replaceAll(key, \"{\\\"exp\\\": \\\"\" + key\
  \ + \"\\\"}\");\n            }\n    \n            return JSON.parse(input);\n  \
  \      }\n    \n        this.buildExpressions = function (logic, varToExpressionMap)\
  \ {\n            const rootExpressionList = [];\n    \n            let rootExpression;\n\
  \            if (logic.and !== null && logic.and !== undefined) {\n            \
  \    for (const internal of logic.and) {\n                    rootExpressionList.push(this.processLogic(internal,\
  \ varToExpressionMap));\n                }\n                rootExpression = new\
  \ Expression(\n                    ExpressionType.CONJUNCTION,\n               \
  \     null,\n                    rootExpressionList,\n                    null,\n\
  \                    null\n                );\n            } else if (logic.or !==\
  \ null && logic.or !== undefined) {\n                for (const internal of logic.or)\
  \ {\n                    rootExpressionList.push(this.processLogic(internal, varToExpressionMap));\n\
  \                }\n                rootExpression = new Expression(\n         \
  \           ExpressionType.DISJUNCTION,\n                    null,\n           \
  \         rootExpressionList,\n                    null,\n                    null\n\
  \                );\n            } else if (logic.not !== null && logic.not !==\
  \ undefined) {\n                for (const internal of logic.not) {\n          \
  \          rootExpressionList.push(this.processLogic(internal, varToExpressionMap));\n\
  \                }\n                rootExpression = new Expression(\n         \
  \           ExpressionType.NEGATION,\n                    null,\n              \
  \      rootExpressionList,\n                    null,\n                    null\n\
  \                );\n            } else {\n                rootExpression = varToExpressionMap.get(logic.exp);\n\
  \            }\n    \n            return rootExpression;\n        }\n    \n    \
  \    this.processLogic = function (internal, varToExpressionMap) {\n           \
  \ if (internal.exp !== null && internal.exp !== undefined) {\n                return\
  \ varToExpressionMap.get(internal.exp);\n            } else if (internal.and !==\
  \ null && internal.and !== undefined) {\n                const andSequenceList =\
  \ [];\n                for (const andEntity of internal.and) {\n               \
  \     andSequenceList.push(this.processLogic(andEntity, varToExpressionMap));\n\
  \                }\n                return new Expression(\n                   \
  \ ExpressionType.CONJUNCTION,\n                    null,\n                    andSequenceList,\n\
  \                    null,\n                    null\n                );\n     \
  \       } else if (internal.or !== null && internal.or !== undefined) {\n      \
  \          const orSequenceList = [];\n                for (const orEntity of internal.or)\
  \ {\n                    orSequenceList.push(this.processLogic(orEntity, varToExpressionMap));\n\
  \                }\n                return new Expression(\n                   \
  \ ExpressionType.DISJUNCTION,\n                    null,\n                    orSequenceList,\n\
  \                    null,\n                    null\n                );\n     \
  \       } else if (internal.not !== null && internal.not !== undefined) {\n    \
  \            const notSequenceList = [];\n                for (const notEntity of\
  \ internal.not) {\n                    notSequenceList.push(this.processLogic(notEntity,\
  \ varToExpressionMap));\n                }\n                return new Expression(\n\
  \                    ExpressionType.NEGATION,\n                    null,\n     \
  \               notSequenceList,\n                    null,\n                  \
  \  null\n                );\n            } else {\n                throw new Error(\"\
  Invalid expression type!\");\n            }\n        }\n    \n        this.surroundedByBrackets\
  \ = function (element) {\n            return element.charAt(0) === '(' && element.charAt(element.length\
  \ - 1) === ')';\n        }\n    \n        this.surroundedByQuotes = function (element)\
  \ {\n            return element.charAt(0) === '\"' && element.charAt(element.length\
  \ - 1) === '\"';\n        }\n    \n        this.isSpaceChar = function (current)\
  \ {\n            return this.charsEquals(current, SPACE);\n        }\n    \n   \
  \     this.charsEquals = function (actual, expected) {\n            if (actual ===\
  \ null) {\n                return false;\n            }\n            return actual\
  \ === expected;\n        }\n    \n        this.parseQuery = function (query) {\n\
  \            const normalized = this.normalize(query);\n    \n            const\
  \ expressions = this.getExpressions(normalized);\n    \n            const replacedByVarsQuery\
  \ = this.replaceQueryByExpressionVars(normalized, expressions);\n    \n        \
  \    const varToExpressionMap = new Map(expressions.map(o => [o.expVar, o]));\n\
  \    \n            const prioritizedQuery = this.buildPrioritizedQuery(replacedByVarsQuery,\
  \ Array.from(varToExpressionMap.keys()));\n    \n            const logicObject =\
  \ this.buildLogicObject(prioritizedQuery, varToExpressionMap);\n    \n         \
  \   return this.buildExpressions(logicObject, varToExpressionMap);\n        }\n\
  \    \n        this.compareQueries = function (queryOne, queryTwo) {\n         \
  \   const expOne = this.parseQuery(queryOne);\n            const expTwo = this.parseQuery(queryTwo);\n\
  \    \n            return this.compareExpressions(expOne, expTwo);\n        }\n\
  \    \n        this.compareExpressions = function (expOne, expTwo) {\n         \
  \   if (Expression.equals(expOne, expTwo)) {\n                return true;\n   \
  \         } else {\n                return false;\n            }\n        }\n  \
  \  \n    }();\n    var references1 = [];\n    // condition[0], conditionIndex:[0..99]\n\
  \    references1.push('Deleted From Google [CA10__disappearanceTime__c]: ' + obj.CA10__disappearanceTime__c);\n\
  \    if (obj.CA10__disappearanceTime__c != null) {\n        return {status: 'DISAPPEARED',\
  \ conditionIndex: 99, conditionText: \"isDisappeared(CA10__disappearanceTime__c)\"\
  , currentStateMessage: \"Object is deleted in the source\", currentStateReferences:\
  \ references1.join('\\n'), remediation: null, runtimeError: null};\n    }\n    var\
  \ count_CA10__Google_Monitoring_Conditions__r_COMPLIANT7 = 0;\n    if (obj.CA10__Google_Monitoring_Conditions__r\
  \ != null) {\n        for (var i8 = 0; i8 < obj.CA10__Google_Monitoring_Conditions__r.length;\
  \ i8++) {\n            if (obj.CA10__Google_Monitoring_Conditions__r[i8].result.status\
  \ == 'COMPLIANT') {\n                count_CA10__Google_Monitoring_Conditions__r_COMPLIANT7\
  \ += 1;\n            }\n        }\n    }\n    // condition[1], conditionIndex:[100..199]\n\
  \    function extract3() { if (!this.out) { this.out = obj.CA10__filter__c; } return\
  \ this.out; };\n    function gcpLoggingQueryMatch6() {\n        var comparingResult5\
  \ = GoogleMetricQueryParser.compareQueries(extract3.call(extract3), 'resource.type=gcs_bucket\
  \ AND protoPayload.methodName=\"storage.setIamPermissions\"');\n        return comparingResult5;\n\
  \    }\n    references1.push('Filter [obj.CA10__filter__c]: ' + obj.CA10__filter__c);\n\
  \    references1.push('Related list [CA10__Google_Monitoring_Conditions__r] ' +\
  \ (count_CA10__Google_Monitoring_Conditions__r_COMPLIANT7 > 0 ? 'has' : 'does not\
  \ have') + ' objects in COMPLIANT status');\n    try {\n        if (gcpLoggingQueryMatch6()\
  \ && count_CA10__Google_Monitoring_Conditions__r_COMPLIANT7 > 0) {\n           \
  \ return {status: 'COMPLIANT', conditionIndex: 199, conditionText: \"extract('CA10__filter__c').loggingQueryMatch('resource.type=gcs_bucket\
  \ AND protoPayload.methodName=\\\"storage.setIamPermissions\\\"') && CA10__Google_Monitoring_Conditions__r.has(COMPLIANT)\"\
  , currentStateMessage: \"Corresponding log metric exists.\", currentStateReferences:\
  \ references1.join('\\n'), remediation: null, runtimeError: null};\n        }\n\
  \    } catch (err) {\n        if (err.cause && err.cause.status) { return err.cause;\
  \ } else { throw err; }\n    }\n    return {status: 'INCOMPLIANT', conditionIndex:\
  \ 200, conditionText: \"otherwise\", currentStateMessage: \"There is no log metric\
  \ with such filter.\", currentStateReferences: references1.join('\\n'), remediation:\
  \ \"Create log metric with the appropriate filter.\", runtimeError: null};\n\"\"\
  \";\n\n\nSELECT\n  expectedResult.Id as Id,\n  IF (\n    IFNULL(expectedResult.expectedResult.status,\
  \ '') = IFNULL(sObject.result.status, '')\n    AND IFNULL(expectedResult.expectedResult.conditionIndex,\
  \ -1) = IFNULL(sObject.result.conditionIndex, -1)\n    AND IFNULL(expectedResult.expectedResult.conditionText,\
  \ '') = IFNULL(sObject.result.conditionText, '')\n    AND IFNULL(expectedResult.expectedResult.runtimeError,\
  \ '') = IFNULL(sObject.result.runtimeError, ''),\n    \"MATCH\",\n    \"FAIL\"\n\
  \  ) as match,\n  expectedResult.expectedResult.status as expectedStatus, sObject.result.status\
  \ as actualStatus,\n  expectedResult.expectedResult.conditionIndex as expectedConditionIndex,\
  \ sObject.result.conditionIndex as actualConditionIndex,\n  expectedResult.expectedResult.conditionText\
  \ as expectedConditionText, sObject.result.conditionText as actualConditionText,\n\
  \  expectedResult.expectedResult.runtimeError as expectedRuntimeError, sObject.result.runtimeError\
  \ as actualRuntimeError\nFROM UNNEST(mock_ExpectedResult()) expectedResult\nLEFT\
  \ JOIN (\n    SELECT\n        sObject.Id AS Id,\n        `CA10__Google_Logging_Log_Metrics__r`.arr\
  \ AS CA10__Google_Logging_Log_Metrics__r,\n        process_CA10__CaGoogleProject__c(\n\
  \            STRUCT(\n                sObject.Id AS Id,\n                `CA10__Google_Logging_Log_Metrics__r`.arr\
  \ AS CA10__Google_Logging_Log_Metrics__r\n            ),\n            sObject.context.snapshotTime\n\
  \        ) as result\n    FROM UNNEST(mock_CA10__CaGoogleProject__c()) AS sObject\n\
  \    LEFT JOIN (\n        SELECT\n            sObject.CA10__project__c,\n      \
  \      ARRAY_AGG(\n                STRUCT(\n                    sObject.Id AS Id,\n\
  \                    sObject.CA10__disappearanceTime__c AS CA10__disappearanceTime__c,\n\
  \                    sObject.CA10__filter__c AS CA10__filter__c,\n             \
  \       sObject.CA10__project__c AS CA10__project__c,\n                    `CA10__Google_Monitoring_Conditions__r`.arr\
  \ AS CA10__Google_Monitoring_Conditions__r,\n                    process_CA10__Google_Logging_Log_Metrics__r(\n\
  \                        STRUCT(\n                            sObject.Id AS Id,\n\
  \                            sObject.CA10__disappearanceTime__c AS CA10__disappearanceTime__c,\n\
  \                            sObject.CA10__filter__c AS CA10__filter__c,\n     \
  \                       sObject.CA10__project__c AS CA10__project__c,\n        \
  \                    `CA10__Google_Monitoring_Conditions__r`.arr AS CA10__Google_Monitoring_Conditions__r\n\
  \                        ),\n                        sObject.context.snapshotTime\n\
  \                    ) as result\n                )\n            ) AS arr\n    \
  \    FROM UNNEST(mock_CA10__CaGoogleLoggingLogMetric__c()) AS sObject\n        LEFT\
  \ JOIN (\n            SELECT\n                sObject.CA10__loggingLogMetric__c,\n\
  \                ARRAY_AGG(\n                    STRUCT(\n                     \
  \   sObject.Id AS Id,\n                        sObject.CA10__disappearanceTime__c\
  \ AS CA10__disappearanceTime__c,\n                        sObject.CA10__alertPolicy__c\
  \ AS CA10__alertPolicy__c,\n                        sObject.CA10__alertPolicyId__c\
  \ AS CA10__alertPolicyId__c,\n                        sObject.CA10__loggingLogMetric__c\
  \ AS CA10__loggingLogMetric__c,\n                        STRUCT (\n            \
  \                `CA10__alertPolicy__r`.Id AS Id,\n                            `CA10__alertPolicy__r`.CA10__disappearanceTime__c\
  \ AS CA10__disappearanceTime__c,\n                            `CA10__alertPolicy__r`.CA10__enabledState__c\
  \ AS CA10__enabledState__c\n                        ) AS CA10__alertPolicy__r,\n\
  \                        process_CA10__Google_Monitoring_Conditions__r(\n      \
  \                      STRUCT(\n                                sObject.Id AS Id,\n\
  \                                sObject.CA10__disappearanceTime__c AS CA10__disappearanceTime__c,\n\
  \                                sObject.CA10__alertPolicy__c AS CA10__alertPolicy__c,\n\
  \                                sObject.CA10__alertPolicyId__c AS CA10__alertPolicyId__c,\n\
  \                                sObject.CA10__loggingLogMetric__c AS CA10__loggingLogMetric__c,\n\
  \                                STRUCT (\n                                    `CA10__alertPolicy__r`.Id\
  \ AS Id,\n                                    `CA10__alertPolicy__r`.CA10__disappearanceTime__c\
  \ AS CA10__disappearanceTime__c,\n                                    `CA10__alertPolicy__r`.CA10__enabledState__c\
  \ AS CA10__enabledState__c\n                                ) AS CA10__alertPolicy__r\n\
  \                            ),\n                            sObject.context.snapshotTime\n\
  \                        ) as result\n                    )\n                ) AS\
  \ arr\n            FROM UNNEST(mock_CA10__CaGoogleMonitoringCondition__c()) AS sObject\n\
  \            LEFT JOIN UNNEST(mock_CA10__CaGoogleMonitoringAlertPolicy__c()) AS\
  \ `CA10__alertPolicy__r`\n                ON sObject.CA10__alertPolicy__c = `CA10__alertPolicy__r`.Id\n\
  \            GROUP BY sObject.CA10__loggingLogMetric__c\n        ) AS `CA10__Google_Monitoring_Conditions__r`\n\
  \            ON sObject.Id = `CA10__Google_Monitoring_Conditions__r`.CA10__loggingLogMetric__c\n\
  \        GROUP BY sObject.CA10__project__c\n    ) AS `CA10__Google_Logging_Log_Metrics__r`\n\
  \        ON sObject.Id = `CA10__Google_Logging_Log_Metrics__r`.CA10__project__c\n\
  ) sObject ON sObject.Id = expectedResult.Id;"
