BrightSide Workbench Full Report + Source Code
DossierGanttWrapper.java
Go to the documentation of this file.
1 /*
2  * TurrĂ³ i Cutiller Foundation. License notice.
3  * Copyright (C) 2023 Lluis TurrĂ³ Cutiller <http://www.turro.org/>
4  *
5  * This program is free software: you can redistribute it and/or modify
6  * it under the terms of the GNU Affero General Public License as published by
7  * the Free Software Foundation, either version 3 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU Affero General Public License for more details.
14  *
15  * You should have received a copy of the GNU Affero General Public License
16  * along with this program. If not, see <http://www.gnu.org/licenses/>.
17  */
18 
19 package org.turro.dossier.gantt;
20 
21 import java.util.ArrayList;
22 import java.util.Date;
23 import java.util.List;
24 import java.util.Set;
25 import java.util.stream.Collectors;
26 import org.amic.util.date.CheckDate;
27 import org.turro.dossier.db.DossierPU;
28 import org.turro.dossier.entity.Dossier;
29 import org.turro.dossier.entity.Issue;
30 import org.turro.dossier.entity.IssuePredecessor;
31 import org.turro.dossier.task.Tasks;
32 import org.turro.jpa.Dao;
33 import org.turro.sql.SqlClause;
34 import org.turro.util.Cached;
35 import org.turro.util.Comparison;
36 import org.turro.util.Converter;
37 import org.turro.web.gantt.GanttWrapper;
38 
43 public class DossierGanttWrapper extends GanttWrapper {
44 
45  private final Dossier dossier;
46  private final List<Issue> issues;
47 
48  private boolean publishable = true;
49 
50  public DossierGanttWrapper(Dossier dossier) {
51  this.dossier = dossier;
52  this.issues = new ArrayList<>();
53  }
54 
55  public boolean getItFits() {
56  return !SqlClause.select("i").from("Issue i")
57  .where().equal("i.milestone", true)
58  .startIf(publishable)
59  .and().equal("i.publishable", true)
60  .endIf()
61  .startIf(dossier != null)
62  .and().equal("i.dossier", dossier)
63  .endIf()
64  .and().group().isNotNull("i.startDate")
65  .or().isNotNull("i.delivery").endGroup()
66  .and().notExists(
67  SqlClause.select("p").from("IssuePredecessor p")
68  .where("p.source = i.id")
69  )
70  .dao(dao.get())
71  .max(1)
72  .resultList(Issue.class)
73  .isEmpty();
74  }
75 
76  public String toJson() {
77  getIssues().forEach(i -> {
78  addItem(i);
79  });
80  return items.toJson();
81  }
82 
83  private List<Issue> getIssues() {
84  return SqlClause.select("i").from("Issue i")
85  .where().equal("i.milestone", true)
86  .startIf(publishable)
87  .and().equal("i.publishable", true)
88  .endIf()
89  .startIf(dossier != null)
90  .and().equal("i.dossier", dossier)
91  .endIf()
92  .and().group().isNotNull("i.startDate")
93  .or().isNotNull("i.delivery").endGroup()
94  .and().notExists(
95  SqlClause.select("p").from("IssuePredecessor p")
96  .where("p.source = i.id")
97  )
98  .dao(dao.get())
99  .resultList(Issue.class);
100  }
101 
102  private void addItem(Issue issue) {
103  Set<IssuePredecessor> incoming = issue.getSources();
104  String dependencies = incoming.stream()
105  .map(i -> i.getSource().getId().toString())
106  .collect(Collectors.joining(","));
107  Date start = getStart(issue, issue.getStartDate());
108  items.addItem(issue.getId().toString(),
109  issue.getDescription(), dependencies,
110  getStart(issue, issue.getStartDate()),
111  getDelivery(start, issue.getDelivery()),
112  Converter.STANDARD.convert(percentDone(issue), Integer.class),
113  getCssClass(issue));
114  incoming.stream()
115  .map(p -> p.getSource())
116  .sorted((i1, i2) -> compare(i1, i2))
117  .forEach(i -> addItem(i));
118  }
119 
120  private int compare(Issue i1, Issue i2) {
121  return Comparison.ascendant()
122  .compare(i1.getStartDate(), i2.getStartDate())
123  .compare(i1.getDescription(), i2.getDescription())
124  .get();
125  }
126 
127  private Date getStart(Issue issue, Date startDate) {
128  if(startDate == null) {
129  for(IssuePredecessor p : issue.getTargets()) {
130  Date tmp = p.getTarget().getStartDate();
131  if(tmp != null) {
132  startDate = tmp;
133  } else {
134  startDate = getStart(p.getTarget(), tmp);
135  }
136  if(startDate != null) {
137  startDate = new CheckDate(startDate).addDays(-1).getDate();
138  break;
139  }
140  }
141  }
142  return startDate;
143  }
144 
145  private Date getDelivery(Date start, Date delivery) {
146  if(delivery == null) {
147  delivery = new CheckDate(start).addDays(1).getDate();
148  }
149  return delivery;
150  }
151 
152  private String getCssClass(Issue issue) {
153  String css = "gantt-task";
154  if(issue.isMilestone()) {
155  css += " milestone";
156  }
157  if(issue.getStatus().isFinished()) {
158  css += " finished";
159  }
160  return css;
161  }
162 
163  /* Done */
164 
165  public double percentDone(Issue issue) {
166  return Tasks.from(issue, false, false).getPercentTasksDone();
167  }
168 
169  /* Dao */
170 
171  private final Cached<Dao> dao = Cached.instance(() -> new DossierPU());
172 
173 }
static Tasks from(Dossier dossier, boolean onlyOpen, boolean sameDossier)
void addItem(String id, String name, List< String > dependencies, Date start, Date end, int progress)
Definition: GanttItems.java:33