Coverage Report - org.jtheque.core.managers.state.StateManager
 
Classes in this File Line Coverage Branch Coverage Complexity
StateManager
0 %
0/115
0 %
0/46
2.667
 
 1  
 package org.jtheque.core.managers.state;
 2  
 
 3  
 /*
 4  
  * This file is part of JTheque.
 5  
  *
 6  
  * JTheque is free software: you can redistribute it and/or modify
 7  
  * it under the terms of the GNU General Public License as published by
 8  
  * the Free Software Foundation, either version 3 of the License.
 9  
  *
 10  
  * JTheque is distributed in the hope that it will be useful,
 11  
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
 12  
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 13  
  * GNU General Public License for more details.
 14  
  *
 15  
  * You should have received a copy of the GNU General Public License
 16  
  * along with JTheque.  If not, see <http://www.gnu.org/licenses/>.
 17  
  */
 18  
 
 19  
 import org.jdom.Attribute;
 20  
 import org.jdom.Element;
 21  
 import org.jtheque.core.managers.AbstractManager;
 22  
 import org.jtheque.core.managers.ManagerException;
 23  
 import org.jtheque.core.managers.Managers;
 24  
 import org.jtheque.core.managers.error.IErrorManager;
 25  
 import org.jtheque.core.managers.error.JThequeError;
 26  
 import org.jtheque.core.utils.file.XMLException;
 27  
 import org.jtheque.core.utils.file.XMLReader;
 28  
 import org.jtheque.core.utils.file.XMLWriter;
 29  
 import org.jtheque.utils.io.FileUtils;
 30  
 
 31  
 import java.io.File;
 32  
 import java.util.ArrayList;
 33  
 import java.util.Collection;
 34  
 import java.util.HashMap;
 35  
 import java.util.Map;
 36  
 
 37  
 /**
 38  
  * A state manager implementation.
 39  
  *
 40  
  * @author Baptiste Wicht
 41  
  */
 42  0
 public final class StateManager extends AbstractManager implements IStateManager {
 43  0
     private final Map<Class<? extends IState>, IState> states = new HashMap<Class<? extends IState>, IState>(10);
 44  
 
 45  
     @Override
 46  
     public void preInit() {
 47  
         try {
 48  0
             loadStates();
 49  0
         } catch (ManagerException e1) {
 50  0
             Managers.getManager(IErrorManager.class).addError(new JThequeError(e1));
 51  0
         }
 52  0
     }
 53  
 
 54  
     /**
 55  
      * Load the states.
 56  
      *
 57  
      * @throws ManagerException If an error occurs during the reading of the states.
 58  
      */
 59  
     @Override
 60  
     public void loadStates() throws ManagerException {
 61  0
         XMLReader reader = new XMLReader();
 62  
 
 63  
         try {
 64  0
             reader.openFile(getConfigFile());
 65  
 
 66  0
             for (Object currentNode : reader.getNodes("state", reader.getRootElement())) {
 67  
 
 68  0
                 Class<?> stateClass = Class.forName(reader.readString("@class", currentNode), true, getClass().getClassLoader());
 69  
 
 70  0
                 if (IState.class.isAssignableFrom(stateClass)) {
 71  0
                     IState state = (IState) stateClass.newInstance();
 72  
 
 73  0
                     loadState(reader, currentNode, state);
 74  
 
 75  0
                     states.put(state.getClass(), state);
 76  
                 }
 77  0
             }
 78  0
         } catch (Exception e) {
 79  0
             throw new ConfigException(e);
 80  
         } finally {
 81  0
             FileUtils.close(reader);
 82  0
         }
 83  0
     }
 84  
 
 85  
     /**
 86  
      * Load the state from the XML file.
 87  
      *
 88  
      * @param reader      The XML reader.
 89  
      * @param currentNode The node to read from.
 90  
      * @param state       The state to fill.
 91  
      * @throws XMLException If an error occurs during the XML reading process.
 92  
      */
 93  
     private static void loadState(XMLReader reader, Object currentNode, IState state) throws XMLException {
 94  0
         if (state.isDelegated()) {
 95  0
             Collection<Element> nodes = reader.getNodes("*", currentNode);
 96  
 
 97  0
             state.delegateLoad(resolveNodeStates(nodes));
 98  0
         } else {
 99  0
             for (Object propertyNode : reader.getNodes("properties/property", currentNode)) {
 100  0
                 state.setProperty(reader.readString("@key", propertyNode), reader.readString("@value", propertyNode));
 101  
             }
 102  
         }
 103  0
     }
 104  
 
 105  
     /**
 106  
      * Resolve the node states from the XML elements.
 107  
      *
 108  
      * @param nodes The nodes to transform to NodeState.
 109  
      * @return A List containing all the resolved NodeState.
 110  
      */
 111  
     private static Collection<NodeState> resolveNodeStates(Collection<Element> nodes) {
 112  0
         Collection<NodeState> nodeStates = new ArrayList<NodeState>(nodes.size());
 113  
 
 114  0
         for (Element element : nodes) {
 115  0
             NodeState nodeState = resolve(element);
 116  
 
 117  0
             nodeStates.add(nodeState);
 118  0
         }
 119  
 
 120  0
         return nodeStates;
 121  
     }
 122  
 
 123  
     /**
 124  
      * Return the config file.
 125  
      *
 126  
      * @return The config file.
 127  
      */
 128  
     private static File getConfigFile() {
 129  0
         File configFile = new File(Managers.getCore().getFolders().getApplicationFolder(), "/core/config.xml");
 130  
 
 131  0
         if (!configFile.exists()) {
 132  0
             FileUtils.createEmptyFile(configFile.getAbsolutePath());
 133  
 
 134  0
             initConfigFile(configFile);
 135  
         }
 136  
 
 137  0
         return configFile;
 138  
     }
 139  
 
 140  
     /**
 141  
      * Init the config file.
 142  
      *
 143  
      * @param file The config file.
 144  
      */
 145  
     private static void initConfigFile(File file) {
 146  0
         XMLWriter writer = new XMLWriter("states");
 147  
 
 148  0
         writer.write(file.getAbsolutePath());
 149  0
     }
 150  
 
 151  
     @Override
 152  
     public void close(){
 153  0
         saveStates();
 154  0
     }
 155  
 
 156  
     /**
 157  
      * Save the states.
 158  
      */
 159  
     private void saveStates() {
 160  0
         XMLWriter writer = new XMLWriter("states");
 161  
 
 162  0
         for (IState state : states.values()) {
 163  0
             writer.add("state");
 164  0
             writer.addAttribute("class", state.getClass().getCanonicalName());
 165  
 
 166  0
             if (state.isDelegated()) {
 167  0
                 delegateSave(state, writer);
 168  
             } else {
 169  0
                 save(state, writer);
 170  
             }
 171  
 
 172  0
             writer.switchToParent();
 173  
         }
 174  
 
 175  0
         writer.write(getConfigFile().getAbsolutePath());
 176  0
     }
 177  
 
 178  
     /**
 179  
      * Save the state to the writer.
 180  
      *
 181  
      * @param state  The state to save.
 182  
      * @param writer The writer.
 183  
      */
 184  
     private static void save(IState state, XMLWriter writer) {
 185  0
         writer.add("properties");
 186  
 
 187  0
         for (String key : state.getProperties()) {
 188  0
             if (state.getProperty(key) != null) {
 189  0
                 writer.add("property");
 190  0
                 writer.addAttribute("key", key);
 191  0
                 writer.addAttribute("value", state.getProperty(key));
 192  
 
 193  0
                 writer.switchToParent();
 194  
             }
 195  
         }
 196  
 
 197  0
         writer.switchToParent();
 198  0
     }
 199  
 
 200  
     /**
 201  
      * Delegate the save to the state.
 202  
      *
 203  
      * @param state  The state to delegate the save process to.
 204  
      * @param writer The writer to use.
 205  
      */
 206  
     private static void delegateSave(IState state, XMLWriter writer) {
 207  0
         Collection<NodeState> nodes = state.delegateSave();
 208  
 
 209  0
         for (NodeState node : nodes) {
 210  0
             add(node, writer);
 211  
         }
 212  0
     }
 213  
 
 214  
     /**
 215  
      * Add the node state to the writer.
 216  
      *
 217  
      * @param node   The node state to add to the writer.
 218  
      * @param writer The XML writer.
 219  
      */
 220  
     private static void add(NodeState node, XMLWriter writer) {
 221  0
         if (node.hasChildren()) {
 222  0
             writer.add(node.getName());
 223  
 
 224  0
             for (NodeState children : node.getChildrens()) {
 225  0
                 add(children, writer);
 226  
             }
 227  
         } else {
 228  0
             writer.add(node.getName(), node.getText());
 229  
         }
 230  
 
 231  0
         if (node.hasAttribute()) {
 232  0
             for (NodeStateAttribute attribute : node.getAttributes()) {
 233  0
                 writer.addAttribute(attribute.getKey(), attribute.getValue());
 234  
             }
 235  
         }
 236  
 
 237  0
         writer.switchToParent();
 238  0
     }
 239  
 
 240  
     /**
 241  
      * Resolve a NodeState apart from an Element.
 242  
      *
 243  
      * @param element The Element representing the NodeState
 244  
      * @return The resolved NodeState.
 245  
      */
 246  
     private static NodeState resolve(Element element) {
 247  0
         NodeState nodeState = new NodeState(element.getName());
 248  
 
 249  0
         readNode(element, nodeState);
 250  0
         readAttributes(element, nodeState);
 251  
 
 252  0
         return nodeState;
 253  
     }
 254  
 
 255  
     /**
 256  
      * Read and fill the NodeState from the element.
 257  
      *
 258  
      * @param element   The element to read.
 259  
      * @param nodeState The node state to fill.
 260  
      */
 261  
     private static void readNode(Element element, NodeState nodeState) {
 262  0
         if (element.getChildren().isEmpty()) {
 263  0
             String text = element.getText();
 264  
 
 265  0
             if (text != null && !text.isEmpty()) {
 266  0
                 nodeState.setText(text);
 267  
             }
 268  0
         } else {
 269  0
             Collection<Element> childrenElements = element.getChildren();
 270  
 
 271  0
             Collection<NodeState> childrens = new ArrayList<NodeState>(childrenElements.size());
 272  
 
 273  0
             for (Element childrenElement : childrenElements) {
 274  0
                 childrens.add(resolve(childrenElement));
 275  
             }
 276  
 
 277  0
             nodeState.setChildrens(childrens);
 278  
         }
 279  0
     }
 280  
 
 281  
     /**
 282  
      * Read the attributes of the node state.
 283  
      *
 284  
      * @param element   The element to get the attributes from.
 285  
      * @param nodeState The node state to fill.
 286  
      */
 287  
     private static void readAttributes(Element element, NodeState nodeState) {
 288  0
         if (!element.getAttributes().isEmpty()) {
 289  0
             Collection<Attribute> attributes = element.getAttributes();
 290  
 
 291  0
             Collection<NodeStateAttribute> nodeAttributes = new ArrayList<NodeStateAttribute>(attributes.size());
 292  
 
 293  0
             for (Attribute attribute : attributes) {
 294  0
                 nodeAttributes.add(new NodeStateAttribute(attribute.getName(), attribute.getValue()));
 295  
             }
 296  
 
 297  0
             nodeState.setAttributes(nodeAttributes);
 298  
         }
 299  0
     }
 300  
 
 301  
     @Override
 302  
     public <T extends IState> T getState(Class<T> c) {
 303  0
         T state = null;
 304  
 
 305  0
         if (states.containsKey(c)) {
 306  0
             state = (T) states.get(c);
 307  
         }
 308  
 
 309  0
         return state;
 310  
     }
 311  
 
 312  
     @Override
 313  
     public <T extends IState> T getOrCreateState(Class<T> c) throws StateException {
 314  0
         return states.containsKey(c) ? (T) states.get(c) : createState(c);
 315  
     }
 316  
 
 317  
     @Override
 318  
     public <T extends IState> T createState(Class<T> c) throws StateException {
 319  
         T state;
 320  
         try {
 321  0
             Object o = c.newInstance();
 322  
 
 323  0
             state = (T) o;
 324  0
         } catch (InstantiationException e) {
 325  0
             throw new StateException(e);
 326  0
         } catch (IllegalAccessException e) {
 327  0
             throw new StateException(e);
 328  0
         }
 329  
 
 330  0
         states.put(c, state);
 331  
 
 332  0
         return state;
 333  
     }
 334  
 
 335  
     @Override
 336  
     public void registerState(IState state) {
 337  0
         states.put(state.getClass(), state);
 338  0
     }
 339  
 }