package org.wiztools.restclient.ui.history; import java.io.File; import java.io.IOException; import java.util.LinkedList; import java.util.List; import java.util.logging.Level; import java.util.logging.Logger; import javax.annotation.PostConstruct; import javax.inject.Inject; import javax.inject.Singleton; import org.wiztools.restclient.IGlobalOptions; import org.wiztools.restclient.persistence.XMLException; import org.wiztools.restclient.bean.Request; import org.wiztools.restclient.ui.lifecycle.LifecycleManager; import org.wiztools.restclient.ui.lifecycle.Shutdown; import org.wiztools.restclient.ui.reqgo.ReqUrlGoPanel; import org.wiztools.restclient.persistence.XMLCollectionUtil; /** * * @author subwiz */ @Singleton public class HistoryManagerImpl implements HistoryManager { private static final Logger LOG = Logger.getLogger(HistoryManagerImpl.class.getName()); private int maxSize = DEFAULT_HISTORY_SIZE; // initialized in @PostConstruct private int cursor; private final LinkedList<Request> data = new LinkedList<>(); @Inject private IGlobalOptions options; @Inject private LifecycleManager lifecycle; @Inject private ReqUrlGoPanel goPanel; @PostConstruct protected void init() { // Initialize History: if(DEFAULT_FILE.exists()) { try { load(DEFAULT_FILE); } catch(IOException | XMLException ex) { ex.printStackTrace(System.err); } } // Add shutdown listener: lifecycle.registerShutdownListener(new Shutdown() { @Override public void onShutdown() { try { save(HistoryManager.DEFAULT_FILE); } catch(IOException ex) { ex.printStackTrace(System.err); } } }); initMaxSize(); } // @PostConstruct -- sequence important, so called from init() protected void initMaxSize() { String tSize = options.getProperty(HISTORY_SIZE_CONFIG_KEY); if(tSize != null) { try { int size = Integer.parseInt(tSize); if(size > 0) { if(size > 50) { LOG.info("History size is configured to greater than 50! Ensure you have enough memory!!"); } setHistorySize(size); return; } else { LOG.log(Level.INFO, "History size is less than 1: {0}", size); } } catch(NumberFormatException ex) { LOG.info("Expected integer property: " + HISTORY_SIZE_CONFIG_KEY); } } LOG.log(Level.INFO, "Reverting to default value: {0}", DEFAULT_HISTORY_SIZE); setHistorySize(DEFAULT_HISTORY_SIZE); updateOptions(); } private void updateOptions() { // Update options to persist during shutdown: if(options != null) { // should not fail tests! options.setProperty(HISTORY_SIZE_CONFIG_KEY, String.valueOf(maxSize)); } } @Override public int getHistorySize() { return maxSize; } @Override public void setHistorySize(int size) { if(size < 1) { throw new IllegalArgumentException("History max size value invalid: " + size); } if(size > 50) { // warning log LOG.info("History size is configured to greater than 50! Ensure you have enough memory!!"); } if(maxSize == size) { return; } if(maxSize > size) { // new size is smaller than existing // reset cursor: if(cursor >= size) { cursor = size - 1; } // Need to trim data? if(data.size() > size) { final int diff = data.size() - size; for(int i=0; i<diff; i++) { data.removeLast(); } } } // Nothing to do if the size is greater than existing! // Finally, set the size: maxSize = size; updateOptions(); } @Override public void add(Request request) { if(cursor != 0) { // discard everything newer than cursor position for(int i=0; i<cursor; i++) { data.removeFirst(); } } // Add: data.addFirst(request); // Verify if threshold reached: if(data.size() > maxSize) { data.removeLast(); } // reset cursor: cursor = 0; } @Override public boolean isOldest() { if(data.isEmpty()) { return true; } return cursor == (data.size() - 1); } @Override public boolean isMostRecent() { return cursor == 0; } @Override public Request back() { if(isOldest()) { return null; } return data.get(++cursor); } @Override public Request forward() { if(isMostRecent()) { return null; } return data.get(--cursor); } @Override public Request current() { if(data.isEmpty()) { return null; } return data.get(cursor); } @Override public Request lastRequest() { if(data.isEmpty()) { return null; } return data.getFirst(); } @Override public void clear() { data.clear(); cursor = 0; // remove combo history too: goPanel.clearHistory(); } @Override public boolean isEmpty() { return data.isEmpty(); } public int size() { return data.size(); } public int cursor() { return cursor; } @Override public void save(File file) throws IOException { if(!data.isEmpty()) { XMLCollectionUtil.writeRequestCollectionXML(data, file); } else { LOG.info("No data to store in history"); } } @Override public void load(File file) throws IOException, XMLException, IllegalStateException { if(data.isEmpty()) { List<Request> requests = XMLCollectionUtil.getRequestCollectionFromXMLFile(file); data.addAll(requests); } else { throw new IllegalStateException("History is already initialized. Cannot initialize now."); } } @Override public String toString() { return "HistoryManagerImpl{" + "maxCount=" + maxSize + ", cursor=" + cursor + ", data=" + data + '}'; } }