More work on commands, statemgmt, EL references
[mkjsf-moved-to-github.git] / src / main / java / com / indexdata / pz2utils4jsf / pazpar2 / state / StateManager.java
1 package com.indexdata.pz2utils4jsf.pazpar2.state;\r
2 \r
3 import java.io.Serializable;\r
4 import java.util.ArrayList;\r
5 import java.util.Arrays;\r
6 import java.util.HashMap;\r
7 import java.util.List;\r
8 import java.util.Map;\r
9 \r
10 import javax.enterprise.context.SessionScoped;\r
11 \r
12 import org.apache.log4j.Logger;\r
13 \r
14 import com.indexdata.pz2utils4jsf.pazpar2.commands.Pazpar2Command;\r
15 import com.indexdata.pz2utils4jsf.utils.Utils;\r
16 \r
17 @SessionScoped\r
18 public class StateManager implements Serializable {\r
19   \r
20   private static final long serialVersionUID = 8152558351351730035L;\r
21 \r
22   Map<String, Pazpar2State> states = new HashMap<String, Pazpar2State>();\r
23   String currentKey = "";\r
24   private static List<String> allCommands = new ArrayList<String>(Arrays.asList("init","ping","settings","search","stat","show","record","termlist","bytarget"));\r
25   Map<String,Boolean> pendingStateChanges = new HashMap<String,Boolean>();\r
26   private static Logger logger = Logger.getLogger(StateManager.class);\r
27   private List<StateListener> listeners = new ArrayList<StateListener>();\r
28   \r
29   public StateManager () {\r
30     logger.info("Initializing a Pazpar2 state manager [" + Utils.objectId(this) + "]");\r
31     Pazpar2State initialState = new Pazpar2State(this);\r
32     states.put(initialState.getKey(), initialState);\r
33     currentKey = initialState.getKey();\r
34     for (String command : allCommands) {\r
35       pendingStateChanges.put(command, new Boolean(false));\r
36     }\r
37   }\r
38   \r
39   public void addStateListener(StateListener listener) {\r
40     listeners.add(listener);\r
41   }\r
42   \r
43   public void removeStateListener (StateListener listener) {\r
44     listeners.remove(listener);\r
45   }\r
46   \r
47   private void updateListeners (String command) {\r
48     for (StateListener lsnr : listeners) {\r
49       lsnr.stateUpdate(command);\r
50     }\r
51   }\r
52   \r
53   /**\r
54    * Registers a Pazpar2 command for execution.\r
55    * \r
56    * The state manager will update current state and flag that\r
57    * a request change was made but that it was not yet carried \r
58    * out against Pazpar2.\r
59    * \r
60    * Any command that is created or modified must be checked in\r
61    * like this to come into effect.\r
62    * \r
63    * @param command\r
64    */\r
65   public void checkIn(Pazpar2Command command) {\r
66     if (getCurrentState().stateMutating(command)) {\r
67       logger.debug("State changed by: " + command.getName());\r
68       Pazpar2State state = new Pazpar2State(getCurrentState(),command);\r
69       states.put(state.getKey(), state);\r
70       currentKey = state.getKey();\r
71       hasPendingStateChange(command.getName(),new Boolean(true));\r
72     } else {\r
73       logger.debug("Command " + command.getName() + " not found to change the state [" + command.getEncodedQueryString() + "]");\r
74     }\r
75   }\r
76   \r
77   /**\r
78    * Gets a detached copy of a command. For the change manager\r
79    * to become aware of any changes to the copy it must be \r
80    * checked back in with 'checkIn(Pazpar2Command)'\r
81    * \r
82    * @param commandName\r
83    * @return Copy this state's instance of the given command\r
84    */\r
85   public Pazpar2Command checkOut (String commandName) {\r
86     logger.info("Getting " + commandName + " from state manager.");\r
87     return getCurrentState().getCommand(commandName).copy();\r
88   }\r
89   \r
90   public Pazpar2State getCurrentState () {\r
91     return states.get(currentKey);\r
92   }\r
93     \r
94   /**\r
95    * Changes the current state key. Invoked from the UI to have the state \r
96    * manager switch to another state than the current one. \r
97    * \r
98    * @param key\r
99    */\r
100   public void setCurrentStateKey(String key) {    \r
101     if (currentKey.equals(key)) {\r
102       logger.debug("setCurrentStateKey: no key change detected");\r
103     } else {\r
104       logger.debug("State key change. Was: [" + currentKey + "]. Will be ["+key+"]");\r
105       if (states.get(key).getCommand("search").equals(states.get(currentKey).getCommand("search"))) {\r
106         logger.debug("No search change detected");\r
107       } else {\r
108         hasPendingStateChange("search",true);\r
109       }\r
110       if (states.get(key).getCommand("record").equals(states.get(currentKey).getCommand("record"))) {\r
111         logger.debug("No record change detected");\r
112       } else {\r
113         hasPendingStateChange("record",true);\r
114       }\r
115       currentKey = key;\r
116     }\r
117   }\r
118 \r
119   /**\r
120    * Sets a pending-state-change flag for the given command and notifies\r
121    * registered listeners. \r
122    * \r
123    * It is up to the listener to reset the flag as needed.\r
124    * \r
125    * @param command\r
126    * @param bool\r
127    */\r
128   public void hasPendingStateChange(String command, boolean bool) {\r
129     pendingStateChanges.put(command, new Boolean(bool));\r
130     if (bool) {\r
131       logger.debug("Updating listeners with state change from " + command);\r
132       updateListeners(command);\r
133     }\r
134   }\r
135   \r
136   /**\r
137    * \r
138    * @param command\r
139    * @return true if there is a non-executed command change in this state\r
140    */\r
141   public boolean hasPendingStateChange (String command) {\r
142     return pendingStateChanges.get(command).booleanValue();\r
143   }\r
144 \r
145 }\r