diff --git a/hit-core-api/src/main/java/gov/nist/hit/core/api/TestContextController.java b/hit-core-api/src/main/java/gov/nist/hit/core/api/TestContextController.java index 88debac..40e475b 100644 --- a/hit-core-api/src/main/java/gov/nist/hit/core/api/TestContextController.java +++ b/hit-core-api/src/main/java/gov/nist/hit/core/api/TestContextController.java @@ -96,9 +96,10 @@ public void validateMessage( try { logger.info("Validating a message"); TestContext testContext = getTestContext(testContextId); + Long userId = SessionContext.getCurrentUserId(request.getSession(false)); + command.setUserId(userId); MessageValidationResult result = getMessageValidator().validate(testContext, command); - TestStepValidationReport report = saveReport(testContext, result, - SessionContext.getCurrentUserId(request.getSession(false))); + TestStepValidationReport report = saveReport(testContext, result, userId); result.setHtml(null); result.setXml(null); result.setReportId(report.getId()); diff --git a/hit-core-domain/src/main/java/gov/nist/hit/core/domain/MessageValidationCommand.java b/hit-core-domain/src/main/java/gov/nist/hit/core/domain/MessageValidationCommand.java index 95bc581..a447bd1 100644 --- a/hit-core-domain/src/main/java/gov/nist/hit/core/domain/MessageValidationCommand.java +++ b/hit-core-domain/src/main/java/gov/nist/hit/core/domain/MessageValidationCommand.java @@ -12,33 +12,35 @@ package gov.nist.hit.core.domain; -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; - import java.util.ArrayList; -import java.util.List; import java.util.Map; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; + /** * @author Harold Affo(NIST) * */ -@ApiModel(value="MessageValidationCommand", description="Data Model representing a request to validate a message") +@ApiModel(value = "MessageValidationCommand", + description = "Data Model representing a request to validate a message") public class MessageValidationCommand extends TestCaseCommand { - @ApiModelProperty(required=true, value="content to parse") + @ApiModelProperty(required = true, value = "content to parse") private String content; - private Map nav;; + private Long userId; + + private Map nav;; + + private String facilityId; + + private String contextType; - private String facilityId; - - private String contextType; - - private String name; - - @ApiModelProperty(required=false, value="data quality codes to validate") - private ArrayList dqaCodes; + private String name; + + @ApiModelProperty(required = false, value = "data quality codes to validate") + private ArrayList dqaCodes; public String getContent() { return content; @@ -48,7 +50,7 @@ public void setContent(String content) { this.content = content; } - + public String getFacilityId() { return facilityId; } @@ -73,7 +75,7 @@ public void setDqaCodes(ArrayList dqaCodes) { this.dqaCodes = dqaCodes; } - + public Map getNav() { return nav; } @@ -90,7 +92,14 @@ public void setName(String name) { this.name = name; } - - - + public Long getUserId() { + return userId; + } + + public void setUserId(Long userId) { + this.userId = userId; + } + + + } diff --git a/hit-core-domain/src/main/java/gov/nist/hit/core/domain/TestCaseCommand.java b/hit-core-domain/src/main/java/gov/nist/hit/core/domain/TestCaseCommand.java index 0a62e7c..5d16bb8 100644 --- a/hit-core-domain/src/main/java/gov/nist/hit/core/domain/TestCaseCommand.java +++ b/hit-core-domain/src/main/java/gov/nist/hit/core/domain/TestCaseCommand.java @@ -17,6 +17,7 @@ * */ public class TestCaseCommand { + protected Long testCaseId; public Long getTestCaseId() { diff --git a/hit-core-domain/src/main/java/gov/nist/hit/core/domain/log/ValidationLog.java b/hit-core-domain/src/main/java/gov/nist/hit/core/domain/log/ValidationLog.java new file mode 100644 index 0000000..446a29e --- /dev/null +++ b/hit-core-domain/src/main/java/gov/nist/hit/core/domain/log/ValidationLog.java @@ -0,0 +1,168 @@ +package gov.nist.hit.core.domain.log; + + +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.HashMap; +import java.util.Map; + +import javax.persistence.CollectionTable; +import javax.persistence.Column; +import javax.persistence.ElementCollection; +import javax.persistence.Entity; +import javax.persistence.FetchType; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.JoinColumn; +import javax.persistence.MapKeyColumn; +import javax.validation.constraints.NotNull; + +/** + * This software was developed at the National Institute of Standards and Technology by employees of + * the Federal Government in the course of their official duties. Pursuant to title 17 Section 105 + * of the United States Code this software is not subject to copyright protection and is in the + * public domain. This is an experimental system. NIST assumes no responsibility whatsoever for its + * use by other parties, and makes no guarantees, expressed or implied, about its quality, + * reliability, or any other characteristic. We would appreciate acknowledgement if the software is + * used. This software can be redistributed and/or modified freely provided that any derivative + * works bear some notice that they are derived from it, and any modified versions bear some notice + * that they have been modified. + * + * Created by mcl1 on 10/21/16. + * + * The ValidationLogReport is a minimalist version of the EnhancedReport that contains only the + * information we need to display the validation logs. + * + */ +@Entity +public class ValidationLog { + + @Id + @GeneratedValue(strategy = GenerationType.AUTO) + protected Long id; + + + @NotNull + @Column(nullable = false) + private Long userId; + + @NotNull + @Column(nullable = false) + private Long testStepId; + private String messageId; + private String format; + private String testingStage; + private int errorCount = 0; + private int warningCount = 0; + + @NotNull + @Column(nullable = false) + private Date date; + + @ElementCollection(fetch = FetchType.EAGER) + @CollectionTable(name = "ErrorCountInSegment", + joinColumns = @JoinColumn(name = "validation_log_id")) + @MapKeyColumn(name = "segment_name") + @Column(name = "number_errors") + private Map errorCountInSegment = new HashMap(); + + private boolean validationResult = true; + + + public ValidationLog() { + + } + + public String getMessageId() { + return messageId; + } + + public void setMessageId(String messageId) { + this.messageId = messageId; + } + + public String getFormat() { + return format; + } + + public void setFormat(String format) { + this.format = format; + } + + public int getErrorCount() { + return errorCount; + } + + public void setErrorCount(int errorCount) { + this.errorCount = errorCount; + } + + public int getWarningCount() { + return warningCount; + } + + public void setWarningCount(int warningCount) { + this.warningCount = warningCount; + } + + public String getDate(String format) { + // Format the date as specified + SimpleDateFormat simpleDateFormat = new SimpleDateFormat(format); + if (this.date == null) { + this.date = new Date(); + } + return simpleDateFormat.format(this.date); + } + + public void setDate(Date date) { + this.date = date; + } + + public Map getErrorCountInSegment() { + return errorCountInSegment; + } + + public void setErrorCountInSegment(Map errorCountInSegment) { + this.errorCountInSegment = errorCountInSegment; + } + + public boolean isValidationResult() { + return validationResult; + } + + public void setValidationResult(boolean validationResult) { + this.validationResult = validationResult; + } + + public String getTestingStage() { + return testingStage; + } + + public void setTestingStage(String testingStage) { + this.testingStage = testingStage; + } + + public Long getTestStepId() { + return testStepId; + } + + public void setTestStepId(Long testStepId) { + this.testStepId = testStepId; + } + + public Long getUserId() { + return userId; + } + + public void setUserId(Long userId) { + this.userId = userId; + } + + public Date getDate() { + return date; + } + + + +} diff --git a/hit-core-repo/src/main/java/gov/nist/hit/core/repo/ValidationLogRepository.java b/hit-core-repo/src/main/java/gov/nist/hit/core/repo/ValidationLogRepository.java new file mode 100644 index 0000000..4455c94 --- /dev/null +++ b/hit-core-repo/src/main/java/gov/nist/hit/core/repo/ValidationLogRepository.java @@ -0,0 +1,38 @@ +/** + * This software was developed at the National Institute of Standards and Technology by employees of + * the Federal Government in the course of their official duties. Pursuant to title 17 Section 105 + * of the United States Code this software is not subject to copyright protection and is in the + * public domain. This is an experimental system. NIST assumes no responsibility whatsoever for its + * use by other parties, and makes no guarantees, expressed or implied, about its quality, + * reliability, or any other characteristic. We would appreciate acknowledgement if the software is + * used. This software can be redistributed and/or modified freely provided that any derivative + * works bear some notice that they are derived from it, and any modified versions bear some notice + * that they have been modified. + */ + +package gov.nist.hit.core.repo; + +import java.util.List; + +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; + +import gov.nist.hit.core.domain.TestArtifact; +import gov.nist.hit.core.domain.log.ValidationLog; + +public interface ValidationLogRepository extends JpaRepository { + + + @Query("select testStep.testStory from TestStep testStep where testStep.id = :id") + public TestArtifact testStory(@Param("id") Long id); + + + @Query("select log from ValidationLog log where log.userId = :userId") + public List findByUserId(@Param("userId") Long userId); + + @Query("select log from ValidationLog log where log.testStepId = :testStepId") + public List findByTestStepId(@Param("testStepId") Long testStepId); + + +} diff --git a/hit-core-service/src/main/java/gov/nist/hit/core/service/ValidationLogService.java b/hit-core-service/src/main/java/gov/nist/hit/core/service/ValidationLogService.java new file mode 100644 index 0000000..f81fe2f --- /dev/null +++ b/hit-core-service/src/main/java/gov/nist/hit/core/service/ValidationLogService.java @@ -0,0 +1,22 @@ +package gov.nist.hit.core.service; + +import java.util.List; + +import gov.nist.healthcare.unified.model.EnhancedReport; +import gov.nist.hit.core.domain.TestContext; +import gov.nist.hit.core.domain.log.ValidationLog; + +public interface ValidationLogService { + + public ValidationLog findOne(Long id); + + public ValidationLog save(ValidationLog log); + + public List findByUserId(Long userId); + + public List findByTestStepId(Long testStepId); + + public ValidationLog generateAndSave(Long userId, TestContext testContext, EnhancedReport report); + + +} diff --git a/hit-core-service/src/main/java/gov/nist/hit/core/service/impl/ValidationLogReport.java b/hit-core-service/src/main/java/gov/nist/hit/core/service/impl/ValidationLogReport.java deleted file mode 100644 index c93f34c..0000000 --- a/hit-core-service/src/main/java/gov/nist/hit/core/service/impl/ValidationLogReport.java +++ /dev/null @@ -1,169 +0,0 @@ -package gov.nist.hit.core.service.impl; - - -import gov.nist.healthcare.unified.exceptions.ConversionException; -import gov.nist.healthcare.unified.exceptions.NotFoundException; -import gov.nist.healthcare.unified.model.*; -import gov.nist.hit.core.domain.TestContext; - -import java.text.SimpleDateFormat; -import java.util.Date; -import java.util.HashMap; -import java.util.Map; - -/** - * This software was developed at the National Institute of Standards and Technology by employees of - * the Federal Government in the course of their official duties. Pursuant to title 17 Section 105 - * of the United States Code this software is not subject to copyright protection and is in the - * public domain. This is an experimental system. NIST assumes no responsibility whatsoever for its - * use by other parties, and makes no guarantees, expressed or implied, about its quality, - * reliability, or any other characteristic. We would appreciate acknowledgement if the software is - * used. This software can be redistributed and/or modified freely provided that any derivative - * works bear some notice that they are derived from it, and any modified versions bear some notice - * that they have been modified. - * - * Created by mcl1 on 10/21/16. - * - * The ValidationLogReport is a minimalist version of the EnhancedReport that contains - * only the information we need to display the validation logs. - * - */ -public class ValidationLogReport { - - private String messageId; - private String format; - private String testingStage; - private int errorCount = 0; - private int warningCount = 0; - private Date date; - private Map errorCountInSegment; - private boolean validationResult = true; - - /* - * This constructor parses the EnhancedReport to take only the information we need from it. - */ - public ValidationLogReport(TestContext testContext, EnhancedReport report) { - this.date = new Date(); - this.errorCountInSegment = new HashMap<>(); - Detections detections = report.getDetections(); - //Loop on the classifications (Affirmative, Warning or Error) - for (Classification classification : detections.classes()) { - if (classification.getName().equals("Affirmative")) { - //No need to display any log here - } else if (classification.getName().equals("Warning")) { - //Get the warning count - this.warningCount = classification.keys().size(); - } else if (classification.getName().equals("Error")) { - //Get the error count - this.errorCount = classification.keys().size(); - if (this.errorCount > 0) { - //If there is more than 0 errors, then the validation failed - this.validationResult = false; - //Loop on the errors - for (String key : classification.keys()) { - Collection collection = null; - try { - collection = classification.getArray(key); - if(collection!=null && collection.size()>0) { - for (int i = 0; i < collection.size(); i++) { - Section section = collection.getObject(i); - //Identify the path of the error - String path = section.getString("path"); - if (path != null && !"".equals(path)) { - path = path.split("\\[")[0]; - int segmentErrorCount = 1; - //If there was already at least 1 error for this segment, then increment its error count. - if (this.errorCountInSegment.containsKey(path)) { - segmentErrorCount = this.errorCountInSegment.get(path) + 1; - } - //Add or update the segment's error count - this.errorCountInSegment.put(path, segmentErrorCount); - } - } - } - } catch (NotFoundException e) { - e.printStackTrace(); - } catch (ConversionException e) { - e.printStackTrace(); - } - } - } - } - } - //Parse the test context - if(testContext != null){ - this.format = (testContext.getFormat()!=null?testContext.getFormat():""); - this.messageId = (testContext.getType()!=null?testContext.getType():""); - this.testingStage = (testContext.getStage().name()!=null?testContext.getStage().name():""); - } - } - - public String getMessageId() { - return messageId; - } - - public void setMessageId(String messageId) { - this.messageId = messageId; - } - - public String getFormat() { - return format; - } - - public void setFormat(String format) { - this.format = format; - } - - public int getErrorCount() { - return errorCount; - } - - public void setErrorCount(int errorCount) { - this.errorCount = errorCount; - } - - public int getWarningCount() { - return warningCount; - } - - public void setWarningCount(int warningCount) { - this.warningCount = warningCount; - } - - public String getDate(String format) { - //Format the date as specified - SimpleDateFormat simpleDateFormat = new SimpleDateFormat(format); - if(this.date==null){ - this.date = new Date(); - } - return simpleDateFormat.format(this.date); - } - - public void setDate(Date date) { - this.date = date; - } - - public Map getErrorCountInSegment() { - return errorCountInSegment; - } - - public void setErrorCountInSegment(Map errorCountInSegment) { - this.errorCountInSegment = errorCountInSegment; - } - - public boolean isValidationResult() { - return validationResult; - } - - public void setValidationResult(boolean validationResult) { - this.validationResult = validationResult; - } - - public String getTestingStage() { - return testingStage; - } - - public void setTestingStage(String testingStage) { - this.testingStage = testingStage; - } -} diff --git a/hit-core-service/src/main/java/gov/nist/hit/core/service/impl/ValidationLogServiceImpl.java b/hit-core-service/src/main/java/gov/nist/hit/core/service/impl/ValidationLogServiceImpl.java new file mode 100644 index 0000000..48c69d1 --- /dev/null +++ b/hit-core-service/src/main/java/gov/nist/hit/core/service/impl/ValidationLogServiceImpl.java @@ -0,0 +1,123 @@ +package gov.nist.hit.core.service.impl; + +import java.util.Date; +import java.util.HashMap; +import java.util.List; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import gov.nist.healthcare.unified.exceptions.ConversionException; +import gov.nist.healthcare.unified.exceptions.NotFoundException; +import gov.nist.healthcare.unified.model.Classification; +import gov.nist.healthcare.unified.model.Collection; +import gov.nist.healthcare.unified.model.Detections; +import gov.nist.healthcare.unified.model.EnhancedReport; +import gov.nist.healthcare.unified.model.Section; +import gov.nist.hit.core.domain.TestContext; +import gov.nist.hit.core.domain.log.ValidationLog; +import gov.nist.hit.core.repo.ValidationLogRepository; +import gov.nist.hit.core.service.ValidationLogService; +import gov.nist.hit.core.service.util.ValidationLogUtil; + +@Service +public class ValidationLogServiceImpl implements ValidationLogService { + + static final Logger logger = LoggerFactory.getLogger(ValidationLogServiceImpl.class); + + @Autowired + private ValidationLogRepository validationLogRepository; + + @Override + public ValidationLog findOne(Long id) { + // TODO Auto-generated method stub + return validationLogRepository.findOne(id); + } + + @Override + public ValidationLog save(ValidationLog log) { + // TODO Auto-generated method stub + return validationLogRepository.saveAndFlush(log); + } + + @Override + public List findByUserId(Long userId) { + // TODO Auto-generated method stub + return validationLogRepository.findByUserId(userId); + } + + @Override + public List findByTestStepId(Long testStepId) { + // TODO Auto-generated method stub + return validationLogRepository.findByTestStepId(testStepId); + } + + @Override + public ValidationLog generateAndSave(Long userId, TestContext testContext, + EnhancedReport report) { + ValidationLog log = new ValidationLog(); + log.setUserId(userId); + log.setTestStepId(testContext.getTestStep().getPersistentId()); + log.setDate(new Date()); + log.setErrorCountInSegment(new HashMap<>()); + Detections detections = report.getDetections(); + // Loop on the classifications (Affirmative, Warning or Error) + for (Classification classification : detections.classes()) { + if (classification.getName().equals("Affirmative")) { + // No need to display any log here + } else if (classification.getName().equals("Warning")) { + // Get the warning count + log.setWarningCount(classification.keys().size()); + } else if (classification.getName().equals("Error")) { + // Get the error count + log.setErrorCount(classification.keys().size()); + if (log.getErrorCount() > 0) { + // If there is more than 0 errors, then the validation failed + log.setValidationResult(false); + // Loop on the errors + for (String key : classification.keys()) { + Collection collection = null; + try { + collection = classification.getArray(key); + if (collection != null && collection.size() > 0) { + for (int i = 0; i < collection.size(); i++) { + Section section = collection.getObject(i); + // Identify the path of the error + String path = section.getString("path"); + if (path != null && !"".equals(path)) { + path = path.split("\\[")[0]; + int segmentErrorCount = 1; + // If there was already at least 1 error for this segment, then increment its + // error count. + if (log.getErrorCountInSegment().containsKey(path)) { + segmentErrorCount = log.getErrorCountInSegment().get(path) + 1; + } + // Add or update the segment's error count + log.getErrorCountInSegment().put(path, segmentErrorCount); + } + } + } + } catch (NotFoundException e) { + e.printStackTrace(); + } catch (ConversionException e) { + e.printStackTrace(); + } + } + } + } + } + // Parse the test context + if (testContext != null) { + log.setFormat((testContext.getFormat() != null ? testContext.getFormat() : "")); + log.setMessageId((testContext.getType() != null ? testContext.getType() : "")); + log.setTestingStage( + (testContext.getStage().name() != null ? testContext.getStage().name() : "")); + } + String validationLog = ValidationLogUtil.toString(log); + logger.info(validationLog.toString()); + return save(log); + } + +} diff --git a/hit-core-service/src/main/java/gov/nist/hit/core/service/util/ValidationLogUtil.java b/hit-core-service/src/main/java/gov/nist/hit/core/service/util/ValidationLogUtil.java index 3fbd2e7..1db3a0b 100644 --- a/hit-core-service/src/main/java/gov/nist/hit/core/service/util/ValidationLogUtil.java +++ b/hit-core-service/src/main/java/gov/nist/hit/core/service/util/ValidationLogUtil.java @@ -8,9 +8,7 @@ import org.springframework.context.annotation.PropertySource; import org.springframework.core.env.Environment; -import gov.nist.healthcare.unified.model.EnhancedReport; -import gov.nist.hit.core.domain.TestContext; -import gov.nist.hit.core.service.impl.ValidationLogReport; +import gov.nist.hit.core.domain.log.ValidationLog; /** * This software was developed at the National Institute of Standards and Technology by employees of @@ -41,11 +39,7 @@ public void setEnvironment(final Environment environment) { this.environment = environment; } - public static String generateValidationLog(TestContext testContext, EnhancedReport report) { - return generateValidationLog(new ValidationLogReport(testContext, report)); - } - - public static String generateValidationLog(ValidationLogReport validationLogReport) { + public static String toString(ValidationLog validationLog) { // Read environment properties related to the validation logs String logFormat = (environment == null || environment.getProperty("validation.logs.format") == null @@ -57,29 +51,28 @@ public static String generateValidationLog(ValidationLogReport validationLogRepo ? DEFAULT_LOG_DATE_FORMAT : environment.getProperty("validation.logs.date.format")); // Replace the fields in log if (logFormat.contains("%date")) { - logFormat = logFormat.replace("%date", validationLogReport.getDate(logDateFormat)); + logFormat = logFormat.replace("%date", validationLog.getDate(logDateFormat)); } if (logFormat.contains("%testingStage")) { - logFormat = logFormat.replace("%testingStage", validationLogReport.getTestingStage()); + logFormat = logFormat.replace("%testingStage", validationLog.getTestingStage()); } if (logFormat.contains("%format")) { - logFormat = logFormat.replace("%format", validationLogReport.getFormat()); + logFormat = logFormat.replace("%format", validationLog.getFormat()); } if (logFormat.contains("%messageId")) { - logFormat = logFormat.replace("%messageId", validationLogReport.getMessageId()); + logFormat = logFormat.replace("%messageId", validationLog.getMessageId()); } if (logFormat.contains("%errorCount")) { - logFormat = - logFormat.replace("%errorCount", String.valueOf(validationLogReport.getErrorCount())); + logFormat = logFormat.replace("%errorCount", String.valueOf(validationLog.getErrorCount())); } if (logFormat.contains("%errorsInSegments")) { // Generate the segment errors log // TODO Make the format a parameter? - if (validationLogReport.getErrorCountInSegment().size() > 0) { + if (validationLog.getErrorCountInSegment().size() > 0) { StringBuilder errorsInSegments = new StringBuilder(); errorsInSegments.append("("); boolean isFirst = true; - for (Map.Entry segment : validationLogReport.getErrorCountInSegment() + for (Map.Entry segment : validationLog.getErrorCountInSegment() .entrySet()) { if (!isFirst) { errorsInSegments.append(", "); @@ -98,10 +91,10 @@ public static String generateValidationLog(ValidationLogReport validationLogRepo } if (logFormat.contains("%warningCount")) { logFormat = - logFormat.replace("%warningCount", String.valueOf(validationLogReport.getWarningCount())); + logFormat.replace("%warningCount", String.valueOf(validationLog.getWarningCount())); } if (logFormat.contains("%validationResult")) { - if (validationLogReport.isValidationResult()) { + if (validationLog.isValidationResult()) { logFormat = logFormat.replace("%validationResult", "SUCCESS"); } else { logFormat = logFormat.replace("%validationResult", "FAILURE");