001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017: package org.apache.cocoon.forms.binding;
018:
019: import java.util.ArrayList;
020: import java.util.Collection;
021: import java.util.Collections;
022: import java.util.HashMap;
023: import java.util.Iterator;
024: import java.util.List;
025: import java.util.Map;
026:
027: import org.apache.cocoon.forms.formmodel.Repeater.RepeaterRow;
028:
029: import org.apache.commons.jxpath.JXPathContext;
030: import org.apache.commons.jxpath.Pointer;
031:
032: /**
033: * @version $Id: RepeaterJXPathAdapter.java 517733 2007-03-13 15:37:22Z vgritsenko $
034: */
035: public class RepeaterJXPathAdapter implements RepeaterAdapter {
036:
037: private int progressive = 100000;
038:
039: private EnhancedRepeaterJXPathBinding binding;
040: private RepeaterJXPathCollection jxCollection;
041: private List sortedItems;
042:
043: public RepeaterFilter getFilter() {
044: return new RepeaterJXPathFilter();
045: }
046:
047: private String findPathFor(String field) {
048: JXPathBindingBase[] childBindings = binding.getRowBinding()
049: .getChildBindings();
050: String path = null;
051: for (int i = 0; i < childBindings.length; i++) {
052: if (childBindings[i] instanceof ValueJXPathBinding) {
053: ValueJXPathBinding bnd = (ValueJXPathBinding) childBindings[i];
054: if (bnd.getFieldId().equals(field)) {
055: path = bnd.getXPath();
056: break;
057: }
058: }
059: }
060: return path;
061: }
062:
063: public RepeaterSorter sortBy(String field) {
064: if (field == null) {
065: sortedItems = null;
066: return new NormalOrderJXPathSorter();
067: }
068: String path = findPathFor(field);
069: if (path == null)
070: throw new IllegalStateException(
071: "Cannot find a path for sorting on widget " + field);
072: RepeaterSorter sort = new RepeaterJXPathSorter(path, field);
073: if (sortedItems == null) {
074: List tsortedItems = new ArrayList();
075: int i = 0;
076: RepeaterItem item = getItem(i);
077: while (item != null) {
078: tsortedItems.add(item);
079: i++;
080: item = getItem(i);
081: }
082: this .sortedItems = tsortedItems;
083: }
084: Collections.sort(sortedItems, sort);
085: return sort;
086: }
087:
088: public void setBinding(EnhancedRepeaterJXPathBinding binding) {
089: this .binding = binding;
090: }
091:
092: public void setCollection(Collection c) {
093: }
094:
095: public void setJXCollection(RepeaterJXPathCollection collection) {
096: this .jxCollection = collection;
097: }
098:
099: public RepeaterItem getItem(int i) {
100: if (i < 0)
101: return null;
102: if (i >= jxCollection.getOriginalCollectionSize())
103: return null;
104: if (this .sortedItems == null) {
105: JXPathContext storageContext = this .jxCollection
106: .getStorageContext();
107: Pointer pointer = storageContext.getPointer(binding
108: .getRowPath()
109: + "[" + (i + 1) + "]");
110: JXPathContext rowContext = storageContext
111: .getRelativeContext(pointer);
112: RepeaterItem item = new RepeaterItem(new Integer(i + 1));
113: item.setContext(rowContext);
114: return item;
115: } else {
116: return (RepeaterItem) sortedItems.get(i);
117: }
118: }
119:
120: class RepeaterJXPathFilter implements RepeaterFilter {
121:
122: private Map fieldsPaths = new HashMap();
123: private Map fieldsValues = new HashMap();
124:
125: public boolean shouldDisplay(RepeaterItem item) {
126: for (Iterator iter = fieldsValues.keySet().iterator(); iter
127: .hasNext();) {
128: String field = (String) iter.next();
129: Object value = fieldsValues.get(field);
130: Object acvalue = null;
131: if (item.getRow() == null) {
132: String path = (String) fieldsPaths.get(field);
133: acvalue = item.getContext().getValue(path);
134: } else {
135: acvalue = item.getRow().getChild(field).getValue();
136: }
137: if (acvalue == null)
138: return false;
139: if (acvalue instanceof String
140: && value instanceof String) {
141: return ((String) acvalue)
142: .startsWith((String) value);
143: } else {
144: return acvalue.equals(value);
145: }
146: }
147: return true;
148: }
149:
150: public void setFilter(String field, Object value) {
151: if (value == null
152: || ((value instanceof String) && ((String) value)
153: .length() == 0)) {
154: fieldsPaths.remove(field);
155: fieldsValues.remove(field);
156: } else {
157: String path = findPathFor(field);
158: if (path == null)
159: throw new IllegalStateException(
160: "Cannot find a path for filtering on widget "
161: + field);
162: fieldsPaths.put(field, path);
163: fieldsValues.put(field, value);
164: }
165: }
166:
167: }
168:
169: static class RepeaterJXPathSorter implements RepeaterSorter {
170:
171: private String path;
172: private String field;
173:
174: public RepeaterJXPathSorter(String path, String field) {
175: this .path = path;
176: this .field = field;
177: }
178:
179: public void setCollection(Collection c) {
180: }
181:
182: public int compare(Object o1, Object o2) {
183: RepeaterItem i1 = (RepeaterItem) o1;
184: RepeaterItem i2 = (RepeaterItem) o2;
185:
186: Object val1;
187: if (i1.getRow() != null) {
188: val1 = i1.getRow().getChild(field).getValue();
189: } else {
190: val1 = i1.getContext().getValue(path);
191: }
192:
193: Object val2;
194: if (i2.getRow() != null) {
195: val2 = i2.getRow().getChild(field).getValue();
196: } else {
197: val2 = i2.getContext().getValue(path);
198: }
199:
200: if (val1 instanceof Comparable) {
201: return ((Comparable) val1).compareTo(val2);
202: }
203: return val1.toString().compareTo(val2.toString());
204: }
205:
206: }
207:
208: static class NormalOrderJXPathSorter implements RepeaterSorter {
209:
210: public void setCollection(Collection c) {
211: }
212:
213: public int compare(Object o1, Object o2) {
214: RepeaterItem i1 = (RepeaterItem) o1;
215: RepeaterItem i2 = (RepeaterItem) o2;
216: return ((Integer) i1.getHandle()).compareTo((Integer) i2
217: .getHandle());
218: }
219: }
220:
221: public RepeaterItem generateItem(RepeaterRow row) {
222: RepeaterItem item = new RepeaterItem(new Integer(progressive++));
223: item.setRow(row);
224: return item;
225: }
226:
227: public void populateRow(RepeaterItem item) throws BindingException {
228: binding.getRowBinding().loadFormFromModel(item.getRow(),
229: item.getContext());
230: }
231:
232: }
|