com.swordlord.gozer.databinding.DataBindingManager.java Source code

Java tutorial

Introduction

Here is the source code for com.swordlord.gozer.databinding.DataBindingManager.java

Source

/*-----------------------------------------------------------------------------
 **
 ** -Gozer is not Zuul-
 **
 ** Copyright 2017 by SwordLord - the coding crew - https://www.swordlord.com/
 **
 ** This program is free software; you can redistribute it and/or modify it
 ** under the terms of the GNU Affero General Public License as published by the Free
 ** Software Foundation, either version 3 of the License, or (at your option)
 ** any later version.
 **
 ** This program is distributed in the hope that it will be useful, but WITHOUT
 ** ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 ** FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Affero General Public License for
 ** more details.
 **
 ** You should have received a copy of the GNU Affero General Public License along
 ** with this program. If not, see <http://www.gnu.org/licenses/>.
 **
 **-----------------------------------------------------------------------------
 **
 ** $Id: DataBindingManager.java 1363 2012-10-19 15:22:22Z LordEidi $
 **
 **
 ** -Gozer is not Zuul-
 **
 ** Copyright 2017 by SwordLord - the coding crew - https://www.swordlord.com/
 **
 ** This program is free software; you can redistribute it and/or modify it
 ** under the terms of the GNU Affero General Public License as published by the Free
 ** Software Foundation, either version 3 of the License, or (at your option)
 ** any later version.
 **
 ** This program is distributed in the hope that it will be useful, but WITHOUT
 ** ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 ** FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Affero General Public License for
 ** more details.
 **
 ** You should have received a copy of the GNU Affero General Public License along
 ** with this program. If not, see <http://www.gnu.org/licenses/>.
 **
 **-----------------------------------------------------------------------------
 **
 ** $Id: DataBindingManager.java 1363 2012-10-19 15:22:22Z LordEidi $
 **
-----------------------------------------------------------------------------*/

package com.swordlord.gozer.databinding;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;

import javax.swing.event.EventListenerList;

import org.apache.cayenne.access.ToManyList;
import org.apache.cayenne.map.EntityResolver;
import org.apache.cayenne.map.ObjEntity;
import org.apache.cayenne.map.ObjRelationship;
import org.apache.commons.lang.NullArgumentException;
import com.swordlord.jalapeno.datacontainer.DataContainer;
import com.swordlord.jalapeno.datarow.DataRowBase;
import com.swordlord.jalapeno.datarow.DataRowKeyBase;
import com.swordlord.jalapeno.datatable.DataTableBase;
import com.swordlord.jalapeno.dataview.DataViewBase;
import com.swordlord.jalapeno.dataview.OrderingParam;
import com.swordlord.jalapeno.dataview.ViewFilter;
import com.swordlord.jalapeno.dataview.ViewFilterBuilder;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

@SuppressWarnings("serial")
public class DataBindingManager implements Serializable {
    protected static final Log LOG = LogFactory.getLog(DataBindingManager.class);

    // DataBinding needs to register itself for updates
    protected EventListenerList _listChangedEventHandler;

    protected HashMap<String, DataViewBase> _dataViews;
    protected DataContainer _dc;

    public DataBindingManager(DataContainer dc, DataBindingMember dataBindingMember) {
        _listChangedEventHandler = new EventListenerList();

        _dc = dc;
        _dataViews = new HashMap<String, DataViewBase>();

        updatePath(dataBindingMember);

        this.moveFirst(dataBindingMember);
    }

    public DataContainer getDataContainer() {
        return _dc;
    }

    public int getCount(DataBindingMember dbm) {
        DataViewBase dvb = getDataViewFromBindingMember(dbm);
        if (dvb == null) {
            return -1;
        }

        return dvb.size();
    }

    // Returns the row of the root table (needed for colouring the lists on
    // linked tables
    public DataRowBase getCurrentRootRow(DataBindingMember dbm) {
        DataViewBase dvb = getRootDataViewFromBindingMember(dbm);
        if (dvb == null) {
            return null;
        }

        return dvb.getCurrentRow();
    }

    public DataRowBase getCurrentRow(DataBindingMember dbm) {
        DataViewBase dvb = getDataViewFromBindingMember(dbm);
        if (dvb == null) {
            return null;
        }

        return dvb.getCurrentRow();
    }

