class OadrXMLSignatureHandler {

	public static void validate(String raw, OadrPayload payload, long nowDate, long millisecondAcceptedDelay)
			throws Oadr20bXMLSignatureValidationException {

		validateReplayProtect(payload, nowDate, millisecondAcceptedDelay);

		DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
		dbf.setNamespaceAware(true);
		DocumentBuilder builder = null;
		Document doc;
		try {
			builder = dbf.newDocumentBuilder();
			doc = builder.parse(new InputSource(new StringReader(raw)));
		} catch (ParserConfigurationException | SAXException | IOException e) {
			throw new Oadr20bXMLSignatureValidationException(e);
		}

		XMLSignatureFactory fac = XMLSignatureFactory.getInstance("DOM");

		NodeList nl = doc.getElementsByTagNameNS(XMLSignature.XMLNS, "Signature");
		if (nl.getLength() == 0) {
			throw new Oadr20bXMLSignatureValidationException("Cannot find Signature element");
		}

		DOMValidateContext valContext = new DOMValidateContext(new KeyValueKeySelector(), nl.item(0));

		XMLSignature signature;
		try {
			signature = fac.unmarshalXMLSignature(valContext);
		} catch (MarshalException e) {
			throw new Oadr20bXMLSignatureValidationException(e);
		}
		try {
			boolean validate = signature.validate(valContext);
			if (!validate) {
				if (!signature.getSignatureValue().validate(valContext)) {
					throw new Oadr20bXMLSignatureValidationException("XMLSignature SignatureValue validation fail");
				}
				for (Object object : signature.getSignedInfo().getReferences()) {
					if (object instanceof Reference) {
						Reference ref = (Reference) object;
						if (!ref.validate(valContext)) {
							throw new Oadr20bXMLSignatureValidationException(
									"XMLSignature Reference uri: " + ref.getURI() + " validation fail");
						}
					}
				}
			}
		} catch (XMLSignatureException e) {
			throw new Oadr20bXMLSignatureValidationException(e);
		}

	}

	private  OadrXMLSignatureHandler();

}