/* * Copyright 2004-2012 the original author or authors. * * 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.springframework.webflow.execution.repository.impl; import java.io.Serializable; import java.util.HashMap; import java.util.LinkedList; import java.util.Map; import org.springframework.webflow.execution.repository.snapshot.FlowExecutionSnapshot; import org.springframework.webflow.execution.repository.snapshot.SnapshotNotFoundException; /** * A group of flow execution snapshots. Simple typed data structure backed by a map and linked list. Supports expelling * the oldest snapshot if the maximum size is met. * * @author Keith Donald */ class SimpleFlowExecutionSnapshotGroup implements FlowExecutionSnapshotGroup, Serializable { /** * The snapshot map; the key is a snapshot id, and the value is a {@link FlowExecutionSnapshot} object. */ private Map<Serializable, FlowExecutionSnapshot> snapshots = new HashMap<Serializable, FlowExecutionSnapshot>(); /** * An ordered list of snapshot ids. Each snapshot id represents an pointer to a {@link FlowExecutionSnapshot} in the * map. The first element is the oldest snapshot and the last is the youngest. */ private LinkedList<Serializable> snapshotIds = new LinkedList<Serializable>(); /** * The maximum number of snapshots allowed in this group. -1 indicates no max limit. */ private int maxSnapshots = -1; /** * The snapshot id sequence ensuring unique snapshot ids within this group; snapshot ids start at 1. */ private int snapshotIdSequence = 1; /** * Returns the maximum number of snapshots allowed in this group. */ public int getMaxSnapshots() { return maxSnapshots; } /** * Sets the maximum number of snapshots allowed in this group. * @param maxSnapshots them max number of snapshots */ public void setMaxSnapshots(int maxSnapshots) { this.maxSnapshots = maxSnapshots; } public FlowExecutionSnapshot getSnapshot(Serializable snapshotId) throws SnapshotNotFoundException { FlowExecutionSnapshot snapshot = snapshots.get(snapshotId); if (snapshot == null) { throw new SnapshotNotFoundException(snapshotId); } return snapshot; } public void addSnapshot(Serializable snapshotId, FlowExecutionSnapshot snapshot) { snapshots.put(snapshotId, snapshot); if (snapshotIds.contains(snapshotId)) { snapshotIds.remove(snapshotId); } snapshotIds.add(snapshotId); if (maxExceeded()) { removeOldestSnapshot(); } } public void updateSnapshot(Serializable snapshotId, FlowExecutionSnapshot snapshot) { if (!snapshots.containsKey(snapshotId)) { return; } snapshots.put(snapshotId, snapshot); } public void removeSnapshot(Serializable snapshotId) { snapshots.remove(snapshotId); snapshotIds.remove(snapshotId); } public void removeAllSnapshots() { snapshots.clear(); snapshotIds.clear(); } public int getSnapshotCount() { return snapshotIds.size(); } public Serializable nextSnapshotId() { Integer nextSnapshotId = Integer.valueOf(snapshotIdSequence); snapshotIdSequence++; return nextSnapshotId; } /** * Has the maximum number of snapshots in this group been exceeded? */ private boolean maxExceeded() { return maxSnapshots > 0 && snapshotIds.size() > maxSnapshots; } /** * Remove the olders snapshot from this group. */ private void removeOldestSnapshot() { snapshots.remove(snapshotIds.removeFirst()); } }