    public void deleteCurrentRow(DataBindingMember dbm) {
        DataViewBase dvb = getDataViewFromBindingMember(dbm);
        if (dvb != null) {
            dvb.deleteCurrentRow();
        }
    }

    public DataViewBase getDataView(DataBindingMember dbm) {
        return getDataViewFromBindingMember(dbm);
    }

    public DataViewBase getDataViewFromPathName(String strPath) {
        return _dataViews.get(strPath);
    }

    private DataViewBase getDataViewFromBindingMember(DataBindingMember dbm) {
        DataViewBase dvb = _dataViews.get(dbm.getDataBindingPathName());
        if (dvb == null) {
            // lazy update
            updatePath(dbm);
            dvb = _dataViews.get(dbm.getDataBindingPathName());
        }
        return dvb;
    }

    public int getPosition(DataBindingMember dbm) {
        DataViewBase dvb = getDataViewFromBindingMember(dbm);
        if (dvb == null) {
            return -1;
        }

        return dvb.getPosition();
    }

    // TODO: This is hell of an ugly hack.
    // lets redo this as fast as possible
    public DataRowBase getResolvedRow(DataBindingMember dbm, DataRowBase rowFather) {
        LinkedList<DataBindingElement> elements = dbm.getDataBindingElements();
        return getResolvedRow(elements, dbm.getDataBindingRootTableName(), rowFather);
    }

    public DataRowBase getResolvedRow(LinkedList<DataBindingElement> elements, String strTableName,
            DataRowBase rowFather) {
        if ((elements == null) || (elements.size() == 0)) {
            LOG.error("elements is empty");
        }

        int i = 0;
        boolean propertyFound = true;
        for (DataBindingElement element : elements) {
            i++;
            if (!element.isField() && i < elements.size()) {
                String strPathElement = element.getPathElement();

                // ignore the same level
                if (strPathElement.compareToIgnoreCase(strTableName) != 0) {
                    Object property = rowFather.getProperty(strPathElement);

                    if (property == null) {
                        // continuous with next
                        propertyFound = false;
                    } else {
                        propertyFound = true;
                        if (property instanceof DataRowBase) {
                            rowFather = (DataRowBase) property;
                        } else if (property instanceof ToManyList) {
                            ToManyList list = (ToManyList) property;
                            if (list.size() > 0) {
                                rowFather = (DataRowBase) list.get(element.getRowNumber());
                            }
                        }
                    }
                    // this is some nice side effect where we just loop as long
                    // as we
                    // are not at the right level
                }
            }
        }

        if (propertyFound)
            return rowFather;
        else
            return null;

    }

    /**
     * TODO need to merge with getResolvedRow(DataBindingMember dbm, DataRowBase
     * rowFather). Today there is too many risk. We need a better Parser and a
     * lot of JUnit Tests.
     * 
     * @param dbm
     * @param rowFather
     * @return
     */
    public DataRowBase[] getResolvedRows(DataBindingMember dbm, DataRowBase rowFather) {
        LinkedList<DataBindingElement> elements = dbm.getDataBindingElements();
        return getResolvedRows(elements, dbm.getDataBindingRootTableName(), rowFather);
    }

