/*******************************************************************************
* Copyright (c) 2012 - 2014 Wind River Systems, Inc. and others. All rights reserved.
* This program and the accompanying materials are made available under the terms
* of the Eclipse Public License v1.0 which accompanies this distribution, and is
* available at http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Wind River Systems - initial API and implementation
*******************************************************************************/
package org.eclipse.tcf.te.runtime.persistence.history;
import java.io.IOException;
import java.net.URI;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.IPath;
import org.eclipse.tcf.te.runtime.events.ChangeEvent;
import org.eclipse.tcf.te.runtime.events.EventManager;
import org.eclipse.tcf.te.runtime.persistence.activator.CoreBundleActivator;
import org.eclipse.tcf.te.runtime.persistence.interfaces.IURIPersistenceService;
import org.eclipse.tcf.te.runtime.services.ServiceManager;
/**
* History manager implementation.
*/
public class HistoryManager {
// the maximum length of the history per id
private final static int HISTORY_LENGTH = 5;
// The map maintaining the history
private Map<String, List<String>> history = new HashMap<String, List<String>>();
/*
* Thread save singleton instance creation.
*/
private static class LazyInstance {
public static HistoryManager instance = new HistoryManager();
}
/**
* Returns the singleton instance of the history point manager.
*/
public static HistoryManager getInstance() {
return LazyInstance.instance;
}
/**
* Constructor.
*/
HistoryManager() {
super();
initialize();
}
/**
* Initialize the history manager.
*/
@SuppressWarnings("unchecked")
private void initialize() {
history.clear();
try {
// Get the persistence service
IURIPersistenceService uRIPersistenceService = ServiceManager.getInstance().getService(IURIPersistenceService.class);
if (uRIPersistenceService == null) {
throw new IOException("Persistence service instance unavailable."); //$NON-NLS-1$
}
// Save the history to the persistence storage
history = (Map<String,List<String>>)uRIPersistenceService.read(history, getURI());
} catch (IOException e) {
}
}
// Get the URI for history persistence
private URI getURI() {
IPath pluginPath = CoreBundleActivator.getDefault().getStateLocation();
pluginPath = pluginPath.append(".history"); //$NON-NLS-1$
return pluginPath.toFile().toURI();
}
/**
* Write the history to disk.
*/
public void flush() {
synchronized (history) {
try {
// Get the persistence service
IURIPersistenceService uRIPersistenceService = ServiceManager.getInstance().getService(IURIPersistenceService.class);
if (uRIPersistenceService == null) {
throw new IOException("Persistence service instance unavailable."); //$NON-NLS-1$
}
// Save the history to the persistence storage
uRIPersistenceService.write(history, getURI());
} catch (IOException e) {
}
}
}
/**
* Get the history for a given history id.
* @param historyId The history id.
* @return The list of entries within the history ids list or an empty list.
*/
public String[] getHistory(String historyId) {
Assert.isNotNull(historyId);
List<String> entries = history.get(historyId);
if (entries == null) {
entries = new ArrayList<String>();
}
return entries.toArray(new String[entries.size()]);
}
/**
* Get all history ids matching the given id pattern.
* @param historyIdPattern The history id regex pattern.
* @return The list of history ids matching the given pattern or an empty list.
*/
public String[] getMatchingHistoryIds(String historyIdPattern) {
Assert.isNotNull(historyIdPattern);
List<String> historyIds = new ArrayList<String>();
for (String historyId : history.keySet()) {
if (historyId.matches(historyIdPattern)) {
historyIds.add(historyId);
}
}
return historyIds.toArray(new String[historyIds.size()]);
}
/**
* Get the fist entry of a history ids list.
* @param historyId The history id.
* @return The first entry for the given history ids or null if no history is available for that id.
*/
public String getFirst(String historyId) {
String[] history = getHistory(historyId);
return history.length > 0 ? history[0] : null;
}
/**
* Add a new history entry to the top of the history ids list.
* If the list size exceeds the HISTORY_LENGTH, the last element of the list will be removed.
* @param historyId The history id.
* @param entry The entry to be added to the top of history ids list.
* @return <code>true</code> if the id
*/
public boolean add(String historyId, String entry) {
return add(historyId, entry, HISTORY_LENGTH);
}
/**
* Add a new history entry to the top of the history ids list.
* If the list size exceeds the HISTORY_LENGTH, the last element of the list will be removed.
* @param historyId The history id.
* @param entry The id to be added to the top of history ids list.
* @param historyLength The maximum length of the history.
* @return <code>true</code> if the entry was added
*/
public boolean add(String historyId, String entry, int historyLength) {
Assert.isNotNull(historyId);
Assert.isNotNull(entry);
Assert.isTrue(historyLength > 0);
List<String> ids = history.get(historyId);
if (ids == null) {
ids = new ArrayList<String>();
history.put(historyId, ids);
}
if (ids.contains(entry)) {
ids.remove(entry);
}
ids.add(0, entry);
while (ids.size() > historyLength) {
ids.remove(historyLength);
}
flush();
EventManager.getInstance().fireEvent(new ChangeEvent(this, ChangeEvent.ID_ADDED, historyId, historyId));
return true;
}
/**
* Set a new list of history entries to the history ids list.
* If the list size exceeds the HISTORY_LENGTH, the last element of the list will be removed.
* @param historyId The history id.
* @param entries The entries to be set to the history ids list.
* @return <code>true</code> if the entries were added
*/
public void set(String historyId, String[] entries) {
set(historyId, entries, HISTORY_LENGTH);
}
/**
* Set a new list of history entries to the history ids list.
* If the list size exceeds the HISTORY_LENGTH, the last element of the list will be removed.
* @param historyId The history id.
* @param entries The entries to be set to the history ids list.
* @param historyLength The maximum length of the history.
* @return <code>true</code> if the entries were set
*/
public void set(String historyId, String[] entries, int historyLength) {
Assert.isNotNull(historyId);
Assert.isNotNull(entries);
history.put(historyId, Arrays.asList(entries));
List<String> newIds = history.get(historyId);
while (newIds.size() > historyLength) {
newIds.remove(historyLength);
}
flush();
EventManager.getInstance().fireEvent(new ChangeEvent(this, ChangeEvent.ID_CHANGED, historyId, historyId));
}
/**
* Remove a id from the history ids list.
* @param historyId The history id.
* @param entry The entry to be removed from the history ids list.
* @return <code>true</code> if the entry was removed from the history ids list.
*/
public boolean remove(String historyId, String entry) {
Assert.isNotNull(historyId);
Assert.isNotNull(entry);
boolean removed = false;
List<String> ids = history.get(historyId);
if (ids != null) {
removed |= ids.remove(entry);
if (ids.isEmpty()) {
history.remove(historyId);
}
}
if (removed) {
flush();
EventManager.getInstance().fireEvent(new ChangeEvent(this, ChangeEvent.ID_REMOVED, historyId, historyId));
}
return removed;
}
/**
* Remove all ids from the history ids list.
* @param historyId The history id.
**/
public void clear(String historyId) {
List<String> entries = null;
if (historyId == null) {
history.clear();
}
else {
entries = history.remove(historyId);
}
if (entries != null || historyId == null) {
flush();
EventManager.getInstance().fireEvent(new ChangeEvent(this, ChangeEvent.ID_REMOVED, historyId, historyId));
}
}
}