18 package org.turro.dossier.entity;
20 import java.time.Instant;
22 import javax.persistence.*;
23 import org.turro.string.Strings;
24 import org.turro.action.Contacts;
25 import org.turro.dossier.db.DossierPU;
26 import org.turro.dossier.dossier.DescriptorSet;
27 import org.turro.dossier.dossier.DescriptorValueSet;
28 import org.turro.dossier.dossier.DossierParticipationsList;
29 import org.turro.dossier.dossier.DossierStageWrapper;
30 import org.turro.dossier.dossier.FieldValueComparator;
31 import org.turro.dossier.dossier.FieldValueMap;
32 import org.turro.dossier.dossier.ParticipantSet;
33 import org.turro.dossier.dossier.WorthSet;
34 import org.turro.dossier.dw.DossierDWReport;
35 import org.turro.dossier.gantt.DossierGanttWrapper;
36 import org.turro.dossier.graph.html.IssueGraphModel;
37 import org.turro.jpa.Dao;
38 import org.turro.jpa.entity.IDaoEntity;
39 import org.turro.plugin.contacts.IContact;
40 import org.turro.reflection.MappingSet;
41 import org.turro.related.RelatedItem;
42 import org.turro.util.Chars;
50 @Index(name=
"StatusIndex", columnList=
"status"),
51 @Index(name=
"PathIndex", columnList=
"uniquePath"),
56 @GeneratedValue(strategy=GenerationType.IDENTITY)
57 @Column(name=
"IDENTIFIER")
60 @Temporal(value = javax.persistence.TemporalType.TIMESTAMP)
61 private java.util.Date creation;
65 private String description;
71 @OneToOne(cascade = CascadeType.ALL, orphanRemoval=true)
77 private String uniquePath;
79 private
boolean publishable;
83 private String searching;
85 @OneToMany(mappedBy = "dossier", fetch = FetchType.EAGER, cascade=CascadeType.ALL, orphanRemoval=true)
88 @OneToMany(mappedBy = "dossier", fetch = FetchType.LAZY, cascade=CascadeType.ALL, orphanRemoval=true)
89 @OrderBy(value="name")
92 @OneToMany(mappedBy = "dossier", fetch = FetchType.EAGER, cascade=CascadeType.ALL, orphanRemoval=true)
96 @OneToMany(mappedBy = "dossier", fetch = FetchType.LAZY, orphanRemoval=true)
97 @OrderBy(value="issueDate")
98 private Set<
Issue> issues = new HashSet<
Issue>();
100 @OneToMany(mappedBy = "dossier", fetch = FetchType.LAZY, cascade=CascadeType.ALL, orphanRemoval=true)
103 @OneToMany(mappedBy = "dossier", fetch = FetchType.LAZY, orphanRemoval=true)
106 @OneToMany(mappedBy = "dossier", fetch = FetchType.LAZY, orphanRemoval=true)
116 this.category = category;
124 this.uniquePath = uniquePath;
132 this.project = project;
140 this.creation = creation;
148 this.description = description;
156 this.fieldValues = fieldValues;
172 this.issues = issues;
177 if(
id !=
null &&
id > 0 && dao.
isNotLoaded(participants)) {
178 participants = dao.lazyLoader(
Dossier.class,
this,
"participants").participants;
184 this.participants = participants;
196 this.status = status;
204 this.publishable = publishable;
224 this.searching = searching;
228 this.versions = versions;
233 if(
id !=
null &&
id > 0 && dao.
isNotLoaded(descriptors)) {
234 descriptors = dao.lazyLoader(
Dossier.class,
this,
"descriptors").descriptors;
240 this.descriptors = descriptors;
245 if(
id !=
null &&
id > 0 && dao.
isNotLoaded(worths)) {
246 worths = dao.lazyLoader(
Dossier.class,
this,
"worths").worths;
252 this.worths = worths;
257 if(
id !=
null &&
id > 0 && dao.
isNotLoaded(offers)) {
258 offers = dao.lazyLoader(
Dossier.class,
this,
"offers").offers;
264 this.offers = offers;
270 TreeSet<DossierVersion> tdv =
new TreeSet<>();
282 return getAllIssues(
false);
286 return getAllIssues(
true);
291 return dao.getResultList(
292 "select issue from Issue as issue " +
293 "where issue.dossier = ? " +
294 (publicOnly ?
"and issue.publishable = TRUE " :
"") +
295 "order by issue.issueDate",
303 return getOpenIssues(
false);
307 return getOpenIssues(
true);
312 return dao.getResultList(
313 "select issue from Issue as issue " +
314 "where issue.dossier = ? " +
315 (publicOnly ?
"and issue.publishable = TRUE " :
"") +
316 "and (issue.status = ? " +
317 "or issue.status = ? " +
318 "or issue.status = ? " +
319 "or issue.status = ? " +
320 "or issue.status = ? " +
321 "or issue.status = ?) " +
322 "order by issue.issueDate",
336 return getClosedIssues(
false);
340 return getClosedIssues(
false);
345 return dao.getResultList(
346 "select issue from Issue as issue " +
347 "where issue.dossier = ? " +
348 (publicOnly ?
"and issue.publishable = TRUE " :
"") +
349 "and (issue.status = ? " +
350 "or issue.status = ? " +
351 "or issue.status = ?) " +
352 "order by issue.issueDate",
364 return dao.getResultList(
367 "where i.dossier = ? " +
369 new Object[] {
this, type });
376 return dao.getResultList(
377 "select distinct i.grouping " +
379 "where i.dossier = ?",
380 new Object[] {
this });
385 return dao.getResultList(
388 "where i.dossier = ? " +
389 "and i.grouping = ?",
390 new Object[] {
this, grouping });
400 if(_participants ==
null) {
402 if(category !=
null) {
403 _participants.
addAll(category.getFullParticipants());
406 return _participants;
410 _participants =
null;
415 if(!Strings.isBlank(p.getIdContact()) && p.getIdContact().equals(participant.
getIdContact())) {
427 return getFullParticipants().stream().filter(p -> p.hasRole()).toList();
437 if(_participations ==
null) {
440 return _participations;
444 _participations =
null;
451 return dao.getResultList(
"select distinct discriminator from Participant");
456 transient Map fieldMap =
null;
459 if(fieldMap ==
null) {
468 return getFullDescription(
true);
472 Participant subject = withSubject ? getSubject() :
null;
473 StringBuilder sb =
new StringBuilder();
474 if(subject !=
null) {
475 sb.append(subject.getName());
476 sb.append(Chars.forward().spaced());
478 sb.append(description);
479 if(category !=
null) {
480 sb.append(Chars.forward().spaced());
481 sb.append(category.getFullDescription());
483 return sb.toString();
489 if(!Strings.isEmpty(fv.getValue()) && fv.getFieldDef().isDescription()) {
490 if(s.length() != 0) s +=
", ";
491 s += fv.getObjectString(
false).trim();
500 if(!Strings.isEmpty(fv.getValue()) &&
501 fv.getFieldDef().isDescription() &&
502 fv.getFieldDef().isPublishable()) {
503 if(s.length() != 0 && !s.endsWith(
", ")) s +=
", ";
504 s += fv.getObjectString(
false).trim();
513 if(!Strings.isEmpty(fv.getValue()) &&
514 fv.getFieldDef().isDescription() &&
515 fv.getFieldDef().isPublishable()) {
516 if(s.length() != 0 && !s.endsWith(
", ")) s +=
", ";
517 s += fv.getLabeledObjectString().trim();
526 if(contact ==
null)
return null;
533 getParticipants().add(p);
538 if(contact ==
null)
return;
545 getParticipants().add(p);
549 if(contact ==
null)
return null;
556 getParticipants().add(p);
562 if(p.getIdContact().equals(contact.
getId())) {
566 return addAssistant(contact);
572 if(contact.
getId().equals(p.getIdContact())) {
577 return category.isDirectOwner(contact);
583 contact.
getId().equals(p.getIdContact()) &&
592 List<IDossierParticipant> list =
new ArrayList<>();
598 list.addAll(category.getDirectOwners());
626 if(getCategory() !=
null) {
628 if(contact !=
null && contact.
isValid()) {
637 if(getCategory() !=
null) {
639 if(contact !=
null && contact.
isValid()) {
651 if(_descriptors ==
null) {
660 if(_descriptorValues ==
null) {
663 return _descriptorValues;
671 if(_worths ==
null) {
682 if(_report ==
null) {
691 if(getStatus().isOpen()) {
692 path = (String) getFieldMap().get(
"dossierOpenUrl");
694 path = (String) getFieldMap().get(
"dossierClosedUrl");
696 return path ==
null ? null : path + getId();
718 return Strings.isBlank(description) || category ==
null;
724 if(category !=
null) {
725 return category.isKnowledgeBase();
740 Date last = getCreation();
741 if(project !=
null) {
742 last = assignLast(project.getStartDate(), last);
743 last = assignLast(project.getApprovedDate(), last);
744 last = assignLast(project.getChangePhase(), last);
745 last = assignLast(project.getEndDate(), last);
746 last = assignLast(project.getOppositingEndDate(), last);
751 private Date assignLast(Date date, Date last) {
752 if(last ==
null || (date !=
null && date.after(last) && !Instant.now().isAfter(date.toInstant()))) {
761 MappingSet
set =
new MappingSet();
762 set.addMapping(
Dossier.class, 1,
763 new String[] {
"id",
"description",
"creation",
"type",
"status",
"publishable" },
764 new String[] {
"category",
"versions",
"participants",
"fieldValues",
765 "project",
"descriptors" });
767 new String[] {
"id",
"description" },
770 new String[] {
"versionId",
"releaseDate",
"active" },
773 new String[] {
"name",
"idContact",
"role",
"showAllAttachments",
"showParticipants",
774 "showAllIssues",
"receiveAllEmails",
"bindingVote",
"discriminator",
"driver",
"coordinator",
775 "beneficiary",
"offerer",
"research",
"funding",
"support",
"consortium",
"admin" },
778 new String[] {
"value" },
780 set.addMapping(
Project.class, 2,
781 new String[] {
"projectCode",
"projectTitle",
"phase",
"estimatedBudget",
782 "assignedBudget",
"startDate",
"approvedDate",
"oppositingEndDate",
"endDate",
"goal" },
783 new String[] {
"matchCriteria" });
785 new String[] {
"hiring",
"idi",
"investment",
"startUp" },
788 new String[] {
"wiki" },
boolean addAll(Collection<? extends P > collection)
void setReportValues(Dossier dossier)
void setCategory(Category category)
String getLabeledPublishableDescription()
DossierDWReport getReport()
void setParticipants(Set< Participant > participants)
Participant addOwner(IContact contact)
Collection< Issue > getAllIssues(boolean publicOnly)
Set< DossierVersion > getActiveVersions()
DescriptorSet getDescriptorSet()
Collection< Issue > getClosedIssues(boolean publicOnly)
String getExtraDescription()
IssueGraphModel getIssueGraphModel(boolean onlyMilestones, boolean onlyOpen)
DossierStatus getStatus()
Set< Participant > getParticipants()
Collection< String > getPossibleDiscriminators()
String getFullDescription(boolean withSubject)
boolean existsParticipant(IDossierParticipant participant)
void setType(DossierType type)
boolean isDirectOwner(IContact contact)
void setDescriptors(Set< DescriptorValue > descriptors)
String getFullDescription()
Collection< Issue > getAllPublishableIssues()
ParticipantSet< IDossierParticipant > getFullParticipants()
void setCreation(Date creation)
void setPublishable(boolean publishable)
void setProject(Project project)
Set< DossierVersion > getVersions()
void setWorths(Set< WorthValue > worths)
List< IDossierParticipant > getRoleParticipants()
Set< FieldValue > getFieldValues()
List< IDossierParticipant > getDirectOwners()
Set< DescriptorValue > getDescriptors()
Collection< Issue > getOpenPublishableIssues()
void setSubject(IContact subject)
Set< DossierOffer > getOffers()
void setDescription(String description)
boolean isKnowledgeBase()
Set< WorthValue > getWorths()
Collection< Issue > getOpenIssues()
void setSearching(String searching)
Collection< Issue > getIssuesByType(IssueType type)
Map< String, Object > getFieldMap()
void resetParticipations()
IContact getDefaultResponsible()
Collection< String > getGroupings()
Collection< Issue > getClosedIssues()
void setVersions(Set< DossierVersion > versions)
void setFieldValues(Set< FieldValue > fieldValues)
DescriptorValueSet getDescriptorValueSet()
DossierParticipationsList getParticipationsList()
DossierStageWrapper getStageWrapper()
Collection< Issue > getIssuesByGrouping(String grouping)
Collection< Issue > getOpenIssues(boolean publicOnly)
Participant addOrReturnAssistant(IContact contact)
void setStatus(DossierStatus status)
void setIssues(Set< Issue > issues)
List< IDossierParticipant > getFullRoleParticipants()
Participant addAssistant(IContact contact)
Collection< Issue > getAllIssues()
String getPublishableDescription()
MappingSet getSerializerMappings()
Collection< Issue > getClosedPublishableIssues()
void addSubject(IContact contact)
void setUniquePath(String uniquePath)
boolean isBranchAdmin(IContact contact)
DossierGanttWrapper getIssueGantt()
void setOffers(Set< DossierOffer > offers)
void setName(String name)
void setIdContact(String idContact)
void setCreation(Date creation)
void setDossier(Dossier dossier)
void setRole(ParticipantRole role)
boolean isNotLoaded(Object o, String attribute)