Skip to content

Method: handle(SendungsAnzahlSpanne)

1: package auftraege;
2:
3: import auftraege.auftragsBildungsParameter.BeilagenArten;
4: import auftraege.auftragsBildungsParameter.BlattAnzahlSpanne;
5: import auftraege.auftragsBildungsParameter.SendungsAnzahlSpanne;
6: import auftraege.auftragsBildungsParameter.abstraction.DokumentenklassenVariable;
7: import auftraege.auftragsBildungsParameter.abstraction.DokumentenklassenVariablenVisitor;
8: import auftraege.auftragsBildungsParameter.abstraction.VoraussichtlicheDokumentenklassenVariable;
9: import auftraege.auftragsBildungsParameter.dokumentenKlassenVariablen.BlattAnzahl;
10: import auftraege.auftragsBildungsParameter.dokumentenKlassenVariablen.Id;
11: import auftraege.auftragsBildungsParameter.dokumentenKlassenVariablen.Kommentar;
12: import auftraege.auftragsBildungsParameter.dokumentenKlassenVariablen.ProzessModell;
13: import auftraege.auftragsBildungsParameter.dokumentenKlassenVariablen.SendungsAnzahl;
14: import auftraege.auftragsBildungsParameter.dokumentenKlassenVariablen.UnbekannteVariable;
15: import auftraege.auftragsBildungsParameter.dokumentenKlassenVariablen.UnbekannteVariablen;
16: import auftraege.versand.Kunde;
17: import maschine.faehigkeit.DruckTyp;
18: import maschine.faehigkeit.Drucken;
19: import maschine.faehigkeit.FaehigkeitVisitor;
20: import maschine.faehigkeit.FarbDruckTyp;
21: import maschine.faehigkeit.Kuvertieren;
22: import maschine.faehigkeit.SimplesDrucken;
23: import maschine.faehigkeit.SimplesKuvertieren;
24: import material.auspraegungen.Papierformat;
25: import material.kuvert.KuvertFormat;
26: import util.ClassObjectMap;
27: import util.Fraction;
28: import util.exceptions.ExceptionConstants;
29: import util.exceptions.SollteNichtPassierenException;
30: import zeit.eintraege.Zeitraum;
31: import zeit.serientermin.IntervallSerienTermin;
32: import zeit.serientermin.SerienTermin;
33:
34: import java.time.LocalDateTime;
35: import java.util.Arrays;
36: import java.util.Collection;
37: import java.util.Iterator;
38: import java.util.Objects;
39: import java.util.Optional;
40:
41: /**
42: * eine {@link VoraussichtlicheDokumentenklasse} ist eine {@link Dokumentenklasse}, welche noch nicht zu 100% definiert ist. <br> Im Gegensatz zu {@link
43: * Dokumentenklasse}n, besitzt sie keine {@link Dokumentenklasse#variablen} in Form von {@link auftraege.auftragsBildungsParameter.abstraction
44: * .DokumentenklassenVariable}n, sondern besteht aus {@link VoraussichtlicheDokumentenklassenVariable}n. Diese können bspw. eine {@link
45: * auftraege.auftragsBildungsParameter.BlattAnzahlSpanne} sein, da noch keine genaue {@link auftraege.auftragsBildungsParameter.dokumentenKlassenVariablen.BlattAnzahl}
46: * vorgegeben ist. Lediglich eine ungefähre Prognose kann gemacht werden.
47: */
48: public final class VoraussichtlicheDokumentenklasse {
49:
50:         private static DokumentenklassenVariablenVisitor<DokumentenklassenVariable> tatsaechlicheZuEchteVariablenAverageCaseVisitor(final int anzahlSchichten) {
51:                 return new DokumentenklassenVariablenVisitor<DokumentenklassenVariable>() {
52:                         @Override
53:                         public DokumentenklassenVariable handle(final KuvertFormat kuvertFormat) {
54:                                 return kuvertFormat;
55:                         }
56:                         @Override
57:                         public DokumentenklassenVariable handle(final ProzessModell prozessModell) {
58:                                 return prozessModell;
59:                         }
60:                         @Override
61:                         public DokumentenklassenVariable handle(final DruckTyp druckTyp) {
62:                                 return druckTyp;
63:                         }
64:                         @Override
65:                         public DokumentenklassenVariable handle(final FarbDruckTyp farbDruckTyp) {
66:                                 return farbDruckTyp;
67:                         }
68:                         @Override
69:                         public DokumentenklassenVariable handle(final ServiceLevelAgreement serviceLevelAgreement) {
70:                                 return serviceLevelAgreement;
71:                         }
72:                         @Override
73:                         public DokumentenklassenVariable handle(final Papierformat papierformat) {
74:                                 return papierformat;
75:                         }
76:                         @Override
77:                         public DokumentenklassenVariable handle(final BlattAnzahl blattAnzahl) {
78:                                 return BlattAnzahl.create(blattAnzahl.intValue() / anzahlSchichten);
79:                         }
80:                         @Override
81:                         public DokumentenklassenVariable handle(final Id id) {
82:                                 return id;
83:                         }
84:                         @Override
85:                         public DokumentenklassenVariable handle(final SendungsAnzahl sendungsAnzahl) {
86:                                 return SendungsAnzahl.create(sendungsAnzahl.intValue() / anzahlSchichten);
87:                         }
88:                         @Override
89:                         public DokumentenklassenVariable handle(final Kunde kunde) {
90:                                 return kunde;
91:                         }
92:                         @Override
93:                         public DokumentenklassenVariable handle(final BeilagenArten beilagenarten) {
94:                                 return beilagenarten;
95:                         }
96:                         @Override
97:                         public DokumentenklassenVariable handle(final UnbekannteVariable unbekannteVariable) {
98:                                 return unbekannteVariable;
99:                         }
100:                         @Override
101:                         public DokumentenklassenVariable handle(final UnbekannteVariablen unbekannteVariablen) {
102:                                 return unbekannteVariablen;
103:                         }
104:                         @Override
105:                         public DokumentenklassenVariable handle(final Kommentar kommentar) {
106:                                 return kommentar;
107:                         }
108:                 };
109:         }
110:
111:         /**
112:          * hierbei handelt es sich um das Äquivalent zu den {@link Dokumentenklasse#variablen} aus der Klasse {@link Dokumentenklasse}. Allerdings werden hier noch keine
113:          * konkreten, sondern nur voraussichtliche Werte angegeben.
114:          */
115:         private final ClassObjectMap<VoraussichtlicheDokumentenklassenVariable> variablen;
116:         private static final VoraussichtlicheDokumentenklassenVariableVisitor<DokumentenklassenVariable> VORAUSSICHTLICHE_ZU_ECHTE_VARIABLEN_WORST_CASE_VISITOR;
117:
118:         private VoraussichtlicheDokumentenklassenVariableVisitor<DokumentenklassenVariable> voraussichtlicheZuEchteVariablenAverageCaseVisistor(
119:                         final int anzahlSchichten) {
120:                 return new VoraussichtlicheDokumentenklassenVariableVisitor<DokumentenklassenVariable>() {
121:                         @Override
122:                         public DokumentenklassenVariable handle(final BlattAnzahlSpanne blattAnzahlSpanne) {
123:                                 final Fraction obere = Fraction.valueOf(blattAnzahlSpanne.getObereGrenze().getValue());
124:                                 final Fraction untere = Fraction.valueOf(blattAnzahlSpanne.getUntereGrenze().getValue());
125:                                 return BlattAnzahl.create(obere.add(untere).divide(Fraction.valueOf(2 * anzahlSchichten)).intValue());
126:                         }
127:
128:                         @Override
129:                         public DokumentenklassenVariable handle(final SendungsAnzahlSpanne sendungsAnzahlSpanne) {
130:                                 final Fraction obere = Fraction.valueOf(sendungsAnzahlSpanne.getObereGrenze().getValue());
131:                                 final Fraction untere = Fraction.valueOf(sendungsAnzahlSpanne.getUntereGrenze().getValue());
132:                                 return SendungsAnzahl.create(obere.add(untere).divide(Fraction.valueOf(2 * anzahlSchichten)).intValue());
133:                         }
134:
135:                         @Override
136:                         public DokumentenklassenVariable handle(final DokumentenklassenVariable dokumentenklassenVariable) {
137:                                 return dokumentenklassenVariable.accept(tatsaechlicheZuEchteVariablenAverageCaseVisitor(anzahlSchichten));
138:                         }
139:
140:                         @Override
141:                         public DokumentenklassenVariable handle(final SerienTermin serienTermin) {
142:                                 //Ja hier soll null stehen. Man könnte überlegen, das alles zu nem Optional zu machen, allerdings ist das dann ein großes Ein- und Ausgepacke
143:                                 //Ich glaube dadurch, dass ich mich in einer privaten Variable befinde, die von außen nicht erreichbar ist, sollte das okay sein...
144:                                 return null;
145:                         }
146:                 };
147:         }
148:
149:         static {
150:                 VORAUSSICHTLICHE_ZU_ECHTE_VARIABLEN_WORST_CASE_VISITOR = new VoraussichtlicheDokumentenklassenVariableVisitor<DokumentenklassenVariable>() {
151:                         @Override
152:                         public DokumentenklassenVariable handle(final BlattAnzahlSpanne blattAnzahlSpanne) {
153:                                 return BlattAnzahl.create(blattAnzahlSpanne.getObereGrenze().intValue() - 1);
154:                         }
155:
156:                         @Override
157:                         public DokumentenklassenVariable handle(final SendungsAnzahlSpanne sendungsAnzahlSpanne) {
158:                                 return SendungsAnzahl.create(sendungsAnzahlSpanne.getObereGrenze().intValue() - 1);
159:                         }
160:
161:                         @Override
162:                         public DokumentenklassenVariable handle(final DokumentenklassenVariable dokumentenklassenVariable) {
163:                                 return dokumentenklassenVariable;
164:                         }
165:
166:                         @Override
167:                         public DokumentenklassenVariable handle(final SerienTermin serienTermin) {
168:                                 //Ja hier soll null stehen. Man könnte überlegen, das alles zu nem Optional zu machen, allerdings ist das dann ein großes Ein- und Ausgepacke
169:                                 //Ich glaube dadurch, dass ich mich in einer privaten Variable befinde, die von außen nicht erreichbar ist, sollte das okay sein...
170:                                 return null;
171:                         }
172:                 };
173:         }
174:
175:         private VoraussichtlicheDokumentenklasse(final ClassObjectMap<VoraussichtlicheDokumentenklassenVariable> variablen) {
176:                 this.variablen = variablen;
177:         }
178:
179:         /**
180:          * @param variablen
181:          *                 {@link Variable}n aus {@link Variable#bezeichung} und {@link Variable#wert}
182:          *
183:          * @return eine {@link VoraussichtlicheDokumentenklasse} auf basis der übergebenen {@link Variable}n.
184:          */
185:         public static VoraussichtlicheDokumentenklasse create(final Collection<Variable> variablen) {
186:                 final ClassObjectMap<VoraussichtlicheDokumentenklassenVariable> com = new ClassObjectMap<>();
187:                 variablen.stream().map(VoraussichtlicheDokumentenklassenVariable::create).forEach(com::put);
188:                 if (com.getBySuperclass(SerienTermin.class).isEmpty()) {
189:                         throw new IllegalArgumentException(ExceptionConstants.VORAUSSICHTLICHE_DOKUMENTENKLASSE_OHNE_TERMIN);
190:                 }
191:                 return new VoraussichtlicheDokumentenklasse(com);
192:         }
193:
194:         /**
195:          * @param variablen
196:          *                 {@link Variable}n aus {@link Variable#bezeichung} und {@link Variable#wert}
197:          *
198:          * @return eine {@link VoraussichtlicheDokumentenklasse} auf basis der übergebenen {@link Variable}n.
199:          */
200:         public static VoraussichtlicheDokumentenklasse create(final Variable... variablen) {
201:                 return create(Arrays.asList(variablen));
202:         }
203:
204:
205:         /**
206:          * @param eingangszeitpunkt
207:          *                 Eingangszeitpunkt, den die Dokumentenklasse haben soll, die aus der voraussichtlichen erstellt wird.
208:          *
209:          * @return ein {@link Optional}, das leer ist, falls die die {@link VoraussichtlicheDokumentenklasse} an dem übergebenen Eingangszeitpunkt gar nicht existieren kann,
210:          * ansonsten die Dokumentenklasse, die schlimmstenfals eintreffen könnte enthält.
211:          */
212:         public Optional<Dokumentenklasse> toDokumentenklasseWorstCase(final LocalDateTime eingangszeitpunkt) {
213:                 this.fuelleAllesAufWasFehlt();
214:                 final Iterator<SerienTermin> serienTermin = this.variablen.getBySuperclass(SerienTermin.class).iterator();
215:                 if (!serienTermin.hasNext()) {
216:                         throw new SollteNichtPassierenException(ExceptionConstants.VORAUSSICHTLICHE_DOKUMENTENKLASSE_OHNE_TERMIN);
217:                 } else if (!serienTermin.next().beinhaltetZeitpunkt(eingangszeitpunkt)) {
218:                         return Optional.empty();
219:                 } else {
220:                         return Optional.of(
221:                                         Dokumentenklasse.create(
222:                                                         eingangszeitpunkt,
223:                                                         this.variablen
224:                                                                         .valueStream()
225:                                                                         .map(voraussichtlicheVariable -> voraussichtlicheVariable.accept(VORAUSSICHTLICHE_ZU_ECHTE_VARIABLEN_WORST_CASE_VISITOR))
226:                                                                         .filter(Objects::nonNull)
227:                                                                         .toArray(DokumentenklassenVariable[]::new)));
228:                 }
229:
230:         }
231:
232:         /**
233:          * Diese Operation füllt je nach erforderlichem Prozessmodell jene planungsrelevanten nicht existierenden Daten mit Standard-Werten auf. Nach Prozessmodell muss
234:          * unterschieden werden, da beispielsweise für eine reine Kuvertierung ohne Druck das Kuvertformat benötigt wird, jedoch nicht der Farbdrucktyp. Bei einem reinen
235:          * Druckauftrag ist es genau andersherum. Es wird davon ausgegangen, dass, falls das Prozessmodell nicht übergeben wurde, sowohl gedruckt, als auch kuvertiert
236:          * werden muss.
237:          */
238:         private void fuelleAllesAufWasFehlt() {
239:                 final ProzessModell prozessModell = this.variablen.putIfNotExists(ProzessModell.DRUCKEN_KUVERTIEREN);
240:                 this.variablen.putIfNotExists(Papierformat.A4);
241:                 prozessModell.getFaehigkeiten().forEach(maschinenFaehigkeit -> maschinenFaehigkeit.accept(new FaehigkeitVisitor<Void>() {
242:                         @Override
243:                         public Void handle(final Drucken drucken) {
244:                                 throw new SollteNichtPassierenException("hier kann nur ein [SimplesDrucken] ankommen.");
245:                         }
246:
247:                         @Override
248:                         public Void handle(final Kuvertieren kuvertieren) {
249:                                 throw new SollteNichtPassierenException("hier kann nur ein [SimplesKuvertieren] ankommen.");
250:                         }
251:
252:                         @Override
253:                         public Void handle(final SimplesDrucken simplesDrucken) {
254:                                 VoraussichtlicheDokumentenklasse.this.fuelleAufFuerDruck();
255:                                 return null;
256:                         }
257:
258:                         @Override
259:                         public Void handle(final SimplesKuvertieren simplesKuvertieren) {
260:                                 VoraussichtlicheDokumentenklasse.this.fuelleAufFuerKuvertierung();
261:                                 return null;
262:                         }
263:                 }));
264:         }
265:
266:         private void fuelleAufFuerDruck() {
267:                 this.variablen.putIfNotExists(FarbDruckTyp.Farbdruck);
268:                 this.variablen.putIfNotExists(DruckTyp.duplex);
269:         }
270:
271:         private void fuelleAufFuerKuvertierung() {
272:                 this.variablen.putIfNotExists(KuvertFormat.C5);
273:         }
274:
275:         /**
276:          * @param eingangszeitpunkt
277:          *                 Eingangszeitpunkt, den die Dokumentenklasse haben soll, die aus der voraussichtlichen erstellt wird.
278:          * @param anzahlSchichten
279:          *                 Anzahl der Schichten, auf die die durchschnittliche Dokumentenklasse aufgeteilt wird.
280:          *
281:          * @return ein Optional, das leer ist, falls die die {@link VoraussichtlicheDokumentenklasse} an dem übergebenen Eingangszeitpunkt gar nicht existieren kann,
282:          * ansonsten die Dokumentenklasse, die im durchschnitt eintreffen könnte enthält. Hierbei wird beispielsweise die errechnete durchschnittliche
283:          * Blattanzahl nochmals durch die Anzahl der Schichten geteilt, um eine Verteilung auf sämtliche Schichten realisieren zu können.
284:          */
285:         public Optional<Dokumentenklasse> toDokumentenklasseAverageCase(final LocalDateTime eingangszeitpunkt, final int anzahlSchichten) {
286:                 this.fuelleAllesAufWasFehlt();
287:                 final Iterator<SerienTermin> serienTermin = this.variablen.getBySuperclass(SerienTermin.class).iterator();
288:                 if (!serienTermin.hasNext()) {
289:                         throw new SollteNichtPassierenException(ExceptionConstants.VORAUSSICHTLICHE_DOKUMENTENKLASSE_OHNE_TERMIN);
290:                 } else if (!serienTermin.next().beinhaltetZeitpunkt(eingangszeitpunkt)) {
291:                         return Optional.empty();
292:                 } else {
293:                         return Optional.of(
294:                                         Dokumentenklasse.create(
295:                                                         eingangszeitpunkt,
296:                                                         this.variablen
297:                                                                         .valueStream()
298:                                                                         .map(v -> v.accept(this.voraussichtlicheZuEchteVariablenAverageCaseVisistor(anzahlSchichten)))
299:                                                                         .filter(Objects::nonNull)
300:                                                                         .toArray(DokumentenklassenVariable[]::new)));
301:                 }
302:         }
303:
304:         /**
305:          * @return liefert den Zeitraum des ursprünglichen Termins der voraussichtlichen Dokumentenklasse.
306:          */
307:         public Zeitraum getZeitraum() {
308:                 return this.variablen.get(IntervallSerienTermin.class).orElseThrow(SollteNichtPassierenException::new)
309:                                 .getEintrag().getZeitraum();
310:         }
311: }