diff --git a/openespi-common/src/main/java/org/greenbuttonalliance/espi/common/domain/usage/ApplicationInformationEntity.java b/openespi-common/src/main/java/org/greenbuttonalliance/espi/common/domain/usage/ApplicationInformationEntity.java index 16107ceb..124d1608 100644 --- a/openespi-common/src/main/java/org/greenbuttonalliance/espi/common/domain/usage/ApplicationInformationEntity.java +++ b/openespi-common/src/main/java/org/greenbuttonalliance/espi/common/domain/usage/ApplicationInformationEntity.java @@ -53,32 +53,29 @@ public class ApplicationInformationEntity extends IdentifiedObject { private static final long serialVersionUID = 1L; + // ======================================== + // ESPI 4.0 XSD Fields in Sequence Order + // Lines follow espi.xsd lines 62-246 + // ======================================== + /** - * Kind/type classification for this application information. + * Data custodian ID. + * ESPI 4.0 XSD field #1 */ - @Column(name = "kind") - private String kind; + @Size(min = 2, max = 64) + @Column(name = "data_custodian_id") + private String dataCustodianId; /** * Data custodian application status. + * ESPI 4.0 XSD field #2 */ @Column(name = "data_custodian_application_status") private String dataCustodianApplicationStatus; - /** - * Data custodian default batch resource URI. - */ - @Column(name = "data_custodian_default_batch_resource") - private String dataCustodianDefaultBatchResource; - - /** - * Data custodian default subscription resource URI. - */ - @Column(name = "data_custodian_default_subscription_resource") - private String dataCustodianDefaultSubscriptionResource; - /** * Third party application description. + * ESPI 4.0 XSD field #3 */ @Column(name = "third_party_application_description") private String thirdPartyApplicationDescription; @@ -139,42 +136,28 @@ public class ApplicationInformationEntity extends IdentifiedObject { /** * Data custodian bulk request URI. + * ESPI 4.0 XSD field #14 */ @Column(name = "data_custodian_bulk_request_uri") private String dataCustodianBulkRequestURI; - /** - * Data custodian third party selection screen URI. - */ - @Column(name = "data_custodian_third_party_selection_screen_uri") - private String dataCustodianThirdPartySelectionScreenURI; - /** * Data custodian resource endpoint. + * ESPI 4.0 XSD field #15 */ @Column(name = "data_custodian_resource_endpoint") private String dataCustodianResourceEndpoint; - /** - * Third party data custodian selection screen URI. - */ - @Column(name = "third_party_data_custodian_selection_screen_uri") - private String thirdPartyDataCustodianSelectionScreenURI; - - /** - * Third party login screen URI. - */ - @Column(name = "third_party_login_screen_uri") - private String thirdPartyLoginScreenURI; - /** * Third party scope selection screen URI. + * ESPI 4.0 XSD field #16 */ @Column(name = "third_party_scope_selection_screen_uri") private String thirdPartyScopeSelectionScreenURI; /** * Third party user portal screen URI. + * ESPI 4.0 XSD field #17 */ @Column(name = "third_party_user_portal_screen_uri") private String thirdPartyUserPortalScreenURI; @@ -268,32 +251,9 @@ public class ApplicationInformationEntity extends IdentifiedObject { @Column(name = "token_endpoint_auth_method") private String tokenEndpointAuthMethod; - /** - * Data custodian scope selection screen URI. - */ - @Column(name = "data_custodian_scope_selection_screen_uri") - private String dataCustodianScopeSelectionScreenURI; - - /** - * Data custodian ID. - * Required field with size constraints. - */ - @Size(min = 2, max = 64) - @Column(name = "data_custodian_id") - private String dataCustodianId; - - /** - * Third party application name. - * Required field with size constraints and default value. - */ - @NotEmpty - @Size(min = 2, max = 64) - @Column(name = "third_party_application_name", nullable = false) - private String thirdPartyApplicationName = "Default Third Party Application Name"; - /** * OAuth2 scopes for this application. - * Stored as element collection in separate table. + * ESPI 4.0 XSD field #33 */ @ElementCollection @LazyCollection(LazyCollectionOption.FALSE) @@ -306,11 +266,12 @@ public class ApplicationInformationEntity extends IdentifiedObject { /** * OAuth2 grant types supported by this application. - * Stored as element collection with enum mapping. + * ESPI 4.0 XSD field #34 + * FIXED: Changed from @JoinTable to @CollectionTable for @ElementCollection */ @ElementCollection(targetClass = GrantType.class) @LazyCollection(LazyCollectionOption.FALSE) - @JoinTable( + @CollectionTable( name = "application_information_grant_types", joinColumns = @JoinColumn(name = "application_information_id") ) @@ -320,6 +281,7 @@ public class ApplicationInformationEntity extends IdentifiedObject { /** * OAuth2 response types supported by this application. + * ESPI 4.0 XSD field #35 */ @Enumerated(EnumType.STRING) @Column(name = "response_types") @@ -327,21 +289,30 @@ public class ApplicationInformationEntity extends IdentifiedObject { /** * Registration client URI. + * ESPI 4.0 XSD field #36 */ @Column(name = "registration_client_uri") private String registrationClientUri; /** * Registration access token. + * ESPI 4.0 XSD field #37 * Encrypted at rest using AES-256-GCM. */ - @Column(name = "registration_access_token") + @Column(name = "registration_access_token") @Convert(converter = FieldEncryptionConverter.class) private String registrationAccessToken; + /** + * Data custodian scope selection screen URI. + * ESPI 4.0 XSD field #38 (last field in XSD sequence) + */ + @Column(name = "data_custodian_scope_selection_screen_uri") + private String dataCustodianScopeSelectionScreenURI; + /** * Gets the scope array for backward compatibility. - * + * * @return array of scope strings */ public String[] getScopeArray() { @@ -351,67 +322,6 @@ public String[] getScopeArray() { return scope.toArray(new String[0]); } - /** - * Merges data from another ApplicationInformationEntity. - * - * @param other the other application information entity to merge from - */ - public void merge(ApplicationInformationEntity other) { - if (other != null) { - super.merge(other); - - // OAuth2 and client information - this.clientId = other.clientId; - this.clientSecret = other.clientSecret; - this.scope = new HashSet<>(other.scope); - this.grantTypes = new HashSet<>(other.grantTypes); - this.redirectUri = other.redirectUri; - this.responseTypes = other.responseTypes; - - // Application status and configuration - this.dataCustodianApplicationStatus = other.dataCustodianApplicationStatus; - this.thirdPartyApplicationStatus = other.thirdPartyApplicationStatus; - this.thirdPartyApplicationType = other.thirdPartyApplicationType; - this.thirdPartyApplicationUse = other.thirdPartyApplicationUse; - this.thirdPartyApplicationDescription = other.thirdPartyApplicationDescription; - this.thirdPartyApplicationName = other.thirdPartyApplicationName; - - // URIs and endpoints - this.authorizationServerUri = other.authorizationServerUri; - this.thirdPartyNotifyUri = other.thirdPartyNotifyUri; - this.authorizationServerAuthorizationEndpoint = other.authorizationServerAuthorizationEndpoint; - this.authorizationServerRegistrationEndpoint = other.authorizationServerRegistrationEndpoint; - this.authorizationServerTokenEndpoint = other.authorizationServerTokenEndpoint; - this.dataCustodianBulkRequestURI = other.dataCustodianBulkRequestURI; - this.dataCustodianResourceEndpoint = other.dataCustodianResourceEndpoint; - this.dataCustodianScopeSelectionScreenURI = other.dataCustodianScopeSelectionScreenURI; - - // Additional application metadata - this.logoUri = other.logoUri; - this.clientName = other.clientName; - this.clientUri = other.clientUri; - this.tosUri = other.tosUri; - this.policyUri = other.policyUri; - this.softwareId = other.softwareId; - this.softwareVersion = other.softwareVersion; - this.clientIdIssuedAt = other.clientIdIssuedAt; - this.clientSecretExpiresAt = other.clientSecretExpiresAt; - this.contacts = other.contacts; - this.tokenEndpointAuthMethod = other.tokenEndpointAuthMethod; - this.registrationClientUri = other.registrationClientUri; - this.registrationAccessToken = other.registrationAccessToken; - - // Data custodian information - this.dataCustodianId = other.dataCustodianId; - this.dataCustodianDefaultBatchResource = other.dataCustodianDefaultBatchResource; - this.dataCustodianDefaultSubscriptionResource = other.dataCustodianDefaultSubscriptionResource; - - // Contact and additional information - this.thirdPartyPhone = other.thirdPartyPhone; - this.kind = other.kind; - } - } - @Override public final boolean equals(Object o) { if (this == o) return true; @@ -432,49 +342,42 @@ public final int hashCode() { public String toString() { return getClass().getSimpleName() + "(" + "id = " + getId() + ", " + - "kind = " + getKind() + ", " + - "dataCustodianApplicationStatus = " + getDataCustodianApplicationStatus() + ", " + - "dataCustodianDefaultBatchResource = " + getDataCustodianDefaultBatchResource() + ", " + - "dataCustodianDefaultSubscriptionResource = " + getDataCustodianDefaultSubscriptionResource() + ", " + - "thirdPartyApplicationDescription = " + getThirdPartyApplicationDescription() + ", " + - "thirdPartyApplicationStatus = " + getThirdPartyApplicationStatus() + ", " + - "thirdPartyApplicationType = " + getThirdPartyApplicationType() + ", " + - "thirdPartyApplicationUse = " + getThirdPartyApplicationUse() + ", " + - "thirdPartyPhone = " + getThirdPartyPhone() + ", " + - "authorizationServerUri = " + getAuthorizationServerUri() + ", " + - "thirdPartyNotifyUri = " + getThirdPartyNotifyUri() + ", " + - "authorizationServerAuthorizationEndpoint = " + getAuthorizationServerAuthorizationEndpoint() + ", " + - "authorizationServerRegistrationEndpoint = " + getAuthorizationServerRegistrationEndpoint() + ", " + - "authorizationServerTokenEndpoint = " + getAuthorizationServerTokenEndpoint() + ", " + - "dataCustodianBulkRequestURI = " + getDataCustodianBulkRequestURI() + ", " + - "dataCustodianThirdPartySelectionScreenURI = " + getDataCustodianThirdPartySelectionScreenURI() + ", " + - "dataCustodianResourceEndpoint = " + getDataCustodianResourceEndpoint() + ", " + - "thirdPartyDataCustodianSelectionScreenURI = " + getThirdPartyDataCustodianSelectionScreenURI() + ", " + - "thirdPartyLoginScreenURI = " + getThirdPartyLoginScreenURI() + ", " + - "thirdPartyScopeSelectionScreenURI = " + getThirdPartyScopeSelectionScreenURI() + ", " + - "thirdPartyUserPortalScreenURI = " + getThirdPartyUserPortalScreenURI() + ", " + - "clientSecret = " + getClientSecret() + ", " + - "logoUri = " + getLogoUri() + ", " + - "clientName = " + getClientName() + ", " + - "clientUri = " + getClientUri() + ", " + - "redirectUri = " + getRedirectUri() + ", " + - "clientId = " + getClientId() + ", " + - "tosUri = " + getTosUri() + ", " + - "policyUri = " + getPolicyUri() + ", " + - "softwareId = " + getSoftwareId() + ", " + - "softwareVersion = " + getSoftwareVersion() + ", " + - "clientIdIssuedAt = " + getClientIdIssuedAt() + ", " + - "clientSecretExpiresAt = " + getClientSecretExpiresAt() + ", " + - "contacts = " + getContacts() + ", " + - "tokenEndpointAuthMethod = " + getTokenEndpointAuthMethod() + ", " + - "dataCustodianScopeSelectionScreenURI = " + getDataCustodianScopeSelectionScreenURI() + ", " + - "dataCustodianId = " + getDataCustodianId() + ", " + - "thirdPartyApplicationName = " + getThirdPartyApplicationName() + ", " + - "scope = " + getScope() + ", " + - "grantTypes = " + getGrantTypes() + ", " + - "responseTypes = " + getResponseTypes() + ", " + - "registrationClientUri = " + getRegistrationClientUri() + ", " + - "registrationAccessToken = " + getRegistrationAccessToken() + ", " + + "dataCustodianId = " + dataCustodianId + ", " + + "dataCustodianApplicationStatus = " + dataCustodianApplicationStatus + ", " + + "thirdPartyApplicationDescription = " + thirdPartyApplicationDescription + ", " + + "thirdPartyApplicationStatus = " + thirdPartyApplicationStatus + ", " + + "thirdPartyApplicationType = " + thirdPartyApplicationType + ", " + + "thirdPartyApplicationUse = " + thirdPartyApplicationUse + ", " + + "thirdPartyPhone = " + thirdPartyPhone + ", " + + "authorizationServerUri = " + authorizationServerUri + ", " + + "thirdPartyNotifyUri = " + thirdPartyNotifyUri + ", " + + "authorizationServerAuthorizationEndpoint = " + authorizationServerAuthorizationEndpoint + ", " + + "authorizationServerRegistrationEndpoint = " + authorizationServerRegistrationEndpoint + ", " + + "authorizationServerTokenEndpoint = " + authorizationServerTokenEndpoint + ", " + + "dataCustodianBulkRequestURI = " + dataCustodianBulkRequestURI + ", " + + "dataCustodianResourceEndpoint = " + dataCustodianResourceEndpoint + ", " + + "thirdPartyScopeSelectionScreenURI = " + thirdPartyScopeSelectionScreenURI + ", " + + "thirdPartyUserPortalScreenURI = " + thirdPartyUserPortalScreenURI + ", " + + "clientSecret = [PROTECTED], " + + "logoUri = " + logoUri + ", " + + "clientName = " + clientName + ", " + + "clientUri = " + clientUri + ", " + + "redirectUri = " + redirectUri + ", " + + "clientId = " + clientId + ", " + + "tosUri = " + tosUri + ", " + + "policyUri = " + policyUri + ", " + + "softwareId = " + softwareId + ", " + + "softwareVersion = " + softwareVersion + ", " + + "clientIdIssuedAt = " + clientIdIssuedAt + ", " + + "clientSecretExpiresAt = " + clientSecretExpiresAt + ", " + + "contacts = " + contacts + ", " + + "tokenEndpointAuthMethod = " + tokenEndpointAuthMethod + ", " + + "scope = " + scope + ", " + + "grantTypes = " + grantTypes + ", " + + "responseTypes = " + responseTypes + ", " + + "registrationClientUri = " + registrationClientUri + ", " + + "registrationAccessToken = [PROTECTED], " + + "dataCustodianScopeSelectionScreenURI = " + dataCustodianScopeSelectionScreenURI + ", " + "description = " + getDescription() + ", " + "created = " + getCreated() + ", " + "updated = " + getUpdated() + ", " + diff --git a/openespi-common/src/main/java/org/greenbuttonalliance/espi/common/dto/usage/ApplicationInformationDto.java b/openespi-common/src/main/java/org/greenbuttonalliance/espi/common/dto/usage/ApplicationInformationDto.java index fc9ac172..602b8384 100644 --- a/openespi-common/src/main/java/org/greenbuttonalliance/espi/common/dto/usage/ApplicationInformationDto.java +++ b/openespi-common/src/main/java/org/greenbuttonalliance/espi/common/dto/usage/ApplicationInformationDto.java @@ -23,62 +23,183 @@ /** * ApplicationInformation DTO record for JAXB XML marshalling/unmarshalling. - * + * * Represents OAuth 2.0 application information for third-party access * to Green Button data. + * + * Field order strictly matches ESPI 4.0 XSD schema sequence (espi.xsd lines 62-246). */ @XmlRootElement(name = "ApplicationInformation", namespace = "http://naesb.org/espi") @XmlAccessorType(XmlAccessType.PROPERTY) @XmlType(name = "ApplicationInformation", namespace = "http://naesb.org/espi", propOrder = { - "dataCustodianBulkRequestURI", "dataCustodianResourceEndpoint", "dataCustodianApplicationStatus", - "thirdPartyApplicationDescription", "thirdPartyApplicationStatus", "thirdPartyApplicationType", - "thirdPartyApplicationUse", "thirdPartyPhone", "authorizationServerAuthorizationEndpoint", - "authorizationServerRegistrationEndpoint", "authorizationServerTokenEndpoint", - "dataCustodianScopeSelectionScreenURI", "thirdPartyLoginScreenURI", "thirdPartyNotifyURI", - "authorizationServerUri", "thirdPartyApplicationName", "clientName", "clientId", "clientSecret", - "clientIdIssuedAt", "clientSecretExpiresAt", "contacts", "clientUri", "logoUri", "policyUri", - "redirectUri", "softwareId", "softwareVersion", "tokenEndpointAuthMethod", "responseType", - "registrationAccessToken", "registrationClientUri", "grantTypes", "scopes" + // Core identification + "dataCustodianId", + "dataCustodianApplicationStatus", + + // Third Party Application Details + "thirdPartyApplicationDescription", + "thirdPartyApplicationStatus", + "thirdPartyApplicationType", + "thirdPartyApplicationUse", + "thirdPartyPhone", + + // Authorization Server URIs + "authorizationServerUri", + "thirdPartyNotifyURI", + "authorizationServerAuthorizationEndpoint", + "authorizationServerRegistrationEndpoint", + "authorizationServerTokenEndpoint", + + // Data Custodian Endpoints + "dataCustodianBulkRequestURI", + "dataCustodianResourceEndpoint", + + // UI Screen URIs + "thirdPartyScopeSelectionScreenURI", + "thirdPartyUserPortalScreenURI", + + // OAuth 2.0 Client Credentials + "clientSecret", // client_secret in XSD + "logoUri", // logo_uri in XSD + "clientName", // client_name in XSD + "clientUri", // client_uri in XSD + "redirectUri", // redirect_uri in XSD + "clientId", // client_id in XSD + "tosUri", // tos_uri in XSD + "policyUri", // policy_uri in XSD + "softwareId", // software_id in XSD + "softwareVersion", // software_version in XSD + "clientIdIssuedAt", // client_id_issued_at in XSD + "clientSecretExpiresAt", // client_secret_expires_at in XSD + + // OAuth 2.0 Additional Fields + "contacts", + "tokenEndpointAuthMethod", + "scopes", // scope in XSD (maxOccurs="unbounded") + "grantTypes", // grant_types in XSD (minOccurs="2") + "responseTypes", // response_types in XSD + + // Registration + "registrationClientUri", + "registrationAccessToken", + + // Deprecated (kept for backward compatibility) + "dataCustodianScopeSelectionScreenURI" }) public record ApplicationInformationDto( - + + // Internal UUID (not in XSD) String uuid, - String dataCustodianBulkRequestURI, - String dataCustodianResourceEndpoint, + + // 1. dataCustodianId - Required + String dataCustodianId, + + // 2. dataCustodianApplicationStatus - Required Short dataCustodianApplicationStatus, + + // 3. thirdPartyApplicationDescription - Optional String thirdPartyApplicationDescription, + + // 4. thirdPartyApplicationStatus - Optional Short thirdPartyApplicationStatus, + + // 5. thirdPartyApplicationType - Optional Short thirdPartyApplicationType, + + // 6. thirdPartyApplicationUse - Optional Short thirdPartyApplicationUse, + + // 7. thirdPartyPhone - Optional String thirdPartyPhone, + + // 8. authorizationServerUri - Optional + String authorizationServerUri, + + // 9. thirdPartyNotifyUri - Required + String thirdPartyNotifyURI, + + // 10. authorizationServerAuthorizationEndpoint - Required String authorizationServerAuthorizationEndpoint, + + // 11. authorizationServerRegistrationEndpoint - Optional String authorizationServerRegistrationEndpoint, + + // 12. authorizationServerTokenEndpoint - Required String authorizationServerTokenEndpoint, - String dataCustodianScopeSelectionScreenURI, - String thirdPartyLoginScreenURI, - String thirdPartyNotifyURI, - String authorizationServerUri, - String thirdPartyApplicationName, - String clientName, - String clientId, + + // 13. dataCustodianBulkRequestURI - Required + String dataCustodianBulkRequestURI, + + // 14. dataCustodianResourceEndpoint - Required + String dataCustodianResourceEndpoint, + + // 15. thirdPartyScopeSelectionScreenURI - Optional + String thirdPartyScopeSelectionScreenURI, + + // 16. thirdPartyUserPortalScreenURI - Optional + String thirdPartyUserPortalScreenURI, + + // 17. client_secret - Required String clientSecret, - Long clientIdIssuedAt, - Long clientSecretExpiresAt, - String contacts, - String clientUri, + + // 18. logo_uri - Optional String logoUri, - String policyUri, + + // 19. client_name - Required + String clientName, + + // 20. client_uri - Optional + String clientUri, + + // 21. redirect_uri - Required (maxOccurs="unbounded") String redirectUri, + + // 22. client_id - Required + String clientId, + + // 23. tos_uri - Optional + String tosUri, + + // 24. policy_uri - Optional + String policyUri, + + // 25. software_id - Required String softwareId, + + // 26. software_version - Required String softwareVersion, + + // 27. client_id_issued_at - Required + Long clientIdIssuedAt, + + // 28. client_secret_expires_at - Required + Long clientSecretExpiresAt, + + // 29. contacts - Optional (maxOccurs="unbounded") + String contacts, + + // 30. token_endpoint_auth_method - Required String tokenEndpointAuthMethod, - String responseType, - String registrationAccessToken, - String registrationClientUri, + + // 31. scope - Required (maxOccurs="unbounded") + String scopes, + + // 32. grant_types - Required (minOccurs="2") String grantTypes, - String scopes + + // 33. response_types - Required + String responseTypes, + + // 34. registration_client_uri - Required + String registrationClientUri, + + // 35. registration_access_token - Required + String registrationAccessToken, + + // 36. dataCustodianScopeSelectionScreenURI - Deprecated + String dataCustodianScopeSelectionScreenURI ) { - + /** * Default constructor for JAXB. */ @@ -86,119 +207,128 @@ public ApplicationInformationDto() { this(null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, - null, null, null, null, null, null, null, null); + null, null, null, null, null, null, null, null, null, + null); } - + /** - * Constructor for basic application information. + * Constructor for basic application information (minimum required fields). */ - public ApplicationInformationDto(String clientId, String clientSecret, String thirdPartyApplicationName) { - this(null, null, null, null, null, null, null, null, null, - null, null, null, null, null, null, null, thirdPartyApplicationName, null, - clientId, clientSecret, null, null, null, null, null, null, null, - null, null, null, null, null, null, null, null); + public ApplicationInformationDto(String dataCustodianId, String clientId, String clientSecret, String clientName) { + this(null, dataCustodianId, null, null, null, null, null, null, null, + null, null, null, null, null, null, null, null, null, + clientSecret, null, clientName, null, null, clientId, null, null, + null, null, null, null, null, null, null, null, null, + null, null); } - - // JAXB property accessors - @XmlElement(name = "dataCustodianBulkRequestURI", namespace = "http://naesb.org/espi") - public String getDataCustodianBulkRequestURI() { return dataCustodianBulkRequestURI; } - - @XmlElement(name = "dataCustodianResourceEndpoint", namespace = "http://naesb.org/espi") - public String getDataCustodianResourceEndpoint() { return dataCustodianResourceEndpoint; } - + + // JAXB property accessors - must match propOrder sequence + + @XmlElement(name = "dataCustodianId", namespace = "http://naesb.org/espi") + public String getDataCustodianId() { return dataCustodianId; } + @XmlElement(name = "dataCustodianApplicationStatus", namespace = "http://naesb.org/espi") public Short getDataCustodianApplicationStatus() { return dataCustodianApplicationStatus; } - + @XmlElement(name = "thirdPartyApplicationDescription", namespace = "http://naesb.org/espi") public String getThirdPartyApplicationDescription() { return thirdPartyApplicationDescription; } - + @XmlElement(name = "thirdPartyApplicationStatus", namespace = "http://naesb.org/espi") public Short getThirdPartyApplicationStatus() { return thirdPartyApplicationStatus; } - + @XmlElement(name = "thirdPartyApplicationType", namespace = "http://naesb.org/espi") public Short getThirdPartyApplicationType() { return thirdPartyApplicationType; } - + @XmlElement(name = "thirdPartyApplicationUse", namespace = "http://naesb.org/espi") public Short getThirdPartyApplicationUse() { return thirdPartyApplicationUse; } - + @XmlElement(name = "thirdPartyPhone", namespace = "http://naesb.org/espi") public String getThirdPartyPhone() { return thirdPartyPhone; } - + + @XmlElement(name = "authorizationServerUri", namespace = "http://naesb.org/espi") + public String getAuthorizationServerUri() { return authorizationServerUri; } + + @XmlElement(name = "thirdPartyNotifyURI", namespace = "http://naesb.org/espi") + public String getThirdPartyNotifyURI() { return thirdPartyNotifyURI; } + @XmlElement(name = "authorizationServerAuthorizationEndpoint", namespace = "http://naesb.org/espi") public String getAuthorizationServerAuthorizationEndpoint() { return authorizationServerAuthorizationEndpoint; } - + @XmlElement(name = "authorizationServerRegistrationEndpoint", namespace = "http://naesb.org/espi") public String getAuthorizationServerRegistrationEndpoint() { return authorizationServerRegistrationEndpoint; } - + @XmlElement(name = "authorizationServerTokenEndpoint", namespace = "http://naesb.org/espi") public String getAuthorizationServerTokenEndpoint() { return authorizationServerTokenEndpoint; } - - @XmlElement(name = "dataCustodianScopeSelectionScreenURI", namespace = "http://naesb.org/espi") - public String getDataCustodianScopeSelectionScreenURI() { return dataCustodianScopeSelectionScreenURI; } - - @XmlElement(name = "thirdPartyLoginScreenURI", namespace = "http://naesb.org/espi") - public String getThirdPartyLoginScreenURI() { return thirdPartyLoginScreenURI; } - - @XmlElement(name = "thirdPartyNotifyURI", namespace = "http://naesb.org/espi") - public String getThirdPartyNotifyURI() { return thirdPartyNotifyURI; } - - @XmlElement(name = "authorizationServerUri", namespace = "http://naesb.org/espi") - public String getAuthorizationServerUri() { return authorizationServerUri; } - - @XmlElement(name = "thirdPartyApplicationName", namespace = "http://naesb.org/espi") - public String getThirdPartyApplicationName() { return thirdPartyApplicationName; } - - @XmlElement(name = "client_name", namespace = "http://naesb.org/espi") - public String getClientName() { return clientName; } - - @XmlElement(name = "client_id", namespace = "http://naesb.org/espi") - public String getClientId() { return clientId; } - + + @XmlElement(name = "dataCustodianBulkRequestURI", namespace = "http://naesb.org/espi") + public String getDataCustodianBulkRequestURI() { return dataCustodianBulkRequestURI; } + + @XmlElement(name = "dataCustodianResourceEndpoint", namespace = "http://naesb.org/espi") + public String getDataCustodianResourceEndpoint() { return dataCustodianResourceEndpoint; } + + @XmlElement(name = "thirdPartyScopeSelectionScreenURI", namespace = "http://naesb.org/espi") + public String getThirdPartyScopeSelectionScreenURI() { return thirdPartyScopeSelectionScreenURI; } + + @XmlElement(name = "thirdPartyUserPortalScreenURI", namespace = "http://naesb.org/espi") + public String getThirdPartyUserPortalScreenURI() { return thirdPartyUserPortalScreenURI; } + @XmlElement(name = "client_secret", namespace = "http://naesb.org/espi") public String getClientSecret() { return clientSecret; } - - @XmlElement(name = "client_id_issued_at", namespace = "http://naesb.org/espi") - public Long getClientIdIssuedAt() { return clientIdIssuedAt; } - - @XmlElement(name = "client_secret_expires_at", namespace = "http://naesb.org/espi") - public Long getClientSecretExpiresAt() { return clientSecretExpiresAt; } - - @XmlElement(name = "contacts", namespace = "http://naesb.org/espi") - public String getContacts() { return contacts; } - - @XmlElement(name = "client_uri", namespace = "http://naesb.org/espi") - public String getClientUri() { return clientUri; } - + @XmlElement(name = "logo_uri", namespace = "http://naesb.org/espi") public String getLogoUri() { return logoUri; } - - @XmlElement(name = "policy_uri", namespace = "http://naesb.org/espi") - public String getPolicyUri() { return policyUri; } - + + @XmlElement(name = "client_name", namespace = "http://naesb.org/espi") + public String getClientName() { return clientName; } + + @XmlElement(name = "client_uri", namespace = "http://naesb.org/espi") + public String getClientUri() { return clientUri; } + @XmlElement(name = "redirect_uri", namespace = "http://naesb.org/espi") public String getRedirectUri() { return redirectUri; } - + + @XmlElement(name = "client_id", namespace = "http://naesb.org/espi") + public String getClientId() { return clientId; } + + @XmlElement(name = "tos_uri", namespace = "http://naesb.org/espi") + public String getTosUri() { return tosUri; } + + @XmlElement(name = "policy_uri", namespace = "http://naesb.org/espi") + public String getPolicyUri() { return policyUri; } + @XmlElement(name = "software_id", namespace = "http://naesb.org/espi") public String getSoftwareId() { return softwareId; } - + @XmlElement(name = "software_version", namespace = "http://naesb.org/espi") public String getSoftwareVersion() { return softwareVersion; } - + + @XmlElement(name = "client_id_issued_at", namespace = "http://naesb.org/espi") + public Long getClientIdIssuedAt() { return clientIdIssuedAt; } + + @XmlElement(name = "client_secret_expires_at", namespace = "http://naesb.org/espi") + public Long getClientSecretExpiresAt() { return clientSecretExpiresAt; } + + @XmlElement(name = "contacts", namespace = "http://naesb.org/espi") + public String getContacts() { return contacts; } + @XmlElement(name = "token_endpoint_auth_method", namespace = "http://naesb.org/espi") public String getTokenEndpointAuthMethod() { return tokenEndpointAuthMethod; } - - @XmlElement(name = "response_type", namespace = "http://naesb.org/espi") - public String getResponseType() { return responseType; } - - @XmlElement(name = "registration_access_token", namespace = "http://naesb.org/espi") - public String getRegistrationAccessToken() { return registrationAccessToken; } - - @XmlElement(name = "registration_client_uri", namespace = "http://naesb.org/espi") - public String getRegistrationClientUri() { return registrationClientUri; } - - @XmlElement(name = "grant_types", namespace = "http://naesb.org/espi") - public String getGrantTypes() { return grantTypes; } - + @XmlElement(name = "scope", namespace = "http://naesb.org/espi") public String getScopes() { return scopes; } -} \ No newline at end of file + + @XmlElement(name = "grant_types", namespace = "http://naesb.org/espi") + public String getGrantTypes() { return grantTypes; } + + @XmlElement(name = "response_types", namespace = "http://naesb.org/espi") + public String getResponseTypes() { return responseTypes; } + + @XmlElement(name = "registration_client_uri", namespace = "http://naesb.org/espi") + public String getRegistrationClientUri() { return registrationClientUri; } + + @XmlElement(name = "registration_access_token", namespace = "http://naesb.org/espi") + public String getRegistrationAccessToken() { return registrationAccessToken; } + + @XmlElement(name = "dataCustodianScopeSelectionScreenURI", namespace = "http://naesb.org/espi") + public String getDataCustodianScopeSelectionScreenURI() { return dataCustodianScopeSelectionScreenURI; } +} diff --git a/openespi-common/src/main/java/org/greenbuttonalliance/espi/common/mapper/usage/ApplicationInformationMapper.java b/openespi-common/src/main/java/org/greenbuttonalliance/espi/common/mapper/usage/ApplicationInformationMapper.java index 74e84b07..22774784 100644 --- a/openespi-common/src/main/java/org/greenbuttonalliance/espi/common/mapper/usage/ApplicationInformationMapper.java +++ b/openespi-common/src/main/java/org/greenbuttonalliance/espi/common/mapper/usage/ApplicationInformationMapper.java @@ -29,9 +29,11 @@ /** * MapStruct mapper for converting between ApplicationInformationEntity and ApplicationInformationDto. - * - * Handles the conversion between the JPA entity used for persistence and the DTO + * + * Handles the conversion between the JPA entity used for persistence and the DTO * used for JAXB XML marshalling in the Green Button API. + * + * Field mappings match ESPI 4.0 XSD schema sequence (espi.xsd lines 62-246). */ @Mapper(componentModel = "spring", uses = { DateTimeMapper.class, @@ -42,51 +44,54 @@ public interface ApplicationInformationMapper { /** * Converts an ApplicationInformationEntity to an ApplicationInformationDto. * Maps all OAuth 2.0 application registration fields for XML marshalling. - * + * * @param entity the application information entity * @return the application information DTO */ @Mapping(target = "uuid", source = "id", qualifiedByName = "uuidToString") - @Mapping(target = "dataCustodianBulkRequestURI", source = "dataCustodianBulkRequestURI") - @Mapping(target = "dataCustodianResourceEndpoint", source = "dataCustodianResourceEndpoint") + // XSD fields in order + @Mapping(target = "dataCustodianId", source = "dataCustodianId") @Mapping(target = "dataCustodianApplicationStatus", source = "dataCustodianApplicationStatus") @Mapping(target = "thirdPartyApplicationDescription", source = "thirdPartyApplicationDescription") @Mapping(target = "thirdPartyApplicationStatus", source = "thirdPartyApplicationStatus") @Mapping(target = "thirdPartyApplicationType", source = "thirdPartyApplicationType") @Mapping(target = "thirdPartyApplicationUse", source = "thirdPartyApplicationUse") @Mapping(target = "thirdPartyPhone", source = "thirdPartyPhone") + @Mapping(target = "authorizationServerUri", source = "authorizationServerUri") + @Mapping(target = "thirdPartyNotifyURI", source = "thirdPartyNotifyUri") @Mapping(target = "authorizationServerAuthorizationEndpoint", source = "authorizationServerAuthorizationEndpoint") @Mapping(target = "authorizationServerRegistrationEndpoint", source = "authorizationServerRegistrationEndpoint") @Mapping(target = "authorizationServerTokenEndpoint", source = "authorizationServerTokenEndpoint") - @Mapping(target = "dataCustodianScopeSelectionScreenURI", source = "dataCustodianScopeSelectionScreenURI") - @Mapping(target = "thirdPartyLoginScreenURI", source = "thirdPartyLoginScreenURI") - @Mapping(target = "thirdPartyNotifyURI", source = "thirdPartyNotifyUri") - @Mapping(target = "authorizationServerUri", source = "authorizationServerUri") - @Mapping(target = "thirdPartyApplicationName", source = "thirdPartyApplicationName") - @Mapping(target = "clientName", source = "clientName") - @Mapping(target = "clientId", source = "clientId") + @Mapping(target = "dataCustodianBulkRequestURI", source = "dataCustodianBulkRequestURI") + @Mapping(target = "dataCustodianResourceEndpoint", source = "dataCustodianResourceEndpoint") + @Mapping(target = "thirdPartyScopeSelectionScreenURI", source = "thirdPartyScopeSelectionScreenURI") + @Mapping(target = "thirdPartyUserPortalScreenURI", source = "thirdPartyUserPortalScreenURI") @Mapping(target = "clientSecret", source = "clientSecret") - @Mapping(target = "clientIdIssuedAt", source = "clientIdIssuedAt") - @Mapping(target = "clientSecretExpiresAt", source = "clientSecretExpiresAt") - @Mapping(target = "contacts", source = "contacts") - @Mapping(target = "clientUri", source = "clientUri") @Mapping(target = "logoUri", source = "logoUri") - @Mapping(target = "policyUri", source = "policyUri") + @Mapping(target = "clientName", source = "clientName") + @Mapping(target = "clientUri", source = "clientUri") @Mapping(target = "redirectUri", source = "redirectUri") + @Mapping(target = "clientId", source = "clientId") + @Mapping(target = "tosUri", source = "tosUri") + @Mapping(target = "policyUri", source = "policyUri") @Mapping(target = "softwareId", source = "softwareId") @Mapping(target = "softwareVersion", source = "softwareVersion") + @Mapping(target = "clientIdIssuedAt", source = "clientIdIssuedAt") + @Mapping(target = "clientSecretExpiresAt", source = "clientSecretExpiresAt") + @Mapping(target = "contacts", source = "contacts") @Mapping(target = "tokenEndpointAuthMethod", source = "tokenEndpointAuthMethod") - @Mapping(target = "responseType", source = "responseTypes") - @Mapping(target = "registrationAccessToken", source = "registrationAccessToken") + @Mapping(target = "scopes", ignore = true) // Complex type conversion needed: Set -> String + @Mapping(target = "grantTypes", ignore = true) // Complex type conversion needed: Set -> String + @Mapping(target = "responseTypes", source = "responseTypes") @Mapping(target = "registrationClientUri", source = "registrationClientUri") - @Mapping(target = "grantTypes", ignore = true) // Complex type conversion needed - @Mapping(target = "scopes", ignore = true) // Complex type conversion needed + @Mapping(target = "registrationAccessToken", source = "registrationAccessToken") + @Mapping(target = "dataCustodianScopeSelectionScreenURI", source = "dataCustodianScopeSelectionScreenURI") ApplicationInformationDto toDto(ApplicationInformationEntity entity); /** * Converts an ApplicationInformationDto to an ApplicationInformationEntity. * Maps all OAuth 2.0 application registration fields for persistence. - * + * * @param dto the application information DTO * @return the application information entity */ @@ -95,17 +100,18 @@ public interface ApplicationInformationMapper { @Mapping(target = "published", ignore = true) @Mapping(target = "updated", ignore = true) @Mapping(target = "description", ignore = true) - @Mapping(target = "grantTypes", ignore = true) // Complex type conversion needed - @Mapping(target = "scope", ignore = true) // Complex type conversion needed @Mapping(target = "relatedLinks", ignore = true) @Mapping(target = "selfLink", ignore = true) @Mapping(target = "upLink", ignore = true) + @Mapping(target = "scope", ignore = true) // Complex type conversion needed: String -> Set + @Mapping(target = "grantTypes", ignore = true) // Complex type conversion needed: String -> Set + @Mapping(target = "relatedLinkHrefs", ignore = true) // Extension field not in ESPI 4.0 XSD ApplicationInformationEntity toEntity(ApplicationInformationDto dto); /** * Updates an existing ApplicationInformationEntity with data from an ApplicationInformationDto. * Useful for merge operations where the entity ID should be preserved. - * + * * @param dto the source DTO * @param entity the target entity to update */ @@ -114,10 +120,11 @@ public interface ApplicationInformationMapper { @Mapping(target = "updated", ignore = true) @Mapping(target = "created", ignore = true) @Mapping(target = "description", ignore = true) - @Mapping(target = "grantTypes", ignore = true) // Complex type conversion needed - @Mapping(target = "scope", ignore = true) // Complex type conversion needed @Mapping(target = "relatedLinks", ignore = true) @Mapping(target = "selfLink", ignore = true) @Mapping(target = "upLink", ignore = true) + @Mapping(target = "scope", ignore = true) // Complex type conversion needed: String -> Set + @Mapping(target = "grantTypes", ignore = true) // Complex type conversion needed: String -> Set + @Mapping(target = "relatedLinkHrefs", ignore = true) // Extension field not in ESPI 4.0 XSD void updateEntity(ApplicationInformationDto dto, @MappingTarget ApplicationInformationEntity entity); -} \ No newline at end of file +} diff --git a/openespi-common/src/main/java/org/greenbuttonalliance/espi/common/repositories/usage/ApplicationInformationRepository.java b/openespi-common/src/main/java/org/greenbuttonalliance/espi/common/repositories/usage/ApplicationInformationRepository.java index 2f16d1d2..bb67bdde 100755 --- a/openespi-common/src/main/java/org/greenbuttonalliance/espi/common/repositories/usage/ApplicationInformationRepository.java +++ b/openespi-common/src/main/java/org/greenbuttonalliance/espi/common/repositories/usage/ApplicationInformationRepository.java @@ -48,12 +48,6 @@ public interface ApplicationInformationRepository extends JpaRepository findByDataCustodianId(@Param("dataCustodianId") String dataCustodianId); - /** - * Find all application information by kind. - */ - @Query("SELECT ai FROM ApplicationInformationEntity ai WHERE ai.kind = :kind") - List findByKind(@Param("kind") String kind); - /** * Find all application information IDs. */ diff --git a/openespi-common/src/main/java/org/greenbuttonalliance/espi/common/service/ApplicationInformationService.java b/openespi-common/src/main/java/org/greenbuttonalliance/espi/common/service/ApplicationInformationService.java index de1e5ab4..88ab2fa5 100755 --- a/openespi-common/src/main/java/org/greenbuttonalliance/espi/common/service/ApplicationInformationService.java +++ b/openespi-common/src/main/java/org/greenbuttonalliance/espi/common/service/ApplicationInformationService.java @@ -26,14 +26,6 @@ public interface ApplicationInformationService { - /** - * @param kind - * String indicating [ DATA_CUSTODIAN_ADMIN | THIRD_PARTY | - * UPLOAD_ADMIN ] - * @return List of ApplicationInformationEntity Resources - */ - public List findByKind(String kind); - /** * Find an ApplicationInformationEntity resource by using it's clientId. * diff --git a/openespi-common/src/main/java/org/greenbuttonalliance/espi/common/service/impl/ApplicationInformationServiceImpl.java b/openespi-common/src/main/java/org/greenbuttonalliance/espi/common/service/impl/ApplicationInformationServiceImpl.java index 56ec2d5b..c0f70295 100755 --- a/openespi-common/src/main/java/org/greenbuttonalliance/espi/common/service/impl/ApplicationInformationServiceImpl.java +++ b/openespi-common/src/main/java/org/greenbuttonalliance/espi/common/service/impl/ApplicationInformationServiceImpl.java @@ -31,8 +31,6 @@ import org.springframework.util.Assert; import java.io.InputStream; -import java.util.ArrayList; -import java.util.List; import java.util.Optional; @Slf4j @@ -47,14 +45,6 @@ public class ApplicationInformationServiceImpl implements private final ApplicationInformationRepository applicationInformationRepository; private final ApplicationInformationMapper applicationInformationMapper; - @Override - public List findByKind(String kind) { - // Use repository to find by kind - this would need a custom query - log.info("Finding ApplicationInformation entities by kind: " + kind); - // TODO: Add repository method findByKind if needed - return new ArrayList<>(); - } - @Override public ApplicationInformationEntity findByClientId(String clientId) { Assert.notNull(clientId, "clientID is required"); diff --git a/openespi-common/src/main/resources/db/migration/V4__Drop_ApplicationInformation_Extension_Columns.sql b/openespi-common/src/main/resources/db/migration/V4__Drop_ApplicationInformation_Extension_Columns.sql new file mode 100644 index 00000000..5f3d5143 --- /dev/null +++ b/openespi-common/src/main/resources/db/migration/V4__Drop_ApplicationInformation_Extension_Columns.sql @@ -0,0 +1,42 @@ +-- ========================================================================================================== +-- V4__Drop_ApplicationInformation_Extension_Columns.sql +-- +-- Purpose: Remove extension columns from application_information table that are not in ESPI 4.0 XSD schema. +-- This migration aligns the database schema with the espi.xsd ApplicationInformation definition. +-- +-- BREAKING CHANGE WARNING: +-- This migration PERMANENTLY deletes columns and data. Applications using these fields will break. +-- Extension fields removed: +-- 1. kind +-- 2. data_custodian_default_batch_resource +-- 3. data_custodian_default_subscription_resource +-- 4. data_custodian_third_party_selection_screen_uri +-- 5. third_party_data_custodian_selection_screen_uri +-- 6. third_party_login_screen_uri +-- 7. third_party_application_name +-- +-- Related: ApplicationInformationEntity.java and ApplicationInformationDto.java have been updated to +-- match XSD field sequence and remove extension fields. +-- +-- Author: Claude Code (feature/fix-ApplicationInformation-structure) +-- Date: 2025-12-17 +-- ========================================================================================================== + +-- Drop extension columns from application_information table +-- Each column is dropped in a separate ALTER TABLE statement for H2 compatibility + +ALTER TABLE application_information DROP COLUMN IF EXISTS kind; + +ALTER TABLE application_information DROP COLUMN IF EXISTS data_custodian_default_batch_resource; + +ALTER TABLE application_information DROP COLUMN IF EXISTS data_custodian_default_subscription_resource; + +ALTER TABLE application_information DROP COLUMN IF EXISTS data_custodian_third_party_selection_screen_uri; + +ALTER TABLE application_information DROP COLUMN IF EXISTS third_party_data_custodian_selection_screen_uri; + +ALTER TABLE application_information DROP COLUMN IF EXISTS third_party_login_screen_uri; + +ALTER TABLE application_information DROP COLUMN IF EXISTS third_party_application_name; + +-- Note: All remaining columns match ESPI 4.0 XSD schema ApplicationInformation sequence (espi.xsd lines 62-246) \ No newline at end of file diff --git a/openespi-common/src/test/java/org/greenbuttonalliance/espi/common/repositories/usage/ApplicationInformationRepositoryTest.java b/openespi-common/src/test/java/org/greenbuttonalliance/espi/common/repositories/usage/ApplicationInformationRepositoryTest.java index 210d1f7c..12224b89 100644 --- a/openespi-common/src/test/java/org/greenbuttonalliance/espi/common/repositories/usage/ApplicationInformationRepositoryTest.java +++ b/openespi-common/src/test/java/org/greenbuttonalliance/espi/common/repositories/usage/ApplicationInformationRepositoryTest.java @@ -56,9 +56,7 @@ private ApplicationInformationEntity createValidApplicationInformation() { app.setDescription("Test Application Information"); app.setClientId(faker.internet().uuid().substring(0, 32)); // Valid length app.setClientSecret(faker.internet().password()); - app.setThirdPartyApplicationName("Test Application"); app.setDataCustodianId("test-datacustodian-" + faker.number().digits(8)); - app.setKind("WEB_APPLICATION"); app.setThirdPartyApplicationStatus("ACTIVE"); app.setDataCustodianApplicationStatus("APPROVED"); app.setAuthorizationServerUri("https://auth.example.com"); @@ -106,7 +104,6 @@ void shouldSaveAndRetrieveApplicationInformationSuccessfully() { assertThat(retrieved).isPresent(); assertThat(retrieved.get().getDescription()).isEqualTo("Test Application for CRUD"); assertThat(retrieved.get().getClientId()).isEqualTo(app.getClientId()); - assertThat(retrieved.get().getThirdPartyApplicationName()).isEqualTo("Test Application"); } @Test @@ -253,36 +250,6 @@ void shouldFindApplicationInformationByDataCustodianId() { assertThat(result.get().getDescription()).isEqualTo("Application with Specific Data Custodian ID"); } - @Test - @DisplayName("Should find all application information by kind") - void shouldFindAllApplicationInformationByKind() { - // Arrange - String kind = "MOBILE_APPLICATION"; - ApplicationInformationEntity app1 = createValidApplicationInformation(); - app1.setKind(kind); - app1.setDescription("Mobile App 1"); - - ApplicationInformationEntity app2 = createValidApplicationInformation(); - app2.setKind(kind); - app2.setDescription("Mobile App 2"); - - ApplicationInformationEntity app3 = createValidApplicationInformation(); - app3.setKind("WEB_APPLICATION"); - app3.setDescription("Web App"); - - applicationInformationRepository.saveAll(List.of(app1, app2, app3)); - flushAndClear(); - - // Act - List results = applicationInformationRepository.findByKind(kind); - - // Assert - assertThat(results).hasSize(2); - assertThat(results).extracting(ApplicationInformationEntity::getKind).containsOnly(kind); - assertThat(results).extracting(ApplicationInformationEntity::getDescription) - .contains("Mobile App 1", "Mobile App 2"); - } - @Test @DisplayName("Should find all application information IDs") void shouldFindAllApplicationInformationIds() { @@ -389,7 +356,6 @@ void shouldHandleEmptyResultsGracefully() { // Act & Assert assertThat(applicationInformationRepository.findByClientId("nonexistent-client")).isEmpty(); assertThat(applicationInformationRepository.findByDataCustodianId("nonexistent-datacustodian")).isEmpty(); - assertThat(applicationInformationRepository.findByKind("NONEXISTENT_KIND")).isEmpty(); assertThat(applicationInformationRepository.findByThirdPartyApplicationStatus("NONEXISTENT_STATUS")).isEmpty(); assertThat(applicationInformationRepository.findByDataCustodianApplicationStatus("NONEXISTENT_STATUS")).isEmpty(); assertThat(applicationInformationRepository.existsByClientId("nonexistent-client")).isFalse(); @@ -468,22 +434,6 @@ void shouldValidateClientIdConstraints() { .contains("clientId"); } - @Test - @DisplayName("Should validate third party application name constraints") - void shouldValidateThirdPartyApplicationNameConstraints() { - // Arrange - ApplicationInformationEntity app = createValidApplicationInformation(); - app.setThirdPartyApplicationName(""); // Empty - - // Act - Set> violations = validator.validate(app); - - // Assert - assertThat(violations).isNotEmpty(); - assertThat(violations).extracting(ConstraintViolation::getPropertyPath) - .extracting(Object::toString) - .contains("thirdPartyApplicationName"); - } } @Nested @@ -579,7 +529,6 @@ void shouldValidateRequiredFields() { // Arrange ApplicationInformationEntity app = new ApplicationInformationEntity(); // Leave required fields null/empty - // Note: thirdPartyApplicationName has a default value, so only clientId will fail validation // Act Set> violations = validator.validate(app); diff --git a/openespi-common/src/test/java/org/greenbuttonalliance/espi/common/repositories/usage/AuthorizationRepositoryTest.java b/openespi-common/src/test/java/org/greenbuttonalliance/espi/common/repositories/usage/AuthorizationRepositoryTest.java index efc3c00b..7a5ea7d3 100644 --- a/openespi-common/src/test/java/org/greenbuttonalliance/espi/common/repositories/usage/AuthorizationRepositoryTest.java +++ b/openespi-common/src/test/java/org/greenbuttonalliance/espi/common/repositories/usage/AuthorizationRepositoryTest.java @@ -97,7 +97,6 @@ private ApplicationInformationEntity createValidApplicationInformation() { app.setDescription("Test Application Information"); app.setClientId("test-client-" + faker.number().digits(8)); app.setClientSecret(faker.internet().password()); - app.setThirdPartyApplicationName("Test Application"); app.setDataCustodianId("test-datacustodian-" + faker.number().digits(8)); Set grantTypes = new HashSet<>(); diff --git a/openespi-common/src/test/java/org/greenbuttonalliance/espi/common/repositories/usage/SubscriptionRepositoryTest.java b/openespi-common/src/test/java/org/greenbuttonalliance/espi/common/repositories/usage/SubscriptionRepositoryTest.java index b9fbeeff..c372c8d7 100644 --- a/openespi-common/src/test/java/org/greenbuttonalliance/espi/common/repositories/usage/SubscriptionRepositoryTest.java +++ b/openespi-common/src/test/java/org/greenbuttonalliance/espi/common/repositories/usage/SubscriptionRepositoryTest.java @@ -83,14 +83,7 @@ private ApplicationInformationEntity createValidApplicationInformation() { app.setClientId(clientId); app.setClientSecret(faker.internet().password()); - - // Ensure thirdPartyApplicationName meets validation constraints (@NotEmpty, 2-64 chars) - String appName = "Test Application " + faker.number().digits(4); - if (appName.length() > 64) { - appName = appName.substring(0, 64); - } - app.setThirdPartyApplicationName(appName); - + // Ensure dataCustodianId meets validation constraints (2-64 chars if present) String dataCustodianId = "test-datacustodian-" + faker.number().digits(6); if (dataCustodianId.length() > 64) { diff --git a/openespi-common/src/test/java/org/greenbuttonalliance/espi/common/test/TestDataBuilders.java b/openespi-common/src/test/java/org/greenbuttonalliance/espi/common/test/TestDataBuilders.java index 9ee14db0..54d32b93 100644 --- a/openespi-common/src/test/java/org/greenbuttonalliance/espi/common/test/TestDataBuilders.java +++ b/openespi-common/src/test/java/org/greenbuttonalliance/espi/common/test/TestDataBuilders.java @@ -268,14 +268,7 @@ public static ApplicationInformationEntity createValidApplicationInformation() { app.setClientId(clientId); app.setClientSecret(faker.internet().password()); - - // Ensure thirdPartyApplicationName meets validation constraints (@NotEmpty, 2-64 chars) - String appName = "Test Application " + faker.number().digits(4); - if (appName.length() > 64) { - appName = appName.substring(0, 64); - } - app.setThirdPartyApplicationName(appName); - + // Ensure dataCustodianId meets validation constraints (2-64 chars if present) String dataCustodianId = "test-datacustodian-" + faker.number().digits(6); if (dataCustodianId.length() > 64) { diff --git a/openespi-datacustodian/src/main/java/org/greenbuttonalliance/espi/datacustodian/web/customer/ThirdPartyController.java b/openespi-datacustodian/src/main/java/org/greenbuttonalliance/espi/datacustodian/web/customer/ThirdPartyController.java index 9c49156b..206271ed 100644 --- a/openespi-datacustodian/src/main/java/org/greenbuttonalliance/espi/datacustodian/web/customer/ThirdPartyController.java +++ b/openespi-datacustodian/src/main/java/org/greenbuttonalliance/espi/datacustodian/web/customer/ThirdPartyController.java @@ -30,6 +30,8 @@ import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; +import java.util.Collections; + // @Controller - COMMENTED OUT: UI not needed in resource server // @Component @RequestMapping("/RetailCustomer/{retailCustomerId}/ThirdPartyList") @@ -40,8 +42,10 @@ public class ThirdPartyController { @GetMapping public String index(ModelMap model) { - model.put("applicationInformationList", - applicationInformationService.findByKind("THIRD_PARTY")); + // NOTE: findByKind() removed - extension field not in ESPI 4.0 XSD + // Controller is disabled anyway (UI not needed in resource server) + // Service doesn't have findAll() method, return empty list + model.put("applicationInformationList", Collections.emptyList()); return "/customer/thirdparties/index"; }