Java tutorial
/* * Copyright (c) 2012. betterFORM Project - http://www.betterform.de * Licensed under the terms of BSD License */ package de.betterform.xml.xforms.action; import de.betterform.xml.events.XFormsEventNames; import de.betterform.xml.xforms.XFormsConstants; import de.betterform.xml.xforms.exception.XFormsComputeException; import de.betterform.xml.xforms.exception.XFormsException; import de.betterform.xml.xforms.model.Instance; import de.betterform.xml.xforms.model.Model; import de.betterform.xml.xpath.impl.saxon.XPathCache; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.w3c.dom.Element; import org.w3c.dom.Node; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; /** * Implements the action as defined in <code>9.3.6 The delete Element</code>. * * @author Ulrich Nicolas Lissé * @version $Id: DeleteAction.java 3474 2008-08-15 22:29:43Z joern $ */ public class DeleteAction extends AbstractBoundAction { private static final Log LOGGER = LogFactory.getLog(DeleteAction.class); private String atAttribute; /** * Creates a delete action implementation. * * @param element the element. * @param model the context model. */ public DeleteAction(Element element, Model model) { super(element, model); } // lifecycle methods /** * Performs element init. */ public void init() throws XFormsException { super.init(); this.atAttribute = getXFormsAttribute(AT_ATTRIBUTE); } // implementation of 'de.betterform.xml.xforms.model.bind.Binding' /** * Returns the context expression. * * @return the context expression. */ public String getContextExpression() { return getXFormsAttribute(CONTEXT_ATTRIBUTE); } // implementation of 'de.betterform.xml.xforms.action.XFormsAction' /** * Performs the <code>delete</code> action as specified by XForms 1.1. * * @throws XFormsException if an error occurred during <code>delete</code> * processing. */ public void perform() throws XFormsException { updateXPathContext(); final int nrOfNodesInNodeset = this.nodeset.size(); if (nrOfNodesInNodeset == 0) { getLogger().warn(this + " perform: nodeset '" + getLocationPath() + "' is empty"); return; } if (this.atAttribute == null) { final Instance instance = this.model.getInstance(getInstanceId()); final String locationPath = getLocationPath(); final String path = locationPath + "[1]"; for (int i = 0; i < this.nodeset.size(); i++) { //evaluate each node and return in case no nodes were deleted if (!(instance.deleteNode( de.betterform.xml.xpath.impl.saxon.XPathUtil.getAsNode(this.nodeset, i + 1), path))) return; } this.container.dispatch(instance.getTarget(), XFormsEventNames.DELETE, constructEventInfo(Double.valueOf(Double.NaN), this.nodeset, locationPath)); } else { final Node target; final String positionInNodeset; final List deleteNodes; if (this.atAttribute.equals("last()")) { deleteNodes = Collections.singletonList(this.nodeset.get(nrOfNodesInNodeset - 1)); target = (Node) de.betterform.xml.xpath.impl.saxon.XPathUtil.getAsNode(this.nodeset, nrOfNodesInNodeset); positionInNodeset = Integer.toString(nrOfNodesInNodeset); } else { Double d; try { d = XPathCache.getInstance().evaluateAsDouble(this.nodeset, this.position, "round(number(" + this.atAttribute + "))", getPrefixMapping(), xpathFunctionContext); } catch (Exception e) { throw new XFormsComputeException("invalid 'at' expression at " + this, e, this.target, this.atAttribute); } if (LOGGER.isDebugEnabled()) { LOGGER.debug("bound to: " + getBindingExpression()); LOGGER.debug("value attribute evaluated to: " + d); } long position = Math.round(d); /* if @at evaluated on the nodeset returns NaN or delete position is bigger than the actual nodeset then new position is equal to the size of the nodeset */ if (Double.isNaN(d) || position > nrOfNodesInNodeset) { position = nrOfNodesInNodeset; } /* if evaluated position is 0 or smaller then new position is 1 */ else if (position < 1) { position = 1; } deleteNodes = Collections.singletonList(this.nodeset.get((int) position - 1)); target = de.betterform.xml.xpath.impl.saxon.XPathUtil.getAsNode(this.nodeset, (int) position); positionInNodeset = Long.toString(position); } // delete specified node and dispatch notification event final Instance instance = this.model.getInstance(getInstanceId()); final String path = getLocationPath() + "[" + positionInNodeset + "]"; if (!(instance.deleteNode(target, path))) return; this.container.dispatch(instance.getTarget(), XFormsEventNames.DELETE, constructEventInfo(Double.valueOf(positionInNodeset), deleteNodes, path)); } // update behaviour doRebuild(true); doRecalculate(true); doRevalidate(true); doRefresh(true); } /** * @param positionInNodeset * @param deleteNodes * @param path * @return */ private Map<String, Object> constructEventInfo(final Double positionInNodeset, final List deleteNodes, final String path) { Map<String, Object> eventInfo = new HashMap<String, Object>(); eventInfo.put("path", path); eventInfo.put(XFormsConstants.DELETE_LOCATION, positionInNodeset); eventInfo.put(XFormsConstants.DELETE_NODES, deleteNodes); return eventInfo; } /** * Returns the logger object. * * @return the logger object. */ protected Log getLogger() { return LOGGER; } } // end of class