org.javers.core.JaversCore Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of javers-core Show documentation
Show all versions of javers-core Show documentation
JaVers - object auditing and diff framework for Java
package org.javers.core;
import org.javers.common.exception.JaversException;
import org.javers.common.validation.Validate;
import org.javers.core.changelog.ChangeListTraverser;
import org.javers.core.changelog.ChangeProcessor;
import org.javers.core.commit.Commit;
import org.javers.core.commit.CommitFactory;
import org.javers.core.diff.Change;
import org.javers.core.diff.Diff;
import org.javers.core.diff.DiffFactory;
import org.javers.core.diff.changetype.PropertyChange;
import org.javers.core.json.JsonConverter;
import org.javers.core.metamodel.annotation.TypeName;
import org.javers.core.metamodel.object.CdoSnapshot;
import org.javers.core.metamodel.object.GlobalIdFactory;
import org.javers.core.metamodel.property.Property;
import org.javers.core.metamodel.type.*;
import org.javers.repository.api.JaversExtendedRepository;
import org.javers.repository.jql.GlobalIdDTO;
import org.javers.repository.jql.JqlQuery;
import org.javers.repository.jql.QueryRunner;
import org.javers.shadow.Shadow;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.lang.reflect.Type;
import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Executor;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import static java.util.concurrent.CompletableFuture.supplyAsync;
import static org.javers.common.exception.JaversExceptionCode.COMMITTING_TOP_LEVEL_VALUES_NOT_SUPPORTED;
import static org.javers.common.validation.Validate.argumentIsNotNull;
import static org.javers.common.validation.Validate.argumentsAreNotNull;
import static org.javers.repository.jql.InstanceIdDTO.instanceId;
/**
* JaVers instance
*
* @author bartosz walacik
*/
class JaversCore implements Javers {
private static final Logger logger = LoggerFactory.getLogger(Javers.class);
private final DiffFactory diffFactory;
private final TypeMapper typeMapper;
private final JsonConverter jsonConverter;
private final CommitFactory commitFactory;
private final JaversExtendedRepository repository;
private final QueryRunner queryRunner;
private final GlobalIdFactory globalIdFactory;
private final CoreConfiguration configuration;
JaversCore(DiffFactory diffFactory, TypeMapper typeMapper, JsonConverter jsonConverter, CommitFactory commitFactory, JaversExtendedRepository repository, QueryRunner queryRunner, GlobalIdFactory globalIdFactory, CoreConfiguration javersCoreConfiguration) {
this.diffFactory = diffFactory;
this.typeMapper = typeMapper;
this.jsonConverter = jsonConverter;
this.commitFactory = commitFactory;
this.repository = repository;
this.queryRunner = queryRunner;
this.globalIdFactory = globalIdFactory;
this.configuration = javersCoreConfiguration;
}
@Override
public Commit commit(String author, Object currentVersion) {
return commit(author, currentVersion, Collections.emptyMap());
}
public CompletableFuture commitAsync(String author, Object currentVersion, Executor executor) {
return commitAsync(author, currentVersion, Collections.emptyMap(), executor);
}
@Override
public Commit commit(String author, Object currentVersion, Map commitProperties) {
long start = System.currentTimeMillis();
argumentIsNotNull(author);
argumentIsNotNull(commitProperties);
argumentIsNotNull(currentVersion);
assertJaversTypeNotValueTypeOrPrimitiveType(currentVersion);
Commit commit = commitFactory.create(author, commitProperties, currentVersion);
long stopCreate = System.currentTimeMillis();
persist(commit);
long stop = System.currentTimeMillis();
logger.info(commit.toString()+", done in "+ (stop-start)+ " ms (diff:{} ms, persist:{} ms)",(stopCreate-start), (stop-stopCreate));
return commit;
}
private void assertJaversTypeNotValueTypeOrPrimitiveType(Object currentVersion) {
JaversType jType = typeMapper.getJaversType(currentVersion.getClass());
if (jType instanceof ValueType || jType instanceof PrimitiveType){
throw new JaversException(COMMITTING_TOP_LEVEL_VALUES_NOT_SUPPORTED,
jType.getClass().getSimpleName(), currentVersion.getClass().getSimpleName());
}
}
private Commit persist(Commit commit) {
if (commit.getSnapshots().isEmpty()) {
logger.info("Skipping persisting empty commit: {}", commit.toString());
} else {
repository.persist(commit);
}
return commit;
}
@Override
public CompletableFuture commitAsync(String author, Object currentVersion, Map commitProperties,
Executor executor) {
long start = System.currentTimeMillis();
argumentsAreNotNull(author, commitProperties, currentVersion);
assertJaversTypeNotValueTypeOrPrimitiveType(currentVersion);
CompletableFuture commit =
supplyAsync(() -> commitFactory.create(author, commitProperties, currentVersion), executor)
.thenApply(it -> new CommitWithTimestamp(it, System.currentTimeMillis()))
.thenApplyAsync(it -> {
persist(it.getCommit());
return it;
}, executor)
.thenApply(it -> logCommitMessage(start, it));
return commit;
}
private Commit logCommitMessage(long start, CommitWithTimestamp it) {
long stop = System.currentTimeMillis();
Commit persistedCommit = it.getCommit();
Long creationTime = it.getTimestamp();
logger.info(persistedCommit.toString()+", done asynchronously in "+ (stop-start)+ " millis (diff:{}, persist:{})",(creationTime-start), (stop-creationTime));
return persistedCommit;
}
@Override
public Commit commitShallowDelete(String author, Object deleted) {
return commitShallowDelete(author, deleted, Collections.emptyMap());
}
@Override
public Commit commitShallowDelete(String author, Object deleted, Map properties) {
argumentsAreNotNull(author, properties, deleted);
Commit commit = commitFactory.createTerminal(author, properties, deleted);
repository.persist(commit);
logger.info(commit.toString());
return commit;
}
@Override
public Commit commitShallowDeleteById(String author, GlobalIdDTO globalId) {
return commitShallowDeleteById(author, globalId, Collections.emptyMap());
}
@Override
public Commit commitShallowDeleteById(String author, GlobalIdDTO globalId, Map properties) {
argumentsAreNotNull(author, properties, globalId);
Commit commit = commitFactory.createTerminalByGlobalId(author, properties, globalIdFactory.createFromDto(globalId));
repository.persist(commit);
logger.info(commit.toString());
return commit;
}
@Override
public Diff compare(Object oldVersion, Object currentVersion) {
return diffFactory.compare(oldVersion, currentVersion);
}
@Override
public Diff initial(Object newDomainObject) {
Validate.argumentIsNotNull(newDomainObject);
return diffFactory.initial(newDomainObject);
}
@Override
public List> findShadows(JqlQuery query) {
Validate.argumentIsNotNull(query);
return (List)findShadowsAndStream(query).collect(Collectors.toList());
}
@Override
public Stream> findShadowsAndStream(JqlQuery query) {
Validate.argumentIsNotNull(query);
return (Stream)queryRunner.queryForShadowsStream(query);
}
@Override
public List findSnapshots(JqlQuery query){
Validate.argumentIsNotNull(query);
return queryRunner.queryForSnapshots(query);
}
@Override
public Changes findChanges(JqlQuery query){
Validate.argumentIsNotNull(query);
return new Changes(queryRunner.queryForChanges(query), configuration.getPrettyValuePrinter());
}
@Override
public Optional getLatestSnapshot(Object localId, Class entity) {
Validate.argumentsAreNotNull(localId, entity);
return queryRunner.runQueryForLatestSnapshot(instanceId(localId, entity));
}
@Override
public Optional getHistoricalSnapshot(Object localId, Class entity, LocalDateTime effectiveDate) {
Validate.argumentsAreNotNull(localId, entity, effectiveDate);
return repository.getHistorical(globalIdFactory.createInstanceId(localId, entity), effectiveDate);
}
@Override
public JsonConverter getJsonConverter() {
return jsonConverter;
}
@Override
public T processChangeList(List changes, ChangeProcessor changeProcessor){
argumentsAreNotNull(changes, changeProcessor);
ChangeListTraverser.traverse(changes, changeProcessor);
return changeProcessor.result();
}
@Override
public T getTypeMapping(Type clientsType) {
return (T) typeMapper.getJaversType(clientsType);
}
/**
* @see TypeName
* @since 2.3
*/
public T getTypeMapping(String typeName) {
return (T) typeMapper.getJaversManagedType(typeName, ManagedType.class);
}
@Override
public Diff compareCollections(Collection oldVersion, Collection currentVersion, Class itemClass) {
return diffFactory.compareCollections(oldVersion, currentVersion, itemClass);
}
@Override
public Property getProperty(PropertyChange propertyChange) {
ManagedType managedType = typeMapper.getJaversManagedType(propertyChange.getAffectedGlobalId());
return managedType.getProperty(propertyChange.getPropertyName());
}
@Override
public CoreConfiguration getCoreConfiguration() {
return configuration;
}
private static class CommitWithTimestamp {
private Commit commit;
private Long timestamp;
CommitWithTimestamp(Commit commit, Long timestamp) {
this.commit = commit;
this.timestamp = timestamp;
}
Commit getCommit() {
return commit;
}
Long getTimestamp() {
return timestamp;
}
}
}