Passed
Push — master ( bc2940...3ad1e4 )
by Alessandro
06:51
created

prepareDecisionVariable(Decision)   B

Complexity

Conditions 6

Size

Total Lines 57
Code Lines 36

Duplication

Lines 22
Ratio 38.6 %

Importance

Changes 0
Metric Value
cc 6
eloc 36
c 0
b 0
f 0
dl 22
loc 57
rs 8.0826

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
package it.cnr.istc.pst.platinum.ai.framework.domain.component.pdb;
2
3
import java.util.ArrayList;
4
import java.util.HashMap;
5
import java.util.HashSet;
6
import java.util.List;
7
import java.util.Map;
8
import java.util.Set;
9
10
import it.cnr.istc.pst.platinum.ai.deliberative.solver.Operator;
11
import it.cnr.istc.pst.platinum.ai.framework.domain.DomainComponentBuilder;
12
import it.cnr.istc.pst.platinum.ai.framework.domain.component.ComponentValue;
13
import it.cnr.istc.pst.platinum.ai.framework.domain.component.Decision;
14
import it.cnr.istc.pst.platinum.ai.framework.domain.component.DomainComponent;
15
import it.cnr.istc.pst.platinum.ai.framework.domain.component.DomainComponentType;
16
import it.cnr.istc.pst.platinum.ai.framework.domain.component.PlanDataBase;
17
import it.cnr.istc.pst.platinum.ai.framework.domain.component.Predicate;
18
import it.cnr.istc.pst.platinum.ai.framework.domain.component.ex.DecisionPropagationException;
19
import it.cnr.istc.pst.platinum.ai.framework.domain.component.ex.FlawSolutionApplicationException;
20
import it.cnr.istc.pst.platinum.ai.framework.domain.component.ex.RelationPropagationException;
21
import it.cnr.istc.pst.platinum.ai.framework.domain.knowledge.DomainKnowledge;
22
import it.cnr.istc.pst.platinum.ai.framework.domain.knowledge.DomainKnowledgeType;
23
import it.cnr.istc.pst.platinum.ai.framework.microkernel.ConstraintCategory;
24
import it.cnr.istc.pst.platinum.ai.framework.microkernel.annotation.cfg.framework.DomainComponentConfiguration;
25
import it.cnr.istc.pst.platinum.ai.framework.microkernel.annotation.cfg.framework.DomainKnowledgeConfiguration;
26
import it.cnr.istc.pst.platinum.ai.framework.microkernel.annotation.cfg.framework.ParameterFacadeConfiguration;
27
import it.cnr.istc.pst.platinum.ai.framework.microkernel.annotation.cfg.framework.TemporalFacadeConfiguration;
28
import it.cnr.istc.pst.platinum.ai.framework.microkernel.annotation.inject.framework.DomainKnowledgePlaceholder;
29
import it.cnr.istc.pst.platinum.ai.framework.microkernel.annotation.lifecycle.PostConstruct;
30
import it.cnr.istc.pst.platinum.ai.framework.microkernel.lang.ex.ConsistencyCheckException;
31
import it.cnr.istc.pst.platinum.ai.framework.microkernel.lang.ex.DomainComponentNotFoundException;
32
import it.cnr.istc.pst.platinum.ai.framework.microkernel.lang.ex.OperatorPropagationException;
33
import it.cnr.istc.pst.platinum.ai.framework.microkernel.lang.ex.ProblemInitializationException;
34
import it.cnr.istc.pst.platinum.ai.framework.microkernel.lang.ex.SynchronizationCycleException;
35
import it.cnr.istc.pst.platinum.ai.framework.microkernel.lang.flaw.Flaw;
36
import it.cnr.istc.pst.platinum.ai.framework.microkernel.lang.flaw.FlawSolution;
37
import it.cnr.istc.pst.platinum.ai.framework.microkernel.lang.flaw.FlawType;
38
import it.cnr.istc.pst.platinum.ai.framework.microkernel.lang.plan.Plan;
39
import it.cnr.istc.pst.platinum.ai.framework.microkernel.lang.plan.SolutionPlan;
40
import it.cnr.istc.pst.platinum.ai.framework.microkernel.lang.problem.ParameterProblemConstraint;
41
import it.cnr.istc.pst.platinum.ai.framework.microkernel.lang.problem.Problem;
42
import it.cnr.istc.pst.platinum.ai.framework.microkernel.lang.problem.ProblemConstraint;
43
import it.cnr.istc.pst.platinum.ai.framework.microkernel.lang.problem.ProblemFact;
44
import it.cnr.istc.pst.platinum.ai.framework.microkernel.lang.problem.ProblemFluent;
45
import it.cnr.istc.pst.platinum.ai.framework.microkernel.lang.problem.ProblemGoal;
46
import it.cnr.istc.pst.platinum.ai.framework.microkernel.lang.problem.TemporalProblemConstraint;
47
import it.cnr.istc.pst.platinum.ai.framework.microkernel.lang.relations.Relation;
48
import it.cnr.istc.pst.platinum.ai.framework.microkernel.lang.relations.RelationType;
49
import it.cnr.istc.pst.platinum.ai.framework.microkernel.lang.relations.parameter.BindParameterRelation;
50
import it.cnr.istc.pst.platinum.ai.framework.microkernel.lang.relations.parameter.EqualParameterRelation;
51
import it.cnr.istc.pst.platinum.ai.framework.microkernel.lang.relations.parameter.NotEqualParameterRelation;
52
import it.cnr.istc.pst.platinum.ai.framework.microkernel.lang.relations.parameter.ParameterRelation;
53
import it.cnr.istc.pst.platinum.ai.framework.microkernel.lang.relations.temporal.TemporalRelation;
54
import it.cnr.istc.pst.platinum.ai.framework.microkernel.query.ParameterQueryType;
55
import it.cnr.istc.pst.platinum.ai.framework.microkernel.query.TemporalQueryType;
56
import it.cnr.istc.pst.platinum.ai.framework.microkernel.resolver.ex.UnsolvableFlawException;
57
import it.cnr.istc.pst.platinum.ai.framework.parameter.csp.solver.ParameterSolverType;
58
import it.cnr.istc.pst.platinum.ai.framework.parameter.lang.EnumerationParameter;
59
import it.cnr.istc.pst.platinum.ai.framework.parameter.lang.NumericParameter;
60
import it.cnr.istc.pst.platinum.ai.framework.parameter.lang.Parameter;
61
import it.cnr.istc.pst.platinum.ai.framework.parameter.lang.ParameterDomain;
62
import it.cnr.istc.pst.platinum.ai.framework.parameter.lang.ParameterDomainType;
63
import it.cnr.istc.pst.platinum.ai.framework.parameter.lang.query.CheckValuesParameterQuery;
64
import it.cnr.istc.pst.platinum.ai.framework.parameter.lang.query.ComputeSolutionParameterQuery;
65
import it.cnr.istc.pst.platinum.ai.framework.time.TemporalInterval;
66
import it.cnr.istc.pst.platinum.ai.framework.time.lang.query.IntervalScheduleQuery;
67
import it.cnr.istc.pst.platinum.ai.framework.time.solver.TemporalSolverType;
68
import it.cnr.istc.pst.platinum.ai.framework.time.tn.TemporalNetworkType;
69
70
/**
71
 * 
72
 * @author anacleto
73
 *
74
 */