    /**
     * TODO need to merge with getResolvedRow(LinkedList<DataBindingElement>
     * elements, String strTableName, DataRowBase rowFather). Today there is too
     * many risk. We need a better Parser and a lot of JUnit Tests.
     * 
     * @param elements
     * @param strTableName
     * @param rowFather
     * @return
     */
    public DataRowBase[] getResolvedRows(LinkedList<DataBindingElement> elements, String strTableName,
            DataRowBase rowFather) {
        if ((elements == null) || (elements.size() == 0)) {
            LOG.error("elements is empty");
        }

        ArrayList<DataRowBase> dataRowBaseLst = new ArrayList<DataRowBase>();
        boolean rowFound = false;
        for (DataBindingElement element : elements) {
            if (!element.isField()) {
                String strPathElement = element.getPathElement();

                // ignore the same level
                if (strPathElement.compareToIgnoreCase(strTableName) != 0) {
                    Object property = rowFather.getProperty(strPathElement);
                    if (property == null) {
                        return new DataRowBase[0];
                    } else {
                        if (property instanceof DataRowBase) {
                            rowFather = (DataRowBase) property;
                            rowFound = true;
                        } else if (property instanceof ToManyList) {
                            ToManyList list = (ToManyList) property;
                            if (list.size() > 0) {
                                if (elements.get(elements.size() - 2).equals(element)) { // Last element without field name
                                    if (list.getValueDirectly() == null) {
                                        try {
                                            rowFather = (DataRowBase) list.get(element.getRowNumber());
                                            rowFound = true;
                                        } catch (Exception e) {
                                            e.printStackTrace();
                                            return new DataRowBase[0];
                                        }
                                        dataRowBaseLst.add(rowFather);
                                        return dataRowBaseLst.toArray(new DataRowBase[dataRowBaseLst.size()]);
                                    } else {
                                        List<DataRowBase> lst = (List) list.getValueDirectly();
                                        return lst.toArray(new DataRowBase[lst.size()]);
                                    }
                                } else {
                                    rowFather = (DataRowBase) list.get(element.getRowNumber());
                                    rowFound = true;
                                }
                            }
                        }
                    }
                    // this is some nice side effect where we just loop as long
                    // as we
                    // are not at the right level
                }
            }
        }

        if (rowFound) {
            dataRowBaseLst.add(rowFather);
            return dataRowBaseLst.toArray(new DataRowBase[dataRowBaseLst.size()]);
        } else {
            return new DataRowBase[0];
        }
    }

    // Returns the dataview from the root table
    private DataViewBase getRootDataViewFromBindingMember(DataBindingMember dbm) {
        DataViewBase dvb = _dataViews.get(dbm.getDataBindingRootTableName());
        if (dvb == null) {
            // lazy update
            updatePath(dbm);
            dvb = _dataViews.get(dbm.getDataBindingRootTableName());
        }
        return dvb;
    }

    public List<DataRowBase> getRows(DataBindingMember dbm) {
        return getRows(dbm, null);
    }

    public List<DataRowBase> getRows(DataBindingMember dbm, long fromIndex, long toIndex) {
        return getRows(dbm, fromIndex, toIndex, null);
    }

    public List<DataRowBase> getRows(DataBindingMember dbm, long fromIndex, long toIndex,
            OrderingParam orderingParam) {
        DataViewBase dvb = getDataViewFromBindingMember(dbm);
        if (dvb == null) {
            return null;
        }

        // only replace the ordering when there already is an ordering!
        if (orderingParam != null) {
            String sort = orderingParam.getField();
            String path = dbm.getDataBindingPathName();

            path = path.replace(dbm.getDataBindingRootTableName() + ".", "");

            sort = sort.replace(path + ".", "");

            orderingParam = new OrderingParam(sort, orderingParam.isAscending());
        }

        return dvb.getRows(fromIndex, toIndex, orderingParam);
    }

    public List<DataRowBase> getRows(DataBindingMember dbm, OrderingParam orderingParam) {
        DataViewBase dvb = getDataViewFromBindingMember(dbm);
        if (dvb == null) {
            return null;
        }

        return dvb.getRows(orderingParam);
    }

    public void setFilter(DataBindingMember dbm, ViewFilter filter) {
        DataViewBase dvb = getDataViewFromBindingMember(dbm);
        if (dvb != null) {
            dvb.setFilter(filter);
        }
    }

    /**
     * Sets dataview ordering of the passed binding member (if there is one).
     * 
     * @param dbm
     *            The binding member for which to configure the data view
     * @param ordering
     *            The desired ordering
     */
    public void setOrdering(DataBindingMember dbm, OrderingParam ordering) {
        DataViewBase dvb = getDataViewFromBindingMember(dbm);
        if (dvb != null) {
            dvb.setOrdering(ordering);
        }
    }

    public boolean move(DataBindingMember dbm, DataRowKeyBase key) {
        DataViewBase dvb = getDataViewFromBindingMember(dbm);
        if (dvb == null) {
            return false;
        }

        return dvb.move(key);
    }

