org.apache.cocoon.forms.binding.RepeaterJXPathAdapter.java Source code

Java tutorial

Introduction

Here is the source code for org.apache.cocoon.forms.binding.RepeaterJXPathAdapter.java

Source

/*
 * 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());
    }

}