001// Copyright 2004, 2005 The Apache Software Foundation
002//
003// Licensed under the Apache License, Version 2.0 (the "License");
004// you may not use this file except in compliance with the License.
005// You may obtain a copy of the License at
006//
007//     http://www.apache.org/licenses/LICENSE-2.0
008//
009// Unless required by applicable law or agreed to in writing, software
010// distributed under the License is distributed on an "AS IS" BASIS,
011// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
012// See the License for the specific language governing permissions and
013// limitations under the License.
014
015package org.apache.tapestry.contrib.tree.components.table;
016
017import java.util.ArrayList;
018import java.util.Iterator;
019import java.util.List;
020
021import org.apache.tapestry.BaseComponent;
022import org.apache.tapestry.IMarkupWriter;
023import org.apache.tapestry.IRequestCycle;
024import org.apache.tapestry.contrib.table.model.ITableColumn;
025import org.apache.tapestry.contrib.table.model.ITableModel;
026import org.apache.tapestry.contrib.table.model.ITableSessionStateManager;
027import org.apache.tapestry.contrib.table.model.simple.SimpleListTableDataModel;
028import org.apache.tapestry.contrib.table.model.simple.SimpleTableColumnModel;
029import org.apache.tapestry.contrib.table.model.simple.SimpleTableModel;
030import org.apache.tapestry.contrib.table.model.simple.SimpleTableSessionStateManager;
031import org.apache.tapestry.contrib.tree.model.ITreeDataModel;
032import org.apache.tapestry.contrib.tree.model.ITreeModel;
033import org.apache.tapestry.contrib.tree.model.ITreeModelSource;
034import org.apache.tapestry.contrib.tree.model.ITreeRowSource;
035import org.apache.tapestry.contrib.tree.model.TreeRowObject;
036import org.apache.tapestry.event.PageDetachListener;
037import org.apache.tapestry.event.PageEvent;
038
039/**
040 */
041public abstract class TreeTableDataView extends BaseComponent implements ITreeRowSource,
042        PageDetachListener
043{
044    private int m_nTreeDeep = -1;
045
046    private TreeRowObject m_objTreeRowObject = null;
047
048    private ArrayList m_arrAllExpandedNodes = null;
049
050    public TreeTableDataView()
051    {
052        super();
053        initialize();
054    }
055
056    public void initialize()
057    {
058        m_nTreeDeep = -1;
059        // m_objTableModel = null;
060        m_objTreeRowObject = null;
061        m_arrAllExpandedNodes = null;
062    }
063
064    /**
065     * @see org.apache.tapestry.event.PageDetachListener#pageDetached(org.apache.tapestry.event.PageEvent)
066     */
067    public void pageDetached(PageEvent event)
068    {
069        initialize();
070    }
071
072    public abstract ITreeModelSource getTreeViewParameter();
073
074    public ITreeModelSource getTreeModelSource()
075    {
076        ITreeModelSource objSource = (ITreeModelSource) getPage().getRequestCycle().getAttribute(
077                ITreeModelSource.TREE_MODEL_SOURCE_ATTRIBUTE);
078
079        return objSource == null ? getTreeViewParameter() : objSource;
080    }
081
082    public List generateNodeList()
083    {
084        if (m_arrAllExpandedNodes == null)
085        {
086            ArrayList arrAllExpandedNodes = new ArrayList();
087
088            // render data
089            ITreeModelSource objTreeModelSource = getTreeModelSource();
090            ITreeModel objTreeModel = objTreeModelSource.getTreeModel();
091            ITreeDataModel objTreeDataModel = objTreeModel.getTreeDataModel();
092
093            Object objRoot = objTreeDataModel.getRoot();
094            Object objRootUID = objTreeDataModel.getUniqueKey(objRoot, null);
095            if (getShowRootNode())
096            {
097                walkTree(
098                        arrAllExpandedNodes,
099                        objRoot,
100                        objRootUID,
101                        0,
102                        objTreeModel,
103                        TreeRowObject.FIRST_LAST_ROW,
104                        new int[0],
105                        true);
106            }
107            else
108            {
109                int nChildenCount = objTreeModel.getTreeDataModel().getChildCount(objRoot);
110                int nRowPossiotionType = nChildenCount == 1 ? TreeRowObject.FIRST_LAST_ROW
111                        : TreeRowObject.FIRST_ROW;
112                boolean bFirst = true;
113                for (Iterator iter = objTreeModel.getTreeDataModel().getChildren(objRoot); iter
114                        .hasNext();)
115                {
116                    Object objChild = iter.next();
117                    Object objChildUID = objTreeModel.getTreeDataModel().getUniqueKey(
118                            objChild,
119                            objRoot);
120                    boolean bChildLast = !iter.hasNext();
121                    if (!bFirst)
122                    {
123                        if (bChildLast)
124                            nRowPossiotionType = TreeRowObject.LAST_ROW;
125                        else
126                            nRowPossiotionType = TreeRowObject.MIDDLE_ROW;
127                    }
128                    walkTree(
129                            arrAllExpandedNodes,
130                            objChild,
131                            objChildUID,
132                            0,
133                            objTreeModel,
134                            nRowPossiotionType,
135                            new int[0],
136                            bChildLast);
137                    bFirst = false;
138                }
139            }
140
141            m_arrAllExpandedNodes = arrAllExpandedNodes;
142        }
143
144        return m_arrAllExpandedNodes;
145    }
146
147    public void walkTree(ArrayList arrAllExpandedNodes, Object objParent, Object objParentUID,
148            int nDepth, ITreeModel objTreeModel, int nRowPossiotionType, int[] arrConnectImages,
149            boolean bLast)
150    {
151        m_nTreeDeep = nDepth;
152
153        int nNumberOfChildren = objTreeModel.getTreeDataModel().getChildCount(objParent);
154        boolean bLeaf = (nNumberOfChildren == 0) ? true : false;
155        TreeRowObject objTreeRowObject = new TreeRowObject(objParent, objParentUID, nDepth, bLeaf,
156                nRowPossiotionType, arrConnectImages);
157        arrAllExpandedNodes.add(objTreeRowObject);
158
159        boolean bContain = objTreeModel.getTreeStateModel().isUniqueKeyExpanded(objParentUID);
160        if (bContain)
161        {
162            int[] arrConnectImagesNew = new int[arrConnectImages.length + 1];
163            System.arraycopy(arrConnectImages, 0, arrConnectImagesNew, 0, arrConnectImages.length);
164            if (bLast)
165                arrConnectImagesNew[arrConnectImagesNew.length - 1] = TreeRowObject.EMPTY_CONN_IMG;
166            else
167                arrConnectImagesNew[arrConnectImagesNew.length - 1] = TreeRowObject.LINE_CONN_IMG;
168            Iterator colChildren = objTreeModel.getTreeDataModel().getChildren(objParent);
169            for (Iterator iter = colChildren; iter.hasNext();)
170            {
171                Object objChild = iter.next();
172                Object objChildUID = objTreeModel.getTreeDataModel().getUniqueKey(
173                        objChild,
174                        objParentUID);
175                boolean bChildLast = !iter.hasNext();
176                if (bChildLast)
177                    nRowPossiotionType = TreeRowObject.LAST_ROW;
178                else
179                    nRowPossiotionType = TreeRowObject.MIDDLE_ROW;
180                walkTree(
181                        arrAllExpandedNodes,
182                        objChild,
183                        objChildUID,
184                        nDepth + 1,
185                        objTreeModel,
186                        nRowPossiotionType,
187                        arrConnectImagesNew,
188                        bChildLast);
189            }
190        }
191    }
192
193    /**
194     * Returns the treeDeep.
195     * 
196     * @return int
197     */
198    public int getTreeDeep()
199    {
200        return m_nTreeDeep;
201    }
202
203    /*
204     * public ITableModel getTableModel() { if(m_objTableModel == null){ m_objTableModel =
205     * createTableModel(); } return m_objTableModel; }
206     */
207    public ITableModel getTableModel()
208    {
209        return createTableModel();
210    }
211
212    private ITableModel createTableModel()
213    {
214        List arrAllNodes = generateNodeList();
215        Object[] arrAllExpandedNodes = new Object[arrAllNodes.size()];
216        arrAllNodes.toArray(arrAllExpandedNodes);
217
218        SimpleTableModel objTableModel = new SimpleTableModel(arrAllExpandedNodes,
219                getTableColumns());
220        objTableModel.getPagingState().setPageSize(getEntriesPerTablePage());
221
222        return objTableModel;
223    }
224
225    public ITableColumn[] getTableColumns()
226    {
227        ArrayList arrColumnsList = new ArrayList();
228        arrColumnsList.add(new TreeTableColumn("Name", false, null));
229
230        List arrTableColumns = getTableColumnsParameter();
231        if (arrTableColumns != null)
232            arrColumnsList.addAll(arrTableColumns);
233
234        ITableColumn[] arrColumns = new ITableColumn[arrColumnsList.size()];
235        arrColumnsList.toArray(arrColumns);
236
237        return arrColumns;
238    }
239
240    public abstract List getTableColumnsParameter();
241
242    public abstract int getEntriesPerTablePage();
243
244    /**
245     * @see org.apache.tapestry.contrib.tree.model.ITreeRowSource#getTreeRow()
246     */
247    public TreeRowObject getTreeRow()
248    {
249        return getTreeRowObject();
250    }
251
252    public ITableSessionStateManager getTableSessionStateManager()
253    {
254        SimpleListTableDataModel objDataModel = new SimpleListTableDataModel(generateNodeList());
255        SimpleTableColumnModel objColumnModel = new SimpleTableColumnModel(getTableColumns());
256        SimpleTableSessionStateManager objStateManager = new SimpleTableSessionStateManager(
257                objDataModel, objColumnModel);
258        return objStateManager;
259        // return NullTableSessionStateManager.NULL_STATE_MANAGER;
260    }
261
262    /**
263     * @see org.apache.tapestry.BaseComponent#renderComponent(org.apache.tapestry.IMarkupWriter,
264     *      org.apache.tapestry.IRequestCycle)
265     */
266    protected void renderComponent(IMarkupWriter writer, IRequestCycle cycle)
267    {
268        Object objExistedTreeModelSource = cycle
269                .getAttribute(ITreeRowSource.TREE_ROW_SOURCE_ATTRIBUTE);
270        cycle.setAttribute(ITreeRowSource.TREE_ROW_SOURCE_ATTRIBUTE, this);
271
272        super.renderComponent(writer, cycle);
273
274        cycle.setAttribute(ITreeRowSource.TREE_ROW_SOURCE_ATTRIBUTE, objExistedTreeModelSource);
275    }
276
277    /**
278     * @see org.apache.tapestry.AbstractComponent#renderBody(org.apache.tapestry.IMarkupWriter,
279     *      org.apache.tapestry.IRequestCycle)
280     */
281    public void renderBody(IMarkupWriter writer, IRequestCycle cycle)
282    {
283        Object objExistedTreeModelSource = cycle
284                .getAttribute(ITreeRowSource.TREE_ROW_SOURCE_ATTRIBUTE);
285        cycle.setAttribute(ITreeRowSource.TREE_ROW_SOURCE_ATTRIBUTE, this);
286
287        super.renderBody(writer, cycle);
288
289        cycle.setAttribute(ITreeRowSource.TREE_ROW_SOURCE_ATTRIBUTE, objExistedTreeModelSource);
290    }
291
292    public TreeRowObject getTreeRowObject()
293    {
294        return m_objTreeRowObject;
295    }
296
297    public void setTreeRowObject(TreeRowObject object)
298    {
299        m_objTreeRowObject = object;
300    }
301
302    public abstract boolean getShowRootNode();
303}