1 16 package org.apache.cocoon.forms.binding; 17 18 import java.util.Iterator ; 19 20 import org.apache.avalon.framework.logger.Logger; 21 import org.apache.cocoon.forms.formmodel.Repeater; 22 import org.apache.cocoon.forms.formmodel.Widget; 23 import org.apache.commons.jxpath.JXPathContext; 24 import org.apache.commons.jxpath.Pointer; 25 import org.w3c.dom.Document ; 26 import org.w3c.dom.Node ; 27 import org.w3c.dom.NodeList ; 28 29 39 public class TempRepeaterJXPathBinding extends JXPathBindingBase { 40 41 private final String repeaterId; 42 private final String repeaterPath; 43 private final String rowPath; 44 private final String rowPathInsert; 45 private final boolean clearOnLoad; 46 private final JXPathBindingBase rowBinding; 47 private final JXPathBindingBase insertRowBinding; 48 private final boolean deleteIfEmpty; 49 private final boolean virtualRows; 50 51 public TempRepeaterJXPathBinding( 52 JXPathBindingBuilderBase.CommonAttributes commonAtts, 53 String repeaterId, String repeaterPath, 54 String rowPath, String rowPathInsert, 55 boolean virtualRows, boolean clearOnLoad, boolean deleteIfEmpty, 56 JXPathBindingBase rowBinding, JXPathBindingBase insertBinding) { 57 super(commonAtts); 58 this.repeaterId = repeaterId; 59 this.repeaterPath = repeaterPath; 60 this.rowPath = rowPath; 61 this.rowPathInsert = rowPathInsert; 62 this.rowBinding = rowBinding; 63 this.rowBinding.setParent(this); 64 this.insertRowBinding = insertBinding; 65 this.insertRowBinding.setParent(this); 66 this.virtualRows = virtualRows; 67 this.clearOnLoad = clearOnLoad; 68 this.deleteIfEmpty = deleteIfEmpty; 69 } 70 71 public String getId() { return repeaterId; } 72 public String getRepeaterPath() { return repeaterPath; } 73 public String getRowPath() { return rowPath; } 74 public String getRowPathInsert() { return rowPathInsert; } 75 public boolean getVirtualRows() { return virtualRows; } 76 public boolean getClearOnLoad() { return clearOnLoad; } 77 public boolean getDeleteIfEmpty() { return deleteIfEmpty; } 78 public JXPathBindingBase[] getChildBindings() { return ((ComposedJXPathBindingBase)rowBinding).getChildBindings(); } 79 public JXPathBindingBase[] getInsertChildBindings() { return ((ComposedJXPathBindingBase)insertRowBinding).getChildBindings(); } 80 81 public void doLoad(Widget frmModel, JXPathContext jctx) throws BindingException { 82 Repeater repeater = (Repeater) selectWidget(frmModel, this.repeaterId); 86 if (repeater == null) { 87 String fullId = frmModel.getRequestParameterName(); 88 if (fullId == null || fullId.length() == 0) { 89 fullId = ""; 90 } else { 91 fullId = fullId + "."; 92 } 93 throw new RuntimeException ( 94 "TempRepeaterJXPathBinding: Repeater \"" + fullId + this.repeaterId + 95 "\" does not exist (" + frmModel.getLocation() + ")"); 96 } 97 98 if (this.clearOnLoad) { 100 repeater.clear(); 101 } 102 103 Pointer repeaterPointer = jctx.getPointer(this.repeaterPath); 105 106 if (repeaterPointer != null) { 111 112 JXPathContext repeaterContext = jctx.getRelativeContext(repeaterPointer); 114 115 Iterator rowPointers = repeaterContext.iteratePointers(this.rowPath); 117 118 int rowNum = 0; 120 while (rowPointers.hasNext()) { 121 122 Repeater.RepeaterRow thisRow; 124 if (repeater.getSize() > rowNum) { 125 thisRow = repeater.getRow(rowNum); 126 } else { 127 thisRow = repeater.addRow(); 128 } 129 rowNum++; 130 131 Pointer rowPointer = (Pointer) rowPointers.next(); 133 JXPathContext rowContext = repeaterContext.getRelativeContext(rowPointer); 134 135 145 if (virtualRows == true) { 146 Node repeaterNode = (Node )repeaterPointer.getNode(); 147 Node virtualNode = repeaterNode.getOwnerDocument().createElementNS(null, "virtual"); 148 Node node = (Node )rowPointer.getNode(); 149 Node clone = node.cloneNode(true); 150 Node fakeDocElement = node.getOwnerDocument().getDocumentElement().cloneNode(false); 151 virtualNode.appendChild(clone); 152 fakeDocElement.appendChild(virtualNode); 153 rowContext = JXPathContext.newContext(repeaterContext, fakeDocElement); 154 rowContext = rowContext.getRelativeContext(rowContext.getPointer("virtual")); 155 } 156 157 this.rowBinding.loadFormFromModel(thisRow, rowContext); 159 } 160 } 161 162 if (getLogger().isDebugEnabled()) 163 getLogger().debug("done loading rows " + toString()); 164 } 165 166 public void doSave(Widget frmModel, JXPathContext jctx) throws BindingException { 167 Repeater repeater = (Repeater) selectWidget(frmModel, this.repeaterId); 169 170 if (repeater.getSize() == 0 && this.deleteIfEmpty) { 173 jctx.removeAll(this.repeaterPath); 175 176 } else { 178 179 JXPathContext repeaterContext = jctx.getRelativeContext(jctx.createPath(this.repeaterPath)); 181 182 repeaterContext.removeAll(this.rowPath); 184 185 if(repeater.getSize() > 0) { 187 if (this.insertRowBinding != null) { 188 189 192 for (int i = 0; i < repeater.getSize(); i++) { 194 195 Pointer rowPointer = repeaterContext.getPointer(this.rowPathInsert); 197 JXPathContext rowContext = repeaterContext.getRelativeContext(rowPointer); 198 199 Node rowNode = null; 202 Node virtualNode = null; 203 204 if (virtualRows == true) { 207 rowNode = (Node )rowContext.getContextBean(); 208 Document document = rowNode.getOwnerDocument(); 209 virtualNode = document.createElementNS(null, "virtual"); 210 Node fakeDocElement = document.getDocumentElement().cloneNode(false); 211 fakeDocElement.appendChild(virtualNode); 212 rowContext = JXPathContext.newContext(repeaterContext, fakeDocElement); 213 rowContext = rowContext.getRelativeContext(rowContext.getPointer("virtual")); 214 } 215 216 this.insertRowBinding.saveFormToModel(repeater, rowContext); 218 219 this.rowBinding.saveFormToModel(repeater.getRow(i), rowContext); 221 222 if (virtualRows == true) { 225 NodeList list = virtualNode.getChildNodes(); 226 int count = list.getLength(); 227 for (int j = 0; j < count; j++) { 228 rowNode.appendChild(list.item(0)); 231 } 232 } 233 getLogger().debug("bound new row"); 234 } 235 } else { 236 getLogger().warn("TempRepeaterBinding has detected rows to insert, " + 237 "but misses the <on-insert-row> binding to do it."); 238 } 239 } 240 } 241 } 242 243 public String toString() { 244 return "TempRepeaterJXPathBinding [widget=" + this.repeaterId + ", xpath=" + this.repeaterPath + "]"; 245 } 246 247 public void enableLogging(Logger logger) { 248 super.enableLogging(logger); 249 if (this.insertRowBinding != null) { 250 this.insertRowBinding.enableLogging(logger); 251 } 252 this.rowBinding.enableLogging(logger); 253 } 254 } 255 | Popular Tags |