package org.javers.core; import java.util.Optional; 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.util.Collection; import java.util.Collections; import java.util.List; import java.util.Map; import static org.javers.common.exception.JaversExceptionCode.COMMITTING_TOP_LEVEL_VALUES_NOT_SUPPORTED; import static org.javers.common.validation.Validate.argumentsAreNotNull; import static org.javers.repository.jql.InstanceIdDTO.instanceId; /** * core 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; JaversCore(DiffFactory diffFactory, TypeMapper typeMapper, JsonConverter jsonConverter, CommitFactory commitFactory, JaversExtendedRepository repository, QueryRunner queryRunner, GlobalIdFactory globalIdFactory) { this.diffFactory = diffFactory; this.typeMapper = typeMapper; this.jsonConverter = jsonConverter; this.commitFactory = commitFactory; this.repository = repository; this.queryRunner = queryRunner; this.globalIdFactory = globalIdFactory; } @Override public Commit commit(String author, Object currentVersion) { return commit(author, currentVersion, Collections.<String, String>emptyMap()); } @Override public Commit commit(String author, Object currentVersion, Map<String, String> commitProperties) { long start = System.currentTimeMillis(); argumentsAreNotNull(author, commitProperties, 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()); } Commit commit = commitFactory.create(author, commitProperties, currentVersion); long stop_f = System.currentTimeMillis(); if (commit.getSnapshots().isEmpty()) { logger.info("Skipping persisting empty commit: {}", commit.toString()); return commit; } repository.persist(commit); long stop = System.currentTimeMillis(); logger.info(commit.toString()+", done in "+ (stop-start)+ " millis (diff:{}, persist:{})",(stop_f-start), (stop-stop_f)); return commit; } @Override public Commit commitShallowDelete(String author, Object deleted) { return commitShallowDelete(author, deleted, Collections.<String, String>emptyMap()); } @Override public Commit commitShallowDelete(String author, Object deleted, Map<String, String> 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.<String, String>emptyMap()); } @Override public Commit commitShallowDeleteById(String author, GlobalIdDTO globalId, Map<String, String> 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) { argumentsAreNotNull(oldVersion, currentVersion); return diffFactory.compare(oldVersion, currentVersion); } @Override public Diff initial(Object newDomainObject) { return diffFactory.initial(newDomainObject); } @Override public <T> List<Shadow<T>> findShadows(JqlQuery query) { return (List)queryRunner.queryForShadows(query); } @Override public List<CdoSnapshot> findSnapshots(JqlQuery query){ return queryRunner.queryForSnapshots(query); } @Override public List<Change> findChanges(JqlQuery query){ return queryRunner.queryForChanges(query); } @Override public Optional<CdoSnapshot> getLatestSnapshot(Object localId, Class entityClass) { Validate.argumentsAreNotNull(localId, entityClass); return queryRunner.runQueryForLatestSnapshot(instanceId(localId, entityClass)); } @Override public JsonConverter getJsonConverter() { return jsonConverter; } @Override public <T> T processChangeList(List<Change> changes, ChangeProcessor<T> changeProcessor){ argumentsAreNotNull(changes, changeProcessor); ChangeListTraverser.traverse(changes, changeProcessor); return changeProcessor.result(); } @Override public <T extends JaversType> T getTypeMapping(Type clientsType) { return (T) typeMapper.getJaversType(clientsType); } /** * @see TypeName * @since 2.3 */ public <T extends ManagedType> T getTypeMapping(String typeName) { return (T) typeMapper.getJaversManagedType(typeName); } @Override public <T> Diff compareCollections(Collection<T> oldVersion, Collection<T> currentVersion, Class<T> itemClass) { return diffFactory.compareCollections(oldVersion, currentVersion, itemClass); } @Override public Property getProperty(PropertyChange propertyChange) { ManagedType managedType = typeMapper.getJaversManagedType(propertyChange.getAffectedGlobalId()); return managedType.getProperty(propertyChange.getPropertyName()); } }