75
@DomainKnowledgeConfiguration(
76
		
77
		// set domain knowledge
78
		knowledge = DomainKnowledgeType.STATIC
79
)
80
@TemporalFacadeConfiguration(
81
		
82
		// set temporal network 
83
		network = TemporalNetworkType.STNU, 
84
		
85
		// set planner solver
86
		solver = TemporalSolverType.APSP
87
)
88
@ParameterFacadeConfiguration(
89
		
90
		// set parameter reasoner
91
		solver = ParameterSolverType.CHOCHO_SOLVER
92
)
93
public final class PlanDataBaseComponent extends DomainComponent implements PlanDataBase
0 ignored issues
show
Bug introduced by
Override the "equals" method in this class.
Loading history...
94
{
95
	@DomainKnowledgePlaceholder
96
	protected DomainKnowledge knowledge;
97
	
98
	// see Composite design pattern
99
	private Map<String, DomainComponent> components;
100
	
101
	// the planning problem
102
	protected Problem problem;
103
	
104
	// domain theory
105
	private Map<String, ParameterDomain> parameterDomains;
106
		
107
	/**
108
	 * 
109
	 * @param name
110
	 */
111
	
112
	@DomainComponentConfiguration(resolvers = {
113
			// no resolver is needed
114
	})
115
	protected PlanDataBaseComponent(String name) 
116
	{
117
		super(name, DomainComponentType.PLAN_DATABASE);
118
		// initialize data structures
119
		this.components = new HashMap<>();
120
		this.parameterDomains = new HashMap<>();
121
		this.problem = null;
122
	}
123
	
124
	/**
125
	 * 
126
	 */
127
	@PostConstruct
128
	protected synchronized void init() {
129
		super.init();
130
		
131
		// clear static (global) information
132
		synchronized (rules) {
133
			// clear if needed global synchronization rules
134
			rules.clear();
135
		}
136
		
137
		synchronized(globalRelations) {
138
			// clear if needed global relations
139
			globalRelations.clear();
140
		}
141
	
142
		// reset predicate counter
143
		PREDICATE_COUNTER.set(0);
144
		// reset decision counter
145
		DecisionIdCounter.set(0);
146
		// reset relation counter
147
		RELATION_COUNTER.set(0);
148
	}
149
	
150
	/**
151
	 * 
152
	 */
153
	@Override
154
	public synchronized void setup(Problem problem) 
155
			throws ProblemInitializationException {
156
		// setup problem
157
		this.doSetupProblem(problem);
158
	}
159
	
160
	/**
161
	 * 
162
	 */
163
	@Override
164
	public synchronized void clear() 
165
	{
166
		// clear components
167
		for (DomainComponent component : this.components.values()) {
168
			// clear component
169
			component.clear();
170
		}
171
172
		// clear local relations
173
		this.localRelations.clear();
174
		// clear global relations
175
		synchronized (globalRelations) {
176
			// clear global active relations
177
			for (Relation rel : globalRelations) {
178
				// delete global relation
179
				this.deactivate(rel);
180
			}
181
			
182
			// clear global relations
183
			globalRelations.clear();
184
		}
185
		// clear problem
186
		this.problem = null;
187
		// clear domain knowledge
188
		this.knowledge = null;
189
	}
190
	
191
	/**
192
	 * 
193
	 */
194
	@Override
195
	public synchronized DomainKnowledge getDomainKnowledge() {
196
		return this.knowledge;
197
	}
198
	
199
	/*
200
	 * 
201
	 */
202
	@Override
203
	public synchronized void addSynchronizationRule(SynchronizationRule rule) 
204
			throws SynchronizationCycleException
205
	{
206
		// get head value
207
		ComponentValue value = rule.getTriggerer().getValue();
208
		// set the trigger as complex
209
		value.setComplex();
210
				
211
		// check data
212
		if (!rules.containsKey(value.getComponent())) {
213
			rules.put(value.getComponent(), new HashMap<ComponentValue, List<SynchronizationRule>>());
214
		}
215
		if (!rules.get(value.getComponent()).containsKey(value)) {
216
			// initialize
217
			rules.get(value.getComponent()).put(value, new ArrayList<SynchronizationRule>());
218
		}
219
		
220
		// look for cycles
221
		for (TokenVariable var : rule.getTokenVariables()) 
222
		{
223
			// get value 
224
			ComponentValue v = var.getValue();
225
			// check if this value is trigger of other synchronizations
226
			if (rules.containsKey(v.getComponent()) && rules.get(v.getComponent()).containsKey(v)) {
227
				// get synchronizations
228
				List<SynchronizationRule> existingRules = rules.get(v.getComponent()).get(v);
229
				for (SynchronizationRule existingRule : existingRules) {
230
					// get rule trigger
231
					TokenVariable existingRuleTrigger = existingRule.getTriggerer();
232
					// check constraint
233
					for (SynchronizationConstraint cons : existingRule.getConstraints()) {
234
						// consider temporal constraint for cycle detection
235
						if (cons.getCategory().equals(ConstraintCategory.TEMPORAL_CONSTRAINT)) {
236
							// get constraint target
237
							TokenVariable target = cons.getTarget();
238
							if (!target.equals(existingRuleTrigger) && target.getValue().equals(value)) { 
239
								// we've got a cycle
240
								throw new SynchronizationCycleException("A cycle has been detected after the introduction of synchronization rule " + rule);
241
							}
242
						}
243
					}
244
				}
245
			}
246
		}
247
		
248
		// add rule if no cycle is detected
249
		rules.get(value.getComponent()).get(value).add(rule);
250
	}
251
	
252
	/**
253
	 * 
254
	 * @param value
255
	 * @return
256
	 */
257
	@Override
258
	public synchronized SynchronizationRule createSynchronizationRule(ComponentValue value, String[] labels) 
259
			throws DomainComponentNotFoundException 
260
	{
261
		// check if related component exists
262
		if (!this.getComponents().contains(value.getComponent())) {
263
			throw new DomainComponentNotFoundException("Value's component not found " + value);
264
		}
265
		
266
		// set value as complex
267
		value.setComplex();
268
		// create synchronization rule
269
		return new SynchronizationRule(value, labels);
270
	}
271
	
272
	/**
273
	 * 
274
	 */
275
	@Override
276
	public synchronized SolutionPlan getSolutionPlan() 
277
	{
278
		// create a plan
279
		SolutionPlan plan = new SolutionPlan(this.name, this.getHorizon());
280
		// set components
281
		for (DomainComponent component : this.components.values()) {
282
			// add a component to the plan
283
			plan.add(component);
284
		}
285
		
286
		// add active relations
287
		for (Relation rel : this.getActiveRelations()) {
288
			// add relation
289
			plan.add(rel);
290
		}
291
		
292
		// computer parameter solutions
293
		ComputeSolutionParameterQuery query = this.pdb.
294
				createQuery(ParameterQueryType.COMPUTE_SOLUTION);
295
		
296
		// process query
297
		this.pdb.process(query);
298
		// get current plan
299
		return plan;
300
	}
301
	
302
	/**
303
	 * Compute the duration of a plan as the minimum and maximal average duration of the activities
304
	 * of its components 
305
	 */
306 View Code Duplication
	@Override
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
307
	public synchronized double[] getMakespan() 
308
	{
309
		// set the initial minimal and maximal values
310
		double[] makespan = new double[] {
311
				0,
312
				0
313
			};
314
		
315
		
316
		// get the list of primitive components
317
		Set<DomainComponent> primset = new HashSet<>();
318
		// compute "local" makespan for each component
319
		for (DomainComponent comp : this.components.values()) 
320
		{
321
			// check type 
322
			if (comp.getType().equals(DomainComponentType.SV_PRIMITIVE)) 
323
			{
324
				// get local makespan
325
				double[] local = comp.getMakespan();
326
				// update "global" minimum makespan
327
				makespan[0] += local[0];
328
				// update "global" maximum makespan
329
				makespan[1] += local[1];
330
				// add component to primset
331
				primset.add(comp);
332
			}
333
		}
334
		
335
		// compute average values
336
		makespan[0] = makespan[0] / primset.size();
337
		makespan[1] = makespan[1] / primset.size();
338
		// get the makespan
339
		return makespan;
340
	}
341
	
342
	/**
343
	 * 
344
	 */
345 View Code Duplication
	@Override
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
346
	public synchronized double[] getBehaviorDuration() 
347
	{
348
		// set the initial minimal and maximal values
349
		double[] duration = new double[] {
350
				0,
351
				0
352
			};
353
		
354
		
355
		// get the list of primitive components
356
		Set<DomainComponent> primset = new HashSet<>();
357
		// compute "local" makespan for each component
358
		for (DomainComponent comp : this.components.values()) 
359
		{
360
			// check type 
361
			if (comp.getType().equals(DomainComponentType.SV_PRIMITIVE)) 
362
			{
363
				// get local makespan
364
				double[] local = comp.getBehaviorDuration();
365
				// update "global" minimum makespan
366
				duration[0] += local[0];
367
				// update "global" maximum makespan
368
				duration[1] += local[1];
369
				// add component to primset
370
				primset.add(comp);
371
			}
372
		}
373
		
374
		// compute average values
375
		duration[0] = duration[0] / primset.size();
376
		duration[1] = duration[1] / primset.size();
377
		// get the duration
378
		return duration;
379
	}
380
	
381
	/**
382
	 * 
383
	 * @param decision
384
	 * @return
385
	 */
386
	private DecisionVariable prepareDecisionVariable(Decision decision) 
387
	{
388
		// get predicate
389
		Predicate predicate = decision.getToken().getPredicate();
390
		// prepare ground predicate
391
		String groundPredicate = predicate.getValue().getLabel();
392
		// check parameters
393
		for (Parameter<?> param : predicate.getParameters()) 
394
		{
395
			// query the plan database to retrieve values
396
			CheckValuesParameterQuery query = this.pdb.createQuery(ParameterQueryType.CHECK_PARAMETER_VALUES);
397
			query.setParameter(param);
398
			this.pdb.process(query);
399
			
400
			String val = "";
401
			// check parameter type
402 View Code Duplication
			switch (param.getType()) 
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
403
			{
404
				case ENUMERATION_PARAMETER_TYPE : 
405
				{
406
					EnumerationParameter ep = (EnumerationParameter) param;
407
					// check bounded values
408
					for (int index = 0; index < ep.getValues().length; index++) {
409
						if (index > 0) {
410
							val += "_";
0 ignored issues
show
Performance introduced by
String concatenation with + is inefficient. Doing so in a loop may incur a significant performance penalty. Consider using a StringBuilder instead
Loading history...
411
						}
412
						
413
						val += ep.getValues()[index];
0 ignored issues
show
Performance introduced by
String concatenation with + is inefficient. Doing so in a loop may incur a significant performance penalty. Consider using a StringBuilder instead
Loading history...
414
					}
415
				}
416
				break;
417
				
418
				case NUMERIC_PARAMETER_TYPE : 
419
				{
420
					NumericParameter np = (NumericParameter) param;
421
					val += np.getLowerBound() + "_" + np.getUpperBound();
422
				}
423
				break;
424
			}
425
			
426
			// update grounded predicate
427
			groundPredicate += "-" + val;
0 ignored issues
show
Performance introduced by
String concatenation with + is inefficient. Doing so in a loop may incur a significant performance penalty. Consider using a StringBuilder instead
Loading history...
428
		}
429
		
430
		IntervalScheduleQuery query = this.tdb.createTemporalQuery(TemporalQueryType.INTERVAL_SCHEDULE);
431
		query.setInterval(decision.getToken().getInterval());
432
		this.tdb.process(query);
433
		TemporalInterval i = query.getInterval();
434
		
435
		// add decision variable to plan description
436
		return new DecisionVariable(
437
				decision.getId(), 
438
				decision.getComponent().getName(), 
439
				groundPredicate, 
440
				new long[] {i.getStartTime().getLowerBound(), i.getStartTime().getUpperBound()}, 
441
				new long[] {i.getEndTime().getLowerBound(), i.getEndTime().getUpperBound()}, 
442
				new long[] {i.getDurationLowerBound(), i.getDurationUpperBound()});
443
	}
444
	
445
	/**
446
	 * 
447
	 * @return
448
	 */
449
	@Override
450
	public synchronized Plan getPlan() 
451
	{
452
		// initialize the plan
453
		Plan plan = new Plan();
454
		// set decisions
455
		for (Decision decision : this.getActiveDecisions())  
456
		{
457
			// add decision variable to plan description
458
			plan.add(decision.getComponent(), this.prepareDecisionVariable(decision));
459
//			plan.add(goal);
460
		}
461
		
462
		// set relations
463
		for (Relation rel : this.getActiveRelations()) {
464
			plan.add(rel);
465
		}
466
		
467
		// get the plan
468
		return plan;
469
	}
470
471
	
472
	/**
473
	 * 
474
	 */
475
//	@Override
476
//	public synchronized Plan getPlan(PlanElementStatus status) 
477
//	{
478
//		// prepare the plan
479
//		Plan plan = new Plan();
480
//		// check desired level
481
//		switch (status) 
482
//		{
483
//			// get the plan
484
//			case ACTIVE : {
485
//				// get currently active plan
486
//				plan = this.getPlan();
487
//			}
488
//			break;
489
//			
490
//			// get the pending plan
491
//			case PENDING : {
492
//				// get pending decisions
493
//				for (Decision decision : this.getPendingDecisions()) {
494
//					plan.add(decision);
495
//				}
496
//				// get pending relations
497
//				for (Relation rel : this.getPendingRelations()) {
498
//					plan.add(rel);
499
//				}
500
//			}
501
//			break;
502
//			
503
//			// get silent plan
504
//			case SILENT : {
505
//				// get silent decisions
506
//				for (Decision decision : this.getSilentDecisions()) {
507
//					plan.add(decision);
508
//				}
509
//				// get silent relations
510
//				for (Relation rel : this.getSilentRelations()) {
511
//					plan.add(rel);
512
//				}
513
//			}
514
//			break;
515
//		}
516
//		
517
//		return plan;
518
//	}
519
	
520
	/**
521
	 * 
522
	 */
523
	@Override
524
	public synchronized List<DomainComponent> getComponents() {
525
		return new ArrayList<>(this.components.values());
526
	}
527
	
528
	/**
529
	 * 
530
	 */
531
	@Override
532
	public synchronized DomainComponent getComponentByName(String name) {
533
		if (!this.components.containsKey(name)) {
534
			throw new RuntimeException("Component with name " + name + " does not exist");
0 ignored issues
show
Best Practice introduced by
Dedicated exceptions should be preferred over throwing the generic Exception.
Loading history...
535
		}
536
		// get component
537
		return this.components.get(name);
538
	}
539
	
540
	/**
541
	 * Verify the temporal consistency of the plan.
542
	 * 
543
	 * If the underlying network is an STNU, then the 
544
	 * procedure checks also the pseudo-controllability
545
	 * of the plan. If the network is not pseudo-controllable
546
	 * the exception reports information concerning the values
547
	 * that have been "squeezed" during the solving process 
548
	 * 
549
	 * @throws ConsistencyCheckException
550
	 */
551
	@Override
552
	public synchronized void verify() 
553
			throws ConsistencyCheckException 
554
	{
555
		// check temporal consistency of the network
556
		this.tdb.verify();
557
		// check parameter consistency
558
		this.pdb.verify();
559
	}
560
561
	/**
562
	 * The method returns the list of all available domain values
563
	 */
564
	@Override
565
	public synchronized List<ComponentValue> getValues() {
566
		List<ComponentValue> values = new ArrayList<>();
567
		for (DomainComponent component : this.components.values()) {
568
			values.addAll(component.getValues());
569
		}
570
		// get all domain values
571
		return values;
572
	}
573
	
574
	/**
575
	 * 
576
	 */
577
	@Override
578
	public synchronized ComponentValue getValueByName(String name) {
579
		ComponentValue value = null;
580
		for (DomainComponent comp : this.components.values()) {
581
			for (ComponentValue v : comp.getValues()) {
582
				if (v.getLabel().equals(name)) {
583
					value = v;
584
					break;
585
				}
586
			}
587
			
588
			if (value != null) {
589
				break;
590
			}
591
		}
592
		
593
		// check if value has been found
594
		if (value == null) {
595
			throw new RuntimeException("Value " + name + " not found");
0 ignored issues
show
Best Practice introduced by
Dedicated exceptions should be preferred over throwing the generic Exception.
Loading history...
596
		}
597
		
598
		// get value
599
		return value;
600
	}
601
	
602
	/**
603
	 * 
604
	 * @param name
605
	 * @param type
606
	 */
607
	@Override
608
	public synchronized <T extends ParameterDomain> T createParameterDomain(String name, ParameterDomainType type) {
609
		// create parameter domain
610
		T pd = this.pdb.createParameterDomain(name, type);
611
		// add parameter domain
612
		this.parameterDomains.put(name, pd);
613
		return pd;
614
	}
615
	
616
	/**
617
	 * 
618
	 * @return
619
	 */
620
	@Override
621
	public synchronized List<ParameterDomain> getParameterDoamins() {
622
		return new ArrayList<>(this.parameterDomains.values());
623
	}
624
	
625
	/**
626
	 * 
627
	 * @param name
628
	 * @return
629
	 */
630
	@Override
631
	public synchronized ParameterDomain getParameterDomainByName(String name) {
632
		return this.parameterDomains.get(name);
633
	}
634
	
635
	/**
636
	 * 
637
	 * @param name
638
	 * @return
639
	 */
640
	@Override
641
	public synchronized <T extends DomainComponent> T createDomainComponent(String name, DomainComponentType type) 
642
	{
643
		// check if a component already exist
644
		if (this.components.containsKey(name)) {
645
			throw new RuntimeException("A component with name " + name + " already exists");
0 ignored issues
show
Best Practice introduced by
Dedicated exceptions should be preferred over throwing the generic Exception.
Loading history...
646
		}
647
	
648
		// create domain component
649
		T c = DomainComponentBuilder.createAndSet(name, type, this.tdb, this.pdb);
650
		// get created component
651
		return c;
652
	}
653
	
654
	/**
655
	 * 
656
	 * @param component
657
	 */
658
	@Override
659
	public synchronized void addDomainComponent(DomainComponent component) {
660
		// add component
661
		this.components.put(component.getName(), component);
662
	}
663
	
664
	/**
665
	 * 
666
	 * @return
667
	 */
668
	@Override
669
	public synchronized List<Decision> getActiveDecisions() {
670
		// list of active decisions with schedule information
671
		List<Decision> list = new ArrayList<>();
672
		// get schedule information from components
673
		for (DomainComponent comp : this.components.values()) {
674
			list.addAll(comp.getActiveDecisions());
675
		}
676
		// get list
677
		return list;
678
	}
679
	
680
	/**
681
	 * 
682
	 * @return
683
	 */
684
	@Override
685
	public synchronized List<Decision> getPendingDecisions() {
686
		// list of pending decisions
687
		List<Decision> list = new ArrayList<>();
688
		for (DomainComponent comp : this.components.values()) {
689
			list.addAll(comp.getPendingDecisions());
690
		}
691
		// get list of pending decisions
692
		return list;
693
	}
694
	
695
	/**
696
	 * 
697
	 */
698
	@Override
699
	public synchronized Set<Relation> getPendingRelations(Decision dec) 
700
	{
701
		// get decision component 
702
		DomainComponent comp = dec.getComponent();
703
		return comp.getPendingRelations(dec);
704
	}
705
	
706
	/**
707
	 * 
708
	 */
709
	@Override 
710
	public synchronized void restore(Decision dec) {
711
		// dispatch request to the related component
712
		dec.getComponent().restore(dec);
713
	}
714
	
715
	/**
716
	 * 
717
	 */
718
	@Override
719
	public synchronized void restore(Relation rel) {
720
		// get reference component
721
		DomainComponent comp = rel.getReference().getComponent();
722
		comp.restore(rel);
723
	}
724
	
725
	/**
726
	 * 
727
	 */
728
	@Override
729
	public synchronized Decision create(ComponentValue value, String[] labels) {
730
		// get the component the value belongs to
731
		DomainComponent comp = value.getComponent();
732
		// create decision
733
		Decision dec = comp.create(value, labels);
734
		// get created decision
735
		return dec;
736
	}
737
	
738
	/**
739
	 * 
740
	 */
741
	@Override
742
	public synchronized Decision create(ComponentValue value, String[] labels, long[] duration) {
743
		// get the component the value belongs to
744
		DomainComponent comp = value.getComponent();
745
		// create decision
746
		Decision dec = comp.create(value, labels, duration);
747
		// get created decision
748
		return dec;
749
	}
750
	
751
	/**
752
	 * 
753
	 */
754
	@Override
755
	public synchronized Decision create(ComponentValue value, String[] labels, long[] end, long[] duration) {
756
		// get the component the value belongs to
757
		DomainComponent comp = value.getComponent();
758
		// create decision
759
		Decision dec = comp.create(value, labels, end, duration);
760
		// get created decision
761
		return dec;
762
	}
763
	
764
	/**
765
	 * 
766
	 */
767
	@Override
768
	public synchronized Decision create(ComponentValue value, String[] labels, long[] start, long[] end, long[] duration) {
769
		// get the component the value belongs to
770
		DomainComponent comp = value.getComponent();
771
		// create decision
772
		Decision dec = comp.create(value, labels, start, end, duration);
773
		// get created decision
774
		return dec;
775
	}
776
	
777
	/**
778
	 * 
779
	 */
780
	@Override
781
	public synchronized Set<Relation> activate(Decision dec) 
782
			throws DecisionPropagationException 
783
	{
784
		// get the component the decision belongs to
785
		DomainComponent c = dec.getComponent();
786
		// add decision and get the list of local and global relations propagated
787
		Set<Relation> set = c.activate(dec);
788
		// get global and local relations propagated
789
		return set;
790
	}
791
	
792
	/**
793
	 * 
794
	 */
795
	@Override
796
	public synchronized Set<Relation> getRelations(Decision dec) 
797
	{
798
		// list of relations concerning the decision
799
		Set<Relation> set = new HashSet<>();
800
		// get decision component
801
		DomainComponent comp = dec.getComponent();
802
		set.addAll(comp.getRelations(dec));
803
		// get the set
804
		return set;
805
	}
806
	
807
	/**
808
	 * Get the set of both active and pending local and global relations on components
809
	 */
810
	@Override
811
	public synchronized Set<Relation> getRelations() {
812
		// list of relations
813
		Set<Relation> set = new HashSet<>();
814
		for (DomainComponent comp : this.components.values()) {
815
			set.addAll(comp.getRelations());
816
		}
817
		
818
		// add global relations
819
		synchronized (globalRelations) {
820
			for (Relation rel : globalRelations) {
821
				set.add(rel);
822
			}
823
		}
824
		
825
		// get the set
826
		return set;
827
	}
828
	
829
	/**
830
	 * Get the set of local active relations and local active relations on components 
831
	 *  
832
	 * @param dec
833
	 * @return
834
	 */
835
	@Override
836
	public synchronized Set<Relation> getActiveRelations()
837
	{
838
		// list of active relations
839
		Set<Relation> set = new HashSet<>();
840
		// check local relations
841
		for (DomainComponent component : this.components.values()) {
842
			// add active local relations
843
			set.addAll(component.getActiveRelations());
844
		}
845
		
846
		// add global active relations
847
		synchronized (globalRelations) {
848
			for (Relation rel : globalRelations) {
849
				if (rel.isActive()) {
850
					set.add(rel);
851
				}
852
			}
853
		}
854
		// get the list
855
		return set;
856
	}
857
	
858
	/**
859
	 * Get the set of pending global relations and pending local relations on components
860
	 * 
861
	 * @return
862
	 */
863
	public synchronized Set<Relation> getPendingRelations()
864
	{
865
		// set of relations
866
		Set<Relation> set = new HashSet<>();
867
		for (DomainComponent comp : this.components.values()) {
868
			set.addAll(comp.getPendingRelations());
869
		}
870
		
871
		// add pending global relations
872
		synchronized (globalRelations) {
873
			for (Relation rel : globalRelations) {
874
				if (rel.isPending()) {
875
					set.add(rel);
876
				}
877
			}
878
		}
879
		// get the set
880
		return set;
881
	}
882
	
883
	/**
884
	 * 
885
	 */
886
	@Override
887
	public synchronized Set<Relation> getActiveRelations(Decision dec) 
888
	{
889
		// list of active relations
890
		Set<Relation> set = new HashSet<>();
891
		// get decision component
892
		DomainComponent comp = dec.getComponent();
893
		set.addAll(comp.getActiveRelations(dec));
894
		// get the set
895
		return set;
896
	}
897
	
898
	/**
899
	 * 
900
	 */
901
	@Override
902
	public synchronized Set<Relation> getToActivateRelations(Decision dec) 
903
	{
904
		// list of relations
905
		Set<Relation> set = new HashSet<>();
906
		// get decision component
907
		DomainComponent comp = dec.getComponent();
908
		set.addAll(comp.getToActivateRelations(dec));
909
		// get the set
910
		return set;
911
	}
912
	
913
	/**
914
	 * 
915
	 * @param dec
916
	 * @throws Exception
917
	 */
918
	@Override
919
	public synchronized void free(Decision dec) 
920
	{
921
		// get decision component
922
		DomainComponent comp = dec.getComponent();
923
		comp.free(dec);
924
	}
925
	
926
	/**
927
	 * 
928
	 */
929
	@Override
930
	public synchronized Set<Relation> deactivate(Decision dec) {
931
		// get decision component
932
		DomainComponent comp = dec.getComponent();
933
		return new HashSet<>(comp.deactivate(dec));
934
	}
935
	
936
	/**
937
	 * 
938
	 * @param relation
939
	 */
940
	@Override
941
	public synchronized void delete(Relation relation) 
942
	{
943
		// get reference component
944
		DomainComponent refComp = relation.getReference().getComponent();
945
		refComp.delete(relation);
946
	}
947
	
948
	/**
949
	 * Only for debugging
950
	 */
951
	@Override
952
	public synchronized List<Decision> getSilentDecisions() {
953
		List<Decision> list = new ArrayList<>();
954
		for (DomainComponent component : this.components.values()) {
955
			list.addAll(component.getSilentDecisions());
956
		}
957
		return list;
958
	}
959
	
960
	/**
961
	 * Only for debugging
962
	 */
963
	@Override
964
	public synchronized Set<Relation> getSilentRelations() {
965
		// set of relations
966
		Set<Relation> set = new HashSet<>();
967
		for (DomainComponent component : this.components.values()) {
968
			set.addAll(component.getSilentRelations());
969
		}
970
		
971
		// check global relations
972
		synchronized (globalRelations) {
973
			for (Relation rel : globalRelations) {
974
				if (rel.isSilent()) {
975
					set.add(rel);
976
				}
977
			}
978
		}
979
		// get the set
980
		return set;
981
	}
982
	
983
	/**
984
	 * 
985
	 */
986
	@Override
987
	public synchronized boolean isActive(Decision dec) {
988
		return dec.getComponent().isActive(dec);
989
	}
990
	
991
	/**
992
	 * 
993
	 */
994
	@Override
995
	public synchronized boolean isPending(Decision dec) {
996
		// forward to component
997
		return dec.getComponent().isPending(dec);
998
	}
999
	
1000
	/**
1001
	 * 
1002
	 */
1003
	@Override
1004
	public synchronized boolean isSilent(Decision dec) {
1005
		// forward to component
1006
		return dec.getComponent().isSilent(dec);
1007
	}
1008
	
1009
	/**
1010
	 * 
1011
	 */
1012
	@Override
1013
	public synchronized boolean activate(Relation rel) 
1014
			throws RelationPropagationException  {
1015
		
1016
		// get reference component
1017
		DomainComponent refComp = rel.getReference().getComponent();
1018
		return refComp.activate(rel);
1019
	}
1020
	
1021
	/**
1022
	 * 
1023
	 */
1024
	@Override
1025
	public synchronized void deactivate(Relation rel) 
1026
	{
1027
		// get reference component
1028
		DomainComponent refComp = rel.getReference().getComponent();
1029
		refComp.deactivate(rel);
1030
	}
1031
	
1032
	/**
1033
	 * 
1034
	 */
1035
	@Override
1036
	public synchronized List<Flaw> checkFlaws() {
1037
		// list of flaws to solve
1038
		List<Flaw> list = new ArrayList<>();
1039
		// simply query the components
1040
		for (DomainComponent comp : this.components.values()) {
1041
			// query each COMPOSITE component for flaws
1042
			List<Flaw> flaws = comp.checkFlaws();
1043
			list.addAll(flaws);
1044
		}
1045
		// get the list of detected flaws in the domain
1046
		return list;
1047
	}
1048
	
1049
	/**
1050
	 * 
1051
	 */
1052
	@Override
1053
	public synchronized List<Flaw> checkFlaws(FlawType[] types) {
1054
		// list of flaws to solve
1055
		List<Flaw> list = new ArrayList<>();
1056
		// simply query the components
1057
		for (DomainComponent comp : this.components.values()) {
1058
			// query each COMPOSITE component for flaws
1059
			List<Flaw> flaws = comp.checkFlaws(types);
1060
			list.addAll(flaws);
1061
		}
1062
		// get the list of detected flaws in the domain
1063
		return list;
1064
	}
1065
	
1066
	/**
1067
	 * 
1068
	 * @return
1069
	 */
1070
	@Override
1071
	public synchronized List<Flaw> detectFlaws() 
1072
			throws UnsolvableFlawException 
1073
	{
1074
		// list of flaws to solve
1075
		List<Flaw> list = new ArrayList<>();
1076
		// simply query the components
1077
		for (DomainComponent comp : this.components.values()) {
1078
			// query each COMPOSITE component for flaws
1079
			List<Flaw> flaws = comp.detectFlaws();
1080
			list.addAll(flaws);
1081
		}
1082
		// get the list of detected flaws in the domain
1083
		return list;
1084
	}
1085
	
1086
	/**
1087
	 * 
1088
	 * @param type
1089
	 * @return
1090
	 * @throws UnsolvableFlawException
1091
	 */
1092
	@Override
1093
	public synchronized List<Flaw> detectFlaws(FlawType type) 
1094
			throws UnsolvableFlawException {
1095
		
1096
		// list of flaws to solve
1097
		List<Flaw> list = new ArrayList<>();
1098
		// simply query the components
1099
		for (DomainComponent comp : this.components.values()) {
1100
			// get the list of flaws
1101
			List<Flaw> flaws = comp.detectFlaws(type);
1102
			list.addAll(flaws);
1103
		}
1104
		
1105
		// get the list of detected flaws
1106
		return list;
1107
	}
1108
	
1109
	/**
1110
	 * 
1111
	 */
1112
	@Override
1113
	public synchronized void rollback(FlawSolution solution) 
1114
	{ 
1115
		// get component
1116
		DomainComponent comp = solution.getFlaw().getComponent();
1117
		comp.rollback(solution);
1118
	}
1119
	
1120
	/**
1121
	 * Solve a flaw by applying the selected solution. 
1122
	 * 
1123
	 * Commit the effect of a flaw solution to the underlying component
1124
	 * 
1125
	 * @param flaw
1126
	 * @param sol
1127
	 * @throws Exception
1128
	 */
1129
	@Override
1130
	public synchronized void commit(FlawSolution solution) 
1131
			throws FlawSolutionApplicationException 
1132
	{
1133
		// get component
1134
		DomainComponent comp = solution.getFlaw().getComponent();
1135
		comp.commit(solution);
1136
	}
1137
	
1138
	/**
1139
	 * 
1140
	 * @param solution
1141
	 * @throws Exception
1142
	 */
1143
	@Override
1144
	public synchronized void restore(FlawSolution solution) 
1145
			throws Exception
1146
	{
1147
		// get component
1148
		DomainComponent comp = solution.getFlaw().getComponent();
1149
		comp.restore(solution);
1150
	}
1151
	
1152
	/**
1153
	 * 
1154
	 */
1155
	@Override
1156
	public synchronized void propagate(Operator operator) 
1157
			throws OperatorPropagationException 
1158
	{
1159
		// check if operator has been applied already
1160
		if (!operator.isApplied()) {
1161
			
1162
			try {
1163
				
1164
				// commit solution 
1165
				this.commit(operator.getFlawSolution());
1166
				// set applied
1167
				operator.setApplied();
1168
			}
1169
			catch (FlawSolutionApplicationException ex) {
1170
				// throw exception
1171
				throw new OperatorPropagationException("Error while propagating operator:\n"
1172
						+ "- Operator: " + operator + "\n");
1173
			}
1174
		}
1175
		else {
1176
			
1177
			try {
1178
				
1179
				// simply restore flaw solution by leveraging "SILENT" plan
1180
				this.restore(operator.getFlawSolution());
1181
			} 
1182
			catch (Exception ex) {
1183
				
1184
				// error while resetting operator
1185
				throw new OperatorPropagationException("Error while restoring operator status:\n"
1186
						+ "- Operator: " + operator + "\n");
1187
			}
1188
		}
1189
	}
1190
	
1191
	/**
1192
	 * 
1193
	 */
1194
	@Override
1195
	public synchronized void retract(Operator operator) 
1196
	{
1197
		// get flaw solution
1198
		FlawSolution solution = operator.getFlawSolution();
1199
		// retract flaw solution
1200
		this.rollback(solution);
1201
	}
1202
	
1203
	/**
1204
	 * 
1205
	 */
1206
	@Override
1207
	public String toString() {
1208
		return "{ \"components\": " + this.components.values() +" }";
1209
	}
1210
	
1211
	/**
1212
	 * 
1213
	 */
1214
	@Override
1215
	public <T extends Relation> T create(RelationType type, Decision reference, Decision target) {
1216
		// get reference component
1217
		DomainComponent refComp = reference.getComponent();
1218
		// create relation
1219
		return refComp.create(type, reference, target);
1220
	}
1221
	
1222
	/**
1223
	 * 
1224
	 * @param problem
1225
	 * @throws ProblemInitializationException
1226
	 */
1227
	private void doSetupProblem(Problem problem) 
1228
			throws ProblemInitializationException
1229
	{
1230
		// check if a problem has been already set up
1231
		if (this.problem == null) 
1232
		{
1233
			// list of committed decisions
1234
			List<Decision> committedDecisions = new ArrayList<>();
1235
			// list of committed relations
1236
			List<Relation> committedRelations = new ArrayList<>();
1237
			// index fluent to added decisions
1238
			Map<ProblemFluent, Decision> fluent2decisions = new HashMap<>();
1239
			
1240
			try 
1241
			{
1242
				// get facts 
1243
				for (ProblemFact fact : problem.getFacts()) {
1244
					// create decision
1245
					Decision dec = this.create(
1246
							fact.getValue(), 
1247
							fact.getParameterLabels(), 
1248
							fact.getStart(), 
1249
							fact.getEnd(), 
1250
							fact.getDuration());
1251
					
1252
					// add decision
1253
					this.activate(dec);
1254
					// add committed decision
1255
					committedDecisions.add(dec);
1256
					// add entry
1257
					fluent2decisions.put(fact, dec);
1258
				}
1259
			}
1260
			catch (Exception ex) {
1261
				// roll-back committed decisions
1262
				for (Decision dec : committedDecisions) {
1263
					try {
1264
						// retract decision
1265
						this.free(dec);
1266
					} catch (Exception exx) {
1267
						throw new RuntimeException(exx.getMessage());
0 ignored issues
show
Best Practice introduced by
Dedicated exceptions should be preferred over throwing the generic Exception.
Loading history...
1268
					}
1269
				}
1270
				// throw exception
1271
				throw new ProblemInitializationException(ex.getMessage());
1272
			}
1273
			
1274
			// create goals
1275
			for (ProblemGoal goal : problem.getGoals()) {
1276
				// create related decisions
1277
				Decision dec = this.create(
1278
						goal.getValue(), 
1279
						goal.getParameterLabels(), 
1280
						goal.getStart(), 
1281
						goal.getEnd(), 
1282
						goal.getDuration());
1283
				
1284
				// set mandatory expansion
1285
				dec.setMandatoryExpansion();
1286
				// add entry
1287
				fluent2decisions.put(goal, dec);
1288
			}
1289
			
1290
			try 
1291
			{
1292
				// check constraints
1293
				for (ProblemConstraint constraint : problem.getConstraints()) 
1294
				{
1295
					// get related decisions
1296
					Decision reference = fluent2decisions.get(constraint.getReference());
1297
					Decision target = fluent2decisions.get(constraint.getTarget());
1298
					
1299
					// check relation type
1300
					switch (constraint.getCategory()) 
1301
					{
1302
						// temporal constraint
1303
						case TEMPORAL_CONSTRAINT : 
1304
						{
1305
							// get temporal constraint
1306
							TemporalProblemConstraint tc = (TemporalProblemConstraint) constraint;
1307
							// create relation
1308
							TemporalRelation rel = this.create(constraint.getType(), reference, target);
1309
							rel.setBounds(tc.getBounds());
1310
							// check if relation can be activated
1311
							if (this.activate(rel)) {
1312
								committedRelations.add(rel);
1313
							}
1314
						}
1315
						break;
1316
						
1317
						// parameter constraint
1318
						case PARAMETER_CONSTRAINT : 
1319
						{
1320
							// get parameter constraint
1321
							ParameterProblemConstraint pc = (ParameterProblemConstraint) constraint;
1322
							// create relation
1323
							ParameterRelation rel = this.create(constraint.getType(), reference, target);
1324
							// set labels
1325
							rel.setReferenceParameterLabel(pc.getReferenceParameterLabel());
1326
							
1327
							// check relation type
1328
							switch (rel.getType())
1329
							{
1330
								// bind parameter relation
1331
								case BIND_PARAMETER :
1332
								{
1333
									// get relation
1334
									BindParameterRelation bind = (BindParameterRelation) rel;
1335
									// set the binding value
1336
									bind.setValue(pc.getTargetParameterLabel());
1337
								}
1338
								break;
1339
								
1340
								// equal parameter relation
1341
								case EQUAL_PARAMETER :  
1342
								{
1343
									// get relation
1344
									EqualParameterRelation eq = (EqualParameterRelation) rel;
1345
									// set target label
1346
									eq.setTargetParameterLabel(pc.getTargetParameterLabel());
1347
								}
1348
								break; 
1349
								
1350
								// not equal parameter relation
1351
								case NOT_EQUAL_PARAMETER : 
1352
								{
1353
									// get relation
1354
									NotEqualParameterRelation neq = (NotEqualParameterRelation) rel;
1355
									// set also the target label
1356
									neq.setTargetParameterLabel(pc.getTargetParameterLabel());
1357
								}
1358
								break;
1359
								
1360
								default : {
1361
									throw new RuntimeException("Unknown parameter relation type - " + rel.getType());
0 ignored issues
show
Best Practice introduced by
Dedicated exceptions should be preferred over throwing the generic Exception.
Loading history...
1362
								}
1363
							}
1364
							
1365
							// check if relation can be activated
1366
							if (this.activate(rel)) {
1367
								committedRelations.add(rel);
1368
							}
1369
						}
1370
						break;
1371
					}
1372
				}
1373
			}
1374
			catch (RelationPropagationException ex) {
1375
				// roll-back committed relations
1376
				for (Relation rel : committedRelations) {
1377
					// retract 
1378
					this.deactivate(rel);
1379
				}
1380
				
1381
				// throw exception
1382
				throw new ProblemInitializationException(ex.getMessage());
1383
			}
1384
			
1385
			try {
1386
				
1387
				// check unsolvable flaws
1388
				this.detectFlaws();
1389
			} 
1390
			catch (UnsolvableFlawException ex) {
1391
				// unsolvable flaws found
1392
				throw new ProblemInitializationException("Inconsistent Problem description\n- Unsolvable flaws have been found\n" + ex.getMessage());
1393
			}
1394
			
1395
			// set problem 
1396
			this.problem = problem;
1397
		}
1398
		else {
1399
			// a problem already exists
1400
			throw new ProblemInitializationException("A problem instace has been already set up... try clear() before setting up a new problem instance");
1401
		}
1402
	}
1403
}
1404