Skip to content

Package: Produktionsplaner

Produktionsplaner

nameinstructionbranchcomplexitylinemethod
Produktionsplaner()
M: 0 C: 3
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
findeBelegung(List, List, List, MaschinenRollenbelegungServiceParameter)
M: 0 C: 9
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
findeBelegungAberErzeugeKeineKalendereintraege(List, List, List, MaschinenRollenbelegungServiceParameter)
M: 0 C: 9
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
getQualifizierteMaschinenProBenoetigteFaehigkeit(Collection, ProduktionsAuftrag)
M: 0 C: 4
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
M: 0 C: 1
100%

Coverage

1: package rollenbelegung;
2:
3: import auftraege.ProduktionsAuftrag;
4: import auftraege.auftragsBildungsParameter.abstraction.DokumentenklassenVariable;
5: import maschine.BegrenzteBeilagenArten;
6: import maschine.Maschine;
7: import maschine.faehigkeit.Drucken;
8: import maschine.faehigkeit.FaehigkeitVisitor;
9: import maschine.faehigkeit.Kuvertieren;
10: import maschine.faehigkeit.MaschinenFaehigkeit;
11: import maschine.faehigkeit.SimplesDrucken;
12: import maschine.faehigkeit.SimplesKuvertieren;
13: import mensch.Mitarbeiter;
14: import rollenbelegung.SortierParameter.MaschinenRollenbelegungServiceParameter;
15: import rollenbelegung.SortierParameter.ZuordnungsParameter;
16: import tec.uom.se.ComparableQuantity;
17: import util.ClassObjectMap;
18: import util.Pair;
19: import util.exceptions.KeineVerfuegbarkeitException;
20: import zeit.TypMitKalender;
21: import zeit.eintraege.KalenderEintrag;
22: import zeit.eintraege.MaschinenBelegungEintrag;
23: import zeit.eintraege.MenschBelegungEintrag;
24:
25: import javax.measure.quantity.Time;
26: import java.time.LocalDateTime;
27: import java.util.ArrayList;
28: import java.util.Collection;
29: import java.util.Comparator;
30: import java.util.HashSet;
31: import java.util.LinkedHashMap;
32: import java.util.List;
33: import java.util.Map;
34: import java.util.Map.Entry;
35: import java.util.stream.Collectors;
36:
37: /**
38: * Der Produktionsplaner sorgt dafür, dass Produktionsauftrage einer Maschine, einem Operator und einem Zeitslot zugeordnet werden. Sowohl Maschine, Operator, als
39: * auch
40: * der Zeitslot müssen verfügbar sein.
41: */
42: public class Produktionsplaner implements MaschinenRollenbelegungService {
43:
44:         @Override
45:         public ErmittelteBelegungen findeBelegung(final List<Maschine> maschinen,
46:          final List<Mitarbeiter> mitarbeiter,
47:          final List<ProduktionsAuftrag> produktionsAuftraege,
48:          final MaschinenRollenbelegungServiceParameter parameter) {
49:                 return new InternalProduktionsplaner(maschinen, mitarbeiter, parameter).plan(produktionsAuftraege);
50:         }
51:
52:         @Override
53:         public ErmittelteBelegungen findeBelegungAberErzeugeKeineKalendereintraege(final List<Maschine> maschinen,
54:          final List<Mitarbeiter> mitarbeiter,
55:          final List<ProduktionsAuftrag> produktionsAuftraege,
56:          final MaschinenRollenbelegungServiceParameter parameter) {
57:                 return new InternalProduktionsplaner(maschinen, mitarbeiter, parameter).planAberErzeugeKeineKalendereintraege(produktionsAuftraege);
58:         }
59:
60:         /**
61:          * TODO irgendwie überlegen, wie man diesen Kommentar mit dem Kommentar aus der internen Klasse konsistent hält.
62:          * @param evtlQualifizierteMaschinen
63:          *                 ich schreib hier nichts hin, guck in die Operation {@link InternalProduktionsplaner#getQualifizierteMaschinenProBenoetigteFaehigkeit(Collection,
64:          * ProduktionsAuftrag) hier}
65:          * @param auftrag
66:          *                 ich schreib hier nichts hin, guck in die Operation
67:          *                 {@link InternalProduktionsplaner#getQualifizierteMaschinenProBenoetigteFaehigkeit(Collection, ProduktionsAuftrag) hier}
68:          *
69:          * @return ich schreib hier nichts hin, guck in die Operation {@link InternalProduktionsplaner#getQualifizierteMaschinenProBenoetigteFaehigkeit(Collection,
70:          * ProduktionsAuftrag) hier}
71:          */
72:         public Map<MaschinenFaehigkeit, Collection<Maschine>> getQualifizierteMaschinenProBenoetigteFaehigkeit(
73:                         final Collection<Maschine> evtlQualifizierteMaschinen,
74:                         final ProduktionsAuftrag auftrag) {
75:                 return InternalProduktionsplaner.getQualifizierteMaschinenProBenoetigteFaehigkeit(evtlQualifizierteMaschinen, auftrag);
76:         }
77:
78:
79:         /**
80:          * Interne Klasse, die die Logik hinter der Schnittstellen-Operation {@link rollenbelegung.MaschinenRollenbelegungService #findeBelegung()} enthält.
81:          */
82:         static class InternalProduktionsplaner {
83:
84:                 private final SortierHelper sortierHelper;
85:                 private final List<Maschine> maschinen;
86:                 private final List<Mitarbeiter> mitarbeiter;
87:                 private final MaschinenRollenbelegungServiceParameter parameter;
88:
89:                 /**
90:                  * Erzeugt einen InternalProduktionsplaner.
91:                  *
92:                  * @param maschinen
93:                  *                 Maschinen, mit denen geplant wird
94:                  * @param mitarbeiter
95:                  *                 Mitarbeiter, mit denen geplant wird
96:                  * @param parameter
97:                  *                 Parameter, nach denen Sortiert wird
98:                  */
99:                 InternalProduktionsplaner(final List<Maschine> maschinen,
100:                  final List<Mitarbeiter> mitarbeiter,
101:                  final MaschinenRollenbelegungServiceParameter parameter) {
102:                         this.sortierHelper = SortierHelper.create();
103:                         this.maschinen = new ArrayList<>(maschinen);
104:                         this.mitarbeiter = new ArrayList<>(mitarbeiter);
105:                         this.parameter = parameter;
106:                 }
107:
108:                 /**
109:                  * Sortiert ProduktionsAuftraege, Maschinen und Mitarbeiter nach den gegebenen Parametern und führt dann die Maschinen-Rollen-Belegung für die übergebenen
110:                  * Produktionsauftraege durch.
111:                  *
112:                  * @param produktionsAuftraege
113:                  *                 die Maschinen und Mitarbeitern zugeordnet werden
114:                  *
115:                  * @return die vom Algorithmus ermittelten Belegungen
116:                  */
117:                 private ErmittelteBelegungen plan(final List<ProduktionsAuftrag> produktionsAuftraege) {
118:                         this.sortierHelper.sortiereProduktionsAuftraegeUndMaschinenUndMitarbeiter(
119:                                         produktionsAuftraege,
120:                                         this.maschinen,
121:                                         this.mitarbeiter,
122:                                         this.parameter);
123:
124:                         final Collection<ProduktionsAuftrag> nichtZugeordneteAuftraege = new ArrayList<>();
125:
126:                         for (final ProduktionsAuftrag auftrag : produktionsAuftraege) {
127:                                 if (!this.zuordnen(auftrag)) {
128:                                         nichtZugeordneteAuftraege.add(auftrag);
129:                                 }
130:                         }
131:                         return new ErmittelteBelegungen(nichtZugeordneteAuftraege, this.getMaschinenBelegungen(this.maschinen),
132:                                         this.getMitarbeiterBelegungen(this.mitarbeiter));
133:                 }
134:
135:
136:                 /**
137:                  * Für jeden ProduktionsAuftrag wird eine Menge an Fähigkeiten benötigt. Diese ergeben sich aus den Variablen
138:                  * der enthaltenen Dokumentenklassen. Es gilt im weiteren Verlauf Maschinen zu finden, die genau die nötigen
139:                  * Fähigkeiten besitzen und Mitarbeiter, die diese Maschinen bedienen können und verfügbar sind und
140:                  * entsprechende Belegungseinträge zu erstellen.
141:                  *
142:                  * @param auftrag
143:                  *                 ProduktionsAuftrag der Maschinen und Mitarbeitern zugeordnet werden soll.
144:                  *
145:                  * @return gibt zurück, ob der ProduktionsAuftrag zugeordnet werden konnte oder nicht.
146:                  */
147:                 private boolean zuordnen(final ProduktionsAuftrag auftrag) {
148:
149:                         final Map<MaschinenFaehigkeit, Collection<Maschine>> qualifizierteMaschinen =
150:                                         InternalProduktionsplaner.getQualifizierteMaschinenProBenoetigteFaehigkeit(this.maschinen, auftrag);
151:
152:                         // wurdeAllesZugeordnet ist true, wenn zu allen Fähigkeiten des Auftrags passende Maschinen und Mitarbeiter
153:                         // gefunden werden konnten
154:                         final boolean wurdeAllesZugeordnet = qualifizierteMaschinen.entrySet().stream()
155:                                         .sorted(Comparator.comparing(Entry::getKey))
156:                                         .map(qualifizierteMaschinenNachFaehigkeit -> {
157:
158:                                                 try {
159:                                                         final Entry<Pair<Maschine, Mitarbeiter>, LocalDateTime> mitarbeiterMaschineUndFruehesteVerfuegbarkeit =
160:                                                                         this.findeMaschineUndMitarbeiterNachZuordnungsParameter(
161:                                                                                         qualifizierteMaschinenNachFaehigkeit,
162:                                                                                         auftrag);
163:
164:                                                         this.erzeugeAuftragsBelegungsEintraege(
165:                                                                         mitarbeiterMaschineUndFruehesteVerfuegbarkeit,
166:                                                                         auftrag);
167:
168:                                                         return true;
169:
170:                                                 } catch (final KeineVerfuegbarkeitException e) {
171:
172:                                                         return false;
173:                                                 }
174:                                         }).reduce(Boolean.TRUE, Boolean::logicalAnd);
175:
176:                         if (wurdeAllesZugeordnet) {
177:                                 auftrag.getMaschinenBelegungen().forEach(TypMitKalender::addBelegungsEintrag);
178:                                 auftrag.getMenschBelegungen().forEach((key, value) -> key.getFirst().addBelegungsEintrag(value));
179:                         } else {
180:                                 auftrag.clearBelegungsEintraege();
181:                         }
182:                         return wurdeAllesZugeordnet;
183:                 }
184:
185:                 /**
186:                  * Erzeugt für den übergebenen {@link Entry} und {@link ProduktionsAuftrag} die entsprechenden Belegungen im {@link ProduktionsAuftrag}. In
187:                  * den Maschinen- und Mitarbeiter-Kalendern wird nichts eingetragen.
188:                  *
189:                  * @param mitarbeiterMaschineUndFruehesteVerfuegbarkeit
190:                  *                 {@link Entry} bestehend aus {@link Maschine}, {@link Mitarbeiter} und deren gemeinsamer frühester Verfügbarkeit
191:                  * @param auftrag
192:                  *                 {@link ProduktionsAuftrag} für den Belegungen erzeugt werden
193:                  */
194:                 private void erzeugeAuftragsBelegungsEintraege(
195:                                 final Entry<Pair<Maschine, Mitarbeiter>, LocalDateTime> mitarbeiterMaschineUndFruehesteVerfuegbarkeit,
196:                                 final ProduktionsAuftrag auftrag) {
197:
198:                         final Maschine maschineFuerAuftrag = mitarbeiterMaschineUndFruehesteVerfuegbarkeit.getKey().getFirst();
199:                         final Mitarbeiter mitarbeiterFuerAuftrag =
200:                                         mitarbeiterMaschineUndFruehesteVerfuegbarkeit.getKey().getSecond();
201:                         final LocalDateTime arbeitsbeginn = mitarbeiterMaschineUndFruehesteVerfuegbarkeit.getValue();
202:                         final ComparableQuantity<Time> benoetigteZeit = maschineFuerAuftrag.berechneBenoetigteZeitInklusiveBeilagen(auftrag, arbeitsbeginn);
203:
204:                         final BegrenzteBeilagenArten zeitbezogeneBeilagenArtenKonfiguration = maschineFuerAuftrag.getLetztenBelegungseintragVorZeitpunkt(arbeitsbeginn)
205:                                         .map(MaschinenBelegungEintrag::getBeilagenKonfiguration)
206:                                         .map(BegrenzteBeilagenArten::copy)
207:                                         .orElseGet(() -> maschineFuerAuftrag.getFaehigkeit().accept(new FaehigkeitVisitor<BegrenzteBeilagenArten>() {
208:                                                 @Override
209:                                                 public BegrenzteBeilagenArten handle(final Drucken drucken) {
210:                                                         return BegrenzteBeilagenArten.EMPTY;
211:                                                 }
212:
213:                                                 @Override
214:                                                 public BegrenzteBeilagenArten handle(final Kuvertieren kuvertieren) {
215:                                                         return new BegrenzteBeilagenArten(new HashSet<>(), kuvertieren.getAnzahlMoeglicherBeilagen());
216:                                                 }
217:
218:                                                 @Override
219:                                                 public BegrenzteBeilagenArten handle(final SimplesDrucken simplesDrucken) {
220:                                                         //darf nicht auftreten
221:                                                         return null;
222:                                                 }
223:
224:                                                 @Override
225:                                                 public BegrenzteBeilagenArten handle(final SimplesKuvertieren simplesKuvertieren) {
226:                                                         //darf nicht auftreten
227:                                                         return null;
228:                                                 }
229:                                         }));
230:
231:                         //an den zeitbezogenen Konfiguration die benötigten umrüstarbeiten anstellen
232:                         if (!zeitbezogeneBeilagenArtenKonfiguration.isNotEditable()) {
233:                                 zeitbezogeneBeilagenArtenKonfiguration.manageNecessaryChangesToFitBeilagenArten(auftrag);
234:                         }
235:
236:                         final MaschinenBelegungEintrag maschinenBelegungEintrag = MaschinenBelegungEintrag
237:                                         .create(arbeitsbeginn, benoetigteZeit, auftrag, zeitbezogeneBeilagenArtenKonfiguration);
238:                         auftrag.addMaschinenBelegungsEintrag(maschineFuerAuftrag, maschinenBelegungEintrag);
239:                         final MenschBelegungEintrag menschBelegungEintrag =
240:                                         MenschBelegungEintrag.create(arbeitsbeginn, benoetigteZeit, auftrag, maschineFuerAuftrag);
241:                         auftrag.addMenschBelegungsEintrag(
242:                                         mitarbeiterFuerAuftrag,
243:                                         maschineFuerAuftrag.getFaehigkeit(),
244:                                         menschBelegungEintrag);
245:                 }
246:
247:                 /**
248:                  * Findet die Kombination aus {@link Maschine}, {@link Mitarbeiter} und dem Zeitpunkt der frühestmöglichen
249:                  * Verfügbarkeit.
250:                  *
251:                  * @param qualifizierteMaschinenNachFaehigkeit
252:                  *                 {@link Entry} bestehend aus einer {@link MaschinenFaehigkeit} und einer {@link List}e von
253:                  *                 {@link Maschine}n, die in der Lage sind, die {@link MaschinenFaehigkeit} zu erfüllen.
254:                  * @param auftrag
255:                  *                 aus dem die {@link MaschinenFaehigkeit} stammt
256:                  *
257:                  * @return {@link Entry} der angibt, wann das erste mal ein {@link Pair} von {@link Maschine} und
258:                  *                 {@link Mitarbeiter} für die {@link MaschinenFaehigkeit} verfügbar ist
259:                  * @throws KeineVerfuegbarkeitException
260:                  *                 sind {@link Maschine} oder {@link Mitarbeiter} nicht verfügbar, wird diese Exception ausgelöst
261:                  */
262:                 private Entry<Pair<Maschine, Mitarbeiter>, LocalDateTime> findeMaschineUndMitarbeiterNachZuordnungsParameter(
263:                                 final Entry<MaschinenFaehigkeit, Collection<Maschine>> qualifizierteMaschinenNachFaehigkeit,
264:                                 final ProduktionsAuftrag auftrag)
265:                                 throws KeineVerfuegbarkeitException {
266:
267:
268:                         final Map<Pair<Maschine, Mitarbeiter>, LocalDateTime> mitarbeiterFuerMaschineMitFruehesterVerfuegbarkeitMap =
269:                                         new LinkedHashMap<>();
270:
271:                         for (final Maschine currentMaschine : qualifizierteMaschinenNachFaehigkeit.getValue()) {
272:                                 try {
273:                                         final Pair<Pair<Maschine, Mitarbeiter>, LocalDateTime> mitarbeiterMaschineUndVerfuegbarkeit =
274:                                                         this.findeMaschineUndMitarbeiter(currentMaschine, auftrag);
275:                                         mitarbeiterFuerMaschineMitFruehesterVerfuegbarkeitMap.put(
276:                                                         mitarbeiterMaschineUndVerfuegbarkeit.getFirst(),
277:                                                         mitarbeiterMaschineUndVerfuegbarkeit.getSecond());
278:                                 } catch (final KeineVerfuegbarkeitException e) {
279:                                         // epmty
280:                                 }
281:                         }
282:                         final ZuordnungsParameter zuordnungsParameter = this.parameter.getZuordnungsParameter();
283:
284:                         switch (zuordnungsParameter) {
285:                                 case FRUEHEST_VERFUEGBARE_MASCHINE:
286:                                         return mitarbeiterFuerMaschineMitFruehesterVerfuegbarkeitMap.entrySet().stream()
287:                                                         .min(Comparator.comparing(Map.Entry::getValue))
288:                                                         .orElseThrow(() -> new KeineVerfuegbarkeitException(""));
289:                                 case GERINGSTE_UMRUESTUNGEN:
290:                                         //TODO theoretisch unterscheiden, ob Kuvertieren oder Drucken --> Druckaufträge können nämlich eigentlich an die nächstbeste Maschine
291:                                         return mitarbeiterFuerMaschineMitFruehesterVerfuegbarkeitMap.entrySet().stream()
292:                                                         .min(Comparator.comparing((Entry<Pair<Maschine, Mitarbeiter>, LocalDateTime> pairLocalDateTimeEntry) ->
293:                                                                         pairLocalDateTimeEntry.getKey().getFirst().calculateUmruestungen(auftrag, pairLocalDateTimeEntry.getValue()))
294:                                                                         .thenComparing(Map.Entry::getValue)
295:                                                         )
296:                                                         .orElseThrow(() -> new KeineVerfuegbarkeitException(""));
297:                                 default:
298:                                         throw new RuntimeException("Es muss ein zuordnungsParameter gesetzt sein!");
299:                         }
300:                 }
301:
302:                 /**
303:                  * Findet für die übergebene {@link Maschine} den am frühesten verfügbaren {@link Mitarbeiter}, der die nötige {@link mensch.Qualifikation} besitzt,
304:                  * sie zu bedienen.
305:                  *
306:                  * @param maschine
307:                  *                 {@link Maschine}, die bedient werden soll
308:                  * @param auftrag
309:                  *                 {@link ProduktionsAuftrag} für den {@link Maschine} und {@link Mitarbeiter} gefunden werden sollen
310:                  *
311:                  * @return {@link Maschine} und {@link Mitarbeiter} und früheste gemeinsame Verfügbarkeit
312:                  * @throws KeineVerfuegbarkeitException
313:                  *                 wird geworfen, wenn kein {@link Mitarbeiter} vor der Frist des {@link auftraege.ServiceLevelAgreement}s des {@link ProduktionsAuftrag}s
314:                  *                 gemeinsam mit der {@link Maschine} ausreichend gleichzeitig verfügbar ist
315:                  */
316:                 private Pair<Pair<Maschine, Mitarbeiter>, LocalDateTime> findeMaschineUndMitarbeiter(
317:                                 final Maschine maschine,
318:                                 final ProduktionsAuftrag auftrag) throws KeineVerfuegbarkeitException {
319:                         final ComparableQuantity<Time> benoetigteZeit = maschine.berechneBenoetigteZeit(auftrag);
320:
321:                         final LocalDateTime start = maschine.getFruehesteVerfuegbarkeit(
322:                                         this.getFruehesteStartZeit(auftrag),
323:                                         benoetigteZeit,
324:                                         auftrag.getSla().getFrist(auftrag.getFruehstenEingangszeitpunkt()));
325:
326:                         final Pair<Mitarbeiter, LocalDateTime> mitarbeiterMitZeitpunkt =
327:                                         maschine.getAmFruehestenVerfuegbarenQualifiziertenMitarbeiter(
328:                                                         this.mitarbeiter,
329:                                                         start,
330:                                                         benoetigteZeit,
331:                                                         auftrag.getSla().getFrist(auftrag.getFruehstenEingangszeitpunkt()));
332:
333:                         return Pair.create(
334:                                         Pair.create(maschine, mitarbeiterMitZeitpunkt.getFirst()),
335:                                         mitarbeiterMitZeitpunkt.getSecond());
336:                 }
337:
338:                 /**
339:                  * Findet den frühesten Zeitpunkt heraus, ab welchem versucht werden kann, den Produktionsauftrag zuzuordnen.
340:                  *
341:                  * @param auftrag
342:                  *                 auftrag, dessen eventuelle bereits existierende Belegungen berücksichtigt werden sollen.
343:                  *
344:                  * @return frühesten Zeitpunkt, ab welchem der Produktionsauftrag bearbeitet werden kann. Ist dieser auftrag noch nirgends eingeplant, so wird
345:                  *                 die per Parameter gesetzte Startzeit zurückgegeben.
346:                  */
347:                 private LocalDateTime getFruehesteStartZeit(final ProduktionsAuftrag auftrag) {
348:                         return auftrag.getMaschinenBelegungen().values().stream()
349:                                         .map(KalenderEintrag::getBis)
350:                                         .max(Comparator.comparing(e -> e))
351:                                         .orElseGet(this.parameter::getStartZeit);
352:                 }
353:
354:                 /**
355:                  * Ermittelt eine {@link Map}, die für jede benötigte {@link MaschinenFaehigkeit} des {@link ProduktionsAuftrag}s eine
356:                  * {@link List}e von {@link Maschine}n enthält, in der jede Maschine alle nötigen {@link MaschinenFaehigkeit}en bzw.
357:                  * Dokumentenklassenvariablen erfüllt.
358:                  *
359:                  * @param evtlQualifizierteMaschinen
360:                  *                 Liste von Maschinen, die durchsucht wird
361:                  * @param auftrag
362:                  *                 ProduktionsAuftrag, der zugeordnet wird
363:                  *
364:                  * @return Map von {@link MaschinenFaehigkeit} auf Liste von {@link Maschine}n, welche die Anforderungen erfüllen. Die
365:                  *                 Key-Value-Paare zeigen an, für welche MaschinenFaehigkeit welche Maschinen geeignet sind.
366:                  */
367:                 private static Map<MaschinenFaehigkeit, Collection<Maschine>> getQualifizierteMaschinenProBenoetigteFaehigkeit(
368:                                 final Collection<Maschine> evtlQualifizierteMaschinen,
369:                                 final ProduktionsAuftrag auftrag) {
370:                         final Map<MaschinenFaehigkeit, ClassObjectMap<DokumentenklassenVariable>> maschinenRelevanteFaehigkeiten =
371:                                         auftrag.getMaschinenRelevanteFaehigkeiten();
372:
373:                         return maschinenRelevanteFaehigkeiten.entrySet().stream().map(entry -> {
374:                                 final ClassObjectMap<DokumentenklassenVariable> zuErfuellendeEigenschaften = entry.getValue();
375:                                 return Pair.create(
376:                                                 entry.getKey(),
377:                                                 evtlQualifizierteMaschinen.stream()
378:                                                                 .filter(maschine -> maschine.erfuellt(zuErfuellendeEigenschaften))
379:                                                                 .collect(Collectors.toList()));
380:                         }).collect(Collectors.toMap(Pair::getFirst, Pair::getSecond));
381:                 }
382:
383:                 /**
384:                  * Erzeugt aus den Einträgen im {@link zeit.MitarbeiterKalender} eine {@link Map} von {@link Mitarbeiter}n auf ihre Belegungen im Format wie sie
385:                  * für {@link ErmittelteBelegungen} gebraucht werden.
386:                  *
387:                  * @param mitarbeiterListe
388:                  *                 {@link List} von {@link Mitarbeiter}n für die die Belegung generiert wird
389:                  *
390:                  * @return {@link Map} von {@link Mitarbeiter}n auf ihre Belegungen
391:                  */
392:                 private Map<Mitarbeiter, MitarbeiterBelegung> getMitarbeiterBelegungen(final List<Mitarbeiter> mitarbeiterListe) {
393:                         return mitarbeiterListe.stream().collect(Collectors.toMap(e -> e, e -> new MitarbeiterBelegung(e.getBelegungen())));
394:                 }
395:
396:                 /**
397:                  * Erzeugt aus den Einträgen im {@link zeit.MaschinenKalender} eine {@link Map} von {@link Maschine}n auf ihre Belegungen im Format wie sie für
398:                  * {@link ErmittelteBelegungen} gebraucht werden.
399:                  *
400:                  * @param maschinenListe
401:                  *                 {@link List} von {@link Maschine}n für die die Belegung generiert wird
402:                  *
403:                  * @return {@link Map} von {@link Maschine}n auf ihre Belegungen
404:                  */
405:                 private Map<Maschine, MaschinenBelegung> getMaschinenBelegungen(final List<Maschine> maschinenListe) {
406:                         return maschinenListe.stream().collect(Collectors.toMap(e -> e, e -> new MaschinenBelegung(e.getBelegungen())));
407:                 }
408:
409:                 /**
410:                  * Sortiert ProduktionsAuftraege, Maschinen und Mitarbeiter nach den gegebenen Parametern und führt dann die Maschinen-Rollen-Belegung für die
411:                  * übergebenen Produktionsauftraege durch. Die Einträge in den Kalendern der Maschinen und Mitarbeiter werden nach Ermittlung der Belegungen
412:                  * wieder gelöscht.
413:                  *
414:                  * @param produktionsAuftraege
415:                  *                 die Maschinen und Mitarbeitern zugeordnet werden
416:                  *
417:                  * @return die vom Algorithmus ermittelten Belegungen
418:                  */
419:                 public ErmittelteBelegungen planAberErzeugeKeineKalendereintraege(final List<ProduktionsAuftrag> produktionsAuftraege) {
420:                         final ErmittelteBelegungen ermittelteBelegungen = this.plan(produktionsAuftraege);
421:                         this.loescheUngueltigeBelegungen(produktionsAuftraege);
422:                         return ermittelteBelegungen;
423:                 }
424:
425:                 /**
426:                  * Löscht die {@link zeit.eintraege.BelegungsEintrag Belegungseinträge} der übergebenen {@link ProduktionsAuftrag Produktionsaufträge} in den zugehörigen
427:                  * {@link zeit.MaschinenKalender}n und {@link zeit.MitarbeiterKalender}n und in den {@link ProduktionsAuftrag}en.
428:                  *
429:                  * @param produktionsAuftraege
430:                  *                 {@link ProduktionsAuftrag Produktionsaufträge} zu denen die Belegungen gelöscht werden.
431:                  */
432:                 private void loescheUngueltigeBelegungen(final List<ProduktionsAuftrag> produktionsAuftraege) {
433:                         produktionsAuftraege.forEach(p -> {
434:                                 p.getMaschinenBelegungen().forEach(Maschine::removeBelegungsEintrag);
435:                                 p.getMenschBelegungen().forEach((key, value) -> key.getFirst().removeBelegungsEintrag(value));
436:                                 p.clearBelegungsEintraege();
437:                         });
438:                 }
439:
440:         }
441: }