Passed
Push — master ( c71db0...37262d )
by Alessandro
05:46 queued 14s
created

doComputeFlawSolutions(Flaw)   F

Complexity

Conditions 22

Size

Total Lines 203
Code Lines 95

Duplication

Lines 53
Ratio 26.11 %

Importance

Changes 0
Metric Value
cc 22
eloc 95
dl 53
loc 203
rs 0
c 0
b 0
f 0

How to fix   Long Method    Complexity   

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:

Complexity

Complex classes like it.cnr.istc.pst.platinum.ai.framework.microkernel.resolver.timeline.behavior.planning.TimelineBehaviorPlanningResolver.doComputeFlawSolutions(Flaw) often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

1
package it.cnr.istc.pst.platinum.ai.framework.microkernel.resolver.timeline.behavior.planning;
2
3
import java.util.ArrayList;
4
import java.util.HashSet;
5
import java.util.List;
6
import java.util.Set;
7
8
import it.cnr.istc.pst.platinum.ai.framework.domain.component.ComponentValue;
9
import it.cnr.istc.pst.platinum.ai.framework.domain.component.Decision;
10
import it.cnr.istc.pst.platinum.ai.framework.domain.component.DomainComponent;
11
import it.cnr.istc.pst.platinum.ai.framework.domain.component.ex.DecisionPropagationException;
12
import it.cnr.istc.pst.platinum.ai.framework.domain.component.ex.FlawSolutionApplicationException;
13
import it.cnr.istc.pst.platinum.ai.framework.domain.component.ex.RelationPropagationException;
14
import it.cnr.istc.pst.platinum.ai.framework.domain.component.ex.TransitionNotFoundException;
15
import it.cnr.istc.pst.platinum.ai.framework.domain.component.sv.StateVariable;
16
import it.cnr.istc.pst.platinum.ai.framework.domain.component.sv.Transition;
17
import it.cnr.istc.pst.platinum.ai.framework.domain.component.sv.ValuePath;
18
import it.cnr.istc.pst.platinum.ai.framework.microkernel.lang.ex.ConsistencyCheckException;
19
import it.cnr.istc.pst.platinum.ai.framework.microkernel.lang.flaw.Flaw;
20
import it.cnr.istc.pst.platinum.ai.framework.microkernel.lang.flaw.FlawSolution;
21
import it.cnr.istc.pst.platinum.ai.framework.microkernel.lang.relations.Relation;
22
import it.cnr.istc.pst.platinum.ai.framework.microkernel.lang.relations.RelationType;
23
import it.cnr.istc.pst.platinum.ai.framework.microkernel.lang.relations.parameter.EqualParameterRelation;
24
import it.cnr.istc.pst.platinum.ai.framework.microkernel.lang.relations.parameter.NotEqualParameterRelation;
25
import it.cnr.istc.pst.platinum.ai.framework.microkernel.lang.relations.temporal.MeetsRelation;
26
import it.cnr.istc.pst.platinum.ai.framework.microkernel.query.TemporalQueryType;
27
import it.cnr.istc.pst.platinum.ai.framework.microkernel.resolver.Resolver;
28
import it.cnr.istc.pst.platinum.ai.framework.microkernel.resolver.ResolverType;
29
import it.cnr.istc.pst.platinum.ai.framework.microkernel.resolver.ex.UnsolvableFlawException;
30
import it.cnr.istc.pst.platinum.ai.framework.parameter.lang.constraints.ParameterConstraintType;
31
import it.cnr.istc.pst.platinum.ai.framework.time.lang.query.IntervalDistanceQuery;
32
import it.cnr.istc.pst.platinum.ai.framework.time.lang.query.IntervalOverlapQuery;
33
import it.cnr.istc.pst.platinum.ai.framework.utils.properties.FilePropertyReader;
34
35
/**
36
 * 
37
 * @author anacleto
38
 *
39
 */
