diff --git a/src/main/java/org/eclipse/tractusx/managedidentitywallets/config/ExceptionHandling.java b/src/main/java/org/eclipse/tractusx/managedidentitywallets/config/ExceptionHandling.java index 38d016213..5eb33d328 100644 --- a/src/main/java/org/eclipse/tractusx/managedidentitywallets/config/ExceptionHandling.java +++ b/src/main/java/org/eclipse/tractusx/managedidentitywallets/config/ExceptionHandling.java @@ -21,10 +21,7 @@ package org.eclipse.tractusx.managedidentitywallets.config; -import org.eclipse.tractusx.managedidentitywallets.exception.BadDataException; -import org.eclipse.tractusx.managedidentitywallets.exception.DuplicateWalletProblem; -import org.eclipse.tractusx.managedidentitywallets.exception.ForbiddenException; -import org.eclipse.tractusx.managedidentitywallets.exception.WalletNotFoundProblem; +import org.eclipse.tractusx.managedidentitywallets.exception.*; import org.springframework.http.HttpStatus; import org.springframework.http.ProblemDetail; import org.springframework.web.bind.annotation.ExceptionHandler; @@ -99,4 +96,18 @@ ProblemDetail handleBadDataException(BadDataException e) { return problemDetail; } + /** + * Handle duplicate credential problem problem detail. + * + * @param e the e + * @return the problem detail + */ + @ExceptionHandler(DuplicateCredentialProblem.class) + ProblemDetail handleDuplicateCredentialProblem(DuplicateCredentialProblem e) { + ProblemDetail problemDetail = ProblemDetail.forStatusAndDetail(HttpStatus.CONFLICT, e.getMessage()); + problemDetail.setTitle(e.getMessage()); + problemDetail.setProperty(TIMESTAMP, System.currentTimeMillis()); + return problemDetail; + } + } diff --git a/src/main/java/org/eclipse/tractusx/managedidentitywallets/config/security/SecurityConfig.java b/src/main/java/org/eclipse/tractusx/managedidentitywallets/config/security/SecurityConfig.java index 635939839..6c5d1f10c 100644 --- a/src/main/java/org/eclipse/tractusx/managedidentitywallets/config/security/SecurityConfig.java +++ b/src/main/java/org/eclipse/tractusx/managedidentitywallets/config/security/SecurityConfig.java @@ -75,6 +75,7 @@ public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { .requestMatchers(new AntPathRequestMatcher(RestURI.API_WALLETS_IDENTIFIER, GET.name())).hasAnyRole(ApplicationConstant.ROLE_VIEW_WALLET, ApplicationConstant.ROLE_VIEW_WALLETS) //get wallet by BPN .requestMatchers(new AntPathRequestMatcher(RestURI.API_WALLETS_IDENTIFIER_CREDENTIALS, POST.name())).hasAnyRole(ApplicationConstant.ROLE_VIEW_WALLET, ApplicationConstant.ROLE_VIEW_WALLETS) //Store credential .requestMatchers(new AntPathRequestMatcher(RestURI.CREDENTIALS, GET.name())).hasAnyRole(ApplicationConstant.ROLE_VIEW_WALLET, ApplicationConstant.ROLE_VIEW_WALLETS) //get credentials + .requestMatchers(new AntPathRequestMatcher(RestURI.CREDENTIALS_ISSUER_MEMBERSHIP, POST.name())).hasAnyRole(ApplicationConstant.ROLE_UPDATE_WALLETS, ApplicationConstant.ROLE_UPDATE_WALLET, ApplicationConstant.ROLE_VIEW_WALLETS) //issue Membership Credential .requestMatchers(new AntPathRequestMatcher("/error")).permitAll() .and().oauth2ResourceServer() .jwt() diff --git a/src/main/java/org/eclipse/tractusx/managedidentitywallets/constant/ApplicationConstant.java b/src/main/java/org/eclipse/tractusx/managedidentitywallets/constant/ApplicationConstant.java index a1abb8735..048d9b4d6 100644 --- a/src/main/java/org/eclipse/tractusx/managedidentitywallets/constant/ApplicationConstant.java +++ b/src/main/java/org/eclipse/tractusx/managedidentitywallets/constant/ApplicationConstant.java @@ -55,8 +55,14 @@ private ApplicationConstant() { public static final String ROLE_UPDATE_WALLET = "update_wallet"; + /** + * The constant DID. + */ public static final String DID = "did"; + /** + * The constant BPN. + */ public static final String BPN = "bpn"; diff --git a/src/main/java/org/eclipse/tractusx/managedidentitywallets/constant/RestURI.java b/src/main/java/org/eclipse/tractusx/managedidentitywallets/constant/RestURI.java index b6723b1d1..2bf30fc1e 100644 --- a/src/main/java/org/eclipse/tractusx/managedidentitywallets/constant/RestURI.java +++ b/src/main/java/org/eclipse/tractusx/managedidentitywallets/constant/RestURI.java @@ -44,7 +44,17 @@ private RestURI() { */ public static final String API_WALLETS_IDENTIFIER = "/api/wallets/{identifier}"; + /** + * The constant API_WALLETS_IDENTIFIER_CREDENTIALS. + */ public static final String API_WALLETS_IDENTIFIER_CREDENTIALS = "/api/wallets/{identifier}/credentials"; + /** + * The constant CREDENTIALS. + */ public static final String CREDENTIALS = "/api/credentials"; + /** + * The constant CREDENTIALS_ISSUER_MEMBERSHIP. + */ + public static final String CREDENTIALS_ISSUER_MEMBERSHIP = "/api/credentials/issuer/membership"; } diff --git a/src/main/java/org/eclipse/tractusx/managedidentitywallets/controller/CredentialController.java b/src/main/java/org/eclipse/tractusx/managedidentitywallets/controller/CredentialController.java index 08d2c049c..0504bf925 100644 --- a/src/main/java/org/eclipse/tractusx/managedidentitywallets/controller/CredentialController.java +++ b/src/main/java/org/eclipse/tractusx/managedidentitywallets/controller/CredentialController.java @@ -23,19 +23,23 @@ import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.validation.Valid; import lombok.RequiredArgsConstructor; import org.eclipse.tractusx.managedidentitywallets.constant.RestURI; import org.eclipse.tractusx.managedidentitywallets.dao.entity.Credential; +import org.eclipse.tractusx.managedidentitywallets.dto.IssueMembershipCredentialRequest; import org.eclipse.tractusx.managedidentitywallets.service.CredentialService; +import org.eclipse.tractusx.ssi.lib.model.verifiable.credential.VerifiableCredential; import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.RequestParam; -import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.bind.annotation.*; import java.util.List; +/** + * The type Credential controller. + */ @RestController @RequiredArgsConstructor @Tag(name = "VerifiableCredentials") @@ -43,9 +47,30 @@ public class CredentialController { private final CredentialService service; + /** + * Gets credentials. + * + * @param holderIdentifier the holder identifier + * @param id the id + * @param issuerIdentifier the issuer identifier + * @param type the type + * @return the credentials + */ @Operation(description = "Permission: **view_wallets** OR **view_wallet** (The BPN of holderIdentifier must equal BPN of caller)\n\n Search verifiable credentials with filter criteria", summary = "Query Verifiable Credentials") @GetMapping(path = RestURI.CREDENTIALS, produces = MediaType.APPLICATION_JSON_VALUE) public ResponseEntity> getCredentials(@RequestParam(required = false) String holderIdentifier, @RequestParam(required = false) String id, @RequestParam(required = false) String issuerIdentifier, @RequestParam(required = false) List type) { return ResponseEntity.status(HttpStatus.OK).body(service.getCredentials(holderIdentifier, id, issuerIdentifier, type)); } + + /** + * Issue membership credential response entity. + * + * @param issueMembershipCredentialRequest the issue membership credential request + * @return the response entity + */ + @Operation(summary = "Issue a Membership Verifiable Credential with base wallet issuer", description = "Permission: **update_wallets** OR **update_wallet** (The BPN of base wallet must equal BPN of caller)\n\n Issue a verifiable credential by base wallet") + @PostMapping(path = RestURI.CREDENTIALS_ISSUER_MEMBERSHIP, consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE) + public ResponseEntity issueMembershipCredential(@Valid @RequestBody IssueMembershipCredentialRequest issueMembershipCredentialRequest) { + return ResponseEntity.status(HttpStatus.CREATED).body(service.issueMembershipCredential(issueMembershipCredentialRequest)); + } } diff --git a/src/main/java/org/eclipse/tractusx/managedidentitywallets/controller/WalletController.java b/src/main/java/org/eclipse/tractusx/managedidentitywallets/controller/WalletController.java index 41546dd51..515a7a0d2 100644 --- a/src/main/java/org/eclipse/tractusx/managedidentitywallets/controller/WalletController.java +++ b/src/main/java/org/eclipse/tractusx/managedidentitywallets/controller/WalletController.java @@ -62,8 +62,8 @@ public ResponseEntity createWallet(@Valid @RequestBody CreateWalletReque /** * Store credential response entity. * - * @param data the data - * @param bpn the bpn + * @param data the data + * @param identifier the identifier * @return the response entity */ @Operation(summary = "Store Verifiable Credential", description = "Permission: **update_wallets** OR **update_wallet** (The BPN of wallet to extract credentials from must equal BPN of caller) \n\n Store a verifiable credential in the wallet of the given identifier") @@ -75,7 +75,8 @@ public ResponseEntity> storeCredential(@RequestBody Map verifiableCredentials; + /** + * Sets did. + * + * @param did the did + */ public void setDid(String did) { this.did = URLDecoder.decode(did, Charset.defaultCharset()); } diff --git a/src/main/java/org/eclipse/tractusx/managedidentitywallets/dao/repository/CredentialRepository.java b/src/main/java/org/eclipse/tractusx/managedidentitywallets/dao/repository/CredentialRepository.java index 34136d9a8..8cff4d7c3 100644 --- a/src/main/java/org/eclipse/tractusx/managedidentitywallets/dao/repository/CredentialRepository.java +++ b/src/main/java/org/eclipse/tractusx/managedidentitywallets/dao/repository/CredentialRepository.java @@ -29,9 +29,42 @@ import java.util.List; +/** + * The interface Credential repository. + */ public interface CredentialRepository extends JpaRepository { + /** + * Gets by holder. + * + * @param id the id + * @return the by holder + */ List getByHolder(Long id); + /** + * Gets credentials by holder. + * + * @param holder the holder + * @return the credentials by holder + */ @Query("select data from Credential where holder=:holder") List getCredentialsByHolder(@Param("holder") Long holder); + + /** + * Gets by holder and type. + * + * @param holderWalletId the holder wallet id + * @param type the type + * @return the by holder and type + */ + Credential getByHolderAndType(Long holderWalletId, String type); + + /** + * Exists by holder and type boolean. + * + * @param holderWalletId the holder wallet id + * @param type the type + * @return the boolean + */ + boolean existsByHolderAndType(Long holderWalletId, String type); } diff --git a/src/main/java/org/eclipse/tractusx/managedidentitywallets/dto/IssueMembershipCredentialRequest.java b/src/main/java/org/eclipse/tractusx/managedidentitywallets/dto/IssueMembershipCredentialRequest.java new file mode 100644 index 000000000..e3a37df59 --- /dev/null +++ b/src/main/java/org/eclipse/tractusx/managedidentitywallets/dto/IssueMembershipCredentialRequest.java @@ -0,0 +1,42 @@ +/* + * ******************************************************************************* + * Copyright (c) 2021,2023 Contributors to the Eclipse Foundation + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://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. + * + * SPDX-License-Identifier: Apache-2.0 + * ****************************************************************************** + */ + +package org.eclipse.tractusx.managedidentitywallets.dto; + +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.Size; +import lombok.*; + +/** + * The type Issue membership credential request. + */ +@Getter +@Setter +@NoArgsConstructor +@Builder +@AllArgsConstructor +public class IssueMembershipCredentialRequest { + + @NotBlank + @Size(min = 5, max = 255) + private String bpn; +} + diff --git a/src/main/java/org/eclipse/tractusx/managedidentitywallets/exception/DuplicateCredentialProblem.java b/src/main/java/org/eclipse/tractusx/managedidentitywallets/exception/DuplicateCredentialProblem.java new file mode 100644 index 000000000..b95ed14c3 --- /dev/null +++ b/src/main/java/org/eclipse/tractusx/managedidentitywallets/exception/DuplicateCredentialProblem.java @@ -0,0 +1,63 @@ +/* + * ******************************************************************************* + * Copyright (c) 2021,2023 Contributors to the Eclipse Foundation + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://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. + * + * SPDX-License-Identifier: Apache-2.0 + * ****************************************************************************** + */ + +package org.eclipse.tractusx.managedidentitywallets.exception; + +/** + * The type Duplicate wallet problem. + */ +public class DuplicateCredentialProblem extends RuntimeException { + + /** + * Instantiates a new Duplicate wallet problem. + */ + public DuplicateCredentialProblem() { + } + + /** + * Instantiates a new Duplicate wallet problem. + * + * @param message the message + */ + public DuplicateCredentialProblem(String message) { + super(message); + } + + /** + * Instantiates a new Duplicate wallet problem. + * + * @param message the message + * @param cause the cause + */ + public DuplicateCredentialProblem(String message, Throwable cause) { + super(message, cause); + } + + /** + * Instantiates a new Duplicate wallet problem. + * + * @param cause the cause + */ + public DuplicateCredentialProblem(Throwable cause) { + super(cause); + } + +} diff --git a/src/main/java/org/eclipse/tractusx/managedidentitywallets/service/CredentialService.java b/src/main/java/org/eclipse/tractusx/managedidentitywallets/service/CredentialService.java index ed0fbb63d..ea4b18a15 100644 --- a/src/main/java/org/eclipse/tractusx/managedidentitywallets/service/CredentialService.java +++ b/src/main/java/org/eclipse/tractusx/managedidentitywallets/service/CredentialService.java @@ -22,21 +22,142 @@ package org.eclipse.tractusx.managedidentitywallets.service; import lombok.RequiredArgsConstructor; +import lombok.SneakyThrows; import lombok.extern.slf4j.Slf4j; +import org.bouncycastle.util.io.pem.PemReader; +import org.eclipse.tractusx.managedidentitywallets.config.MIWSettings; import org.eclipse.tractusx.managedidentitywallets.dao.entity.Credential; +import org.eclipse.tractusx.managedidentitywallets.dao.entity.Wallet; +import org.eclipse.tractusx.managedidentitywallets.dao.entity.WalletKey; import org.eclipse.tractusx.managedidentitywallets.dao.repository.CredentialRepository; +import org.eclipse.tractusx.managedidentitywallets.dao.repository.WalletKeyRepository; +import org.eclipse.tractusx.managedidentitywallets.dto.IssueMembershipCredentialRequest; +import org.eclipse.tractusx.managedidentitywallets.exception.DuplicateCredentialProblem; +import org.eclipse.tractusx.managedidentitywallets.utils.EncryptionUtils; +import org.eclipse.tractusx.managedidentitywallets.utils.Validate; +import org.eclipse.tractusx.ssi.lib.model.Ed25519Signature2020; +import org.eclipse.tractusx.ssi.lib.model.verifiable.credential.VerifiableCredential; +import org.eclipse.tractusx.ssi.lib.model.verifiable.credential.VerifiableCredentialBuilder; +import org.eclipse.tractusx.ssi.lib.model.verifiable.credential.VerifiableCredentialSubject; +import org.eclipse.tractusx.ssi.lib.model.verifiable.credential.VerifiableCredentialType; +import org.eclipse.tractusx.ssi.lib.proof.LinkedDataProofGenerator; import org.springframework.stereotype.Service; +import java.io.StringReader; +import java.net.URI; +import java.time.Instant; import java.util.List; +import java.util.Map; +import java.util.UUID; +/** + * The type Credential service. + */ @Service @RequiredArgsConstructor @Slf4j public class CredentialService { - private final CredentialRepository credentialRepositrory; + private final CredentialRepository credentialRepository; + private final MIWSettings miwSettings; + private final WalletKeyRepository walletKeyRepository; + private final EncryptionUtils encryptionUtils; + + private final WalletService walletService; + /** + * Gets credentials. + * + * @param holderIdentifier the holder identifier + * @param id the id + * @param issuerIdentifier the issuer identifier + * @param type the type + * @return the credentials + */ public List getCredentials(String holderIdentifier, String id, String issuerIdentifier, List type) { - return credentialRepositrory.findAll();//TODO with params + return credentialRepository.findAll();//TODO with params + } + + /** + * Issue membership credential verifiable credential. + * + * @param issueMembershipCredentialRequest the issue membership credential request + * @return the verifiable credential + */ + @SneakyThrows + public VerifiableCredential issueMembershipCredential(IssueMembershipCredentialRequest issueMembershipCredentialRequest) { + + //Fetch Holder Wallet + Wallet holderWallet = walletService.getWalletByIdentifier(issueMembershipCredentialRequest.getBpn()); + + //check duplicate + isCredentialExit(holderWallet.getId(), VerifiableCredentialType.MEMBERSHIP_CREDENTIAL); + + // Fetch Issuer Wallet + Wallet baseWallet = walletService.getWalletByIdentifier(miwSettings.authorityWalletBpn()); + byte[] privateKeyBytes = getPrivateKeyById(baseWallet.getId()); + + //VC Subject + VerifiableCredentialSubject verifiableCredentialSubject = + new VerifiableCredentialSubject(Map.of("type", VerifiableCredentialType.MEMBERSHIP_CREDENTIAL, + "holderIdentifier", holderWallet.getBpn(), + "memberOf", baseWallet.getName(), + "status", "Active", + "startTime", Instant.now().toString())); + + // VC Type + List verifiableCredentialType = List.of(VerifiableCredentialType.VERIFIABLE_CREDENTIAL, VerifiableCredentialType.MEMBERSHIP_CREDENTIAL); + + // Create VC + VerifiableCredential verifiableCredential = createVerifiableCredential(baseWallet.getDid(), verifiableCredentialType, verifiableCredentialSubject, privateKeyBytes); + + // Create Credential + Credential credential = Credential.builder() + .holder(holderWallet.getId()) + .issuer(baseWallet.getId()) + .type(VerifiableCredentialType.MEMBERSHIP_CREDENTIAL) + .data(verifiableCredential) + .build(); + + //Store Credential + credentialRepository.save(credential); + + // Return VC + return credential.getData(); + } + + private VerifiableCredential createVerifiableCredential(String issuerDid, List verifiableCredentialType, VerifiableCredentialSubject verifiableCredentialSubject, byte[] privateKey) { + List context = List.of("https://www.w3.org/2018/credentials/v1", "https://raw.githubusercontent.com/catenax-ng/product-core-schemas/main/businessPartnerData"); + //VC Builder + VerifiableCredentialBuilder builder = + new VerifiableCredentialBuilder() + .context(context) + .id(URI.create(UUID.randomUUID().toString())) + .type(verifiableCredentialType) + .issuer(URI.create(issuerDid)) + .expirationDate(Instant.now().plusSeconds(365 * 86400)) //TODO need to verify expiry time + .issuanceDate(Instant.now()) + .credentialSubject(verifiableCredentialSubject); + + //Ed25519 Proof Builder + LinkedDataProofGenerator generator = LinkedDataProofGenerator.create(); + Ed25519Signature2020 proof = generator.createEd25519Signature2020(builder.build(), URI.create(issuerDid + "#key-1"), privateKey); + + //Adding Proof to VC + builder.proof(proof); + + //Create Credential + return builder.build(); + } + + @SneakyThrows + private byte[] getPrivateKeyById(Long id) { + WalletKey baseWalletKey = walletKeyRepository.getByWalletId(id); + String privateKey = encryptionUtils.decrypt(baseWalletKey.getPrivateKey()); + return new PemReader(new StringReader(privateKey)).readPemObject().getContent(); + } + + private void isCredentialExit(Long holderId, String credentialType) { + Validate.isTrue(credentialRepository.existsByHolderAndType(holderId, credentialType)).launch(new DuplicateCredentialProblem("Credential of type " + credentialType + " is already exists ")); } } diff --git a/src/main/java/org/eclipse/tractusx/managedidentitywallets/service/WalletService.java b/src/main/java/org/eclipse/tractusx/managedidentitywallets/service/WalletService.java index 53745998d..e5125a1b1 100644 --- a/src/main/java/org/eclipse/tractusx/managedidentitywallets/service/WalletService.java +++ b/src/main/java/org/eclipse/tractusx/managedidentitywallets/service/WalletService.java @@ -88,8 +88,8 @@ public class WalletService { /** * Store credential map. * - * @param data the data - * @param bpn the bpn + * @param data the data + * @param identifier the identifier * @return the map */ public Map storeCredential(Map data, String identifier) { @@ -218,6 +218,9 @@ public Wallet createWallet(CreateWalletRequest request) { return wallet; } + /** + * Create authority wallet. + */ @PostConstruct public void createAuthorityWallet() { boolean exist = walletRepository.existsByBpn(miwSettings.authorityWalletBpn()); diff --git a/src/main/java/org/eclipse/tractusx/managedidentitywallets/utils/StringToCredentialConverter.java b/src/main/java/org/eclipse/tractusx/managedidentitywallets/utils/StringToCredentialConverter.java index 0485d7a70..84ce2ccd5 100644 --- a/src/main/java/org/eclipse/tractusx/managedidentitywallets/utils/StringToCredentialConverter.java +++ b/src/main/java/org/eclipse/tractusx/managedidentitywallets/utils/StringToCredentialConverter.java @@ -29,10 +29,18 @@ import java.util.Map; +/** + * The type String to credential converter. + */ public class StringToCredentialConverter implements AttributeConverter { private final ObjectMapper objectMapper; + /** + * Instantiates a new String to credential converter. + * + * @param objectMapper the object mapper + */ public StringToCredentialConverter(ObjectMapper objectMapper) { this.objectMapper = objectMapper; } diff --git a/src/main/java/org/eclipse/tractusx/managedidentitywallets/utils/StringToDidDocumentConverter.java b/src/main/java/org/eclipse/tractusx/managedidentitywallets/utils/StringToDidDocumentConverter.java index 43ef157ed..15e9a4a4f 100644 --- a/src/main/java/org/eclipse/tractusx/managedidentitywallets/utils/StringToDidDocumentConverter.java +++ b/src/main/java/org/eclipse/tractusx/managedidentitywallets/utils/StringToDidDocumentConverter.java @@ -24,6 +24,9 @@ import jakarta.persistence.AttributeConverter; import org.eclipse.tractusx.ssi.lib.model.did.DidDocument; +/** + * The type String to did document converter. + */ public class StringToDidDocumentConverter implements AttributeConverter { @Override diff --git a/src/main/java/org/eclipse/tractusx/managedidentitywallets/utils/Validate.java b/src/main/java/org/eclipse/tractusx/managedidentitywallets/utils/Validate.java index c878965d4..a33fb97c7 100644 --- a/src/main/java/org/eclipse/tractusx/managedidentitywallets/utils/Validate.java +++ b/src/main/java/org/eclipse/tractusx/managedidentitywallets/utils/Validate.java @@ -23,6 +23,11 @@ import java.util.Objects; +/** + * The type Validate. + * + * @param the type parameter + */ public class Validate { private T value; private boolean match = false; @@ -65,7 +70,7 @@ public static Validate isTrue(boolean condition) { * * @param the type parameter * @param condition the condition - * @return validate + * @return validate validate */ public static Validate isFalse(boolean condition) { Validate validate = new Validate<>();