/*
* Copyright 2013 Robert von Burg <eitch@eitchnet.ch>
*
* 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 li.strolch.persistence.inmemory;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import li.strolch.model.StrolchElement;
import li.strolch.persistence.api.StrolchDao;
import li.strolch.persistence.api.StrolchPersistenceException;
public class InMemoryDao<T extends StrolchElement> implements StrolchDao<T> {
private Map<String, Map<String, T>> elementMap;
public InMemoryDao() {
this.elementMap = new HashMap<>();
}
@Override
public synchronized boolean hasElement(String type, String id) {
Map<String, T> byType = this.elementMap.get(type);
if (byType == null)
return false;
return byType.containsKey(id);
}
@Override
public synchronized long querySize() {
long size = 0;
for (String type : this.elementMap.keySet()) {
Map<String, T> byType = this.elementMap.get(type);
size += byType.size();
}
return size;
}
@Override
public synchronized long querySize(String type) {
Map<String, T> byType = this.elementMap.get(type);
if (byType == null)
return 0;
return byType.size();
}
@Override
public synchronized Set<String> queryKeySet() {
Set<String> keySet = new HashSet<>();
for (String type : this.elementMap.keySet()) {
Map<String, T> byType = this.elementMap.get(type);
for (String id : byType.keySet()) {
keySet.add(id);
}
}
return keySet;
}
@Override
public synchronized Set<String> queryKeySet(String type) {
Map<String, T> byType = this.elementMap.get(type);
if (byType == null)
return new HashSet<>(0);
return new HashSet<>(byType.keySet());
}
@Override
public synchronized Set<String> queryTypes() {
return new HashSet<>(this.elementMap.keySet());
}
@Override
public synchronized T queryBy(String type, String id) {
Map<String, T> byType = this.elementMap.get(type);
if (byType == null)
return null;
return byType.get(id);
}
@Override
public synchronized List<T> queryAll() {
List<T> elements = new ArrayList<>();
for (String type : this.elementMap.keySet()) {
Map<String, T> byType = this.elementMap.get(type);
for (String id : byType.keySet()) {
elements.add(byType.get(id));
}
}
return elements;
}
@Override
public synchronized List<T> queryAll(String type) {
Map<String, T> byType = this.elementMap.get(type);
if (byType == null)
return new ArrayList<>(0);
return new ArrayList<>(byType.values());
}
@Override
public synchronized void save(T element) {
Map<String, T> byType = this.elementMap.get(element.getType());
if (byType == null) {
byType = new HashMap<>();
this.elementMap.put(element.getType(), byType);
}
if (byType.containsKey(element.getId())) {
String msg = "An element already exists with the id {0}. Elements of the same class must always have a unique id, regardless of their type!"; //$NON-NLS-1$
msg = MessageFormat.format(msg, element.getId());
throw new StrolchPersistenceException(msg);
}
byType.put(element.getId(), element);
}
@Override
public synchronized void saveAll(List<T> elements) {
for (T element : elements) {
save(element);
}
}
@Override
public synchronized void update(T element) {
Map<String, T> byType = this.elementMap.get(element.getType());
if (byType == null) {
byType = new HashMap<>();
this.elementMap.put(element.getType(), byType);
}
byType.put(element.getId(), element);
}
@Override
public synchronized void updateAll(List<T> elements) {
for (T element : elements) {
update(element);
}
}
@Override
public synchronized void remove(T element) {
Map<String, T> byType = this.elementMap.get(element.getType());
if (byType != null) {
byType.remove(element.getId());
if (byType.isEmpty()) {
this.elementMap.remove(element.getType());
}
}
}
@Override
public synchronized void removeAll(List<T> elements) {
for (T element : elements) {
remove(element);
}
}
@Override
public synchronized long removeAll() {
long removed = 0;
Set<String> keySet = new HashSet<>(this.elementMap.keySet());
for (String type : keySet) {
Map<String, T> byType = this.elementMap.remove(type);
removed += byType.size();
byType.clear();
}
return removed;
}
@Override
public synchronized long removeAllBy(String type) {
Map<String, T> byType = this.elementMap.remove(type);
if (byType == null)
return 0;
long removed = byType.size();
byType.clear();
return removed;
}
}