    public void moveFirst(DataBindingMember dbm) {
        DataViewBase dvb = getDataViewFromBindingMember(dbm);
        if (dvb == null) {
            return;
        }

        dvb.moveFirst();
    }

    public void moveLast(DataBindingMember dbm) {
        DataViewBase dvb = getDataViewFromBindingMember(dbm);
        if (dvb == null) {
            return;
        }

        dvb.moveLast();
    }

    public void moveNext(DataBindingMember dbm) {
        DataViewBase dvb = getDataViewFromBindingMember(dbm);
        if (dvb == null) {
            return;
        }

        dvb.moveNext();
    }

    public void movePrevious(DataBindingMember dbm) {
        DataViewBase dvb = getDataViewFromBindingMember(dbm);
        if (dvb == null) {
            return;
        }

        dvb.movePrevious();
    }

    public boolean moveRoot(DataBindingMember dbm, DataRowKeyBase key) {
        DataViewBase dvb = getRootDataViewFromBindingMember(dbm);
        if (dvb == null) {
            return false;
        }

        return dvb.move(key);
    }

    private void updatePath(DataBindingMember dbm) {
        LinkedList<DataBindingElement> elements = dbm.getDataBindingElements();
        if ((elements == null) || (elements.size() == 0)) {
            throw new NullArgumentException("dataBindingMember");
        }

        ObjEntity oeLastTable = null;
        ObjEntity oeCurrentTable = null;

        String strConcatPath = "";

        EntityResolver er = _dc.getObjectContext().getEntityResolver();

        for (DataBindingElement element : elements) {
            String strPathElement = element.getPathElement();

            // Find table from binding info
            if (strPathElement.startsWith("rel_")) {
                ObjRelationship rel = (ObjRelationship) oeLastTable.getRelationship(strPathElement);

                if (rel == null) {
                    LOG.error("Relation is not known: " + strPathElement);
                    throw new NullArgumentException(strPathElement);
                }

                oeCurrentTable = (ObjEntity) rel.getTargetEntity();
            } else {
                oeCurrentTable = er.getObjEntity(strPathElement);
            }

            // add the whole path instead of current element only to make sure
            // that binding over the same table multiple times does not confuse
            // the binding
            String strFather = strConcatPath;
            strConcatPath += strConcatPath.length() > 0 ? "." + strPathElement : strPathElement;
            if (!_dataViews.containsKey(strConcatPath) && !element.isField()) {
                String strTableName = oeCurrentTable.getClassName();

                strTableName = strTableName.replaceAll("DataRow", "DataTable");
                strTableName = strTableName.replaceAll("datarow", "datatable");

                DataTableBase dtb = _dc.getTableByAbsoluteName(strTableName);
                if (dtb == null) {
                    LOG.info("Table can not be found: " + strTableName);
                }

                DataViewBase dvFather = null;

                if (strFather.length() > 0) {
                    dvFather = _dataViews.get(strFather);
                }

                DataViewBase dvb = new DataViewBase(strConcatPath, strPathElement, dvFather, dtb);
                dvb.setPosition(element.getRowNumber());

                if (element.hasFilter()) {
                    dvb.setFilter(ViewFilterBuilder.createSimple(element.getFilter()));
                }

                // Store the dataviewbase under the name of the path element so
                // that no
                // further lookup is needed to find dataview from path element
                // during binding
                _dataViews.put(strConcatPath, dvb);
            }

            // set last table so that next path element can load correct
            // objentity.
            oeLastTable = oeCurrentTable;
        }
    }

    /**
     * Search the parent DataViewBase from the given DataViewBase
     * 
     * @param dataViewBase
     *            The Child DataViewBase
     * @return
     */
    public DataViewBase getParentDataViewBase(String dataViewName) {
        String dvbNameParent = dataViewName.substring(0, dataViewName.lastIndexOf("."));

        return _dataViews.get(dvbNameParent);
    }

    /**
     * Refresh the parent
     * 
     * @param dbMember
     */
    public void refreshParent(DataBindingMember dbMember) {
        DataViewBase dv = getDataView(dbMember);
        DataViewBase dvParent = getParentDataViewBase(dv.getAbsoluteDataBindingPathName());

        dvParent.fireCurrentRowChangedEvent();
    }
}