| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You under the Apache License, Version 2.0 |
| * (the "License"); you may not use this file except in compliance with |
| * the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| package org.apache.cocoon.forms.binding; |
| |
| import java.util.ArrayList; |
| import java.util.Collection; |
| import java.util.Collections; |
| import java.util.HashMap; |
| import java.util.Iterator; |
| import java.util.List; |
| import java.util.Map; |
| |
| import org.apache.cocoon.forms.formmodel.Repeater.RepeaterRow; |
| |
| import org.apache.commons.jxpath.JXPathContext; |
| import org.apache.commons.jxpath.Pointer; |
| |
| /** |
| * @version $Id: RepeaterJXPathAdapter.java 517733 2007-03-13 15:37:22Z |
| * vgritsenko $ |
| */ |
| public class RepeaterJXPathAdapter implements RepeaterAdapter { |
| |
| private int progressive = 100000; |
| |
| private EnhancedRepeaterJXPathBinding binding; |
| private RepeaterJXPathCollection jxCollection; |
| private List sortedItems; |
| |
| public RepeaterFilter getFilter() { |
| return new RepeaterJXPathFilter(); |
| } |
| |
| private String findPathFor(String field) { |
| JXPathBindingBase[] childBindings = binding.getRowBinding().getChildBindings(); |
| String path = null; |
| for (int i = 0; i < childBindings.length; i++) { |
| if (childBindings[i] instanceof ValueJXPathBinding) { |
| ValueJXPathBinding bnd = (ValueJXPathBinding) childBindings[i]; |
| if (bnd.getFieldId().equals(field)) { |
| path = bnd.getXPath(); |
| break; |
| } |
| } |
| } |
| return path; |
| } |
| |
| public RepeaterSorter sortBy(String field) { |
| if (field == null) { |
| sortedItems = null; |
| return new NormalOrderJXPathSorter(); |
| } |
| String path = findPathFor(field); |
| if (path == null) { |
| throw new IllegalStateException("Cannot find a path for sorting on widget " + field); |
| } |
| RepeaterSorter sort = new RepeaterJXPathSorter(path, field); |
| if (sortedItems == null) { |
| List tsortedItems = new ArrayList(); |
| int i = 0; |
| RepeaterItem item = getItem(i); |
| while (item != null) { |
| tsortedItems.add(item); |
| i++; |
| item = getItem(i); |
| } |
| this.sortedItems = tsortedItems; |
| } |
| Collections.sort(sortedItems, sort); |
| return sort; |
| } |
| |
| public void setBinding(EnhancedRepeaterJXPathBinding binding) { |
| this.binding = binding; |
| } |
| |
| public void setCollection(Collection c) { |
| } |
| |
| public void setJXCollection(RepeaterJXPathCollection collection) { |
| this.jxCollection = collection; |
| } |
| |
| public RepeaterItem getItem(int i) { |
| if (i < 0) { |
| return null; |
| } |
| if (i >= jxCollection.getOriginalCollectionSize()) { |
| return null; |
| } |
| if (this.sortedItems == null) { |
| JXPathContext storageContext = this.jxCollection.getStorageContext(); |
| Pointer pointer = storageContext.getPointer(binding.getRowPath() + "[" + (i + 1) + "]"); |
| JXPathContext rowContext = storageContext.getRelativeContext(pointer); |
| RepeaterItem item = new RepeaterItem(new Integer(i + 1)); |
| item.setContext(rowContext); |
| return item; |
| } else { |
| return (RepeaterItem) sortedItems.get(i); |
| } |
| } |
| |
| class RepeaterJXPathFilter implements RepeaterFilter { |
| |
| private Map fieldsPaths = new HashMap(); |
| private Map fieldsValues = new HashMap(); |
| |
| public boolean shouldDisplay(RepeaterItem item) { |
| for (Iterator iter = fieldsValues.keySet().iterator(); iter.hasNext();) { |
| String field = (String) iter.next(); |
| Object value = fieldsValues.get(field); |
| Object acvalue = null; |
| if (item.getRow() == null) { |
| String path = (String) fieldsPaths.get(field); |
| acvalue = item.getContext().getValue(path); |
| } else { |
| acvalue = item.getRow().getChild(field).getValue(); |
| } |
| if (acvalue == null) { |
| return false; |
| } |
| if (acvalue instanceof String && value instanceof String) { |
| return ((String) acvalue).startsWith((String) value); |
| } else { |
| return acvalue.equals(value); |
| } |
| } |
| return true; |
| } |
| |
| public void setFilter(String field, Object value) { |
| if (value == null || ((value instanceof String) && ((String)value).length() == 0)) { |
| fieldsPaths.remove(field); |
| fieldsValues.remove(field); |
| } else { |
| String path = findPathFor(field); |
| if (path == null) { |
| throw new IllegalStateException("Cannot find a path for filtering on widget " + field); |
| } |
| fieldsPaths.put(field, path); |
| fieldsValues.put(field, value); |
| } |
| } |
| |
| } |
| |
| static class RepeaterJXPathSorter implements RepeaterSorter { |
| |
| private String path; |
| private String field; |
| |
| public RepeaterJXPathSorter(String path, String field) { |
| this.path = path; |
| this.field = field; |
| } |
| |
| public void setCollection(Collection c) { |
| } |
| |
| public int compare(Object o1, Object o2) { |
| RepeaterItem i1 = (RepeaterItem) o1; |
| RepeaterItem i2 = (RepeaterItem) o2; |
| |
| Object val1; |
| if (i1.getRow() != null) { |
| val1 = i1.getRow().getChild(field).getValue(); |
| } else { |
| val1 = i1.getContext().getValue(path); |
| } |
| |
| Object val2; |
| if (i2.getRow() != null) { |
| val2 = i2.getRow().getChild(field).getValue(); |
| } else { |
| val2 = i2.getContext().getValue(path); |
| } |
| |
| if (val1 instanceof Comparable) { |
| return ((Comparable) val1).compareTo(val2); |
| } |
| return val1.toString().compareTo(val2.toString()); |
| } |
| |
| } |
| |
| static class NormalOrderJXPathSorter implements RepeaterSorter { |
| |
| public void setCollection(Collection c) { |
| } |
| |
| public int compare(Object o1, Object o2) { |
| RepeaterItem i1 = (RepeaterItem) o1; |
| RepeaterItem i2 = (RepeaterItem) o2; |
| return ((Integer) i1.getHandle()).compareTo((Integer) i2.getHandle()); |
| } |
| } |
| |
| public RepeaterItem generateItem(RepeaterRow row) { |
| RepeaterItem item = new RepeaterItem(new Integer(progressive++)); |
| item.setRow(row); |
| return item; |
| } |
| |
| public void populateRow(RepeaterItem item) throws BindingException { |
| binding.getRowBinding().loadFormFromModel(item.getRow(), item.getContext()); |
| } |
| |
| } |