Make ZAP generation check do a clean of java folders first (#30956)

* Clean java before zap check

* Remove obsolete file

* One more file removed

---------

Co-authored-by: Andrei Litvin <andreilitvin@google.com>
diff --git a/.github/workflows/zap_templates.yaml b/.github/workflows/zap_templates.yaml
index f08ca5f..fc17648 100644
--- a/.github/workflows/zap_templates.yaml
+++ b/.github/workflows/zap_templates.yaml
@@ -51,6 +51,11 @@
               run: |
                 apt-get update
                 DEBIAN_FRONTEND=noninteractive apt-get install -fy --fix-missing openjdk-17-jre
+            # Clean out java generated files: since java codegen will generate one file per
+            # structure/cluster, if clusters and structures are ever changed (for in progress work)
+            # this may leave obsolete files. Ensure we always check for clean regen.
+            - name: Ensure clean java
+              run: rm -rf src/controller/java/generated/
             - name: Generate all
               run: ./scripts/run_in_build_env.sh scripts/tools/zap_regen_all.py
             - name: Generate script-maintained items (ERROR_CODES.md)
diff --git a/src/controller/java/generated/java/chip/devicecontroller/cluster/structs/ThermostatClusterThermostatScheduleTransition.kt b/src/controller/java/generated/java/chip/devicecontroller/cluster/structs/ThermostatClusterThermostatScheduleTransition.kt
deleted file mode 100644
index 385f331..0000000
--- a/src/controller/java/generated/java/chip/devicecontroller/cluster/structs/ThermostatClusterThermostatScheduleTransition.kt
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- *
- *    Copyright (c) 2023 Project CHIP Authors
- *
- *    Licensed under the Apache License, Version 2.0 (the "License");
- *    you may not use this file except in compliance with the License.
- *    You may obtain a copy of the License at
- *
- *        http://www.apache.org/licenses/LICENSE-2.0
- *
- *    Unless required by applicable law or agreed to in writing, software
- *    distributed under the License is distributed on an "AS IS" BASIS,
- *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *    See the License for the specific language governing permissions and
- *    limitations under the License.
- */
-package chip.devicecontroller.cluster.structs
-
-import chip.devicecontroller.cluster.*
-import matter.tlv.ContextSpecificTag
-import matter.tlv.Tag
-import matter.tlv.TlvReader
-import matter.tlv.TlvWriter
-
-class ThermostatClusterThermostatScheduleTransition(
-  val transitionTime: UInt,
-  val heatSetpoint: Int?,
-  val coolSetpoint: Int?
-) {
-  override fun toString(): String = buildString {
-    append("ThermostatClusterThermostatScheduleTransition {\n")
-    append("\ttransitionTime : $transitionTime\n")
-    append("\theatSetpoint : $heatSetpoint\n")
-    append("\tcoolSetpoint : $coolSetpoint\n")
-    append("}\n")
-  }
-
-  fun toTlv(tlvTag: Tag, tlvWriter: TlvWriter) {
-    tlvWriter.apply {
-      startStructure(tlvTag)
-      put(ContextSpecificTag(TAG_TRANSITION_TIME), transitionTime)
-      if (heatSetpoint != null) {
-        put(ContextSpecificTag(TAG_HEAT_SETPOINT), heatSetpoint)
-      } else {
-        putNull(ContextSpecificTag(TAG_HEAT_SETPOINT))
-      }
-      if (coolSetpoint != null) {
-        put(ContextSpecificTag(TAG_COOL_SETPOINT), coolSetpoint)
-      } else {
-        putNull(ContextSpecificTag(TAG_COOL_SETPOINT))
-      }
-      endStructure()
-    }
-  }
-
-  companion object {
-    private const val TAG_TRANSITION_TIME = 0
-    private const val TAG_HEAT_SETPOINT = 1
-    private const val TAG_COOL_SETPOINT = 2
-
-    fun fromTlv(tlvTag: Tag, tlvReader: TlvReader): ThermostatClusterThermostatScheduleTransition {
-      tlvReader.enterStructure(tlvTag)
-      val transitionTime = tlvReader.getUInt(ContextSpecificTag(TAG_TRANSITION_TIME))
-      val heatSetpoint =
-        if (!tlvReader.isNull()) {
-          tlvReader.getInt(ContextSpecificTag(TAG_HEAT_SETPOINT))
-        } else {
-          tlvReader.getNull(ContextSpecificTag(TAG_HEAT_SETPOINT))
-          null
-        }
-      val coolSetpoint =
-        if (!tlvReader.isNull()) {
-          tlvReader.getInt(ContextSpecificTag(TAG_COOL_SETPOINT))
-        } else {
-          tlvReader.getNull(ContextSpecificTag(TAG_COOL_SETPOINT))
-          null
-        }
-
-      tlvReader.exitContainer()
-
-      return ThermostatClusterThermostatScheduleTransition(
-        transitionTime,
-        heatSetpoint,
-        coolSetpoint
-      )
-    }
-  }
-}
diff --git a/src/controller/java/generated/java/matter/devicecontroller/cluster/clusters/ElectricalEnergyMeasurementCluster.kt b/src/controller/java/generated/java/matter/devicecontroller/cluster/clusters/ElectricalEnergyMeasurementCluster.kt
deleted file mode 100644
index d9c3677..0000000
--- a/src/controller/java/generated/java/matter/devicecontroller/cluster/clusters/ElectricalEnergyMeasurementCluster.kt
+++ /dev/null
@@ -1,472 +0,0 @@
-/*
- *
- *    Copyright (c) 2023 Project CHIP Authors
- *
- *    Licensed under the Apache License, Version 2.0 (the "License");
- *    you may not use this file except in compliance with the License.
- *    You may obtain a copy of the License at
- *
- *        http://www.apache.org/licenses/LICENSE-2.0
- *
- *    Unless required by applicable law or agreed to in writing, software
- *    distributed under the License is distributed on an "AS IS" BASIS,
- *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *    See the License for the specific language governing permissions and
- *    limitations under the License.
- */
-
-package matter.devicecontroller.cluster.clusters
-
-import java.util.logging.Level
-import java.util.logging.Logger
-import matter.controller.*
-import matter.controller.model.AttributePath
-import matter.devicecontroller.cluster.structs.*
-import matter.tlv.AnonymousTag
-import matter.tlv.TlvReader
-
-class ElectricalEnergyMeasurementCluster(
-  private val controller: MatterController,
-  private val endpointId: UShort
-) {
-  class AccuracyAttribute(val value: ElectricalEnergyMeasurementClusterMeasurementAccuracyStruct)
-
-  class CumulativeEnergyImportedAttribute(
-    val value: ElectricalEnergyMeasurementClusterEnergyMeasurementStruct?
-  )
-
-  class CumulativeEnergyExportedAttribute(
-    val value: ElectricalEnergyMeasurementClusterEnergyMeasurementStruct?
-  )
-
-  class PeriodicEnergyImportedAttribute(
-    val value: ElectricalEnergyMeasurementClusterEnergyMeasurementStruct?
-  )
-
-  class PeriodicEnergyExportedAttribute(
-    val value: ElectricalEnergyMeasurementClusterEnergyMeasurementStruct?
-  )
-
-  class GeneratedCommandListAttribute(val value: List<UInt>)
-
-  class AcceptedCommandListAttribute(val value: List<UInt>)
-
-  class EventListAttribute(val value: List<UInt>)
-
-  class AttributeListAttribute(val value: List<UInt>)
-
-  suspend fun readAccuracyAttribute(): AccuracyAttribute {
-    val ATTRIBUTE_ID: UInt = 0u
-
-    val attributePath =
-      AttributePath(endpointId = endpointId, clusterId = CLUSTER_ID, attributeId = ATTRIBUTE_ID)
-
-    val readRequest = ReadRequest(eventPaths = emptyList(), attributePaths = listOf(attributePath))
-
-    val response = controller.read(readRequest)
-
-    if (response.successes.isEmpty()) {
-      logger.log(Level.WARNING, "Read command failed")
-      throw IllegalStateException("Read command failed with failures: ${response.failures}")
-    }
-
-    logger.log(Level.FINE, "Read command succeeded")
-
-    val attributeData =
-      response.successes.filterIsInstance<ReadData.Attribute>().firstOrNull {
-        it.path.attributeId == ATTRIBUTE_ID
-      }
-
-    requireNotNull(attributeData) { "Accuracy attribute not found in response" }
-
-    // Decode the TLV data into the appropriate type
-    val tlvReader = TlvReader(attributeData.data)
-    val decodedValue: ElectricalEnergyMeasurementClusterMeasurementAccuracyStruct =
-      ElectricalEnergyMeasurementClusterMeasurementAccuracyStruct.fromTlv(AnonymousTag, tlvReader)
-
-    return AccuracyAttribute(decodedValue)
-  }
-
-  suspend fun readCumulativeEnergyImportedAttribute(): CumulativeEnergyImportedAttribute {
-    val ATTRIBUTE_ID: UInt = 1u
-
-    val attributePath =
-      AttributePath(endpointId = endpointId, clusterId = CLUSTER_ID, attributeId = ATTRIBUTE_ID)
-
-    val readRequest = ReadRequest(eventPaths = emptyList(), attributePaths = listOf(attributePath))
-
-    val response = controller.read(readRequest)
-
-    if (response.successes.isEmpty()) {
-      logger.log(Level.WARNING, "Read command failed")
-      throw IllegalStateException("Read command failed with failures: ${response.failures}")
-    }
-
-    logger.log(Level.FINE, "Read command succeeded")
-
-    val attributeData =
-      response.successes.filterIsInstance<ReadData.Attribute>().firstOrNull {
-        it.path.attributeId == ATTRIBUTE_ID
-      }
-
-    requireNotNull(attributeData) { "Cumulativeenergyimported attribute not found in response" }
-
-    // Decode the TLV data into the appropriate type
-    val tlvReader = TlvReader(attributeData.data)
-    val decodedValue: ElectricalEnergyMeasurementClusterEnergyMeasurementStruct? =
-      if (!tlvReader.isNull()) {
-        if (tlvReader.isNextTag(AnonymousTag)) {
-          ElectricalEnergyMeasurementClusterEnergyMeasurementStruct.fromTlv(AnonymousTag, tlvReader)
-        } else {
-          null
-        }
-      } else {
-        tlvReader.getNull(AnonymousTag)
-        null
-      }
-
-    return CumulativeEnergyImportedAttribute(decodedValue)
-  }
-
-  suspend fun readCumulativeEnergyExportedAttribute(): CumulativeEnergyExportedAttribute {
-    val ATTRIBUTE_ID: UInt = 2u
-
-    val attributePath =
-      AttributePath(endpointId = endpointId, clusterId = CLUSTER_ID, attributeId = ATTRIBUTE_ID)
-
-    val readRequest = ReadRequest(eventPaths = emptyList(), attributePaths = listOf(attributePath))
-
-    val response = controller.read(readRequest)
-
-    if (response.successes.isEmpty()) {
-      logger.log(Level.WARNING, "Read command failed")
-      throw IllegalStateException("Read command failed with failures: ${response.failures}")
-    }
-
-    logger.log(Level.FINE, "Read command succeeded")
-
-    val attributeData =
-      response.successes.filterIsInstance<ReadData.Attribute>().firstOrNull {
-        it.path.attributeId == ATTRIBUTE_ID
-      }
-
-    requireNotNull(attributeData) { "Cumulativeenergyexported attribute not found in response" }
-
-    // Decode the TLV data into the appropriate type
-    val tlvReader = TlvReader(attributeData.data)
-    val decodedValue: ElectricalEnergyMeasurementClusterEnergyMeasurementStruct? =
-      if (!tlvReader.isNull()) {
-        if (tlvReader.isNextTag(AnonymousTag)) {
-          ElectricalEnergyMeasurementClusterEnergyMeasurementStruct.fromTlv(AnonymousTag, tlvReader)
-        } else {
-          null
-        }
-      } else {
-        tlvReader.getNull(AnonymousTag)
-        null
-      }
-
-    return CumulativeEnergyExportedAttribute(decodedValue)
-  }
-
-  suspend fun readPeriodicEnergyImportedAttribute(): PeriodicEnergyImportedAttribute {
-    val ATTRIBUTE_ID: UInt = 3u
-
-    val attributePath =
-      AttributePath(endpointId = endpointId, clusterId = CLUSTER_ID, attributeId = ATTRIBUTE_ID)
-
-    val readRequest = ReadRequest(eventPaths = emptyList(), attributePaths = listOf(attributePath))
-
-    val response = controller.read(readRequest)
-
-    if (response.successes.isEmpty()) {
-      logger.log(Level.WARNING, "Read command failed")
-      throw IllegalStateException("Read command failed with failures: ${response.failures}")
-    }
-
-    logger.log(Level.FINE, "Read command succeeded")
-
-    val attributeData =
-      response.successes.filterIsInstance<ReadData.Attribute>().firstOrNull {
-        it.path.attributeId == ATTRIBUTE_ID
-      }
-
-    requireNotNull(attributeData) { "Periodicenergyimported attribute not found in response" }
-
-    // Decode the TLV data into the appropriate type
-    val tlvReader = TlvReader(attributeData.data)
-    val decodedValue: ElectricalEnergyMeasurementClusterEnergyMeasurementStruct? =
-      if (!tlvReader.isNull()) {
-        if (tlvReader.isNextTag(AnonymousTag)) {
-          ElectricalEnergyMeasurementClusterEnergyMeasurementStruct.fromTlv(AnonymousTag, tlvReader)
-        } else {
-          null
-        }
-      } else {
-        tlvReader.getNull(AnonymousTag)
-        null
-      }
-
-    return PeriodicEnergyImportedAttribute(decodedValue)
-  }
-
-  suspend fun readPeriodicEnergyExportedAttribute(): PeriodicEnergyExportedAttribute {
-    val ATTRIBUTE_ID: UInt = 4u
-
-    val attributePath =
-      AttributePath(endpointId = endpointId, clusterId = CLUSTER_ID, attributeId = ATTRIBUTE_ID)
-
-    val readRequest = ReadRequest(eventPaths = emptyList(), attributePaths = listOf(attributePath))
-
-    val response = controller.read(readRequest)
-
-    if (response.successes.isEmpty()) {
-      logger.log(Level.WARNING, "Read command failed")
-      throw IllegalStateException("Read command failed with failures: ${response.failures}")
-    }
-
-    logger.log(Level.FINE, "Read command succeeded")
-
-    val attributeData =
-      response.successes.filterIsInstance<ReadData.Attribute>().firstOrNull {
-        it.path.attributeId == ATTRIBUTE_ID
-      }
-
-    requireNotNull(attributeData) { "Periodicenergyexported attribute not found in response" }
-
-    // Decode the TLV data into the appropriate type
-    val tlvReader = TlvReader(attributeData.data)
-    val decodedValue: ElectricalEnergyMeasurementClusterEnergyMeasurementStruct? =
-      if (!tlvReader.isNull()) {
-        if (tlvReader.isNextTag(AnonymousTag)) {
-          ElectricalEnergyMeasurementClusterEnergyMeasurementStruct.fromTlv(AnonymousTag, tlvReader)
-        } else {
-          null
-        }
-      } else {
-        tlvReader.getNull(AnonymousTag)
-        null
-      }
-
-    return PeriodicEnergyExportedAttribute(decodedValue)
-  }
-
-  suspend fun readGeneratedCommandListAttribute(): GeneratedCommandListAttribute {
-    val ATTRIBUTE_ID: UInt = 65528u
-
-    val attributePath =
-      AttributePath(endpointId = endpointId, clusterId = CLUSTER_ID, attributeId = ATTRIBUTE_ID)
-
-    val readRequest = ReadRequest(eventPaths = emptyList(), attributePaths = listOf(attributePath))
-
-    val response = controller.read(readRequest)
-
-    if (response.successes.isEmpty()) {
-      logger.log(Level.WARNING, "Read command failed")
-      throw IllegalStateException("Read command failed with failures: ${response.failures}")
-    }
-
-    logger.log(Level.FINE, "Read command succeeded")
-
-    val attributeData =
-      response.successes.filterIsInstance<ReadData.Attribute>().firstOrNull {
-        it.path.attributeId == ATTRIBUTE_ID
-      }
-
-    requireNotNull(attributeData) { "Generatedcommandlist attribute not found in response" }
-
-    // Decode the TLV data into the appropriate type
-    val tlvReader = TlvReader(attributeData.data)
-    val decodedValue: List<UInt> =
-      buildList<UInt> {
-        tlvReader.enterArray(AnonymousTag)
-        while (!tlvReader.isEndOfContainer()) {
-          add(tlvReader.getUInt(AnonymousTag))
-        }
-        tlvReader.exitContainer()
-      }
-
-    return GeneratedCommandListAttribute(decodedValue)
-  }
-
-  suspend fun readAcceptedCommandListAttribute(): AcceptedCommandListAttribute {
-    val ATTRIBUTE_ID: UInt = 65529u
-
-    val attributePath =
-      AttributePath(endpointId = endpointId, clusterId = CLUSTER_ID, attributeId = ATTRIBUTE_ID)
-
-    val readRequest = ReadRequest(eventPaths = emptyList(), attributePaths = listOf(attributePath))
-
-    val response = controller.read(readRequest)
-
-    if (response.successes.isEmpty()) {
-      logger.log(Level.WARNING, "Read command failed")
-      throw IllegalStateException("Read command failed with failures: ${response.failures}")
-    }
-
-    logger.log(Level.FINE, "Read command succeeded")
-
-    val attributeData =
-      response.successes.filterIsInstance<ReadData.Attribute>().firstOrNull {
-        it.path.attributeId == ATTRIBUTE_ID
-      }
-
-    requireNotNull(attributeData) { "Acceptedcommandlist attribute not found in response" }
-
-    // Decode the TLV data into the appropriate type
-    val tlvReader = TlvReader(attributeData.data)
-    val decodedValue: List<UInt> =
-      buildList<UInt> {
-        tlvReader.enterArray(AnonymousTag)
-        while (!tlvReader.isEndOfContainer()) {
-          add(tlvReader.getUInt(AnonymousTag))
-        }
-        tlvReader.exitContainer()
-      }
-
-    return AcceptedCommandListAttribute(decodedValue)
-  }
-
-  suspend fun readEventListAttribute(): EventListAttribute {
-    val ATTRIBUTE_ID: UInt = 65530u
-
-    val attributePath =
-      AttributePath(endpointId = endpointId, clusterId = CLUSTER_ID, attributeId = ATTRIBUTE_ID)
-
-    val readRequest = ReadRequest(eventPaths = emptyList(), attributePaths = listOf(attributePath))
-
-    val response = controller.read(readRequest)
-
-    if (response.successes.isEmpty()) {
-      logger.log(Level.WARNING, "Read command failed")
-      throw IllegalStateException("Read command failed with failures: ${response.failures}")
-    }
-
-    logger.log(Level.FINE, "Read command succeeded")
-
-    val attributeData =
-      response.successes.filterIsInstance<ReadData.Attribute>().firstOrNull {
-        it.path.attributeId == ATTRIBUTE_ID
-      }
-
-    requireNotNull(attributeData) { "Eventlist attribute not found in response" }
-
-    // Decode the TLV data into the appropriate type
-    val tlvReader = TlvReader(attributeData.data)
-    val decodedValue: List<UInt> =
-      buildList<UInt> {
-        tlvReader.enterArray(AnonymousTag)
-        while (!tlvReader.isEndOfContainer()) {
-          add(tlvReader.getUInt(AnonymousTag))
-        }
-        tlvReader.exitContainer()
-      }
-
-    return EventListAttribute(decodedValue)
-  }
-
-  suspend fun readAttributeListAttribute(): AttributeListAttribute {
-    val ATTRIBUTE_ID: UInt = 65531u
-
-    val attributePath =
-      AttributePath(endpointId = endpointId, clusterId = CLUSTER_ID, attributeId = ATTRIBUTE_ID)
-
-    val readRequest = ReadRequest(eventPaths = emptyList(), attributePaths = listOf(attributePath))
-
-    val response = controller.read(readRequest)
-
-    if (response.successes.isEmpty()) {
-      logger.log(Level.WARNING, "Read command failed")
-      throw IllegalStateException("Read command failed with failures: ${response.failures}")
-    }
-
-    logger.log(Level.FINE, "Read command succeeded")
-
-    val attributeData =
-      response.successes.filterIsInstance<ReadData.Attribute>().firstOrNull {
-        it.path.attributeId == ATTRIBUTE_ID
-      }
-
-    requireNotNull(attributeData) { "Attributelist attribute not found in response" }
-
-    // Decode the TLV data into the appropriate type
-    val tlvReader = TlvReader(attributeData.data)
-    val decodedValue: List<UInt> =
-      buildList<UInt> {
-        tlvReader.enterArray(AnonymousTag)
-        while (!tlvReader.isEndOfContainer()) {
-          add(tlvReader.getUInt(AnonymousTag))
-        }
-        tlvReader.exitContainer()
-      }
-
-    return AttributeListAttribute(decodedValue)
-  }
-
-  suspend fun readFeatureMapAttribute(): UInt {
-    val ATTRIBUTE_ID: UInt = 65532u
-
-    val attributePath =
-      AttributePath(endpointId = endpointId, clusterId = CLUSTER_ID, attributeId = ATTRIBUTE_ID)
-
-    val readRequest = ReadRequest(eventPaths = emptyList(), attributePaths = listOf(attributePath))
-
-    val response = controller.read(readRequest)
-
-    if (response.successes.isEmpty()) {
-      logger.log(Level.WARNING, "Read command failed")
-      throw IllegalStateException("Read command failed with failures: ${response.failures}")
-    }
-
-    logger.log(Level.FINE, "Read command succeeded")
-
-    val attributeData =
-      response.successes.filterIsInstance<ReadData.Attribute>().firstOrNull {
-        it.path.attributeId == ATTRIBUTE_ID
-      }
-
-    requireNotNull(attributeData) { "Featuremap attribute not found in response" }
-
-    // Decode the TLV data into the appropriate type
-    val tlvReader = TlvReader(attributeData.data)
-    val decodedValue: UInt = tlvReader.getUInt(AnonymousTag)
-
-    return decodedValue
-  }
-
-  suspend fun readClusterRevisionAttribute(): UShort {
-    val ATTRIBUTE_ID: UInt = 65533u
-
-    val attributePath =
-      AttributePath(endpointId = endpointId, clusterId = CLUSTER_ID, attributeId = ATTRIBUTE_ID)
-
-    val readRequest = ReadRequest(eventPaths = emptyList(), attributePaths = listOf(attributePath))
-
-    val response = controller.read(readRequest)
-
-    if (response.successes.isEmpty()) {
-      logger.log(Level.WARNING, "Read command failed")
-      throw IllegalStateException("Read command failed with failures: ${response.failures}")
-    }
-
-    logger.log(Level.FINE, "Read command succeeded")
-
-    val attributeData =
-      response.successes.filterIsInstance<ReadData.Attribute>().firstOrNull {
-        it.path.attributeId == ATTRIBUTE_ID
-      }
-
-    requireNotNull(attributeData) { "Clusterrevision attribute not found in response" }
-
-    // Decode the TLV data into the appropriate type
-    val tlvReader = TlvReader(attributeData.data)
-    val decodedValue: UShort = tlvReader.getUShort(AnonymousTag)
-
-    return decodedValue
-  }
-
-  companion object {
-    private val logger = Logger.getLogger(ElectricalEnergyMeasurementCluster::class.java.name)
-    const val CLUSTER_ID: UInt = 145u
-  }
-}