use of gov.nih.nci.ctd2.dashboard.model.ObservedSubject in project nci-ctd2-dashboard by CBIIT.
the class DashboardDaoImpl method search.
@Override
@Cacheable(value = "searchCache")
public SearchResults search(String queryString) {
queryString = queryString.trim();
final String[] searchTerms = parseWords(queryString);
log.debug("search terms: " + String.join(",", searchTerms));
Map<Subject, Integer> subjects = new HashMap<Subject, Integer>();
Map<Submission, Integer> submissions = new HashMap<Submission, Integer>();
for (String singleTerm : searchTerms) {
searchSingleTerm(singleTerm, subjects, submissions);
}
SearchResults searchResults = new SearchResults();
searchResults.submission_result = submissions.keySet().stream().map(submission -> {
ObservationTemplate template = submission.getObservationTemplate();
return new SearchResults.SubmissionResult(submission.getStableURL(), submission.getSubmissionDate(), template.getDescription(), template.getTier(), template.getSubmissionCenter().getDisplayName(), submission.getId(), findObservationsBySubmission(submission).size(), template.getIsSubmissionStory());
}).collect(Collectors.toList());
Map<String, Set<Observation>> observationMap = new HashMap<String, Set<Observation>>();
List<SubjectResult> subject_result = new ArrayList<SubjectResult>();
for (Subject subject : subjects.keySet()) {
Set<Observation> observations = new HashSet<Observation>();
Set<SubmissionCenter> submissionCenters = new HashSet<SubmissionCenter>();
Set<String> roles = new HashSet<String>();
for (ObservedSubject observedSubject : findObservedSubjectBySubject(subject)) {
Observation observation = observedSubject.getObservation();
observations.add(observation);
ObservationTemplate observationTemplate = observation.getSubmission().getObservationTemplate();
submissionCenters.add(observationTemplate.getSubmissionCenter());
roles.add(observedSubject.getObservedSubjectRole().getSubjectRole().getDisplayName());
}
SubjectResult x = new SubjectResult(subject, observations.size(), submissionCenters.size(), subjects.get(subject), roles);
Arrays.stream(searchTerms).filter(term -> matchSubject(term, subject)).forEach(term -> {
Set<Observation> obset = observationMap.get(term);
if (obset == null) {
obset = new HashSet<Observation>();
}
obset.addAll(observations);
observationMap.put(term, obset);
});
subject_result.add(x);
}
/* search ECO terms */
List<ECOTerm> ecoterms = findECOTerms(queryString);
for (ECOTerm ecoterm : ecoterms) {
List<Integer> observationIds = observationIdsForEcoCode(ecoterm.getCode());
int observationNumber = observationIds.size();
if (observationNumber == 0)
continue;
SubjectResult entity = new SubjectResult(ecoterm, observationNumber, centerCount(ecoterm.getCode()), null, // no matchNumber, no roles
null);
subject_result.add(entity);
Set<Observation> observations = new HashSet<Observation>();
observationIds.forEach(obid -> observations.add(getEntityById(Observation.class, obid)));
Arrays.stream(searchTerms).filter(term -> ecoterm.containsTerm(term)).forEach(term -> {
Set<Observation> obset = observationMap.get(term);
if (obset == null) {
obset = new HashSet<Observation>();
}
obset.addAll(observations);
observationMap.put(term, obset);
});
}
/*
* Limit the size. This should be done more efficiently during the process of
* builing up of the list.
* Because the limit needs to be based on 'match number' ranking, which depends
* on all terms, an efficient algorithm is not obvious.
* Unfortunately, we also have to do this after processing all results because
* we need (in fact more often) observation numbers as well in ranking. TODO
*/
if (subject_result.size() > maxNumberOfSearchResults) {
searchResults.oversized = subject_result.size();
subject_result = subject_result.stream().sorted(new SearchResultComparator()).limit(maxNumberOfSearchResults).collect(Collectors.toList());
log.debug("size after limiting: " + subject_result.size());
}
searchResults.subject_result = subject_result;
if (searchTerms.length <= 1) {
return searchResults;
}
// add intersection of observations
Set<Observation> set0 = observationMap.get(searchTerms[0]);
if (set0 == null) {
log.debug("no observation for " + searchTerms[0]);
return searchResults;
}
log.debug("set0 size=" + set0.size());
for (int i = 1; i < searchTerms.length; i++) {
Set<Observation> obset = observationMap.get(searchTerms[i]);
if (obset == null) {
log.debug("... no observation for " + searchTerms[i]);
return searchResults;
}
log.debug("set " + i + " size=" + obset.size());
set0.retainAll(obset);
}
// set0 is now the intersection
if (set0.size() == 0) {
log.debug("no intersection of observations");
}
if (set0.size() > maxNumberOfSearchResults) {
searchResults.oversized_observations = set0.size();
// no particular ranking is enforced when limiting
set0 = set0.stream().limit(maxNumberOfSearchResults).collect(Collectors.toSet());
log.debug("observation results count after limiting: " + set0.size());
}
searchResults.observation_result = new ArrayList<Observation>(set0);
return searchResults;
}
use of gov.nih.nci.ctd2.dashboard.model.ObservedSubject in project nci-ctd2-dashboard by CBIIT.
the class SubjectScorer method scoreAllRoles.
@Transactional
public void scoreAllRoles() {
log.info("Removing all role-based scores...");
List<SubjectWithSummaries> oldEntities = dashboardDao.findEntities(SubjectWithSummaries.class);
for (SubjectWithSummaries subjectWithSummaries : oldEntities) {
dashboardDao.delete(subjectWithSummaries);
}
log.info("Removed " + oldEntities.size() + " old scores.");
log.info("Re-scoring all roles...");
List<SubjectWithSummaries> subjectWithSummariesList = new ArrayList<SubjectWithSummaries>();
List<SubjectRole> entities = dashboardDao.findEntities(SubjectRole.class);
for (SubjectRole subjectRole : entities) {
String keyword = subjectRole.getDisplayName();
log.info("Scoring subject with role: " + keyword);
HashMap<Subject, SubjectWithSummaries> subjectToSummaries = new HashMap<Subject, SubjectWithSummaries>();
HashMap<Subject, HashSet<SubmissionCenter>> subjectToCenters = new HashMap<Subject, HashSet<SubmissionCenter>>();
HashMap<Subject, HashMap<SubmissionCenter, Integer>> centerBasedScores = new HashMap<Subject, HashMap<SubmissionCenter, Integer>>();
for (ObservedSubject observedSubject : dashboardDao.findObservedSubjectByRole(keyword)) {
Subject subject = observedSubject.getSubject();
SubjectWithSummaries withSummaries = subjectToSummaries.get(subject);
ObservationTemplate observationTemplate = observedSubject.getObservation().getSubmission().getObservationTemplate();
SubmissionCenter submissionCenter = observationTemplate.getSubmissionCenter();
Integer tier = observationTemplate.getTier();
if (withSummaries == null) {
withSummaries = new SubjectWithSummaries();
withSummaries.setRole(keyword);
withSummaries.setSubject(subject);
withSummaries.setMaxTier(tier);
withSummaries.setNumberOfObservations(1);
HashSet<SubmissionCenter> centers = new HashSet<SubmissionCenter>();
centers.add(submissionCenter);
withSummaries.setNumberOfSubmissionCenters(1);
withSummaries.addSubmission(tier, submissionCenter.getId());
subjectToCenters.put(subject, centers);
subjectToSummaries.put(subject, withSummaries);
HashMap<SubmissionCenter, Integer> cScores = new HashMap<>();
cScores.put(submissionCenter, tier);
centerBasedScores.put(subject, cScores);
} else {
withSummaries.setMaxTier(Math.max(withSummaries.getMaxTier(), tier));
withSummaries.setNumberOfObservations(withSummaries.getNumberOfObservations() + 1);
HashSet<SubmissionCenter> submissionCenters = subjectToCenters.get(subject);
submissionCenters.add(submissionCenter);
withSummaries.setNumberOfSubmissionCenters(submissionCenters.size());
withSummaries.addSubmission(tier, submissionCenter.getId());
HashMap<SubmissionCenter, Integer> cScores = centerBasedScores.get(subject);
Integer previousScore = cScores.get(submissionCenter);
cScores.put(submissionCenter, previousScore == null ? tier : Math.max(tier, previousScore));
}
}
Collection<SubjectWithSummaries> perRole = subjectToSummaries.values();
for (SubjectWithSummaries subjectWithSummaries : perRole) {
Integer totalScore = 0;
for (Integer aScore : centerBasedScores.get(subjectWithSummaries.getSubject()).values()) {
totalScore += aScore;
}
subjectWithSummaries.setScore(totalScore);
}
subjectWithSummariesList.addAll(perRole);
log.info("Done scoring role: " + keyword);
}
dashboardDao.batchSave(subjectWithSummariesList, 0);
log.info("Done scoring all roles...");
}
use of gov.nih.nci.ctd2.dashboard.model.ObservedSubject in project nci-ctd2-dashboard by CBIIT.
the class ObservationDataWriter method write.
public void write(List<? extends ObservationData> items) throws Exception {
// calls) (2) there is at least one observation in each call
if (items.size() == 0) {
// this might happen when some suject is rejected
log.debug("no item");
return;
}
final Submission submission = items.get(0).observation.getSubmission();
final String submissionName = submission.getDisplayName();
StableURL stableURL = new StableURL();
synchronized (submission) {
log.debug("[" + ++counter + "]SUBMISSION " + submissionName + ": " + items.size() + " observation(s)");
final String submissionCacheKey = submissionName + new SimpleDateFormat("yyyy.MM.dd").format(submission.getSubmissionDate()) + submission.getObservationTemplate().getDisplayName();
if (!submissionCache.contains(submissionCacheKey)) {
submission.setStableURL(stableURL.createURLWithPrefix("submission", submissionName));
dashboardDao.save(submission);
submissionCache.add(submissionCacheKey);
observationIndex.put(submissionName, 0);
}
}
List<Observation> observations = new ArrayList<Observation>();
List<Evidence> evidences = new ArrayList<Evidence>();
List<ObservedSubject> observedSubjects = new ArrayList<ObservedSubject>();
List<ObservedEvidence> observedEvidences = new ArrayList<ObservedEvidence>();
for (ObservationData observationData : items) {
Observation observation = observationData.observation;
int index = observationIndex.get(submissionName);
observation.setStableURL(stableURL.createURLWithPrefix("observation", submissionName) + "-" + index);
observations.add(observation);
observationIndex.put(submissionName, index + 1);
for (DashboardEntity e : observationData.evidence) {
evidences.add((Evidence) e);
}
for (DashboardEntity e : observationData.observedEntities) {
String className = e.getClass().getName();
switch(className) {
case "gov.nih.nci.ctd2.dashboard.impl.ObservedSubjectImpl":
observedSubjects.add((ObservedSubject) e);
break;
case "gov.nih.nci.ctd2.dashboard.impl.ObservedEvidenceImpl":
observedEvidences.add((ObservedEvidence) e);
break;
default:
log.error("unexpected type " + className);
}
}
}
// use a smaller batch size to prevent 'lock wait timeout'
int batchSize = 100;
log.debug("observations to write " + observations.size());
dashboardDao.batchSave(observations, batchSize);
log.debug("observedSubjects to write " + observedSubjects.size());
dashboardDao.batchSave(observedSubjects, batchSize);
log.debug("evidences to write " + evidences.size());
dashboardDao.batchSave(evidences, batchSize);
log.debug("observedEvidences to write " + observedEvidences.size());
dashboardDao.batchSave(observedEvidences, batchSize);
log.debug("ALL WRITTEN: " + submissionName);
}
use of gov.nih.nci.ctd2.dashboard.model.ObservedSubject in project nci-ctd2-dashboard by CBIIT.
the class RssController method generateFeed.
private String generateFeed(List<? extends DashboardEntity> dashboardEntities, String rssTitlePostfix, String rssDescription, String rssLink) {
String dashboardUrl = context.getScheme() + "://" + context.getServerName() + context.getContextPath() + "/";
// Set the stage and define metadata on the RSS feed
SyndFeed feed = new SyndFeedImpl();
feed.setFeedType("rss_2.0");
feed.setTitle("CTD^2 Dashboard - " + rssTitlePostfix);
feed.setDescription(rssDescription);
feed.setLink(rssLink);
// We will have two major categories: Subject and Submission
// and will have subcategories of Subject for each particular subject
List<SyndCategory> categories = new ArrayList<SyndCategory>();
SyndCategory subjectCategory = new SyndCategoryImpl();
subjectCategory.setName("Subject");
categories.add(subjectCategory);
SyndCategory submissionCategory = new SyndCategoryImpl();
submissionCategory.setName("Submission");
categories.add(submissionCategory);
feed.setCategories(categories);
feed.setLanguage("en");
feed.setManagingEditor("ocg@mail.nih.gov (CTD^2 Network)");
SyndImage feedImg = new SyndImageImpl();
feedImg.setTitle("CTD^2 Logo");
feedImg.setUrl(dashboardUrl + "img/logos/ctd2_overall.png");
feedImg.setLink(dashboardUrl);
feed.setImage(feedImg);
// And prepare the items to be put into the RSS
List<SyndEntry> rssItems = new ArrayList<SyndEntry>();
for (DashboardEntity entity : dashboardEntities) {
if (entity instanceof Subject) {
Subject subject = (Subject) entity;
// Collect all role & submission pairs for this particular subject
Map<Submission, Set<String>> roleMap = new HashMap<Submission, Set<String>>();
Map<Submission, Set<ObservedSubject>> osMap = new HashMap<Submission, Set<ObservedSubject>>();
List<ObservedSubject> sObservations = dashboardDao.findObservedSubjectBySubject((Subject) entity);
for (ObservedSubject sObservation : sObservations) {
String role = sObservation.getObservedSubjectRole().getSubjectRole().getDisplayName();
Submission submission = sObservation.getObservation().getSubmission();
Set<String> roles = roleMap.get(submission);
if (roles == null) {
roles = new HashSet<String>();
roleMap.put(submission, roles);
}
roles.add(role);
Set<ObservedSubject> oses = osMap.get(submission);
if (oses == null) {
oses = new HashSet<ObservedSubject>();
osMap.put(submission, oses);
}
oses.add(sObservation);
}
// These will always belong to "Subject"
List<SyndCategory> sCategories = new ArrayList<SyndCategory>();
sCategories.add(subjectCategory);
// and "Subject/<name>" categories
SyndCategory sCategory = new SyndCategoryImpl();
sCategory.setName(subjectCategory.getName() + "/" + entity.getDisplayName());
categories.add(sCategory);
// Also add this specific category to the global list
sCategories.add(sCategory);
// And now combine this information into individual items around submissions/subject
for (Submission submission : roleMap.keySet()) {
Set<String> roles = roleMap.get(submission);
assert roles != null;
Set<ObservedSubject> oses = osMap.get(submission);
assert oses != null;
SyndEntry item = new SyndEntryImpl();
item.setCategories(sCategories);
// Construct title
ObservationTemplate observationTemplate = submission.getObservationTemplate();
String description = observationTemplate.getDescription();
Integer tier = observationTemplate.getTier();
String combinedRoles = StringUtils.join(roles, ", ");
String name = subject.getDisplayName();
int noOfObservations = oses.size();
StringBuilder title = new StringBuilder();
title.append("Role '").append(combinedRoles).append("'").append(": ").append(description).append(" ").append("(").append("Tier ").append(tier).append(" - ").append(noOfObservations).append(" ").append(noOfObservations > 1 ? "observations" : "observation").append(" on ").append(name).append(")");
item.setTitle(title.toString());
String centerName = observationTemplate.getSubmissionCenter().getDisplayName();
item.setAuthor(centerName);
item.setPublishedDate(submission.getSubmissionDate());
String submissionDescription = observationTemplate.getSubmissionDescription();
StringBuilder itemDescStr = new StringBuilder();
itemDescStr.append("<b>Project</b>: ").append(observationTemplate.getProject()).append("<br />");
if (submissionDescription != null && !submissionDescription.isEmpty()) {
itemDescStr.append("<b>Summary</b>: ").append(submissionDescription);
}
SyndContent itemDesc = new SyndContentImpl();
itemDesc.setType("text/html");
itemDesc.setValue(itemDescStr.toString());
item.setDescription(itemDesc);
// Create a link to the subject page with filters enabled
item.setLink(dashboardUrl + "#subject/" + subject.getId() + "/" + combinedRoles + "/" + tier);
item.setUri(String.format("#ctd2#subject#%s#%d", name, title.hashCode() & Integer.MAX_VALUE));
rssItems.add(item);
}
// End of subject-centered items
} else if (entity instanceof Submission) {
Submission submission = (Submission) entity;
SyndEntry item = new SyndEntryImpl();
ObservationTemplate observationTemplate = submission.getObservationTemplate();
int noOfObservations = dashboardDao.findObservationsBySubmission(submission).size();
StringBuilder title = new StringBuilder();
Boolean isStory = observationTemplate.getIsSubmissionStory();
title.append(isStory ? "Story" : "Submission").append(": ");
title.append(observationTemplate.getDescription().replaceAll("\\.$", "")).append(" (").append("Tier ").append(observationTemplate.getTier()).append(" - ").append(noOfObservations).append(" ").append(noOfObservations > 1 ? "observations" : "observation").append(")");
item.setTitle(title.toString());
String submissionDescription = observationTemplate.getSubmissionDescription();
StringBuilder itemDescStr = new StringBuilder();
itemDescStr.append("<b>Project</b>: ").append(observationTemplate.getProject()).append("<br />");
if (submissionDescription != null && !submissionDescription.isEmpty()) {
itemDescStr.append("<b>Summary</b>: ").append(submissionDescription);
}
SyndContent itemDesc = new SyndContentImpl();
itemDesc.setType("text/html");
itemDesc.setValue(itemDescStr.toString());
item.setDescription(itemDesc);
item.setPublishedDate(submission.getSubmissionDate());
String centerName = observationTemplate.getSubmissionCenter().getDisplayName();
item.setAuthor(centerName);
item.setLink(dashboardUrl + "#submission/" + submission.getId());
item.setUri(String.format("ctd2#submission#%d", title.hashCode() & Integer.MAX_VALUE));
rssItems.add(item);
}
// End of submission item(s)
}
// Add all items into the feed
feed.setEntries(rssItems);
// And print the XML/RSS version out
SyndFeedOutput feedOutput = new SyndFeedOutput();
String feedStr = null;
try {
feedStr = feedOutput.outputString(feed, true);
} catch (FeedException e) {
e.printStackTrace();
}
return feedStr;
}
use of gov.nih.nci.ctd2.dashboard.model.ObservedSubject in project nci-ctd2-dashboard by CBIIT.
the class JSONController method getEntityInJson.
@Transactional
@RequestMapping(value = "{type}/{id}", method = { RequestMethod.GET, RequestMethod.POST }, headers = "Accept=application/json")
public ResponseEntity<String> getEntityInJson(@PathVariable String type, @PathVariable String id) {
DashboardEntity entityById = null;
Class<? extends DashboardEntity> clazz = Subject.class;
if (type.equalsIgnoreCase("subject")) {
clazz = Subject.class;
} else if (type.equals("observedsubject")) {
clazz = ObservedSubject.class;
}
HttpHeaders headers = new HttpHeaders();
headers.add("Content-Type", "application/json; charset=utf-8");
log.debug("JSONController " + type + " " + id);
if (typesWithStableURL.contains(type)) {
String stableURL = type + "/" + id;
if (type.equals("observedevidence"))
stableURL = "mra/" + id;
entityById = dashboardDao.getEntityByStableURL(type, stableURL);
} else {
entityById = dashboardDao.getEntityById(clazz, Integer.parseInt(id));
}
if (entityById == null) {
return new ResponseEntity<String>(headers, HttpStatus.NOT_FOUND);
}
JSONSerializer jsonSerializer = new JSONSerializer().transform(new ImplTransformer(), Class.class).transform(new DateTransformer(), Date.class);
return new ResponseEntity<String>(jsonSerializer.deepSerialize(entityById), headers, HttpStatus.OK);
}
Aggregations