package org.openlca.app.navigation.actions; import static org.openlca.app.cloud.index.DiffType.CHANGED; import static org.openlca.app.cloud.index.DiffType.DELETED; import static org.openlca.app.cloud.index.DiffType.NEW; import static org.openlca.app.cloud.index.DiffType.NO_DIFF; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import java.util.function.Consumer; import org.openlca.app.cloud.index.DiffIndex; import org.openlca.app.cloud.index.DiffType; import org.openlca.app.cloud.ui.diff.DiffResult; import org.openlca.app.cloud.ui.diff.DiffResult.DiffResponse; import org.openlca.app.db.Database; import org.openlca.cloud.model.data.Dataset; import org.openlca.core.database.CategorizedEntityDao; import org.openlca.core.database.Daos; import org.openlca.core.database.IDatabase; import org.openlca.core.model.ModelType; import org.openlca.core.model.descriptors.CategorizedDescriptor; import org.slf4j.Logger; import org.slf4j.LoggerFactory; class FetchIndexHelper { private final static Logger log = LoggerFactory.getLogger(FetchIndexHelper.class); private DiffIndex index; private Map<String, Long> localIds = new HashMap<>(); private FetchIndexHelper(DiffIndex index) { this.index = index; } static void index(List<DiffResult> changed, DiffIndex index) { index(changed, index, null); } static void index(List<DiffResult> changed, DiffIndex index, Consumer<DiffResult> callback) { FetchIndexHelper helper = new FetchIndexHelper(index); helper.localIds = getLocalIds(changed); for (DiffResult diff : changed) { helper.index(diff); if (callback == null) continue; callback.accept(diff); } index.commit(); } private static Map<String, Long> getLocalIds(List<DiffResult> changed) { Map<ModelType, Set<String>> refIds = groupRefIdsByModelType(changed); Map<String, Long> refIdToLocalId = new HashMap<>(); IDatabase db = Database.get(); for (ModelType type : refIds.keySet()) { CategorizedEntityDao<?, ? extends CategorizedDescriptor> dao = Daos .createCategorizedDao(db, type); List<? extends CategorizedDescriptor> descriptors = dao .getDescriptorsForRefIds(refIds.get(type)); for (CategorizedDescriptor descriptor : descriptors) refIdToLocalId.put(descriptor.getRefId(), descriptor.getId()); } return refIdToLocalId; } private static Map<ModelType, Set<String>> groupRefIdsByModelType( List<DiffResult> changed) { Map<ModelType, Set<String>> refIds = new HashMap<>(); for (DiffResult result : changed) { if (result.getType() != DiffResponse.ADD_TO_LOCAL) continue; ModelType mType = result.getDataset().type; if (!mType.isCategorized()) continue; Set<String> ids = refIds.get(mType); if (ids == null) refIds.put(mType, ids = new HashSet<>()); ids.add(result.getDataset().refId); } return refIds; } private void index(DiffResult diff) { log.debug("Indexing: " + diff.toString()); Dataset dataset = diff.getDataset(); if (!dataset.type.isCategorized()) return; DiffResponse responseType = diff.getType(); switch (responseType) { case NONE: if (bothDeleted(diff)) index.remove(dataset.refId); else index.update(dataset, NO_DIFF); break; case MODIFY_IN_LOCAL: index.update(dataset, NO_DIFF); break; case ADD_TO_LOCAL: index.add(dataset, localIds.get(dataset.refId)); break; case DELETE_FROM_LOCAL: index.remove(dataset.refId); break; case CONFLICT: indexConflict(diff); break; default: break; } } private void indexConflict(DiffResult diff) { if (diff.local.type == CHANGED) indexChanged(diff); else if (diff.local.type == DELETED) indexDeleted(diff); } private void indexDeleted(DiffResult diff) { Dataset dataset = diff.getDataset(); if (diff.overwriteRemoteChanges()) index.update(dataset, DELETED); else if (diff.overwriteLocalChanges()) index.update(dataset, NO_DIFF); } private void indexChanged(DiffResult diff) { if (diff.overwriteRemoteChanges()) indexOverwritten(diff); else indexMerged(diff); } private void indexOverwritten(DiffResult diff) { Dataset dataset = diff.getDataset(); if (diff.remote.isDeleted()) { index.add(dataset, localIds.get(dataset.refId)); index.update(dataset, NEW); } else { DiffType previousType = index.get(dataset.refId).type; if (previousType != NEW) index.update(dataset, CHANGED); } } private void indexMerged(DiffResult diff) { Dataset dataset = diff.getDataset(); if (diff.remote.isDeleted()) index.remove(dataset.refId); else index.update(dataset, NO_DIFF); } private boolean bothDeleted(DiffResult diff) { if (diff.remote == null) return false; if (!diff.remote.isDeleted()) return false; return diff.local == null; } }