/** * Copyright 2005-2016 hdiv.org * * Licensed 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.hdiv.state; import java.io.Serializable; import java.util.ArrayList; import java.util.List; /** * Data structure to store states of a page. * * @author Roberto Velasco */ public class Page implements IPage, Serializable { /** * Universal version identifier. Deserialization uses this number to ensure that a loaded class corresponds exactly to a serialized * object. */ private static final long serialVersionUID = -5701140762067196143L; /** * Contains the states of the page. Only used in memory strategy. */ protected List<IState> states = new ArrayList<IState>(); /** * Page <code>this</code> identifier. */ protected int id; /** * Unique id of flow */ protected String flowId; /** * Unique random token. Used only for links. * * @since HDIV 2.0.4 */ protected String randomToken; /** * Unique random token. Used only for forms with PATCH, POST, PUT or DELETE methods. * * @since 2.1.7 */ protected String formRandomToken; /** * Page size. */ protected transient int size; /** * Sequential counter to generate state ids. * * @since 2.1.11 */ protected int stateIdCounter; /** * True if this page is reused. The most common case is in an Ajax request. * * @since 2.1.11 */ protected boolean isReused; /** * Parent's state id * * @since 2.1.13 */ protected String parentStateId; @Deprecated public Page() { } public Page(final int id) { this.id = id; } /** * Adds a new state to the page <code>this</code>. * * @param state State that represents all the data that composes a possible request. */ public void addState(final IState state) { int stateId = state.getId(); int statesSize = states.size(); if (statesSize < stateId) { // There are empty positions before id, fill with null values for (int i = statesSize; i < stateId; i++) { states.add(i, null); } states.add(stateId, state); } else if (statesSize > stateId) { // overwrite existing position states.set(stateId, state); } else { // list size == id states.add(stateId, state); } } /** * Checks if exists a state with the given identifier <code>id</code>. * * @param id State identifier */ public boolean existState(final int id) { return states.get(id) != null; } /** * Returns the state with the given identifier <code>id</code> from the map of states * * @param id State identifier * @return IState State with the identifier <code>id</code>. */ public IState getState(final int id) { IState state = states.get(id); if (state != null) { state.setPage(this); } return state; } /** * @return Returns the page id. */ public int getId() { return id; } /** * @return Returns the page states. */ public List<? extends IState> getStates() { return states; } public int getNextStateId() { if (isReused) { // We have to synchronize reused Pages due to concurrency problems synchronized (this) { return stateIdCounter++; } } return stateIdCounter++; } public void markAsReused() { isReused = true; } public boolean isReused() { return isReused; } /** * @return Returns number of states. */ public int getStatesCount() { return states.size(); } /** * Returns the unique id of flow. * * @return the flow id */ public String getFlowId() { return flowId; } /** * @param flowId the flowId to set */ public void setFlowId(final String flowId) { this.flowId = flowId; } /** * Returns the corresponding token for the given HTTP method. * * @param type Token type * @return the randomToken * @since HDIV 2.1.7 */ public final String getRandomToken(final RandomTokenType type) { if (type == RandomTokenType.FORM) { return formRandomToken; } else { return randomToken; } } /** * @param randomToken the randomToken to set * @param type Token type * @since HDIV 2.1.7 */ public void setRandomToken(final String randomToken, final RandomTokenType type) { if (type == RandomTokenType.FORM) { formRandomToken = randomToken; } else { this.randomToken = randomToken; } } /** * @return the size */ public int getSize() { return size; } /** * @param size the size to set */ public void setSize(final int size) { this.size = size; } /** * @param parentStateId the parentStateId to set */ public void setParentStateId(final String parentStateId) { this.parentStateId = parentStateId; } /** * @return the parentStateId */ public String getParentStateId() { return parentStateId; } @Override public String toString() { StringBuilder result = new StringBuilder(); result.append("Page:").append(id).append(' '); for (IState state : states) { result.append(" ").append(String.valueOf(state)); } return result.toString(); } }