40
public final class TimelineBehaviorPlanningResolver extends Resolver<StateVariable> 
41
{
42
	private boolean load;
43
	private double cost;
44
	
45
	/**
46
	 * 
47
	 */
48
	protected TimelineBehaviorPlanningResolver() {
49
		super(ResolverType.TIMELINE_BEHAVIOR_PLANNING_RESOLVER.getLabel(), 
50
				ResolverType.TIMELINE_BEHAVIOR_PLANNING_RESOLVER.getFlawTypes());
51
		// set load flag
52
		this.load = false;
53
	}
54
	
55
	/**
56
	 * 
57
	 */
58
	private void load() {
59
		// get deliberative property file
60
		FilePropertyReader properties = new FilePropertyReader(
61
				FRAMEWORK_HOME + FilePropertyReader.DEFAULT_DELIBERATIVE_PROPERTY);
62
		// get weight
63
		this.cost = Double.parseDouble(properties.getProperty("completion-cost"));
64
		// set flag
65
		this.load = true;
66
	}
67
	
68
	/**
69
	 * 
70
	 */
71
	@Override
72
	protected void doApply(FlawSolution solution) 
73
			throws FlawSolutionApplicationException 
74
	{
75
		// get the flaw solution to apply
76
		GapCompletion completion = (GapCompletion) solution;
77
		// check solution path
78
		if (completion.getPath().isEmpty()) 
79
		{
80
			try 
81
			{
82
				// direct token transition between active decisions
83
				Decision reference = completion.getLeftDecision();
84
				Decision target = completion.getRightDecision();
85
				
86
				// create meets constraint to enforce the desired transition
87
				MeetsRelation meets = this.component.create(RelationType.MEETS, reference, target);
88
				// add created relation
89
				solution.addCreatedRelation(meets);
90
				// propagate relation
91
				if (this.component.activate(meets)) {
92
					// add activated relation to solution
93
					solution.addActivatedRelation(meets);
94
				}
95
				
96
				// create parameter relations
97
				Set<Relation> pRels = this.createParameterRelations(reference, target);
98
				// add created relation
99
				solution.addCreatedRelations(pRels);
100
				// propagate relation
101
				for (Relation pRel : pRels) {
102
					// activate relation if possible
103
					if (this.component.activate(pRel)) {
104
						// add activated relation to solution
105
						solution.addActivatedRelation(pRel);
106
					}
107
				}
108
				
109
				// check feasibility
110
				this.tdb.verify();
111
				this.pdb.verify();
112
			}
113
			catch (TransitionNotFoundException | RelationPropagationException | ConsistencyCheckException ex) 
114
			{
115
				// deactivate activated relations
116
				for (Relation rel : solution.getActivatedRelations()) {
117
					// get reference component
118
					DomainComponent refComp = rel.getReference().getComponent();
119
					refComp.deactivate(rel);
120
				}
121
				
122
				// delete created relations
123
				for (Relation rel : solution.getCreatedRelations()) {
124
					// get reference component
125
					DomainComponent refComp = rel.getReference().getComponent();
126
					// delete relation
127
					refComp.delete(rel);
128
				}
129
				
130
				// not feasible solution
131
				throw new FlawSolutionApplicationException(ex.getMessage());
132
			}
133
		}
134
		else 
135
		{
136
			// create the list of the decisions
137
			List<Decision> transition = new ArrayList<>();
138
			// add the gap-left decision
139
			transition.add(completion.getLeftDecision());
140
			try {
141
				
142
				// intermediate values and related relations can be activated since no synchronization is entailed
143 View Code Duplication
				for (ComponentValue value : completion.getPath()) 
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
144
				{
145
					// create parameters' labels
146
					String[] labels = new String[value.getNumberOfParameterPlaceHolders()];
147
					for (int index = 0; index < labels.length; index++) {
148
						// set parameter label
149
						labels[index] = "label-" + index;
150
					}
151
					
152
					// create pending decision
153
					Decision dec = this.component.create(value, labels);
154
					// these decisions can be set as mandatory expansion
155
					dec.setMandatoryExpansion();
156
					// add created decision to transition
157
					transition.add(dec);
158
					// add pending decision
159
					solution.addCreatedDecision(dec);
160
161
					// activate the decision if possible
162
					if (!value.isComplex()) {
163
						
164
						// activated decision
165
						Set<Relation> list = this.component.activate(dec);
166
						// add activated decisions
167
						solution.addActivatedDecision(dec);
168
						// add activated relations
169
						solution.addActivatedRelations(list);
170
					}
171
				}
172
				
173
				// add the gap-right decision
174
				transition.add(completion.getRightDecision());
175
				
176
				// create relations needed to enforce the transition
177 View Code Duplication
				for (int index = 0; index < transition.size() - 1; index++) 
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
178
				{
179
					// get adjacent decisions
180
					Decision reference = transition.get(index);
181
					Decision target = transition.get(index + 1);
182
					
183
					// create pending relation
184
					MeetsRelation meets = this.component.create(RelationType.MEETS, reference, target);
185
					// add created relation
186
					solution.addCreatedRelation(meets);
187
					// activate relation if possible
188
					if (this.component.activate(meets)) {
189
						// add to activated relations
190
						solution.addActivatedRelation(meets);
191
					}
192
						
193
					// create parameter relations
194
					Set<Relation> pRels = this.createParameterRelations(reference, target);
195
					// check relations
196
					for (Relation prel : pRels) {
197
						// add relation to solution
198
						solution.addCreatedRelation(prel);
199
						// activate relation if possible
200
						if (this.component.activate(prel)) {
201
							// add to activated relations
202
							solution.addActivatedRelation(prel);
203
						}
204
					}
205
				}
206
				
207
				// check consistency
208
				this.tdb.verify();
209
				this.pdb.verify();
210
			}
211
			catch (Exception ex) {
212
			
213
				// deactivate relations
214
				for (Relation rel : solution.getActivatedRelations()) {
215
					this.component.deactivate(rel);
216
				}
217
				
218
				// delete created relations
219
				for (Relation rel : solution.getCreatedRelations()) {
220
					this.component.delete(rel);
221
				}
222
				
223
				// deactivate decisions
224
				for (Decision dec : solution.getActivatedDecisions()) {
225
					this.component.deactivate(dec);
226
				}
227
				
228
				// free created decisions
229
				for (Decision dec : solution.getCreatedDecisions()) {
230
					this.component.free(dec);
231
				}
232
				
233
				// throw exception
234
				throw new FlawSolutionApplicationException("Error while applying flaw solution:\n"
235
						+ "- behavior-completion: " + completion + "\n"
236
						+ "- message: " + ex.getMessage() + "\n");
237
			}
238
		}
239
	}
240
	
241
	/**
242
	 * 
243
	 * @return
244
	 */
245
	@Override
246
	protected List<Flaw> doFindFlaws() 
247
	{
248
		// load flat
249
		if (!this.load) {
250
			this.load();
251
		}
252
				
253
		// list of gaps
254
		List<Flaw> flaws = new ArrayList<>();
255
		// get the "ordered" list of tokens on the component
256
		List<Decision> list = this.component.getActiveDecisions();
257
		
258
		// check gaps between adjacent decisions
259
		for (int index = 0; index < list.size() - 1; index++) 
260
		{
261
			// get two adjacent decisions
262
			Decision left = list.get(index);
263
			Decision right = list.get(index + 1);
264
			
265
			// check if scheduled
266
			IntervalOverlapQuery query = this.tdb.createTemporalQuery(
267
					TemporalQueryType.INTERVAL_OVERLAP);
268
			// set time points
269
			query.setReference(left.getToken().getInterval());
270
			query.setTarget(right.getToken().getInterval());
271
			
272
			// process query
273
			this.tdb.process(query);
274
			// check if they intervals can overlap
275
			if (query.canOverlap())
276
			{
277
				// precondition not satisfied
278
				debug("No timeline behavior flaw can be detected as tokens are not scheduled:\n"
279
						+ "- component: " + this.component + "\n"
280
						+ "- [reason] Behaviors cannot be plant due to potentially overlapping tokens:\n"
281
						+ "\t- reference: " + left + "\n"
282
						+ "\t- target: " + right + "\n");
283
				
284
				// clear data structures and stop inspecting this component for this type of flaws
285
				flaws = new ArrayList<>();
286
				break;
287
			}
288
			else 
289
			{
290
				// check if scheduled
291
				IntervalDistanceQuery distance = this.tdb.createTemporalQuery(
292
						TemporalQueryType.INTERVAL_DISTANCE);
293
				// set time points
294
				distance.setReference(left.getToken().getInterval());
295
				distance.setTarget(right.getToken().getInterval());
296
				// process query
297
				this.tdb.process(distance);
298
				
299
				// check the distance between the two decisions 
300
				if (distance.getDistanceLowerBound() >= 0 && distance.getDistanceUpperBound() > 0) 
301
				{
302
					// a gap has been found on the timeline 
303
					Gap gap = new Gap(FLAW_COUNTER.getAndIncrement(),
304
							this.component, 
305
							left, 
306
							right, 
307
							new long[] {
308
									distance.getDistanceLowerBound(), 
309
									distance.getDistanceUpperBound()});
310
					
311
					// add gap
312
					flaws.add(gap);
313
					debug("Gap found on component: "
314
							+ "- component: " + this.component + "\n"
315
							+ "- reference: " + left + "\n"
316
							+ "- target: " + right + "\n"
317
							+ "- distance: [" + distance.getDistanceLowerBound() + ", " + distance.getDistanceUpperBound() + "]\n");
318
				}
319
			}
320
		}
321
		
322
		
323
		// get flaws
324
		return flaws;
325
	}
326
	
327
	/**
328
	 * 
329
	 */
330
	@Override
331
	protected void doComputeFlawSolutions(Flaw flaw) 
332
			throws UnsolvableFlawException 
333
	{
334
		// get the gap
335
		Gap gap = (Gap) flaw;
336
		// check gap type
337
		switch (gap.getGapType()) 
338
		{
339
			// incomplete time-line
340
			case INCOMPLETE_TIMELINE : 
341
			{
342
				// check all (acyclic) paths among tokens
343
				List<ValuePath> paths = this.component.getPaths(
344
						gap.getLeftDecision().getValue(), 
345
						gap.getRightDecision().getValue());
346
				
347
				// check found solutions
348
				if (paths.isEmpty()) {
349
					// not gap completion found between the two tokens
350
					throw new UnsolvableFlawException("Not gap completion found:\n"
351
							+ "- gap: " + gap + "\n");
352
				}
353
				else 
354
				{
355
					// compute a solution for each possible value path
356
					for (ValuePath path : paths) 
357
					{
358
						// get steps
359
						List<ComponentValue> steps = path.getSteps();
360
						// remove the source and destination values from the path
361
						steps.remove(0);
362
						steps.remove(steps.size() - 1);
363
						// gap solution
364
						GapCompletion solution = new GapCompletion(gap, steps, this.cost);
365
						
366
						try 
367
						{
368
							// check solution feasibility
369
							if (solution.getPath().isEmpty()) 
370
							{
371
								// direct token transition between active decisions
372
								Decision reference = solution.getLeftDecision();
373
								Decision target = solution.getRightDecision();
374
								
375
								// create meets constraint to enforce the desired transition
376
								MeetsRelation meets = this.component.create(RelationType.MEETS, reference, target);
377
								// add created relation
378
								solution.addCreatedRelation(meets);
379
								// propagate relation and activate it if possible
380
								if (this.component.activate(meets)) {
381
									// add activated relation to solution
382
									solution.addActivatedRelation(meets);
383
								}
384
								
385
								// create parameter relations
386
								Set<Relation> pRels = this.createParameterRelations(reference, target);
387
								// add created relation
388
								solution.addCreatedRelation(meets);
389
								// propagate relation
390
								for (Relation pRel : pRels) {
391
									// activate relation if possible
392
									if (this.component.activate(pRel)) {
393
										// add activated relation to solution
394
										solution.addActivatedRelation(pRel);
395
									}
396
								}
397
							}
398
							else 
399
							{
400
								// create the list of the decisions
401
								List<Decision> transition = new ArrayList<>();
402
								// add the gap-left decision
403
								transition.add(solution.getLeftDecision());
404
									
405
								// intermediate values and related relations can be activated since no synchronization is entailed
406 View Code Duplication
								for (ComponentValue value : solution.getPath()) 
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
407
								{
408
									// create parameters' labels
409
									String[] labels = new String[value.getNumberOfParameterPlaceHolders()];
410
									for (int index = 0; index < labels.length; index++) {
411
										// set parameter label
412
										labels[index] = "label-" + index;
413
									}
414
									
415
									// create pending decision
416
									Decision dec = this.component.create(value, labels);
417
									// these decisions can be set as mandatory expansion
418
									dec.setMandatoryExpansion();
419
									// add created decision to transition
420
									transition.add(dec);
421
									// add pending decision
422
									solution.addCreatedDecision(dec);
423
424
									// activate the decision if possible
425
									if (!value.isComplex()) {
426
										
427
										// activated decision
428
										Set<Relation> list = this.component.activate(dec);
429
										// add activated decisions
430
										solution.addActivatedDecision(dec);
431
										// add activated relations
432
										solution.addActivatedRelations(list);
433
									}
434
								}
435
									
436
								// add the gap-right decision
437
								transition.add(solution.getRightDecision());
438
								
439
								// create relations needed to enforce the transition
440 View Code Duplication
								for (int index = 0; index < transition.size() - 1; index++) 
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
441
								{
442
									// get adjacent decisions
443
									Decision reference = transition.get(index);
444
									Decision target = transition.get(index + 1);
445
									
446
									// create pending relation
447
									MeetsRelation meets = this.component.create(RelationType.MEETS, reference, target);
448
									// add created relation
449
									solution.addCreatedRelation(meets);
450
									// activate relation if possible
451
									if (this.component.activate(meets)) {
452
										// add to activated relations
453
										solution.addActivatedRelation(meets);
454
									}
455
									
456
									// create parameter relations
457
									Set<Relation> pRels = this.createParameterRelations(reference, target);
458
									// check relations
459
									for (Relation prel : pRels) {
460
										// add relation to solution
461
										solution.addCreatedRelation(prel);
462
										// activate relation if possible
463
										if (this.component.activate(prel)) {
464
											// add to activated relations
465
											solution.addActivatedRelation(prel);
466
										}
467
									}
468
								}
469
							}
470
471
							// check feasibility
472
							this.tdb.verify();
473
							this.pdb.verify();
474
							
475
							// add solution to the flaw since everything is feasible
476
							gap.addSolution(solution);
477
							// print gap information
478
							debug("Gap found on component " + this.component.getName() + ":\n"
479
									+ "- gap distance: [dmin= " + gap.getDmin() + ", dmax= " +  gap.getDmax() + "] \n"
480
									+ "- left-side decision: " + gap.getLeftDecision() + "\n"
481
									+ "- right-side decision: " + gap.getRightDecision() + "\n"
482
									+ "- solution path: " + path + "\n");
483
						}
484
						catch (RelationPropagationException | TransitionNotFoundException | DecisionPropagationException |  ConsistencyCheckException ex) {
485
							// discard this path as not temporally feasible
486
							warning("Unfeasible transition path for timelime behavior completion:\n"
487
									+ "- gap distance: [dmin= " + gap.getDmin() +", " + gap.getDmax() + "]\n"
488
									+ "- path: " + path + "\n");
489
//										+ "- path duration: [dmin= " + tranMinDuration + ", " + tranMaxDuration + "]");
490
						}
491
						finally {
492
							
493
							// deactivate relations
494
							for (Relation rel : solution.getActivatedRelations()) {
495
								this.component.deactivate(rel);
496
							}
497
							
498
							// delete relation
499
							for (Relation rel : solution.getCreatedRelations()) {
500
								this.component.delete(rel);
501
							}
502
							
503
							// deactivate decision
504
							for (Decision dec : solution.getActivatedDecisions()) {
505
								this.component.deactivate(dec);
506
							}
507
							
508
							// free decision
509
							for (Decision dec : solution.getCreatedDecisions()) {
510
								this.component.free(dec);
511
							}
512
						}
513
					}	
514
				}
515
			}
516
			break;
517
		
518
			// semantic connection missing
519
			case SEMANTIC_CONNECTION : {
520
				
521
				// direct connection between decisions
522
				GapCompletion solution = new GapCompletion(gap, new ArrayList<ComponentValue>(), this.cost);
523
				// add gap solution
524
				gap.addSolution(solution);
525
			}
526
			break;
527
		}
528
		
529
		// check if solvable
530
		if (!gap.isSolvable()) {
531
			throw new UnsolvableFlawException("Unsolvable gap found on component " + this.component.getName() + ":"
532
					+ "\n- gap: " + flaw + "\n");
533
		}
534
	}
535
	
536
	/**
537
	 * 
538
	 * @param reference
539
	 * @param target
540
	 * @return
541
	 * @throws TransitionNotFoundException
542
	 */
543
	private Set<Relation> createParameterRelations(Decision reference, Decision target) 
544
			throws TransitionNotFoundException 
545
	{
546
		// relations
547
		Set<Relation> rels = new HashSet<>();
548
		// get transition between values
549
		Transition t = this.component.getTransition(reference.getValue(), target.getValue());
550
		
551
		// reference parameter position index
552
		int referenceParameterIndex = 0;
553
		while (referenceParameterIndex < reference.getParameterLabels().length) {
554
			
555
			// target parameter position index
556
			int targetParameterIndex = 0;
557
			while (targetParameterIndex < target.getParameterLabels().length) {
558
				
559
				// check if a parameter constraint exists
560
				if (t.existsParameterConstraint(referenceParameterIndex, targetParameterIndex)) {
561
					// get parameter constraint type
562
					ParameterConstraintType pConsType = t.getParameterConstraintType(referenceParameterIndex, targetParameterIndex);
563
					
564
					// add (local) pending parameter constraint
565
					switch (pConsType) {
566
					
567
						// equal parameter constraint
568
						case EQUAL : {
569
							
570
							// create (pending) local relation
571
							EqualParameterRelation equal = (EqualParameterRelation) this.component.create(RelationType.EQUAL_PARAMETER, reference, target);
572
							// set reference parameter label
573
							equal.setReferenceParameterLabel(reference.getParameterLabelByIndex(referenceParameterIndex));
574
							// set target parameter label
575
							equal.setTargetParameterLabel(target.getParameterLabelByIndex(targetParameterIndex));
576
							// add create relation to solution
577
							rels.add(equal);
578
						}
579
						break;
580
						
581
						// not equal parameter
582
						case NOT_EQUAL : {
583
							
584
							// create (pending) local relation
585
							NotEqualParameterRelation notEqual = (NotEqualParameterRelation) this.component.create(RelationType.NOT_EQUAL_PARAMETER, reference, target);
586
							// set reference parameter label
587
							notEqual.setReferenceParameterLabel(reference.getParameterLabelByIndex(referenceParameterIndex));
588
							notEqual.setTargetParameterLabel(target.getParameterLabelByIndex(targetParameterIndex));
589
							// add create relation to solution
590
							rels.add(notEqual);
591
						}
592
						break;
593
						
594
						default : {
595
							
596
							/*
597
							 * TODO: <<<<----- VERIFICARE SE VANNO GESTITI ALTRI TIPI DI VINCOLI
598
							 */
599
							
600
							throw new RuntimeException("Unknown parameter constraint type in state variable transition " + pConsType);
0 ignored issues
show
Best Practice introduced by
Dedicated exceptions should be preferred over throwing the generic Exception.
Loading history...
601
						}
602
					}
603
				}
604
				
605
				// next target parameter index
606
				targetParameterIndex++;
607
			}
608
			
609
			// next index
610
			referenceParameterIndex++;
611
		}
612
		
613
		// get created relations
614
		return rels;
615
	}
616
}
617