blob: 306a0cb125315b3f5a52184ab9e7741cab50e779 [file] [log] [blame]
/*********************************************************************
* Copyright (c) 2015 Boeing
*
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Boeing - initial API and implementation
**********************************************************************/
package org.eclipse.osee.orcs.rest.internal;
import static org.eclipse.osee.framework.core.data.CoreActivityTypes.BRANCH_OPERATION;
import static org.eclipse.osee.framework.jdk.core.util.Compare.isDifferent;
import static org.eclipse.osee.orcs.rest.internal.OrcsRestUtil.asResponse;
import static org.eclipse.osee.orcs.rest.internal.OrcsRestUtil.asTransaction;
import static org.eclipse.osee.orcs.rest.internal.OrcsRestUtil.asTransactions;
import static org.eclipse.osee.orcs.rest.internal.OrcsRestUtil.executeCallable;
import com.google.common.collect.Lists;
import java.net.URI;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.Callable;
import java.util.logging.Level;
import javax.ws.rs.Consumes;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status;
import javax.ws.rs.core.UriInfo;
import org.eclipse.osee.activity.api.ActivityLog;
import org.eclipse.osee.framework.core.data.ArtifactId;
import org.eclipse.osee.framework.core.data.ArtifactTypeToken;
import org.eclipse.osee.framework.core.data.Branch;
import org.eclipse.osee.framework.core.data.BranchId;
import org.eclipse.osee.framework.core.data.IOseeBranch;
import org.eclipse.osee.framework.core.data.JsonArtifact;
import org.eclipse.osee.framework.core.data.JsonAttribute;
import org.eclipse.osee.framework.core.data.JsonRelation;
import org.eclipse.osee.framework.core.data.JsonRelations;
import org.eclipse.osee.framework.core.data.RelationTypeToken;
import org.eclipse.osee.framework.core.data.TransactionId;
import org.eclipse.osee.framework.core.data.TransactionResult;
import org.eclipse.osee.framework.core.data.TransactionToken;
import org.eclipse.osee.framework.core.data.UpdateBranchData;
import org.eclipse.osee.framework.core.data.UserId;
import org.eclipse.osee.framework.core.enums.BranchState;
import org.eclipse.osee.framework.core.enums.BranchType;
import org.eclipse.osee.framework.core.enums.PermissionEnum;
import org.eclipse.osee.framework.core.model.change.ChangeItem;
import org.eclipse.osee.framework.jdk.core.result.XResultData;
import org.eclipse.osee.framework.jdk.core.type.OseeArgumentException;
import org.eclipse.osee.framework.jdk.core.type.OseeCoreException;
import org.eclipse.osee.framework.jdk.core.type.PropertyStore;
import org.eclipse.osee.framework.jdk.core.type.ResultSet;
import org.eclipse.osee.framework.jdk.core.util.Collections;
import org.eclipse.osee.framework.jdk.core.util.Compare;
import org.eclipse.osee.framework.jdk.core.util.Conditions;
import org.eclipse.osee.framework.jdk.core.util.Lib;
import org.eclipse.osee.framework.jdk.core.util.Strings;
import org.eclipse.osee.framework.logging.OseeLevel;
import org.eclipse.osee.framework.logging.OseeLog;
import org.eclipse.osee.framework.resource.management.IResourceLocator;
import org.eclipse.osee.framework.resource.management.IResourceManager;
import org.eclipse.osee.jaxrs.OseeWebApplicationException;
import org.eclipse.osee.jdbc.JdbcStatement;
import org.eclipse.osee.orcs.ExportOptions;
import org.eclipse.osee.orcs.ImportOptions;
import org.eclipse.osee.orcs.OrcsApi;
import org.eclipse.osee.orcs.OrcsBranch;
import org.eclipse.osee.orcs.data.ArchiveOperation;
import org.eclipse.osee.orcs.data.ArtifactReadable;
import org.eclipse.osee.orcs.data.AttributeReadable;
import org.eclipse.osee.orcs.data.CreateBranchData;
import org.eclipse.osee.orcs.data.TransactionReadable;
import org.eclipse.osee.orcs.rest.internal.branch.UpdateBranchOperation;
import org.eclipse.osee.orcs.rest.internal.email.SupportEmailService;
import org.eclipse.osee.orcs.rest.model.BranchCommitOptions;
import org.eclipse.osee.orcs.rest.model.BranchEndpoint;
import org.eclipse.osee.orcs.rest.model.BranchExportOptions;
import org.eclipse.osee.orcs.rest.model.BranchImportOptions;
import org.eclipse.osee.orcs.rest.model.BranchQueryData;
import org.eclipse.osee.orcs.rest.model.NewBranch;
import org.eclipse.osee.orcs.rest.model.NewTransaction;
import org.eclipse.osee.orcs.rest.model.Transaction;
import org.eclipse.osee.orcs.search.BranchQuery;
import org.eclipse.osee.orcs.search.QueryFactory;
import org.eclipse.osee.orcs.search.TransactionQuery;
import org.eclipse.osee.orcs.transaction.TransactionBuilder;
import org.eclipse.osee.orcs.transaction.TransactionFactory;
/**
* @author Roberto E. Escobar
*/
public class BranchEndpointImpl implements BranchEndpoint {
private final OrcsApi orcsApi;
private final IResourceManager resourceManager;
private final ActivityLog activityLog;
private final OrcsBranch branchOps;
private final SupportEmailService supportEmailService;
@Context
private UriInfo uriInfo;
@Context
private HttpHeaders httpHeaders;
public BranchEndpointImpl(OrcsApi orcsApi, IResourceManager resourceManager, ActivityLog activityLog) {
this.orcsApi = orcsApi;
this.resourceManager = resourceManager;
this.activityLog = activityLog;
this.branchOps = orcsApi.getBranchOps();
this.supportEmailService = new SupportEmailService();
}
public HttpHeaders getHeaders() {
return httpHeaders;
}
public void setHeaders(HttpHeaders httpHeaders) {
this.httpHeaders = httpHeaders;
}
public void setUriInfo(UriInfo uriInfo) {
this.uriInfo = uriInfo;
}
public UriInfo getUriInfo() {
return uriInfo;
}
private QueryFactory newQuery() {
return orcsApi.getQueryFactory();
}
private BranchQuery newBranchQuery() {
return newQuery().branchQuery();
}
private TransactionQuery newTxQuery() {
return newQuery().transactionQuery();
}
private TransactionReadable getTxByBranchAndId(BranchId branch, TransactionId txId) {
return newTxQuery().andBranch(branch).andTxId(txId).getResults().getExactlyOne();
}
private TransactionFactory newTxFactory() {
return orcsApi.getTransactionFactory();
}
@Override
public List<Branch> getBranches(BranchQueryData options) {
ResultSet<Branch> results = searchBranches(options);
return results.getList();
}
@Override
public List<Branch> getFromQuery(BranchQueryData options) {
ResultSet<Branch> results = searchBranches(options);
Set<Branch> branches = new HashSet<>();
branches.addAll(results.getList());
List<Branch> branchList = new ArrayList<>();
branchList.addAll(branches);
return branchList;
}
@Override
public List<Branch> getBranches(String branchUuids, String branchTypes, String branchStates, boolean deleted, boolean archived, String nameEquals, String namePattern, Long childOf, Long ancestorOf) {
BranchQueryData options = new BranchQueryData();
options.setBranchIds(Collections.fromString(branchUuids, ",", BranchId::valueOf));
if (Strings.isValid(branchTypes)) {
List<BranchType> branchTypeVals = new LinkedList<>();
for (String branchType : branchTypes.split(",")) {
branchTypeVals.add(BranchType.fromName(branchType.toUpperCase()));
}
options.setBranchTypes(branchTypeVals);
}
if (Strings.isValid(branchStates)) {
List<BranchState> branchStateVals = new LinkedList<>();
for (String branchState : branchStates.split(",")) {
branchStateVals.add(BranchState.fromName(branchState.toUpperCase()));
}
options.setBranchStates(branchStateVals);
}
options.setIncludeDeleted(deleted);
options.setIncludeArchived(archived);
if (Strings.isValid(nameEquals)) {
options.setNameEquals(nameEquals);
}
if (Strings.isValid(namePattern)) {
options.setNamePattern(namePattern);
}
if (childOf != null) {
options.setIsChildOf(childOf);
}
if (ancestorOf != null) {
options.setIsAncestorOf(ancestorOf);
}
return getBranches(options);
}
@Override
public List<Branch> getBaselineBranches() {
return newBranchQuery().includeArchived(false).includeDeleted(false).andIsOfType(
BranchType.BASELINE).getResults().getList();
}
@Override
public List<Branch> getWorkingBranches() {
return newBranchQuery().includeArchived(false).includeDeleted(false).andIsOfType(
BranchType.WORKING).getResults().getList();
}
@Override
public Branch getBranchById(BranchId branch) {
return newBranchQuery().andId(branch).includeArchived().includeDeleted().getResults().getExactlyOne();
}
@Override
public List<Transaction> getAllBranchTxs(BranchId branch) {
return asTransactions(newTxQuery().andBranch(branch).getResults());
}
@Override
public Transaction getBranchTx(BranchId branchUuid, TransactionId txId) {
return asTransaction(getTxByBranchAndId(branchUuid, txId));
}
@Override
public List<JsonArtifact> getArtifactDetailsByType(BranchId branchId, String artifactTypes) {
return getArtifactDetailsByType(branchId, ArtifactId.SENTINEL, artifactTypes);
}
@Override
public List<JsonArtifact> getArtifactDetailsByType(BranchId branchId, ArtifactId viewId, String artifactTypes) {
List<JsonArtifact> arts = new ArrayList<JsonArtifact>();
List<Long> typesLong = Collections.fromString(artifactTypes, ",", Long::valueOf);
List<ArtifactTypeToken> types = new ArrayList<ArtifactTypeToken>();
for (Long typeId : typesLong) {
types.add(orcsApi.tokenService().getArtifactType(typeId));
}
List<ArtifactReadable> artifacts = null;
if (viewId.isValid()) {
artifacts = orcsApi.getQueryFactory().fromBranch(branchId, viewId).andIsOfType(types).getResults().getList();
} else {
artifacts = orcsApi.getQueryFactory().fromBranch(branchId).andIsOfType(types).getResults().getList();
}
for (ArtifactReadable art : artifacts) {
JsonArtifact jArt = new JsonArtifact();
jArt.setType(art.getArtifactType());
jArt.setTypeName(art.getArtifactType().getName());
jArt.setId(ArtifactId.valueOf(art.getId()));
jArt.setName(art.getName());
List<JsonAttribute> attrList = new ArrayList<JsonAttribute>();
List<? extends AttributeReadable<Object>> list = art.getAttributes().getList();
for (AttributeReadable<?> attr : list) {
JsonAttribute attrRep = new JsonAttribute();
attrRep.setTypeId(attr.getAttributeType());
attrRep.setTypeName(attr.getAttributeType().getName());
if (attr.getAttributeType().getMediaType().startsWith("application")) {
attrRep.setValue("<large>");
} else {
attrRep.setValue(attr.getDisplayableString());
}
attrList.add(attrRep);
}
jArt.setAttrs(attrList);
arts.add(jArt);
}
return arts;
}
@Override
public List<ChangeItem> compareBranches(BranchId branch, BranchId branch2) {
TransactionToken sourceTx = newTxQuery().andIsHead(branch).getResults().getExactlyOne();
TransactionToken destinationTx = newTxQuery().andIsHead(branch2).getResults().getExactlyOne();
List<ChangeItem> data = branchOps.compareBranch(sourceTx, destinationTx);
try {
activityLog.createEntry(BRANCH_OPERATION, ActivityLog.INITIAL_STATUS,
String.format("Branch Operation Compare Branches {sourceTx: %s, destTx: %s}", sourceTx.toString(),
destinationTx.toString()));
} catch (OseeCoreException ex) {
OseeLog.log(ActivityLog.class, OseeLevel.SEVERE_POPUP, ex);
}
return data;
}
@Override
public BranchId createBranch(NewBranch data) {
return createBranch(new CreateBranchData(), data);
}
@Override
public BranchId createBranchWithId(BranchId branch, NewBranch data) {
if (branch.isInvalid()) {
throw new OseeWebApplicationException(Status.BAD_REQUEST, "branchUuid [%d] uuid must be > 0", branch);
}
CreateBranchData createData = new CreateBranchData(branch);
return createBranch(createData, data);
}
@Override
@POST
@Consumes({MediaType.APPLICATION_JSON})
@Produces({MediaType.APPLICATION_JSON})
public XResultData createBranchValidation(NewBranch data) {
CreateBranchData branchData = new CreateBranchData();
createBranchData(branchData, data);
return branchOps.createBranchValidation(branchData);
}
@Override
@POST
@Path("{branch}/update")
@Consumes({MediaType.APPLICATION_JSON})
@Produces({MediaType.APPLICATION_JSON})
public UpdateBranchData updateBranch(@PathParam("branch") BranchId branch, UpdateBranchData branchData) {
UpdateBranchOperation op = new UpdateBranchOperation(branchData, orcsApi);
return op.run();
}
private BranchId createBranch(CreateBranchData createData, NewBranch data) {
createBranchData(createData, data);
Branch result = branchOps.createBranch(createData);
try {
activityLog.createEntry(BRANCH_OPERATION, ActivityLog.INITIAL_STATUS,
String.format("Branch Operation Create Branch {branchId: %s, branchName: %s}", createData.getBranch(),
data.getBranchName()));
} catch (OseeCoreException ex) {
OseeLog.log(ActivityLog.class, OseeLevel.SEVERE_POPUP, ex);
}
return result;
}
private void createBranchData(CreateBranchData createData, NewBranch data) {
createData.setName(data.getBranchName());
createData.setBranchType(data.getBranchType());
createData.setCreationComment(data.getCreationComment());
createData.setAuthor(data.getAuthor());
createData.setAssociatedArtifact(data.getAssociatedArtifact());
createData.setFromTransaction(data.getSourceTransaction());
createData.setParentBranch(data.getParentBranch());
createData.setMergeDestinationBranchId(data.getMergeDestinationBranchId());
createData.setMergeAddressingQueryId(data.getMergeAddressingQueryId());
createData.setTxCopyBranchType(data.isTxCopyBranchType());
}
@Override
public TransactionResult commitBranch(BranchId branch, BranchId destinationBranch, BranchCommitOptions options) {
Branch srcBranch = getBranchById(branch);
Branch destBranch = getBranchById(destinationBranch);
TransactionResult tr = new TransactionResult();
tr.getResults().logf("Commiting Branch\n");
tr.getResults().logf("Source Branch [%s]\n", branch);
tr.getResults().logf("Destination Branch [%s]\n", destBranch);
tr.getResults().logf("Options [%s]\n\n", options);
Callable<TransactionToken> op = branchOps.commitBranch(options.getCommitter(), srcBranch, destBranch);
try {
TransactionToken tx = executeCallable(op);
tr.setTx(tx);
} catch (Exception ex) {
tr.getResults().errorf("Exception commiting branch [%s]", Lib.exceptionToString(ex));
return tr;
}
if (options.isArchive()) {
Callable<?> op2 = branchOps.archiveUnarchiveBranch(srcBranch, ArchiveOperation.ARCHIVE);
executeCallable(op2);
}
try {
activityLog.createEntry(BRANCH_OPERATION, ActivityLog.INITIAL_STATUS,
String.format("Branch Operation Commit Branch {branchId: %s srcBranch: %s destBranch: %s}", branch,
srcBranch, destBranch));
} catch (OseeCoreException ex) {
tr.getResults().errorf("Exception logging activity [%s]", Lib.exceptionToString(ex));
return tr;
}
return tr;
}
@Override
public Response archiveBranch(BranchId branchId) {
Branch branch = getBranchById(branchId);
boolean modified = false;
if (!branch.isArchived()) {
try {
Callable<?> op = branchOps.archiveUnarchiveBranch(branch, ArchiveOperation.ARCHIVE);
executeCallable(op);
} catch (Exception ex) {
supportEmailService.sendSupportEmail("Exception caught during archival of branch " + branchId.getIdString(),
ex.getLocalizedMessage());
OseeLog.log(ActivityLog.class, Level.SEVERE, ex);
return asResponse(modified);
}
modified = true;
try {
activityLog.createEntry(BRANCH_OPERATION, ActivityLog.INITIAL_STATUS,
String.format("Branch Operation Archive Branch {branchId: %s}", branchId));
} catch (OseeCoreException ex) {
OseeLog.log(ActivityLog.class, OseeLevel.SEVERE_POPUP, ex);
}
}
return asResponse(modified);
}
@Override
public Response unarchiveBranch(BranchId branchId) {
Branch branch = getBranchById(branchId);
boolean modified = false;
if (branch.isArchived()) {
try {
Callable<?> op = branchOps.archiveUnarchiveBranch(branch, ArchiveOperation.UNARCHIVE);
executeCallable(op);
} catch (Exception ex) {
supportEmailService.sendSupportEmail(
"Exception caught during unarchival of branch " + branchId.getIdString(), ex.getLocalizedMessage());
OseeLog.log(ActivityLog.class, Level.SEVERE, ex);
return asResponse(modified);
}
modified = true;
try {
activityLog.createEntry(BRANCH_OPERATION, ActivityLog.INITIAL_STATUS,
String.format("Branch Operation Unarchive Branch {branchId: %s}", branchId));
} catch (OseeCoreException ex) {
OseeLog.log(ActivityLog.class, OseeLevel.SEVERE_POPUP, ex);
}
}
return asResponse(modified);
}
@Override
public Response writeTx(BranchId branch, NewTransaction data) {
String comment = data.getComment();
TransactionFactory txFactory = newTxFactory();
TransactionBuilder txBuilder = txFactory.createTransaction(branch, null, comment);
//TODO: Integrate data with TxBuilder
TransactionToken txId = txBuilder.commit();
TransactionReadable tx = orcsApi.getQueryFactory().transactionQuery().andTxId(txId).getResults().getExactlyOne();
if (tx.isValid()) {
URI location = uriInfo.getRequestUriBuilder().path("{tx-id}").build(tx);
return Response.created(location).entity(asTransaction(tx)).build();
} else {
throw new OseeArgumentException("No Data Modified");
}
}
@Override
public Response validateExchange(String path) {
String exchangePath = asExchangeLocator(path);
IResourceLocator locator = resourceManager.getResourceLocator(exchangePath);
Callable<URI> op = branchOps.checkBranchExchangeIntegrity(locator.getLocation());
URI verifyUri = executeCallable(op);
UriInfo uriInfo = getUriInfo();
URI location = getExchangeResourceURI(uriInfo, verifyUri);
return Response.created(location).build();
}
@Override
public Response deleteBranchExchange(String path) {
boolean modified = false;
String exchangePath = asExchangeLocator(path);
IResourceLocator locator = resourceManager.getResourceLocator(exchangePath);
if (locator != null) {
int deleteResult = resourceManager.delete(locator);
switch (deleteResult) {
case IResourceManager.OK:
try {
activityLog.createEntry(BRANCH_OPERATION, ActivityLog.INITIAL_STATUS,
String.format("Branch Operation Delete Branch Exachange Resource {resource: %s, locator %s}", path,
locator.getLocation()));
} catch (OseeCoreException ex) {
OseeLog.log(ActivityLog.class, OseeLevel.SEVERE_POPUP, ex);
}
modified = true;
break;
case IResourceManager.FAIL:
throw new OseeWebApplicationException(Status.INTERNAL_SERVER_ERROR,
"Error deleting exchange resource [%s] - locator [%s]", path, locator.getLocation());
case IResourceManager.RESOURCE_NOT_FOUND:
default:
// do nothing - no modification
break;
}
}
return OrcsRestUtil.asResponse(modified);
}
@Override
public Response exportBranches(BranchExportOptions options) {
List<IOseeBranch> branches = getExportImportBranches(options.getBranchUuids());
PropertyStore exportOptions = new PropertyStore();
addOption(exportOptions, ExportOptions.MIN_TXS, options.getMinTx());
addOption(exportOptions, ExportOptions.MAX_TXS, options.getMaxTx());
addOption(exportOptions, ExportOptions.COMPRESS, options.isCompress());
Callable<URI> op = branchOps.exportBranch(branches, exportOptions, options.getFileName());
URI exportURI = executeCallable(op);
UriInfo uriInfo = getUriInfo();
URI location = getExchangeExportUri(uriInfo, exportURI, options.isCompress());
try {
activityLog.createEntry(BRANCH_OPERATION, ActivityLog.INITIAL_STATUS,
String.format("Branch Operation Export Branches {branchUUID(s): %s}", branches));
} catch (OseeCoreException ex) {
OseeLog.log(ActivityLog.class, OseeLevel.SEVERE_POPUP, ex);
}
return Response.created(location).build();
}
@Override
public Response importBranches(BranchImportOptions options) {
List<IOseeBranch> branches;
if (!options.getBranchUuids().isEmpty()) {
branches = getExportImportBranches(options.getBranchUuids());
} else {
branches = java.util.Collections.emptyList();
}
String path = options.getExchangeFile();
String exchangePath = asExchangeLocator(path);
IResourceLocator locator = resourceManager.getResourceLocator(exchangePath);
PropertyStore importOptions = new PropertyStore();
addOption(importOptions, ImportOptions.MIN_TXS, options.getMinTx());
addOption(importOptions, ImportOptions.MAX_TXS, options.getMaxTx());
addOption(importOptions, ImportOptions.USE_IDS_FROM_IMPORT_FILE, options.isUseIdsFromImportFile());
addOption(importOptions, ImportOptions.EXCLUDE_BASELINE_TXS, options.isExcludeBaselineTxs());
addOption(importOptions, ImportOptions.ALL_AS_ROOT_BRANCHES, options.isAllAsRootBranches());
addOption(importOptions, ImportOptions.CLEAN_BEFORE_IMPORT, options.isCleanBeforeImport());
Callable<URI> op = branchOps.importBranch(locator.getLocation(), branches, importOptions);
URI importURI = executeCallable(op);
Response response;
if (importURI != null) {
UriInfo uriInfo = getUriInfo();
URI location = getExchangeResourceURI(uriInfo, importURI);
response = Response.created(location).build();
} else {
response = Response.ok().build();
}
try {
activityLog.createEntry(BRANCH_OPERATION, ActivityLog.INITIAL_STATUS,
String.format("Branch Operation Import Branches {branchUUID(s): %s}", branches));
} catch (OseeCoreException ex) {
OseeLog.log(ActivityLog.class, OseeLevel.SEVERE_POPUP, ex);
}
return response;
}
private void addOption(PropertyStore data, Enum<?> enumKey, Object value) {
if (value != null) {
data.put(enumKey.name(), String.valueOf(value));
}
}
private String asExchangeLocator(String path) {
String toReturn = path;
if (Strings.isValid(toReturn)) {
if (!toReturn.startsWith("exchange://")) {
toReturn = "exchange://" + toReturn;
}
}
return toReturn;
}
private URI getExchangeResourceURI(UriInfo uriInfo, URI rawUri) {
URI toReturn = rawUri;
String path = rawUri.toASCIIString();
int index = path.indexOf("exchange/");
if (index > 0 && index < path.length()) {
path = path.substring(index);
toReturn = uriInfo.getBaseUriBuilder().path("resources").queryParam("path", path).build();
}
return toReturn;
}
private URI getExchangeExportUri(UriInfo uriInfo, URI rawUri, boolean isCompressed) {
String path = rawUri.toASCIIString();
path = path.replace("://", "/");
if (isCompressed && !path.endsWith(".zip")) {
path = path + ".zip";
} else {
path = path + "/export.manifest.xml";
}
URI toReturn = uriInfo.getBaseUriBuilder().path("resources").queryParam("path", path).build();
return toReturn;
}
private List<IOseeBranch> getExportImportBranches(Collection<BranchId> branchUids) {
ResultSet<IOseeBranch> resultsAsId = newBranchQuery().andIds(branchUids) //
.includeArchived()//
.includeDeleted()//
.getResultsAsId();
return Lists.newLinkedList(resultsAsId);
}
@Override
public Response setBranchName(BranchId branchId, String newName) {
Branch branch = getBranchById(branchId);
boolean modified = false;
if (isDifferent(branch.getName(), newName)) {
Callable<?> op = branchOps.changeBranchName(branch, newName);
executeCallable(op);
modified = true;
try {
activityLog.createEntry(BRANCH_OPERATION, ActivityLog.INITIAL_STATUS,
String.format("Branch Operation Set Branch Name {branchId: %s prevName: %s newName: %s}", branchId,
branch.getName(), newName));
} catch (OseeCoreException ex) {
OseeLog.log(ActivityLog.class, OseeLevel.SEVERE_POPUP, ex);
}
}
return asResponse(modified);
}
@Override
public Response setBranchType(BranchId branchId, BranchType newType) {
Branch branch = getBranchById(branchId);
boolean modified = false;
if (isDifferent(branch.getBranchType(), newType)) {
try {
activityLog.createEntry(BRANCH_OPERATION, ActivityLog.INITIAL_STATUS,
String.format("Branch Operation Set Branch Type {branchUUID: %s prevType: %s newType: %s}", branchId,
branch.getBranchType(), newType));
} catch (OseeCoreException ex) {
OseeLog.log(ActivityLog.class, OseeLevel.SEVERE_POPUP, ex);
}
Callable<?> op = branchOps.changeBranchType(branch, newType);
executeCallable(op);
modified = true;
}
return asResponse(modified);
}
@Override
public Response setBranchState(BranchId branchId, BranchState newState) {
Branch branch = getBranchById(branchId);
boolean modified = false;
if (isDifferent(branch.getBranchState(), newState)) {
Callable<?> op = branchOps.changeBranchState(branch, newState);
executeCallable(op);
modified = true;
try {
activityLog.createEntry(BRANCH_OPERATION, ActivityLog.INITIAL_STATUS,
String.format("Branch Operation Branch State Changed {branchId: %s prevState: %s newState: %s}",
branchId, branch.getBranchType(), newState));
} catch (OseeCoreException ex) {
OseeLog.log(ActivityLog.class, OseeLevel.SEVERE_POPUP, ex);
}
}
return asResponse(modified);
}
@Override
public void setBranchPermission(ArtifactId subject, BranchId branch, PermissionEnum permission) {
branchOps.setBranchPermission(subject, branch, permission);
}
@Override
public Response associateBranchToArtifact(BranchId branchId, ArtifactId artifact) {
Branch branch = getBranchById(branchId);
boolean modified = false;
if (isDifferent(branch.getAssociatedArtifact(), artifact)) {
try {
activityLog.createEntry(BRANCH_OPERATION, ActivityLog.INITIAL_STATUS,
String.format("Branch Operation Associate Branch to Artifact {branchId: %s prevArt: %s newArt: %s}",
branchId, branch.getAssociatedArtifact(), artifact));
} catch (OseeCoreException ex) {
OseeLog.log(ActivityLog.class, OseeLevel.SEVERE_POPUP, ex);
}
Callable<?> op = branchOps.associateBranchToArtifact(branch, artifact);
executeCallable(op);
modified = true;
}
return asResponse(modified);
}
@Override
public Response setTxComment(BranchId branch, TransactionId txId, String comment) {
TransactionReadable tx = getTxByBranchAndId(branch, txId);
boolean modified = false;
if (Compare.isDifferent(tx.getComment(), comment)) {
try {
activityLog.createEntry(BRANCH_OPERATION, ActivityLog.INITIAL_STATUS,
String.format("Branch Operation Set Tx Comment {branchId: %s prevComment: %s newComment: %s}", branch,
tx.getComment(), comment));
} catch (OseeCoreException ex) {
OseeLog.log(ActivityLog.class, OseeLevel.SEVERE_POPUP, ex);
}
TransactionFactory txFactory = newTxFactory();
txFactory.setTransactionComment(tx, comment);
modified = true;
}
return asResponse(modified);
}
@Override
public Response purgeBranch(BranchId branchId, boolean recurse) {
boolean modified = false;
Branch branch = getBranchById(branchId);
if (branch != null) {
Callable<?> op = branchOps.purgeBranch(branch, recurse);
executeCallable(op);
modified = true;
}
try {
activityLog.createEntry(BRANCH_OPERATION, ActivityLog.INITIAL_STATUS,
String.format("Branch Operation Purge Branch {branchId: %s}", branchId));
} catch (OseeCoreException ex) {
OseeLog.log(ActivityLog.class, OseeLevel.SEVERE_POPUP, ex);
}
return asResponse(modified);
}
@Override
public Response unCommitBranch(BranchId branch, BranchId destinationBranch) {
throw new UnsupportedOperationException("Not yet implemented");
}
@Override
public Response unassociateBranch(BranchId branchId) {
Branch branch = getBranchById(branchId);
boolean modified = false;
if (branch.getAssociatedArtifact().isValid()) {
Callable<?> op = branchOps.unassociateBranch(branch);
executeCallable(op);
modified = true;
try {
activityLog.createEntry(BRANCH_OPERATION, ActivityLog.INITIAL_STATUS,
String.format("Branch Operation Unassociate Branch {branchId: %s}", branchId));
} catch (OseeCoreException ex) {
OseeLog.log(ActivityLog.class, OseeLevel.SEVERE_POPUP, ex);
}
}
return asResponse(modified);
}
@Override
public Response purgeTxs(BranchId branch, String txIds) {
boolean modified = false;
List<TransactionId> txsToDelete = Collections.fromString(txIds, TransactionId::valueOf);
if (!txsToDelete.isEmpty()) {
ResultSet<? extends TransactionId> results = newTxQuery().andBranch(branch).andTxIds(txsToDelete).getResults();
if (!results.isEmpty()) {
checkAllTxFoundAreOnBranch("Purge Transaction", branch, txsToDelete, results);
List<TransactionId> list = Lists.newArrayList(results);
Callable<?> op = newTxFactory().purgeTransaction(list);
executeCallable(op);
modified = true;
try {
activityLog.createEntry(BRANCH_OPERATION, ActivityLog.INITIAL_STATUS,
String.format("Branch Operation Purge Txs {branchId: %s, txsToDelete: %s}", branch, txIds));
} catch (OseeCoreException ex) {
OseeLog.log(ActivityLog.class, OseeLevel.SEVERE_POPUP, ex);
}
}
}
return asResponse(modified);
}
private void checkAllTxFoundAreOnBranch(String opName, BranchId branch, List<TransactionId> txIds, ResultSet<? extends TransactionId> result) {
if (txIds.size() != result.size()) {
List<TransactionId> difference = Collections.setComplement(txIds, result.getList());
if (!difference.isEmpty()) {
throw new OseeWebApplicationException(Status.BAD_REQUEST,
"%s Error - The following transactions from %s were not found on branch [%s] - txs %s - Please remove them from the request and try again.",
opName, txIds, branch, difference);
}
}
}
private ResultSet<Branch> searchBranches(BranchQueryData options) {
BranchQuery query = orcsApi.getQueryFactory().branchQuery();
Collection<BranchId> branchIds = options.getBranchIds();
if (Conditions.hasValues(branchIds)) {
query.andIds(branchIds);
}
Collection<BranchState> branchStates = options.getBranchStates();
if (Conditions.hasValues(branchStates)) {
query.andStateIs(branchStates.toArray(new BranchState[branchStates.size()]));
}
Collection<BranchType> branchTypes = options.getBranchTypes();
if (Conditions.hasValues(branchTypes)) {
query.andIsOfType(branchTypes.toArray(new BranchType[branchTypes.size()]));
}
if (options.isIncludeArchived()) {
query.includeArchived();
} else {
query.excludeArchived();
}
if (options.isIncludeDeleted()) {
query.includeDeleted();
} else {
query.excludeDeleted();
}
String nameEquals = options.getNameEquals();
if (Strings.isValid(nameEquals)) {
query.andNameEquals(nameEquals);
}
String namePattern = options.getNamePattern();
if (Strings.isValid(namePattern)) {
query.andNamePattern(namePattern);
}
String namePatternIgnoreCase = options.getNamePatternIgnoreCase();
if (Strings.isValid(namePatternIgnoreCase)) {
query.andNamePatternIgnoreCase(namePatternIgnoreCase);
}
Long ancestorOf = options.getIsAncestorOf();
if (ancestorOf > 0) {
BranchId ancestorOfToken = BranchId.valueOf(ancestorOf);
query.andIsAncestorOf(ancestorOfToken);
}
Long childOf = options.getIsChildOf();
if (childOf > 0) {
BranchId childOfToken = BranchId.valueOf(ancestorOf);
query.andIsAncestorOf(childOfToken);
}
return query.getResults();
}
@Override
public Response logBranchActivity(String comment) {
try {
activityLog.createEntry(BRANCH_OPERATION, ActivityLog.INITIAL_STATUS, comment);
} catch (OseeCoreException ex) {
OseeLog.log(ActivityLog.class, OseeLevel.SEVERE_POPUP, ex);
}
return Response.ok().build();
}
@Override
public IOseeBranch createProgramBranch(UserId account, BranchId branch, String branchName) {
IOseeBranch branchToken =
branch.isValid() ? IOseeBranch.create(branch, branchName) : IOseeBranch.create(branchName);
return branchOps.createProgramBranch(branchToken, account);
}
@Override
public JsonRelations getRelationsByType(BranchId branch, String relationTypes) {
String query = "select * from osee_relation_link rel, osee_txs txs " //
+ "where txs.branch_id = ? " //
+ "and rel.gamma_id = txs.gamma_id " //
+ "and rel_link_type_id = ? " //
+ "and txs.mod_type in (1,2,6) " //
+ "and tx_current = 1";
JsonRelations relations = new JsonRelations();
Set<ArtifactId> artIds = new HashSet<>();
for (String relTypeId : relationTypes.split(",")) {
relTypeId = relTypeId.replaceAll(" ", "");
if (Strings.isNumeric(relTypeId)) {
orcsApi.getJdbcService().getClient().runQuery(chStmt -> relations.add(getJaxRelation(chStmt, artIds)),
query, branch.getIdString(), relTypeId);
}
}
Map<ArtifactId, ArtifactReadable> artifactMap = new HashMap<ArtifactId, ArtifactReadable>();
for (ArtifactReadable art : orcsApi.getQueryFactory().fromBranch(branch).andIds(artIds).getResults().getList()) {
artifactMap.put(art, art);
}
for (JsonRelation rel : relations.getRelations()) {
RelationTypeToken relationType = orcsApi.tokenService().getRelationType(Long.valueOf(rel.getTypeId()));
rel.setTypeName(relationType.getName());
ArtifactReadable art = artifactMap.get(ArtifactId.valueOf(rel.getArtA()));
rel.setArtAName(art.getName());
ArtifactReadable art2 = artifactMap.get(ArtifactId.valueOf(rel.getArtB()));
rel.setArtBName(art2.getName());
}
return relations;
}
private JsonRelation getJaxRelation(JdbcStatement chStmt, Set<ArtifactId> artIds) {
JsonRelation rel = new JsonRelation();
String artA = chStmt.getString("a_art_id");
artIds.add(ArtifactId.valueOf(artA));
rel.setArtA(artA);
String artB = chStmt.getString("b_art_id");
artIds.add(ArtifactId.valueOf(artB));
rel.setArtB(artB);
rel.setTypeId(chStmt.getString("rel_link_type_id"));
return rel;
}
}