VersioningFacade.java
package com.taxonomy.versioning.service;
import com.taxonomy.dto.ContextComparison;
import com.taxonomy.dto.ContextMode;
import com.taxonomy.dto.ContextRef;
import com.taxonomy.dto.RepositoryState;
import com.taxonomy.versioning.model.ContextHistoryRecord;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.io.IOException;
import java.time.Instant;
import java.util.List;
/**
* High-level facade that aggregates the versioning domain services.
*
* <p>This class provides coarse-grained operations that coordinate
* {@link ContextNavigationService}, {@link ContextCompareService},
* {@link ContextHistoryService}, and {@link RepositoryStateService}
* into workflows that controllers and other consumers can call
* without orchestrating the individual services themselves.
*/
@Service
public class VersioningFacade {
private static final Logger log = LoggerFactory.getLogger(VersioningFacade.class);
private final ContextNavigationService navigationService;
private final ContextCompareService compareService;
private final ContextHistoryService historyService;
private final RepositoryStateService stateService;
public VersioningFacade(ContextNavigationService navigationService,
ContextCompareService compareService,
ContextHistoryService historyService,
RepositoryStateService stateService) {
this.navigationService = navigationService;
this.compareService = compareService;
this.historyService = historyService;
this.stateService = stateService;
}
// ── Composite result records ────────────────────────────────────
/**
* Combines a newly created variant context with a snapshot of the
* repository state on that variant branch.
*
* @param variantContext the context on the new variant branch
* @param repositoryState the repository state for the variant branch
*/
public record VariantPreview(
ContextRef variantContext,
RepositoryState repositoryState
) {}
/**
* Combines the user's current navigation context, repository state,
* and recent persistent navigation history.
*
* @param currentContext the user's active context reference
* @param repositoryState the repository state for the active branch
* @param history the user's recent navigation history (newest first)
*/
public record FullContextState(
ContextRef currentContext,
RepositoryState repositoryState,
List<ContextHistoryRecord> history
) {}
// ── High-level operations ───────────────────────────────────────
/**
* Create a new branch variant from the user's current context and
* return a preview that includes the variant context and the
* repository state on the new branch.
*
* @param username the user creating the variant
* @param variantName the name for the new branch
* @return the variant context paired with the repository state
* @throws IOException if the branch creation fails
*/
public VariantPreview createVariantWithPreview(String username,
String variantName) throws IOException {
ContextRef variant = navigationService.createVariantFromCurrent(username, variantName);
RepositoryState repoState = stateService.getState(username, variant.branch());
log.info("User '{}': created variant '{}' with preview", username, variantName);
return new VariantPreview(variant, repoState);
}
/**
* Compare two branches at their HEAD commits and return a semantic
* comparison summary.
*
* @param leftBranch the left (source/older) branch name
* @param rightBranch the right (target/newer) branch name
* @return the comparison result including diff summary and semantic changes
* @throws IOException if Git operations fail
*/
@Transactional(readOnly = true)
public ContextComparison compareAndSummarize(String leftBranch,
String rightBranch) throws IOException {
ContextRef left = branchRef(leftBranch);
ContextRef right = branchRef(rightBranch);
log.debug("Comparing branches: '{}' vs '{}'", leftBranch, rightBranch);
return compareService.compareBranches(left, right);
}
/**
* Build a complete picture of a user's current versioning state:
* the active navigation context, the repository state on that branch,
* and the user's recent persistent navigation history.
*
* @param username the user whose state to retrieve
* @return the combined context, repository, and history state
*/
@Transactional(readOnly = true)
public FullContextState getFullContextState(String username) {
ContextRef current = navigationService.getCurrentContext(username);
RepositoryState repoState = stateService.getState(username, current.branch());
List<ContextHistoryRecord> history = historyService.getHistory(username);
log.debug("User '{}': assembled full context state on branch '{}'",
username, current.branch());
return new FullContextState(current, repoState, history);
}
// ── Internal helpers ────────────────────────────────────────────
/**
* Build a minimal {@link ContextRef} that identifies a branch without
* a specific commit (HEAD is implied).
*
* <p>Most fields are {@code null} because
* {@link ContextCompareService#compareBranches} only reads
* {@link ContextRef#branch()} — the remaining fields are unused.
*/
private static ContextRef branchRef(String branch) {
return new ContextRef(
null, branch, null, Instant.now(),
ContextMode.READ_ONLY,
null, null, null, null, null, false
);
}
}