Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -4,62 +4,118 @@
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import uk.gov.companieshouse.api.model.transaction.SubmittedBy;
import uk.gov.companieshouse.api.model.transaction.Transaction;
import uk.gov.companieshouse.filing.received.FilingReceived;
import uk.gov.companieshouse.filing.received.PresenterRecord;
import uk.gov.companieshouse.filing.received.SubmissionRecord;
import uk.gov.companieshouse.filingresourcehandler.exception.RetryableException;
import uk.gov.companieshouse.filingresourcehandler.logging.DataMapHolder;
import uk.gov.companieshouse.filingresourcehandler.util.RetryErrorHandler;
import uk.gov.companieshouse.logging.Logger;
import uk.gov.companieshouse.logging.LoggerFactory;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;

import static uk.gov.companieshouse.filingresourcehandler.Application.NAMESPACE;

@Component
public class FilingReceivedFactory {

private static final Logger logger = LoggerFactory.getLogger(NAMESPACE);

private static final String CHANNEL_CHS = "chs";
private static final String CHANNEL_API_FILING = "api-filing";
private static final String FIELD_COMPANY_NUMBER = "company_number";
private static final String FIELD_COMPANY_NAME = "company_name";
private static final String FIELD_FORENAME = "forename";
private static final String FIELD_LANGUAGE = "language";
private static final String FIELD_SURNAME = "surname";
private static final String FIELD_ID = "id";
private static final int DEFAULT_ATTEMPT = 0;

private final String oauthClientId;
private final ObjectMapper objectMapper;

public FilingReceivedFactory(@Value("${oauth2.client.id}") String oauthClientId, ObjectMapper objectMapper) {
public FilingReceivedFactory(@Value("${oauth2.client.id}") String oauthClientId,
ObjectMapper objectMapper) {
this.oauthClientId = oauthClientId;
this.objectMapper = objectMapper;
}

public FilingReceived getFilingReceived(List<uk.gov.companieshouse.filing.received.Transaction> items, Transaction transaction) {
public FilingReceived getFilingReceived(List<uk.gov.companieshouse.filing.received.Transaction> items,
Transaction transaction) {
if (transaction == null) {
//Added to counter SonarQube issue as SonarQube was unable to detect logAndThrowRetryableException
String message = "Transaction is null in getFilingReceived";
logger.error(message, DataMapHolder.getLogMap());
throw new RetryableException(message);
}
String transactionId = transaction.getId() != null ? transaction.getId() : "";

PresenterRecord presenterRecord = createPresenterRecord(transaction);
String companyName = transaction.getCompanyName();
String companyNumber = transaction.getCompanyNumber();
if (companyName.isEmpty() || companyNumber.isBlank()) {
Map<String, Object> tempFiling = new HashMap<>();

if (isBlank(companyName) || isBlank(companyNumber)) {
if (items.getFirst().getData() == null) {
String errorMessage = "Items list has no data for transaction id %s".formatted(transactionId);
RetryErrorHandler.logAndThrowRetryableException(errorMessage);
}
Map<String, Object> tempFiling = Map.of();
try {
tempFiling = objectMapper.readValue(items.getFirst().getData(), new TypeReference<>() {
});
tempFiling = objectMapper.readValue(
items.getFirst().getData(),
new TypeReference<>() {
});
} catch (Exception err) {
String errorMessage = "Unable to parse json for transaction id %s".formatted(transaction.getId());
String errorMessage = "Unable to parse json for transaction id %s".formatted(transactionId);
RetryErrorHandler.logAndThrowRetryableException(errorMessage);
}
if (tempFiling.get("company_number") != null) {
companyNumber = tempFiling.get("company_number").toString();
}
if (tempFiling.get("company_name") != null) {
companyName = tempFiling.get("company_name").toString();
}
Map<String, Object> filingData = Optional.ofNullable(tempFiling).orElse(Map.of());
Object companyNumberObject = filingData.get(FIELD_COMPANY_NUMBER);
if (companyNumberObject != null) companyNumber = companyNumberObject.toString();

Object companyNameObject = filingData.get(FIELD_COMPANY_NAME);
if (companyNameObject != null) companyName = companyNameObject.toString();
}
String channelId = transaction.getSubmittedBy().getApplicationId().equals(oauthClientId) ? "chs" : "api-filing";
SubmissionRecord submissionRecord = getSubmissionRecord(companyName, companyNumber, transaction.getClosedAt(), transaction.getId());
return new FilingReceived(transaction.getSubmittedBy().getApplicationId(), 0, channelId, presenterRecord, submissionRecord, items);
}

private SubmissionRecord getSubmissionRecord(String companyName, String companyNumber, String closedAt, String id) {
return new SubmissionRecord(companyNumber, companyName, closedAt, id);
String applicationId = Optional.ofNullable(transaction.getSubmittedBy())
.map(SubmittedBy::getApplicationId)
.orElse("");

String channelId = Objects.equals(applicationId, oauthClientId)
? CHANNEL_CHS
: CHANNEL_API_FILING;

SubmissionRecord submissionRecord = new SubmissionRecord(
companyNumber, companyName, transaction.getClosedAt(), transactionId);

return new FilingReceived(
applicationId,
DEFAULT_ATTEMPT,
channelId,
presenterRecord,
submissionRecord,
items);
}

private PresenterRecord createPresenterRecord(Transaction transaction) {
Map<String, String> closedBy = transaction.getClosedBy() != null
? transaction.getClosedBy()
: Map.of();

return new PresenterRecord(
transaction.getClosedBy().get("forename"),
transaction.getClosedBy().get("language"),
transaction.getClosedBy().get("surname"),
transaction.getClosedBy().get("id")
);
closedBy.get(FIELD_FORENAME),
closedBy.get(FIELD_LANGUAGE),
closedBy.get(FIELD_SURNAME),
closedBy.get(FIELD_ID));
}

private static boolean isBlank(String s) {
return s == null || s.isBlank();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,36 +11,51 @@
@Component
public class ResourceMapFactory {

public Map<String, Resource> createResourceMap(Transaction transaction, String transactionFilingMode, String transactionUrl) {
private static final String DEFAULT = "default";
private static final String ERROR_NO_MATCH =
"filing mode %s is set for a master resource but no resource on transaction URL %s has that kind";
private static final String ERROR_MULTIPLE_MATCHES =
"filing mode %s is set for a master resource but more than one resource on the transaction URL %s has that kind";

public Map<String, Resource> createResourceMap(Transaction transaction,
String transactionFilingMode,
String transactionUrl) {
Map<String, Resource> resources = transaction.getResources();
if (transaction.getFilingMode() != null && !transaction.getFilingMode().isBlank() && !transaction.getFilingMode().equals("default")) {
resources = new HashMap<>();
populateResourceMap(transaction, transactionFilingMode, resources, transactionUrl);

boolean isCustomMode = transactionFilingMode != null
&& !transactionFilingMode.isBlank()
&& !DEFAULT.equals(transactionFilingMode);

if (!isCustomMode || resources == null) {
return resources != null ? resources : new HashMap<>();
}

Map<String, Resource> filtered = getStringResourceMap(transactionFilingMode, resources);

if (filtered.isEmpty()) {
RetryErrorHandler.logAndThrowRetryableException(
ERROR_NO_MATCH.formatted(transactionFilingMode, transactionUrl));
} else if (filtered.size() > 1) {
RetryErrorHandler.logAndThrowRetryableException(
ERROR_MULTIPLE_MATCHES.formatted(transactionFilingMode, transactionUrl));
}
return resources;
return filtered;
}

private void populateResourceMap(Transaction transaction, String transactionFilingMode, Map<String, Resource> resources, String transactionUrl) {
for (Map.Entry<String, Resource> resourceEntry : transaction.getResources().entrySet()) {
String kind = resourceEntry.getValue().getKind();
private static Map<String, Resource> getStringResourceMap(String transactionFilingMode, Map<String, Resource> resources) {
Map<String, Resource> filtered = new HashMap<>();
for (Map.Entry<String, Resource> entry : resources.entrySet()) {
Resource resource = entry.getValue();
String kind = resource != null ? resource.getKind() : null;
if (kind == null) {
continue;
}
String mainKind = kind.indexOf('#') == -1 ? kind : kind.substring(0, kind.indexOf('#'));
int hashIdx = kind.indexOf('#');
String mainKind = hashIdx == -1 ? kind : kind.substring(0, hashIdx);
if (mainKind.equals(transactionFilingMode)) {
resources.put(resourceEntry.getKey(), resourceEntry.getValue());
filtered.put(entry.getKey(), resource);
}
}
if (resources.isEmpty()) {
String errorMessage = ("filing mode %s is set for a master resource but no resource on " +
"transaction URL %s has that kind").formatted(transactionFilingMode, transactionUrl);
RetryErrorHandler.logAndThrowRetryableException(errorMessage);
} else if (resources.size() > 1) {
String errorMessage = ("filing mode %s is set for a master resource but more than one" +
" resource on the transaction URL %s has that kind").
formatted(transactionFilingMode, transactionUrl);
RetryErrorHandler.logAndThrowRetryableException(errorMessage);
}
return filtered;
}

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import uk.gov.companieshouse.logging.Logger;
import uk.gov.companieshouse.logging.LoggerFactory;

import java.util.HashMap;
import java.util.Map;
import java.util.Optional;

Expand All @@ -30,7 +31,7 @@ public FilingPatchService(FilingFactory filingFactory) {


public void addFilingToPatch(Map<String, Filing> transactionsFilingMap, FilingApi filing, String submissionId, String link, String companyNumber) {
String filingKind = filing.getKind();
String filingKind = filing.getKind() != null ? filing.getKind() : "";
if (filingKind != null && filingKind.toLowerCase().contains(INSOLVENCY)) {
companyNumber = Optional.ofNullable(filing.getData())
.map(data -> data.get(COMPANY_NUMBER))
Expand All @@ -42,7 +43,8 @@ public void addFilingToPatch(Map<String, Filing> transactionsFilingMap, FilingAp
return new NonRetryableException(message);
});
}
Map<String, String> links = Map.of(RESOURCE, link);
Map<String, String> links = new HashMap<>();
links.put(RESOURCE, link != null ? link : "");
Filing patchFiling = filingFactory.getFiling(filing, companyNumber, links);
transactionsFilingMap.put(submissionId, patchFiling);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,40 +28,92 @@ public class FilingResourceProcessorService {
private final FilingPatchService filingPatchService;
private final ItemService itemService;

public FilingResourceProcessorService(FilingClient filingClient, SubmissionIdService submissionIdService, FilingPatchService filingPatchService, ItemService itemService) {
public FilingResourceProcessorService(FilingClient filingClient,
SubmissionIdService submissionIdService,
FilingPatchService filingPatchService,
ItemService itemService) {
this.filingClient = filingClient;
this.itemService = itemService;
this.submissionIdService = submissionIdService;
this.filingPatchService = filingPatchService;
this.itemService = itemService;
}

public FilingProcessingResult processResources(Transaction transaction, Map<String, Resource> resources) {
Map<String, Filing> transactionsFilingMap = new HashMap<>();
Map<String, Filing> filingsToPatch = new HashMap<>();
List<uk.gov.companieshouse.filing.received.Transaction> items = new ArrayList<>();
Map<String, String> transactionMatcher = new HashMap<>();
int offset = submissionIdService.findSubmissionIDOffset(transaction, transactionMatcher);
String companyNumber = transaction.getCompanyNumber();
Map<String, String> matcher = new HashMap<>();
int offset = submissionIdService.findSubmissionIDOffset(transaction, matcher);

if (resources == null) {
return new FilingProcessingResult(filingsToPatch, items);
}

for (Resource resource : resources.values()) {
String link = resource.getLinks().get("resource");
LOGGER.info("Found resource for current transaction", DataMapHolder.getLogMap());
FilingApi[] filings = filingClient.getFilingApi(link, transaction.getCompanyName(), transaction.getCompanyNumber()).orElseThrow(() -> {
String errorMessage = "Empty Filings response for transactionId %s".formatted(transaction.getId());
LOGGER.error(errorMessage, DataMapHolder.getLogMap());
return new RetryableException(errorMessage);
});
for (FilingApi filing : filings) {
String submissionId = transactionMatcher.get("%s:%s".formatted(filing.getKind(), link));
if (submissionId == null) {
offset++;
submissionId = "%s-%d".formatted(transaction.getId(), offset);
LOGGER.info("Add filing to patch request with submissionId %s".formatted(submissionId), DataMapHolder.getLogMap());
filingPatchService.addFilingToPatch(transactionsFilingMap, filing, submissionId, link, companyNumber);
}
itemService.addItems(filing, submissionId, items);
if (resource == null) {
continue;
}
offset = processResource(resource, transaction, matcher, filingsToPatch, items, offset);
}

return new FilingProcessingResult(transactionsFilingMap, items);
return new FilingProcessingResult(filingsToPatch, items);
}

private int processResource(Resource resource,
Transaction transaction,
Map<String, String> matcher,
Map<String, Filing> filingsToPatch,
List<uk.gov.companieshouse.filing.received.Transaction> items,
int offset) {
String link = resourceLink(resource);
LOGGER.info("Found resource of type %s".formatted(orEmpty(resource.getKind())), DataMapHolder.getLogMap());

FilingApi[] filings = filingClient
.getFilingApi(link, transaction.getCompanyName(), transaction.getCompanyNumber())
.orElseThrow(() -> emptyFilingsError(transaction.getId()));

for (FilingApi filing : filings) {
if (filing == null || filing.getKind() == null) {
continue;
}
offset = processFiling(filing, link, transaction, matcher, filingsToPatch, items, offset);
}
return offset;
}

private int processFiling(FilingApi filing,
String link,
Transaction transaction,
Map<String, String> matcher,
Map<String, Filing> filingsToPatch,
List<uk.gov.companieshouse.filing.received.Transaction> items,
int offset) {
String key = "%s:%s".formatted(filing.getKind(), link);
String submissionId = matcher.get(key);

if (submissionId == null) {
offset++;
submissionId = "%s-%d".formatted(transaction.getId(), offset);
LOGGER.info("Add filing to patch request with submissionId %s".formatted(submissionId),
DataMapHolder.getLogMap());
filingPatchService.addFilingToPatch(
filingsToPatch, filing, submissionId, link, transaction.getCompanyNumber());
}
itemService.addItems(filing, submissionId, items);
return offset;
}

private static String resourceLink(Resource resource) {
Map<String, String> links = resource.getLinks();
return links != null ? links.getOrDefault("resource", "") : "";
}

private static String orEmpty(String value) {
return value != null ? value : "";
}

private RetryableException emptyFilingsError(String transactionId) {
String message = "Empty Filings response for transactionId %s".formatted(transactionId);
LOGGER.error(message, DataMapHolder.getLogMap());
return new RetryableException(message);
}

}
}
Loading