org.apache.cayenne.modeler.util.CayenneTableModel.java Source code

Java tutorial

Introduction

Here is the source code for org.apache.cayenne.modeler.util.CayenneTableModel.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.cayenne.modeler.util;

import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Method;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

import javax.swing.JOptionPane;
import javax.swing.table.AbstractTableModel;

import org.apache.cayenne.CayenneRuntimeException;
import org.apache.cayenne.modeler.Application;
import org.apache.cayenne.modeler.ProjectController;
import org.apache.cayenne.modeler.undo.CayenneTableModelUndoableEdit;
import org.apache.cayenne.util.Util;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/**
 * Superclass of CayenneModeler table model classes.
 * 
 */
public abstract class CayenneTableModel<T> extends AbstractTableModel {

    protected ProjectController mediator;
    protected Object eventSource;
    protected List<T> objectList;

    private static Log logObj = LogFactory.getLog(CayenneTableModel.class);

    /**
     * Constructor for CayenneTableModel.
     */
    public CayenneTableModel(ProjectController mediator, Object eventSource, java.util.List<T> objectList) {

        super();
        this.eventSource = eventSource;
        this.mediator = mediator;
        this.objectList = objectList;

        //orderList();
    }

    public void setValueAt(Object newVal, int row, int col) {
        try {

            Object oldValue = getValueAt(row, col);
            if (!Util.nullSafeEquals(newVal, oldValue)) {

                setUpdatedValueAt(newVal, row, col);

                this.mediator.getApplication().getUndoManager()
                        .addEdit(new CayenneTableModelUndoableEdit(this, oldValue, newVal, row, col));
            }
        } catch (IllegalArgumentException e) {
            logObj.error("Error setting table model value", e);
            JOptionPane.showMessageDialog(Application.getFrame(), e.getMessage(), "Invalid value",
                    JOptionPane.ERROR_MESSAGE);
        }
    }

    /**
     * Sets a new value after it is already checked by the superclass and it is determined
     * that the value has changed.
     */
    public abstract void setUpdatedValueAt(Object newVal, int row, int col);

    /**
     * Orders internal object list. Key returned by <code>getOrderingKey</code> is used
     * for comparison.
     */
    protected void orderList() {
        String key = getOrderingKey();
        if (key != null) {
            Collections.sort(objectList, new PropertyComparator(getOrderingKey(), getElementsClass()));
        }
    }

    /**
     * Returns Java class of the internal list elements.
     */
    public abstract Class<?> getElementsClass();

    /**
     * Returns the key by which to order elements in the object list. Default value is
     * "name".
     */
    public String getOrderingKey() {
        return "name";
    }

    /**
     * Returns the number of objects on the list.
     */
    public int getRowCount() {
        return objectList.size();
    }

    /**
     * Returns an object used as an event source.
     */
    public Object getEventSource() {
        return eventSource;
    }

    /**
     * Returns EventController object.
     */
    public ProjectController getMediator() {
        return mediator;
    }

    /**
     * Returns internal object list.
     */
    public java.util.List<T> getObjectList() {
        return objectList;
    }

    public void addRow(T row) {
        objectList.add(row);
        fireTableDataChanged();
    }

    public void removeRow(Object row) {
        objectList.remove(row);
        fireTableDataChanged();
    }

    /**
     * Moves a row up, jumping down if row is already at the top.
     */
    public int moveRowUp(Object row) {
        int len = objectList.size();
        if (len < 2) {
            return -1;
        }

        int ind = objectList.indexOf(row);
        if (ind <= 0) {
            return -1;
        }

        int neighborIndex = ind - 1;
        if (neighborIndex < 0) {
            neighborIndex = len - 1;
        }

        swapRows(ind, neighborIndex);
        return neighborIndex;
    }

    /**
     * Moves a row down, jumping up if row is already at the bottom.
     */
    public int moveRowDown(Object row) {
        int len = objectList.size();
        if (len < 2) {
            return -1;
        }

        int ind = objectList.indexOf(row);
        // not valid if it is not found or it is at the end of the list
        if (ind < 0 || (ind + 1) >= len) {
            return -1;
        }

        int neighborIndex = ind + 1;

        swapRows(ind, neighborIndex);
        return neighborIndex;
    }

    protected void swapRows(int i, int j) {
        Collections.swap(objectList, i, j);
        fireTableDataChanged();
    }

    /**
     * Correct errors that model has.
     */
    public void resetModel() {
        // do nothing by default
    }

    /**
     * @return false, if model is not valid. 
     */
    public boolean isValid() {
        return true;
    }

    protected class PropertyComparator implements Comparator {

        Method getter;

        PropertyComparator(String propertyName, Class beanClass) {
            try {
                getter = findGetter(beanClass, propertyName);
            } catch (IntrospectionException e) {
                throw new CayenneRuntimeException("Introspection error", e);
            }
        }

        Method findGetter(Class beanClass, String propertyName) throws IntrospectionException {
            BeanInfo info = Introspector.getBeanInfo(beanClass);
            PropertyDescriptor[] descriptors = info.getPropertyDescriptors();

            for (PropertyDescriptor descriptor : descriptors) {
                if (propertyName.equals(descriptor.getName())) {
                    return descriptor.getReadMethod();
                }
            }

            throw new IntrospectionException("No getter found for " + propertyName);
        }

        public int compare(Object o1, Object o2) {

            if ((o1 == null && o2 == null) || o1 == o2) {
                return 0;
            } else if (o1 == null && o2 != null) {
                return -1;
            } else if (o1 != null && o2 == null) {
                return 1;
            }

            try {
                Comparable p1 = (Comparable) getter.invoke(o1);
                Comparable p2 = (Comparable) getter.invoke(o2);

                return (p1 == null) ? -1 : (p2 == null) ? 1 : p1.compareTo(p2);
            } catch (Exception ex) {
                throw new CayenneRuntimeException("Error reading property.", ex);
            }
        }
    }

    public abstract void sortByColumn(int sortCol, boolean isAscent);

    public abstract boolean isColumnSortable(int sortCol);

    public void sortByElementProperty(String string, boolean isAscent) {
        Collections.sort(objectList, new PropertyComparator(string, getElementsClass()));
        if (!isAscent) {
            Collections.reverse(objectList);
        }
    }

}