001/**
002 * Copyright 2005-2018 The Kuali Foundation
003 *
004 * Licensed under the Educational Community License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 * http://www.opensource.org/licenses/ecl2.php
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016package org.kuali.rice.krad.web.form;
017
018import org.kuali.rice.krad.uif.element.BreadcrumbItem;
019import org.kuali.rice.krad.uif.util.UrlInfo;
020
021import java.io.Serializable;
022import java.util.ArrayList;
023import java.util.List;
024import java.util.Stack;
025
026/**
027 * HistoryFlow represents the a flow of urls.  When the flow is continued, the flow inherits the urls/breadcrumbs from
028 * a previous flow.  Using a flow key it is possible to jump back to previous flows.
029 *
030 * @author Kuali Rice Team (rice.collab@kuali.org)
031 */
032public class HistoryFlow implements Serializable {
033    private static final long serialVersionUID = 452587887145986691L;
034
035    protected String flowKey;
036    protected String flowReturnPoint;
037    protected String flowStartPoint;
038
039    protected Stack<UrlInfo> flowUrls = new Stack<UrlInfo>();
040
041    protected BreadcrumbItem currentViewItem;
042    protected List<BreadcrumbItem> pastItems;
043
044    /**
045     * Initialize a new HistoryFlow with a key
046     *
047     * @param flowKey the flowKey to use
048     */
049    public HistoryFlow (String flowKey) {
050        this.flowKey = flowKey;
051    }
052
053    /**
054     * Get all urls in the HistoryFlow stack
055     *
056     * @return the stack of HistoryFlow urls
057     */
058    public Stack<UrlInfo> getFlowUrls() {
059        return flowUrls;
060    }
061
062    /**
063     * Set the flowUrls for this HistoryFlow
064     *
065     * @param flowUrls
066     */
067    public void setFlowUrls(Stack<UrlInfo> flowUrls) {
068        this.flowUrls = flowUrls;
069    }
070
071    /**
072     * The returnPoint used to jump back to a previous flow
073     *
074     * @return the flowReturnPoint
075     */
076    public String getFlowReturnPoint() {
077        return flowReturnPoint;
078    }
079
080    /**
081     * Set the returnPoint for use to jump back to the previous flow
082     *
083     * @param flowReturnPoint
084     */
085    public void setFlowReturnPoint(String flowReturnPoint) {
086        this.flowReturnPoint = flowReturnPoint;
087    }
088
089    /**
090     * Represents the very first url in the flow, the "start point", the view that initiated this flow trail
091     *
092     * @return the very first url in the flow
093     */
094    public String getFlowStartPoint() {
095        return flowStartPoint;
096    }
097
098    /**
099     * @see HistoryFlow#getFlowStartPoint()
100     */
101    public void setFlowStartPoint(String flowStartPoint) {
102        this.flowStartPoint = flowStartPoint;
103    }
104
105    /**
106     * The flowKey used to identify the HistoryFlow
107     *
108     * @return
109     */
110    public String getFlowKey() {
111        return flowKey;
112    }
113
114    /**
115     * Set the flowKey for this HistoryFlow
116     *
117     * @param flowKey
118     */
119    public void setFlowKey(String flowKey) {
120        this.flowKey = flowKey;
121    }
122
123    /**
124     * Push the url onto the history stack
125     *
126     * @param url the url to push
127     */
128    public void push(String url){
129        UrlInfo urlInfo = new UrlInfo();
130        urlInfo.setHref(url);
131        flowUrls.push(urlInfo);
132    }
133
134    /**
135     * Push the url onto the history stack
136     *
137     * @param urlInfo the urlInfo object to push
138     */
139    public void push(UrlInfo urlInfo){
140        flowUrls.push(urlInfo);
141    }
142
143    /**
144     * Update the last url on the history stack with the new value
145     *
146     * @param url the url to update to
147     */
148    public void update(String url){
149        UrlInfo urlInfo = new UrlInfo();
150        urlInfo.setHref(url);
151
152        if(flowUrls.empty()){
153            flowUrls.push(urlInfo);
154        }
155        else{
156            flowUrls.pop();
157            flowUrls.push(urlInfo);
158        }
159    }
160
161    /**
162     * Update the last url on the history stack with the new value
163     *
164     * @param urlInfo the UrlInfo object to update to
165     */
166    public void update(UrlInfo urlInfo){
167        if(flowUrls.empty()){
168            flowUrls.push(urlInfo);
169        }
170        else{
171            flowUrls.pop();
172            flowUrls.push(urlInfo);
173        }
174    }
175
176    /**
177     * Get the last url on the history stack
178     *
179     * @return the last url on the history stack
180     */
181    public String getCurrentLocation(){
182        if(flowUrls != null && !flowUrls.isEmpty()){
183            return flowUrls.peek().getHref();
184        }
185
186        return null;
187    }
188
189    /**
190     * Clear all urls on the history stack and accumulated breadcrumbs
191     */
192    public void clear(){
193        flowUrls.clear();
194        pastItems.clear();
195        currentViewItem = null;
196        flowReturnPoint = null;
197    }
198
199    /**
200     * Continue a new flow from a previous flow.  This will copy the prevFlow's flow urls to flowUrls,
201     * pastItems and currentViewItem to the new flow's pastItems, and set the flowReturnPoint to the currentLocation
202     * of the prevFlow.
203     *
204     * @param prevFlow
205     */
206    public void continueFlow(HistoryFlow prevFlow){
207        if(prevFlow != null){
208            flowReturnPoint = prevFlow.getCurrentLocation();
209            this.setFlowUrls(prevFlow.getFlowUrls());
210
211            if(this.getFlowUrls() != null && !this.getFlowUrls().isEmpty()){
212                flowStartPoint = this.getFlowUrls().firstElement().getHref();
213            }
214
215            pastItems = new ArrayList<BreadcrumbItem>();
216
217            if (prevFlow.getPastItems() != null){
218                pastItems.addAll(prevFlow.getPastItems());
219            }
220
221            if (prevFlow.getCurrentViewItem() != null){
222                pastItems.add(prevFlow.getCurrentViewItem());
223            }
224        }
225    }
226
227    /**
228     * Get the item which represents the most current BreadcrumbItem for the View for this flow
229     *
230     * @return the View BreadcrumbItem
231     */
232    public BreadcrumbItem getCurrentViewItem() {
233        return currentViewItem;
234    }
235
236    /**
237     * Set the current BreadcrumbItem
238     *
239     * @param currentViewItem
240     */
241    public void setCurrentViewItem(BreadcrumbItem currentViewItem) {
242        this.currentViewItem = currentViewItem;
243    }
244
245    /**
246     * Get all the past BreadcrumbItems (these represents the path to the current item)
247     *
248     * @return the past BreadcrumbItems
249     */
250    public List<BreadcrumbItem> getPastItems() {
251        return pastItems;
252    }
253
254    /**
255     * Set the past BreadcrumbItems
256     *
257     * @param pastItems
258     */
259    public void setPastItems(List<BreadcrumbItem> pastItems) {
260        this.pastItems = pastItems;
261    }
262}