271 lines
8.1 KiB
Java
271 lines
8.1 KiB
Java
/*
|
|
* 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.agent.impl;
|
|
|
|
import java.text.MessageFormat;
|
|
import java.util.List;
|
|
|
|
import li.strolch.agent.api.StrolchRealm;
|
|
import li.strolch.exception.StrolchException;
|
|
import li.strolch.model.StrolchRootElement;
|
|
import li.strolch.model.Version;
|
|
import li.strolch.model.parameter.Parameter;
|
|
import li.strolch.persistence.api.StrolchDao;
|
|
import li.strolch.persistence.api.StrolchPersistenceException;
|
|
import li.strolch.persistence.api.StrolchTransaction;
|
|
|
|
/**
|
|
* @author Robert von Burg <eitch@eitchnet.ch>
|
|
*/
|
|
public abstract class CachedElementMap<T extends StrolchRootElement> extends TransientElementMap<T> {
|
|
|
|
private final StrolchRealm realm;
|
|
|
|
public CachedElementMap(StrolchRealm realm) {
|
|
super();
|
|
this.realm = realm;
|
|
}
|
|
|
|
protected abstract StrolchDao<T> getDbDao(StrolchTransaction tx);
|
|
|
|
@Override
|
|
public synchronized void add(StrolchTransaction tx, T element) {
|
|
if (this.realm.isVersioningEnabled()) {
|
|
int latestVersion = getLatestVersionFor(tx, element.getType(), element.getId()) + 1;
|
|
Version.updateVersionFor(element, latestVersion, tx.getCertificate().getUsername(), false);
|
|
} else {
|
|
Version.setInitialVersionFor(element, tx.getCertificate().getUsername());
|
|
}
|
|
|
|
// first perform cached change
|
|
super.internalAdd(tx, element);
|
|
|
|
// last is to perform DB changes
|
|
getDbDao(tx).save(element);
|
|
}
|
|
|
|
@Override
|
|
public synchronized void addAll(StrolchTransaction tx, List<T> elements) {
|
|
|
|
// first perform cached change
|
|
for (T element : elements) {
|
|
if (this.realm.isVersioningEnabled()) {
|
|
int latestVersion = getLatestVersionFor(tx, element.getType(), element.getId()) + 1;
|
|
Version.updateVersionFor(element, latestVersion, tx.getCertificate().getUsername(), false);
|
|
} else {
|
|
Version.setInitialVersionFor(element, tx.getCertificate().getUsername());
|
|
}
|
|
|
|
internalAdd(tx, element);
|
|
}
|
|
|
|
// last is to perform DB changes
|
|
getDbDao(tx).saveAll(elements);
|
|
}
|
|
|
|
private void updateVersion(StrolchTransaction tx, T element, boolean deleted) {
|
|
if (this.realm.isVersioningEnabled()) {
|
|
if (!element.hasVersion()) {
|
|
T current = getBy(tx, element.getType(), element.getId(), true);
|
|
if (current.hasVersion()) {
|
|
element.setVersion(current.getVersion());
|
|
} else {
|
|
int currentVersion = getLatestVersionFor(tx, element.getType(), element.getId());
|
|
Version.updateVersionFor(element, currentVersion, tx.getCertificate().getUsername(), deleted);
|
|
}
|
|
}
|
|
Version.updateVersionFor(element, tx.getCertificate().getUsername(), deleted);
|
|
} else {
|
|
element.setVersion(getBy(tx, element.getType(), element.getId(), true).getVersion());
|
|
Version.updateVersionFor(element, 0, tx.getCertificate().getUsername(), deleted);
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public synchronized void update(StrolchTransaction tx, T element) {
|
|
updateVersion(tx, element, false);
|
|
|
|
// first perform cached change
|
|
super.internalUpdate(tx, element);
|
|
|
|
// last is to perform DB changes
|
|
getDbDao(tx).update(element);
|
|
}
|
|
|
|
@Override
|
|
public synchronized void updateAll(StrolchTransaction tx, List<T> elements) {
|
|
|
|
// first perform cached change
|
|
for (T t : elements) {
|
|
updateVersion(tx, t, false);
|
|
internalUpdate(tx, t);
|
|
}
|
|
|
|
// last is to perform DB changes
|
|
getDbDao(tx).updateAll(elements);
|
|
}
|
|
|
|
@Override
|
|
public synchronized void remove(StrolchTransaction tx, T element) {
|
|
updateVersion(tx, element, true);
|
|
|
|
// first perform cached change
|
|
super.remove(tx, element);
|
|
|
|
// last is to perform DB changes
|
|
if (this.realm.isVersioningEnabled()) {
|
|
getDbDao(tx).update(element);
|
|
} else {
|
|
getDbDao(tx).remove(element);
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public synchronized void removeAll(StrolchTransaction tx, List<T> elements) {
|
|
for (T t : elements) {
|
|
updateVersion(tx, t, true);
|
|
}
|
|
|
|
// first perform cached change
|
|
super.removeAll(tx, elements);
|
|
|
|
// last is to perform DB changes
|
|
if (this.realm.isVersioningEnabled()) {
|
|
getDbDao(tx).updateAll(elements);
|
|
} else {
|
|
getDbDao(tx).removeAll(elements);
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public synchronized long removeAll(StrolchTransaction tx) {
|
|
|
|
// first perform cached change
|
|
long removed = super.removeAll(tx);
|
|
|
|
// last is to perform DB changes
|
|
long daoRemoved = getDbDao(tx).removeAll();
|
|
|
|
if (removed != daoRemoved) {
|
|
String msg = "Removed {0} elements from cached map, but dao removed {1} elements!"; //$NON-NLS-1$
|
|
logger.error(MessageFormat.format(msg, removed, daoRemoved));
|
|
}
|
|
|
|
return removed;
|
|
}
|
|
|
|
@Override
|
|
public synchronized long removeAllBy(StrolchTransaction tx, String type) {
|
|
|
|
// first perform cached change
|
|
long removed = super.removeAllBy(tx, type);
|
|
|
|
// last is to perform DB changes
|
|
long daoRemoved = getDbDao(tx).removeAllBy(type);
|
|
|
|
if (removed != daoRemoved) {
|
|
String msg = "Removed {0} elements from cached map for type {1}, but dao removed {3} elements!"; //$NON-NLS-1$
|
|
logger.error(MessageFormat.format(msg, removed, type, daoRemoved));
|
|
}
|
|
|
|
return removed;
|
|
}
|
|
|
|
@Override
|
|
public T getBy(StrolchTransaction tx, String type, String id, int version) {
|
|
return getBy(tx, type, id, version, false);
|
|
}
|
|
|
|
@Override
|
|
public T getBy(StrolchTransaction tx, String type, String id, int version, boolean assertExists)
|
|
throws StrolchException {
|
|
T t = getDbDao(tx).queryBy(type, id, version);
|
|
if (assertExists && t == null) {
|
|
String msg = "The element with type \"{0}\" and id \"{1}\" and version \"{2}\" does not exist!"; //$NON-NLS-1$
|
|
msg = MessageFormat.format(msg, type, id, version);
|
|
throw new StrolchException(msg);
|
|
}
|
|
|
|
return t;
|
|
}
|
|
|
|
@Override
|
|
public List<T> getVersionsFor(StrolchTransaction tx, String type, String id) {
|
|
return getDbDao(tx).queryVersionsFor(type, id);
|
|
}
|
|
|
|
@Override
|
|
public int getLatestVersionFor(StrolchTransaction tx, String type, String id) {
|
|
return getDbDao(tx).queryLatestVersionFor(type, id);
|
|
}
|
|
|
|
@Override
|
|
public T revertToVersion(StrolchTransaction tx, T element) throws StrolchException {
|
|
return revertToVersion(tx, element.getType(), element.getId(), element.getVersion().getVersion());
|
|
}
|
|
|
|
@Override
|
|
public T revertToVersion(StrolchTransaction tx, String type, String id, int version) throws StrolchException {
|
|
if (!this.realm.isVersioningEnabled())
|
|
throw new StrolchPersistenceException("Can not undo a version if versioning is not enabled!");
|
|
|
|
// get the current and specified version
|
|
T current = getBy(tx, type, id, true);
|
|
T versionT = getBy(tx, type, id, version, true);
|
|
|
|
// create the new version
|
|
@SuppressWarnings("unchecked")
|
|
T clone = (T) versionT.getClone();
|
|
clone.setVersion(current.getVersion());
|
|
|
|
// save the new version
|
|
update(tx, clone);
|
|
|
|
// and return new version
|
|
return clone;
|
|
}
|
|
|
|
@Override
|
|
public void undoVersion(StrolchTransaction tx, T element) throws StrolchException {
|
|
if (!this.realm.isVersioningEnabled())
|
|
throw new StrolchPersistenceException("Can not undo a version if versioning is not enabled!");
|
|
|
|
String type = element.getType();
|
|
String id = element.getId();
|
|
|
|
Version elementVersion = element.getVersion();
|
|
|
|
// make sure the given element is the latest version
|
|
T current = getBy(tx, type, id, true);
|
|
if (!current.getVersion().equals(elementVersion)) {
|
|
String msg = "Can not undo the version {0} as it is not the latest!"; //$NON-NLS-1$
|
|
msg = MessageFormat.format(msg, elementVersion);
|
|
throw new StrolchException(msg);
|
|
}
|
|
|
|
if (elementVersion.isFirstVersion()) {
|
|
super.remove(tx, element);
|
|
getDbDao(tx).remove(element);
|
|
} else {
|
|
T previous = getBy(tx, type, id, elementVersion.getPreviousVersion(), true);
|
|
super.internalUpdate(tx, previous);
|
|
getDbDao(tx).removeVersion(current);
|
|
}
|
|
}
|
|
|
|
protected abstract void assertIsRefParam(Parameter<?> refP);
|
|
}
|