package com.ausregistry.jtoolkit2.se.fee;
import com.ausregistry.jtoolkit2.se.*;
import com.ausregistry.jtoolkit2.xml.XMLDocument;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import javax.xml.xpath.XPathExpressionException;
import java.math.BigDecimal;
import java.util.*;
import static com.ausregistry.jtoolkit2.se.ReceiveSE.replaceIndex;
/**
* <p>Extension for the EPP Domain Check response, representing the Fee
* extension.</p>
*
* <p>Use this to check the price associated with this domain name as part of an EPP Domain Check
* command compliant with RFC5730 and RFC5731. The "name", "command", "phase", "unit", "period", "class", "currency"
* and "fee" values supplied, should match the fields that are requested for the domain name check for the requested
* period. The response expected from a server should be handled by a Domain Check Response.</p>
*
* @see DomainCreateCommand
* @see DomainCreateResponse
* @see <a href="https://tools.ietf.org/html/draft-brown-epp-fees-03">Domain Name Fee Extension
* Mapping for the Extensible Provisioning Protocol (EPP)</a>
*/
public class DomainCheckFeeResponseExtension extends ResponseExtension {
private static final String FEE_CHECK_PREFIX = ExtendedObjectType.FEE.getName();
private static final String CHKDATA_EXPR = replaceResponseType(ResponseExtension.EXTENSION_EXPR
+ "/" + FEE_CHECK_PREFIX + ":RESPONSE_TYPE", ResponseExtension.CHK_DATA);
private static final String CHKDATA_COUNT_EXPR = "count(" + CHKDATA_EXPR + "/*)";
private static final String CHKDATA_IND_EXPR = CHKDATA_EXPR + "/" + FEE_CHECK_PREFIX + ":cd[IDX]";
private static final String CHKDATA_DOMAIN_NAME_EXPR = "/" + FEE_CHECK_PREFIX + ":name/text()";
private static final String CHKDATA_DOMAIN_CURRENCY_EXPR = "/" + FEE_CHECK_PREFIX + ":currency/text()";
private static final String CHKDATA_DOMAIN_COMMAND_EXPR = "/" + FEE_CHECK_PREFIX + ":command/text()";
private static final String CHKDATA_DOMAIN_COMMAND_PHASE_EXPR = "/" + FEE_CHECK_PREFIX + ":command/@phase";
private static final String CHKDATA_DOMAIN_COMMAND_SUBPHASE_EXPR = "/" + FEE_CHECK_PREFIX + ":command/@subphase";
private static final String CHKDATA_DOMAIN_PERIOD_EXPR = "/" + FEE_CHECK_PREFIX + ":period/text()";
private static final String CHKDATA_DOMAIN_PERIOD_UNIT_EXPR = "/" + FEE_CHECK_PREFIX + ":period/@unit";
private static final String CHKDATA_DOMAIN_FEE_CLASS_EXPR = "/" + FEE_CHECK_PREFIX + ":class/text()";
private static final String CHKDATA_FEE_NODES_EXPR = "/" + FEE_CHECK_PREFIX + ":fee";
private boolean initialised;
private List<FeeCheckData> feeDomains = new ArrayList<FeeCheckData>();
@Override
public void fromXML(XMLDocument xmlDoc) throws XPathExpressionException {
int checkDataCount = xmlDoc.getNodeCount(CHKDATA_COUNT_EXPR);
for (int checkDataIndex = 0; checkDataIndex < checkDataCount; checkDataIndex++) {
parseFeeCheckDataNodes(xmlDoc, checkDataIndex);
}
initialised = checkDataCount > 0;
}
private void parseFeeCheckDataNodes(XMLDocument xmlDoc, int checkDataIndex) throws XPathExpressionException {
String checkDataQueryPath = replaceIndex(CHKDATA_IND_EXPR, checkDataIndex + 1);
final String domainName = parseTextValue(xmlDoc, checkDataQueryPath + CHKDATA_DOMAIN_NAME_EXPR);
final FeeCheckData.Command command = parseCommandNode(xmlDoc, checkDataQueryPath);
FeeCheckData feeCheckData = new FeeCheckData(domainName, command);
feeCheckData.setCurrency(parseTextValue(xmlDoc, checkDataQueryPath + CHKDATA_DOMAIN_CURRENCY_EXPR));
feeCheckData.setFeeClass(parseTextValue(xmlDoc, checkDataQueryPath + CHKDATA_DOMAIN_FEE_CLASS_EXPR));
feeCheckData.setPeriod(parsePeriod(xmlDoc, checkDataQueryPath));
parseFeeNodes(xmlDoc, feeCheckData, checkDataQueryPath + CHKDATA_FEE_NODES_EXPR);
feeDomains.add(feeCheckData);
}
private String parseTextValue(XMLDocument xmlDoc, String queryPath) throws XPathExpressionException {
return xmlDoc.getNodeValue(queryPath);
}
private FeeCheckData.Command parseCommandNode(XMLDocument xmlDoc, String checkDataQueryPath)
throws XPathExpressionException {
final FeeCheckData.Command command = new FeeCheckData.Command(
xmlDoc.getNodeValue(checkDataQueryPath + CHKDATA_DOMAIN_COMMAND_EXPR));
command.setPhase(xmlDoc.getNodeValue(checkDataQueryPath + CHKDATA_DOMAIN_COMMAND_PHASE_EXPR));
command.setSubphase(xmlDoc.getNodeValue(checkDataQueryPath + CHKDATA_DOMAIN_COMMAND_SUBPHASE_EXPR));
return command;
}
private Period parsePeriod(XMLDocument xmlDoc, String checkDataQueryPath) throws XPathExpressionException {
final String periodValue = parseTextValue(xmlDoc, checkDataQueryPath + CHKDATA_DOMAIN_PERIOD_EXPR);
final String unitValue = parseTextValue(xmlDoc, checkDataQueryPath + CHKDATA_DOMAIN_PERIOD_UNIT_EXPR);
return (periodValue != null)
? new Period(PeriodUnit.value(unitValue), Integer.parseInt(periodValue))
: null;
}
private void parseFeeNodes(XMLDocument xmlDoc, FeeCheckData feeCheckData, String feeNodesQueryPath)
throws XPathExpressionException {
NodeList feeNodes = xmlDoc.getElements(feeNodesQueryPath);
if (feeNodes != null) {
for (int feeNodeIndex = 0; feeNodeIndex < feeNodes.getLength(); feeNodeIndex++) {
Node feeNode = feeNodes.item(feeNodeIndex);
feeCheckData.addFee(parseFee(feeNode));
}
}
}
private FeeCheckData.Fee parseFee(Node feeNode) {
BigDecimal feeValue = new BigDecimal(feeNode.getTextContent());
String description = feeNode.getAttributes().getNamedItem("description").getTextContent();
FeeCheckData.Fee fee = new FeeCheckData.Fee(feeValue, description);
String refundable = feeNode.getAttributes().getNamedItem("refundable") != null
? feeNode.getAttributes().getNamedItem("refundable").getTextContent() : null;
fee.setRefundable("1".equals(refundable));
return fee;
}
@Override
public boolean isInitialised() {
return initialised;
}
public List<FeeCheckData> getFeeDomains() {
return Collections.unmodifiableList(feeDomains);
}
}