PageRenderTime 23ms CodeModel.GetById 17ms RepoModel.GetById 1ms app.codeStats 0ms

/blocks/cocoon-forms/cocoon-forms-impl/src/main/java/org/apache/cocoon/forms/binding/RepeaterJXPathAdapter.java

https://github.com/apache/cocoon
Java | 228 lines | 163 code | 36 blank | 29 comment | 44 complexity | 481d173941bb26aed976bac7d4b9742d MD5 | raw file
  1. /*
  2. * Licensed to the Apache Software Foundation (ASF) under one or more
  3. * contributor license agreements. See the NOTICE file distributed with
  4. * this work for additional information regarding copyright ownership.
  5. * The ASF licenses this file to You under the Apache License, Version 2.0
  6. * (the "License"); you may not use this file except in compliance with
  7. * the License. You may obtain a copy of the License at
  8. *
  9. * http://www.apache.org/licenses/LICENSE-2.0
  10. *
  11. * Unless required by applicable law or agreed to in writing, software
  12. * distributed under the License is distributed on an "AS IS" BASIS,
  13. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. * See the License for the specific language governing permissions and
  15. * limitations under the License.
  16. */
  17. package org.apache.cocoon.forms.binding;
  18. import org.apache.cocoon.forms.formmodel.Repeater.RepeaterRow;
  19. import org.apache.commons.jxpath.JXPathContext;
  20. import org.apache.commons.jxpath.Pointer;
  21. import java.util.*;
  22. /**
  23. * @version $Id$
  24. */
  25. public class RepeaterJXPathAdapter implements RepeaterAdapter {
  26. private int progressive = 100000;
  27. private EnhancedRepeaterJXPathBinding binding;
  28. private RepeaterJXPathCollection jxCollection;
  29. private List sortedItems;
  30. public RepeaterFilter getFilter() {
  31. return new RepeaterJXPathFilter();
  32. }
  33. private String findPathFor(String field) {
  34. JXPathBindingBase[] childBindings = binding.getRowBinding().getChildBindings();
  35. String path = null;
  36. for (int i = 0; i < childBindings.length; i++) {
  37. if (childBindings[i] instanceof ValueJXPathBinding) {
  38. ValueJXPathBinding bnd = (ValueJXPathBinding) childBindings[i];
  39. if (bnd.getFieldId().equals(field)) {
  40. path = bnd.getXPath();
  41. break;
  42. }
  43. }
  44. }
  45. return path;
  46. }
  47. public RepeaterSorter sortBy(String field) {
  48. if (field == null) {
  49. sortedItems = null;
  50. return new NormalOrderJXPathSorter();
  51. }
  52. String path = findPathFor(field);
  53. if (path == null) throw new IllegalStateException("Cannot find a path for sorting on widget " + field);
  54. RepeaterSorter sort = new RepeaterJXPathSorter(path, field, false);
  55. if (sortedItems == null) {
  56. List tsortedItems = new ArrayList();
  57. int i = 0;
  58. RepeaterItem item = getItem(i);
  59. while (item != null) {
  60. tsortedItems.add(item);
  61. i++;
  62. item = getItem(i);
  63. }
  64. this.sortedItems = tsortedItems;
  65. }
  66. Collections.sort(sortedItems, sort);
  67. return sort;
  68. }
  69. public void setBinding(EnhancedRepeaterJXPathBinding binding) {
  70. this.binding = binding;
  71. }
  72. public void setCollection(Collection c) {
  73. }
  74. public void setJXCollection(RepeaterJXPathCollection collection) {
  75. this.jxCollection = collection;
  76. }
  77. public RepeaterItem getItem(int i) {
  78. if (i < 0) return null;
  79. if (i >= jxCollection.getOriginalCollectionSize()) return null;
  80. if (this.sortedItems == null) {
  81. JXPathContext storageContext = this.jxCollection.getStorageContext();
  82. Pointer pointer = storageContext.getPointer(binding.getRowPath() + "[" + (i + 1) + "]");
  83. JXPathContext rowContext = storageContext.getRelativeContext(pointer);
  84. RepeaterItem item = new RepeaterItem(new Integer(i + 1));
  85. item.setContext(rowContext);
  86. return item;
  87. } else {
  88. return (RepeaterItem) sortedItems.get(i);
  89. }
  90. }
  91. class RepeaterJXPathFilter implements RepeaterFilter {
  92. private Map fieldsPaths = new HashMap();
  93. private Map fieldsValues = new HashMap();
  94. public boolean shouldDisplay(RepeaterItem item) {
  95. for (Iterator iter = fieldsValues.keySet().iterator(); iter.hasNext();) {
  96. String field = (String) iter.next();
  97. Object value = fieldsValues.get(field);
  98. Object acvalue = null;
  99. if (item.getRow() == null) {
  100. String path = (String) fieldsPaths.get(field);
  101. acvalue = item.getContext().getValue(path);
  102. } else {
  103. acvalue = item.getRow().getChild(field).getValue();
  104. }
  105. if (acvalue == null) return false;
  106. if (acvalue instanceof String && value instanceof String) {
  107. return ((String) acvalue).startsWith((String) value);
  108. } else {
  109. return acvalue.equals(value);
  110. }
  111. }
  112. return true;
  113. }
  114. public void setFilter(String field, Object value) {
  115. if (value == null || ((value instanceof String) && ((String) value).length() == 0)) {
  116. fieldsPaths.remove(field);
  117. fieldsValues.remove(field);
  118. } else {
  119. String path = findPathFor(field);
  120. if (path == null)
  121. throw new IllegalStateException("Cannot find a path for filtering on widget " + field);
  122. fieldsPaths.put(field, path);
  123. fieldsValues.put(field, value);
  124. }
  125. }
  126. }
  127. /**
  128. * Sorter for JXPath based repeaters
  129. */
  130. static class RepeaterJXPathSorter implements RepeaterSorter {
  131. private String path;
  132. private String field;
  133. private boolean nullsAreHigher;
  134. /**
  135. * JXPath based sorter for repeater
  136. * @param path the path of the field to sort on
  137. * @param field the name of the field to sort on
  138. * @param nullsAreHigher indicates if null values are seen as higher then other values.
  139. * When this value is set to false, it means that nulls are lower than anything else.
  140. */
  141. public RepeaterJXPathSorter(String path, String field, boolean nullsAreHigher) {
  142. this.path = path;
  143. this.field = field;
  144. this.nullsAreHigher = nullsAreHigher;
  145. }
  146. public void setCollection(Collection c) {
  147. }
  148. public int compare(Object o1, Object o2) {
  149. RepeaterItem i1 = (RepeaterItem) o1;
  150. RepeaterItem i2 = (RepeaterItem) o2;
  151. Object val1;
  152. if (i1.getRow() != null) {
  153. val1 = i1.getRow().getChild(field).getValue();
  154. } else {
  155. val1 = i1.getContext().getValue(path);
  156. }
  157. Object val2;
  158. if (i2.getRow() != null) {
  159. val2 = i2.getRow().getChild(field).getValue();
  160. } else {
  161. val2 = i2.getContext().getValue(path);
  162. }
  163. if(val1 == null) {
  164. return (this.nullsAreHigher ? 1 : -1);
  165. }
  166. if(val2 == null) {
  167. return (this.nullsAreHigher ? -1 : 1);
  168. }
  169. if (val1 instanceof Comparable) {
  170. return ((Comparable) val1).compareTo(val2);
  171. }
  172. return val1.toString().compareTo(val2.toString());
  173. }
  174. }
  175. static class NormalOrderJXPathSorter implements RepeaterSorter {
  176. public void setCollection(Collection c) {
  177. }
  178. public int compare(Object o1, Object o2) {
  179. RepeaterItem i1 = (RepeaterItem) o1;
  180. RepeaterItem i2 = (RepeaterItem) o2;
  181. return ((Integer) i1.getHandle()).compareTo((Integer) i2.getHandle());
  182. }
  183. }
  184. public RepeaterItem generateItem(RepeaterRow row) {
  185. RepeaterItem item = new RepeaterItem(new Integer(progressive++));
  186. item.setRow(row);
  187. return item;
  188. }
  189. public void populateRow(RepeaterItem item) throws BindingException {
  190. binding.getRowBinding().loadFormFromModel(item.getRow(), item.getContext());
  191. }
  192. }