package at.gv.egiz.eaaf.modules.auth.sl20.utils; import java.security.cert.CertificateEncodingException; import java.security.cert.X509Certificate; import java.util.Arrays; import java.util.Base64; import java.util.List; import java.util.Map; import java.util.Map.Entry; import com.fasterxml.jackson.databind.node.ArrayNode; import com.fasterxml.jackson.databind.node.ObjectNode; import at.gv.egiz.eaaf.modules.auth.sl20.Constants; import at.gv.egiz.eaaf.modules.auth.sl20.exceptions.SLCommandoBuildException; public class SL20JSONBuilderUtils { private static JsonMapper mapper = new JsonMapper(); /** * Create command request * @param name * @param params * @throws SLCommandoBuildException * @return */ public static ObjectNode createCommand(String name, ObjectNode params) throws SLCommandoBuildException { final ObjectNode command = mapper.getMapper().createObjectNode(); addSingleStringElement(command, SL20Constants.SL20_COMMAND_CONTAINER_NAME, name, true); addSingleJSONElement(command, SL20Constants.SL20_COMMAND_CONTAINER_PARAMS, params, true); return command; } /** * Create signed command request * * @param name * @param params * @param signer * @return * @throws SLCommandoBuildException */ public static String createSignedCommand(String name, ObjectNode params, IJOSETools signer) throws SLCommandoBuildException { final ObjectNode command = mapper.getMapper().createObjectNode(); addSingleStringElement(command, SL20Constants.SL20_COMMAND_CONTAINER_NAME, name, true); addSingleJSONElement(command, SL20Constants.SL20_COMMAND_CONTAINER_PARAMS, params, true); return signer.createSignature(command.toString()); } /** * Create encrypted command result * * @param result * @param encrypter * @return * @throws SLCommandoBuildException */ public static String createEncryptedCommandoResult(ObjectNode result, JsonSecurityUtils encrypter) throws SLCommandoBuildException { //TODO: add real implementation //create header and footer final String dummyHeader = createJsonEncryptionHeader(encrypter).toString(); final String payLoad = result.toString(); final String dummyFooter = createJsonSignedFooter(encrypter); return Base64.getUrlEncoder().encodeToString(dummyHeader.getBytes()) + "." + Base64.getUrlEncoder().encodeToString(payLoad.getBytes()) + "." + Base64.getUrlEncoder().encodeToString(dummyFooter.getBytes()); } /** * Create command result * * @param name * @param result * @param encryptedResult * @throws SLCommandoBuildException * @return */ public static ObjectNode createCommandResponse(String name, ObjectNode result, String encryptedResult) throws SLCommandoBuildException { final ObjectNode command = mapper.getMapper().createObjectNode(); addSingleStringElement(command, SL20Constants.SL20_COMMAND_CONTAINER_NAME, name, true); addOnlyOnceOfTwo(command, SL20Constants.SL20_COMMAND_CONTAINER_RESULT, SL20Constants.SL20_COMMAND_CONTAINER_ENCRYPTEDRESULT, result, encryptedResult); return command; } /** * Create command result * * @param name * @param result * @param encryptedResult * @throws SLCommandoBuildException * @return */ public static String createSignedCommandResponse(String name, ObjectNode result, String encryptedResult, JsonSecurityUtils signer) throws SLCommandoBuildException { final ObjectNode command = mapper.getMapper().createObjectNode(); addSingleStringElement(command, SL20Constants.SL20_COMMAND_CONTAINER_NAME, name, true); addOnlyOnceOfTwo(command, SL20Constants.SL20_COMMAND_CONTAINER_RESULT, SL20Constants.SL20_COMMAND_CONTAINER_ENCRYPTEDRESULT, result, encryptedResult); final String encodedCommand = command.toString(); //TODO: add real implementation //create header and footer final String dummyHeader = createJsonSignedHeader(signer).toString(); final String dummyFooter = createJsonSignedFooter(signer); return Base64.getUrlEncoder().encodeToString(dummyHeader.getBytes()) + "." + Base64.getUrlEncoder().encodeToString(encodedCommand.getBytes()) + "." + Base64.getUrlEncoder().encodeToString(dummyFooter.getBytes()); } /** * Create parameters for Redirect command * * @param url * @param command * @param signedCommand * @param ipcRedirect * @return * @throws SLCommandoBuildException */ public static ObjectNode createRedirectCommandParameters(String url, ObjectNode command, ObjectNode signedCommand, Boolean ipcRedirect) throws SLCommandoBuildException{ final ObjectNode redirectReqParams = mapper.getMapper().createObjectNode(); addOnlyOnceOfTwo(redirectReqParams, SL20Constants.SL20_COMMAND_PARAM_GENERAL_REDIRECT_COMMAND, SL20Constants.SL20_COMMAND_PARAM_GENERAL_REDIRECT_SIGNEDCOMMAND, command, signedCommand); addSingleStringElement(redirectReqParams, SL20Constants.SL20_COMMAND_PARAM_GENERAL_REDIRECT_URL, url, false); addSingleBooleanElement(redirectReqParams, SL20Constants.SL20_COMMAND_PARAM_GENERAL_REDIRECT_IPCREDIRECT, ipcRedirect, false); return redirectReqParams; } /** * Create parameters for Call command * * @param url * @param method * @param includeTransactionId * @param reqParameters * @return * @throws SLCommandoBuildException */ public static ObjectNode createCallCommandParameters(String url, String method, Boolean includeTransactionId, Map reqParameters) throws SLCommandoBuildException { final ObjectNode callReqParams = mapper.getMapper().createObjectNode(); addSingleStringElement(callReqParams, SL20Constants.SL20_COMMAND_PARAM_GENERAL_CALL_URL, url, true); addSingleStringElement(callReqParams, SL20Constants.SL20_COMMAND_PARAM_GENERAL_CALL_METHOD, method, true); addSingleBooleanElement(callReqParams, SL20Constants.SL20_COMMAND_PARAM_GENERAL_CALL_INCLUDETRANSACTIONID, includeTransactionId, false); addArrayOfStringElements(callReqParams, SL20Constants.SL20_COMMAND_PARAM_GENERAL_CALL_REQPARAMETER, reqParameters); return callReqParams; } /** * Create result for Error command * * @param errorCode * @param errorMsg * @return * @throws SLCommandoBuildException */ public static ObjectNode createErrorCommandResult(String errorCode, String errorMsg) throws SLCommandoBuildException { final ObjectNode result = mapper.getMapper().createObjectNode(); addSingleStringElement(result, SL20Constants.SL20_COMMAND_PARAM_GENERAL_RESPONSE_ERRORCODE, errorCode, true); addSingleStringElement(result, SL20Constants.SL20_COMMAND_PARAM_GENERAL_RESPONSE_ERRORMESSAGE, errorMsg, true); return result; } /** * Create parameters for qualifiedeID command * * @param consentTemplateId Identifier of the template that is used for consent visualization * @param consent Consent that has to be signed by user * @param dataUrl * @param additionalReqParameters * @param x5cEnc * @return * @throws CertificateEncodingException * @throws SLCommandoBuildException */ public static ObjectNode createQualifiedeEIDConsent(String consentTemplateId, byte[] consent, String dataUrl, X509Certificate x5cEnc) throws CertificateEncodingException, SLCommandoBuildException { final ObjectNode params = mapper.getMapper().createObjectNode(); addSingleStringElement(params, SL20Constants.SL20_COMMAND_PARAM_EID_CONSENTTEMPLATEID, consentTemplateId, true); addSingleByteElement(params, SL20Constants.SL20_COMMAND_PARAM_EID_CONSENT, consent, true); addSingleStringElement(params, SL20Constants.SL20_COMMAND_PARAM_EID_DATAURL, dataUrl, true); addSingleCertificateElement(params, SL20Constants.SL20_COMMAND_PARAM_EID_X5CENC, x5cEnc, false); return params; } /** * Create parameters for qualifiedeID command * * @param authBlockId * @param dataUrl * @param additionalReqParameters * @param x5cEnc * @return * @throws CertificateEncodingException * @throws SLCommandoBuildException */ @Deprecated public static ObjectNode createQualifiedeIDCommandParameters(String authBlockId, String dataUrl, Map additionalReqParameters, X509Certificate x5cEnc) throws CertificateEncodingException, SLCommandoBuildException { final ObjectNode params = mapper.getMapper().createObjectNode(); addSingleStringElement(params, SL20Constants.SL20_COMMAND_PARAM_EID_AUTHBLOCKID, authBlockId, true); addSingleStringElement(params, SL20Constants.SL20_COMMAND_PARAM_EID_DATAURL, dataUrl, true); addArrayOfStringElements(params, SL20Constants.SL20_COMMAND_PARAM_EID_ATTRIBUTES, additionalReqParameters); addSingleCertificateElement(params, SL20Constants.SL20_COMMAND_PARAM_EID_X5CENC, x5cEnc, false); return params; } /** * Create result for qualifiedeID command * * @param idl * @param authBlock * @param ccsURL * @param LoA * @return * @throws SLCommandoBuildException */ public static ObjectNode createQualifiedeIDCommandResult(byte[] idl, byte[] authBlock, String ccsURL, String LoA) throws SLCommandoBuildException { final ObjectNode result = mapper.getMapper().createObjectNode(); addSingleByteElement(result, SL20Constants.SL20_COMMAND_PARAM_EID_RESULT_IDL, idl, true); addSingleByteElement(result, SL20Constants.SL20_COMMAND_PARAM_EID_RESULT_AUTHBLOCK, authBlock, true); addSingleStringElement(result, SL20Constants.SL20_COMMAND_PARAM_EID_RESULT_CCSURL, ccsURL, true); addSingleStringElement(result, SL20Constants.SL20_COMMAND_PARAM_EID_RESULT_LOA, LoA, true); return result; } /** * Create Binding-Key command parameters * * @param kontoId * @param subjectName * @param keySize * @param keyAlg * @param policies * @param dataUrl * @param x5cVdaTrust * @param reqUserPassword * @param x5cEnc * @return * @throws SLCommandoBuildException * @throws CertificateEncodingException */ public static ObjectNode createBindingKeyCommandParams(String kontoId, String subjectName, int keySize, String keyAlg, Map policies, String dataUrl, X509Certificate x5cVdaTrust, Boolean reqUserPassword, X509Certificate x5cEnc) throws SLCommandoBuildException, CertificateEncodingException { final ObjectNode params = mapper.getMapper().createObjectNode(); addSingleStringElement(params, SL20Constants.SL20_COMMAND_PARAM_BINDING_CREATE_KONTOID, kontoId, true); addSingleStringElement(params, SL20Constants.SL20_COMMAND_PARAM_BINDING_CREATE_SN, subjectName, true); addSingleNumberElement(params, SL20Constants.SL20_COMMAND_PARAM_BINDING_CREATE_KEYLENGTH, keySize, true); addSingleStringElement(params, SL20Constants.SL20_COMMAND_PARAM_BINDING_CREATE_KEYALG, keyAlg, true); addArrayOfStringElements(params, SL20Constants.SL20_COMMAND_PARAM_BINDING_CREATE_POLICIES, policies); addSingleStringElement(params, SL20Constants.SL20_COMMAND_PARAM_BINDING_CREATE_DATAURL, dataUrl, true); addSingleCertificateElement(params, SL20Constants.SL20_COMMAND_PARAM_BINDING_CREATE_X5CVDATRUST, x5cVdaTrust, false); addSingleBooleanElement(params, SL20Constants.SL20_COMMAND_PARAM_BINDING_CREATE_REQUESTUSERPASSWORD, reqUserPassword, false); addSingleCertificateElement(params, SL20Constants.SL20_COMMAND_PARAM_BINDING_CREATE_X5CENC, x5cEnc, false); return params; } /** * Create Binding-Key command result * * @param appId * @param csr * @param attCert * @param password * @return * @throws SLCommandoBuildException * @throws CertificateEncodingException */ public static ObjectNode createBindingKeyCommandResult(String appId, byte[] csr, X509Certificate attCert, byte[] password) throws SLCommandoBuildException, CertificateEncodingException { final ObjectNode result = mapper.getMapper().createObjectNode(); addSingleStringElement(result, SL20Constants.SL20_COMMAND_PARAM_BINDING_CREATE_RESULT_APPID, appId, true); addSingleByteElement(result, SL20Constants.SL20_COMMAND_PARAM_BINDING_CREATE_RESULT_CSR, csr, true); addSingleCertificateElement(result, SL20Constants.SL20_COMMAND_PARAM_BINDING_CREATE_RESULT_KEYATTESTATIONZERTIFICATE, attCert, false); addSingleByteElement(result, SL20Constants.SL20_COMMAND_PARAM_BINDING_CREATE_RESULT_USERPASSWORD, password, false); return result; } /** * Create Store Binding-Certificate command parameters * * @param cert * @param dataUrl * @return * @throws CertificateEncodingException * @throws SLCommandoBuildException */ public static ObjectNode createStoreBindingCertCommandParams(X509Certificate cert, String dataUrl) throws CertificateEncodingException, SLCommandoBuildException { final ObjectNode params = mapper.getMapper().createObjectNode(); addSingleCertificateElement(params, SL20Constants.SL20_COMMAND_PARAM_BINDING_STORE_CERTIFICATE, cert, true); addSingleStringElement(params, SL20Constants.SL20_COMMAND_PARAM_BINDING_STORE_DATAURL, dataUrl, true); return params; } /** * Create Store Binding-Certificate command result * * @return * @throws SLCommandoBuildException */ public static ObjectNode createStoreBindingCertCommandSuccessResult() throws SLCommandoBuildException { final ObjectNode result = mapper.getMapper().createObjectNode(); addSingleStringElement(result, SL20Constants.SL20_COMMAND_PARAM_BINDING_STORE_RESULT_SUCESS, SL20Constants.SL20_COMMAND_PARAM_BINDING_STORE_RESULT_SUCESS_VALUE, true); return result; } /** * Create idAndPassword command parameters * * @param keyAlg * @param dataUrl * @param x5cEnc * @return * @throws SLCommandoBuildException * @throws CertificateEncodingException */ public static ObjectNode createIdAndPasswordCommandParameters(String keyAlg, String dataUrl, X509Certificate x5cEnc) throws SLCommandoBuildException, CertificateEncodingException { final ObjectNode params = mapper.getMapper().createObjectNode(); addSingleStringElement(params, SL20Constants.SL20_COMMAND_PARAM_AUTH_IDANDPASSWORD_KEYALG, keyAlg, true); addSingleStringElement(params, SL20Constants.SL20_COMMAND_PARAM_AUTH_IDANDPASSWORD_DATAURL, dataUrl, true); addSingleCertificateElement(params, SL20Constants.SL20_COMMAND_PARAM_AUTH_IDANDPASSWORD_X5CENC, x5cEnc, false); return params; } /** * Create idAndPassword command result * * @param kontoId * @param password * @return * @throws SLCommandoBuildException */ public static ObjectNode createIdAndPasswordCommandResult(String kontoId, byte[] password) throws SLCommandoBuildException { final ObjectNode result = mapper.getMapper().createObjectNode(); addSingleStringElement(result, SL20Constants.SL20_COMMAND_PARAM_AUTH_IDANDPASSWORD_RESULT_KONTOID, kontoId, true); addSingleByteElement(result, SL20Constants.SL20_COMMAND_PARAM_AUTH_IDANDPASSWORD_RESULT_USERPASSWORD, password, true); return result; } /** * Create JWS Token Authentication command * * @param nonce * @param dataUrl * @param displayData * @param displayUrl * @return * @throws SLCommandoBuildException */ public static ObjectNode createJwsTokenAuthCommandParams(String nonce, String dataUrl, List displayData, List displayUrl) throws SLCommandoBuildException { final ObjectNode params = mapper.getMapper().createObjectNode(); addSingleStringElement(params, SL20Constants.SL20_COMMAND_PARAM_AUTH_JWSTOKEN_NONCE, nonce, true); addSingleStringElement(params, SL20Constants.SL20_COMMAND_PARAM_AUTH_JWSTOKEN_DATAURL, dataUrl, true); addArrayOfStrings(params, SL20Constants.SL20_COMMAND_PARAM_AUTH_JWSTOKEN_DISPLAYDATA, displayData); addArrayOfStrings(params, SL20Constants.SL20_COMMAND_PARAM_AUTH_JWSTOKEN_DISPLAYURL, displayUrl); return params; } /** * Create JWS Token Authentication command result * * @param nonce * @return * @throws SLCommandoBuildException */ public static ObjectNode createJwsTokenAuthCommandResult(String nonce) throws SLCommandoBuildException { final ObjectNode result = mapper.getMapper().createObjectNode(); addSingleStringElement(result, SL20Constants.SL20_COMMAND_PARAM_AUTH_JWSTOKEN_RESULT_NONCE, nonce, true); return result; } /** * Create Generic Request Container * * @param reqId * @param transactionId * @param payLoad * @param signedPayload * @return * @throws SLCommandoBuildException */ public static ObjectNode createGenericRequest(String reqId, String transactionId, ObjectNode payLoad, String signedPayload) throws SLCommandoBuildException { final ObjectNode req = mapper.getMapper().createObjectNode(); addSingleIntegerElement(req, SL20Constants.SL20_VERSION, SL20Constants.CURRENT_SL20_VERSION, true); addSingleStringElement(req, SL20Constants.SL20_REQID, reqId, true); addSingleStringElement(req, SL20Constants.SL20_TRANSACTIONID, transactionId, false); addOnlyOnceOfTwo(req, SL20Constants.SL20_PAYLOAD, SL20Constants.SL20_SIGNEDPAYLOAD, payLoad, signedPayload); return req; } /** * Create Generic Response Container * * @param respId * @param inResponseTo * @param transactionId * @param payLoad * @param signedPayload * @return * @throws SLCommandoBuildException */ public static final ObjectNode createGenericResponse(String respId, String inResponseTo, String transactionId, ObjectNode payLoad, String signedPayload) throws SLCommandoBuildException { final ObjectNode req = mapper.getMapper().createObjectNode(); addSingleIntegerElement(req, SL20Constants.SL20_VERSION, SL20Constants.CURRENT_SL20_VERSION, true); addSingleStringElement(req, SL20Constants.SL20_RESPID, respId, true); addSingleStringElement(req, SL20Constants.SL20_INRESPTO, inResponseTo, false); addSingleStringElement(req, SL20Constants.SL20_TRANSACTIONID, transactionId, false); addOnlyOnceOfTwo(req, SL20Constants.SL20_PAYLOAD, SL20Constants.SL20_SIGNEDPAYLOAD, payLoad, signedPayload); return req; } /** * Add one element of two possible elements
* This method adds either the first element or the second element to parent JSON, but never both. * * @param parent Parent JSON element * @param firstKeyId first element Id * @param secondKeyId second element Id * @param first first element * @param second second element * @throws SLCommandoBuildException */ public static void addOnlyOnceOfTwo(ObjectNode parent, String firstKeyId, String secondKeyId, ObjectNode first, String second) throws SLCommandoBuildException { if (first == null && (second == null || second.isEmpty())) throw new SLCommandoBuildException(firstKeyId + " and " + secondKeyId + " is NULL"); else if (first != null && second != null) throw new SLCommandoBuildException(firstKeyId + " and " + secondKeyId + " can not SET TWICE"); else if (first != null) parent.set(firstKeyId, first); else if (second != null && !second.isEmpty()) parent.put(secondKeyId, second); else throw new SLCommandoBuildException("Internal build error"); } //TODO!!!! private static ObjectNode createJsonSignedHeader(JsonSecurityUtils signer) throws SLCommandoBuildException { final ObjectNode header = mapper.getMapper().createObjectNode(); addSingleStringElement(header, SL20Constants.JSON_ALGORITHM, SL20Constants.JSON_ALGORITHM_SIGNING_RS256, true); addSingleStringElement(header, SL20Constants.JSON_CONTENTTYPE, SL20Constants.SL20_CONTENTTYPE_SIGNED_COMMAND, true); addArrayOfStrings(header, SL20Constants.JSON_X509_CERTIFICATE, Arrays.asList(Constants.DUMMY_SIGNING_CERT)); return header; } //TODO!!!! private static ObjectNode createJsonEncryptionHeader(JsonSecurityUtils signer) throws SLCommandoBuildException { final ObjectNode header = mapper.getMapper().createObjectNode(); addSingleStringElement(header, SL20Constants.JSON_ALGORITHM, SL20Constants.JSON_ALGORITHM_ENC_KEY_RSAOAEP, true); addSingleStringElement(header, SL20Constants.JSON_ENCRYPTION_PAYLOAD, SL20Constants.JSON_ALGORITHM_ENC_PAYLOAD_A128CBCHS256, true); addSingleStringElement(header, SL20Constants.JSON_CONTENTTYPE, SL20Constants.SL20_CONTENTTYPE_ENCRYPTED_RESULT, true); addSingleStringElement(header, SL20Constants.JSON_X509_FINGERPRINT, Constants.DUMMY_SIGNING_CERT_FINGERPRINT, true); return header; } //TODO!!!! private static String createJsonSignedFooter(JsonSecurityUtils signer) { return "cC4hiUPoj9Eetdgtv3hF80EGrhuB__dzERat0XF9g2VtQgr9PJbu3XOiZj5RZmh7\n" + " AAuHIm4Bh-0Qc_lF5YKt_O8W2Fp5jujGbds9uJdbF9CUAr7t1dnZcAcQjbKBYNX4\n" + " BAynRFdiuB--f_nZLgrnbyTyWzO75vRK5h6xBArLIARNPvkSjtQBMHlb1L07Qe7K\n" + " 0GarZRmB_eSN9383LcOLn6_dO--xi12jzDwusC-eOkHWEsqtFZESc6BfI7noOPqv\n" + " hJ1phCnvWh6IeYI2w9QOYEUipUTI8np6LbgGY9Fs98rqVt5AXLIhWkWywlVmtVrB\n" + " p0igcN_IoypGlUPQGe77Rw"; } private static void addArrayOfStrings(ObjectNode parent, String keyId, List values) throws SLCommandoBuildException { validateParentAndKey(parent, keyId); if (values != null) { final ArrayNode callReqParamsArray = mapper.getMapper().createArrayNode(); parent.set(keyId, callReqParamsArray ); for(final String el : values) callReqParamsArray.add(el); } } private static void addArrayOfStringElements(ObjectNode parent, String keyId, Map keyValuePairs) throws SLCommandoBuildException { validateParentAndKey(parent, keyId); if (keyValuePairs != null) { final ArrayNode callReqParamsArray = mapper.getMapper().createArrayNode(); parent.set(keyId, callReqParamsArray); for(final Entry el : keyValuePairs.entrySet()) { final ObjectNode callReqParams = mapper.getMapper().createObjectNode(); callReqParams.put(el.getKey(), el.getValue()); callReqParamsArray.add(callReqParams); } } } private static void addSingleCertificateElement(ObjectNode parent, String keyId, X509Certificate cert, boolean isRequired) throws CertificateEncodingException, SLCommandoBuildException { if (cert != null) addSingleByteElement(parent, keyId, cert.getEncoded(), isRequired); else if (isRequired) throw new SLCommandoBuildException(keyId + " is marked as REQUIRED"); } private static void addSingleByteElement(ObjectNode parent, String keyId, byte[] value, boolean isRequired) throws SLCommandoBuildException { validateParentAndKey(parent, keyId); if (isRequired && value == null) throw new SLCommandoBuildException(keyId + " has NULL value"); else if (value != null) parent.put(keyId, Base64.getEncoder().encodeToString(value)); } private static void addSingleBooleanElement(ObjectNode parent, String keyId, Boolean value, boolean isRequired) throws SLCommandoBuildException { validateParentAndKey(parent, keyId); if (isRequired && value == null) throw new SLCommandoBuildException(keyId + " has a NULL value"); else if (value != null) parent.put(keyId, value); } private static void addSingleNumberElement(ObjectNode parent, String keyId, Integer value, boolean isRequired) throws SLCommandoBuildException { validateParentAndKey(parent, keyId); if (isRequired && value == null) throw new SLCommandoBuildException(keyId + " has a NULL value"); else if (value != null) parent.put(keyId, value);; } private static void addSingleStringElement(ObjectNode parent, String keyId, String value, boolean isRequired) throws SLCommandoBuildException { validateParentAndKey(parent, keyId); if (isRequired && (value == null || value.isEmpty())) throw new SLCommandoBuildException(keyId + " has an empty value"); else if (value != null && !value.isEmpty()) parent.put(keyId, value); } private static void addSingleIntegerElement(ObjectNode parent, String keyId, Integer value, boolean isRequired) throws SLCommandoBuildException { validateParentAndKey(parent, keyId); if (isRequired && value == null) throw new SLCommandoBuildException(keyId + " has an empty value"); else if (value != null) parent.put(keyId, value); } private static void addSingleJSONElement(ObjectNode parent, String keyId, ObjectNode element, boolean isRequired) throws SLCommandoBuildException { validateParentAndKey(parent, keyId); if (isRequired && element == null) throw new SLCommandoBuildException("No commando name included"); else if (element != null) parent.set(keyId, element); } private static void addOnlyOnceOfTwo(ObjectNode parent, String firstKeyId, String secondKeyId, ObjectNode first, ObjectNode second) throws SLCommandoBuildException { if (first == null && second == null) throw new SLCommandoBuildException(firstKeyId + " and " + secondKeyId + " is NULL"); else if (first != null && second != null) throw new SLCommandoBuildException(firstKeyId + " and " + secondKeyId + " can not SET TWICE"); else if (first != null) parent.set(firstKeyId, first); else if (second != null) parent.set(secondKeyId, second); else throw new SLCommandoBuildException("Internal build error"); } private static void validateParentAndKey(ObjectNode parent, String keyId) throws SLCommandoBuildException { if (parent == null) throw new SLCommandoBuildException("NO parent JSON element"); if (keyId == null || keyId.isEmpty()) throw new SLCommandoBuildException("NO JSON element identifier"); } }