it.cnr.istc.pst.platinum.ai.framework.microkernel.lang.plan.SolutionPlan   F
last analyzed

Complexity

Total Complexity 67

Size/Duplication

Total Lines 626
Duplicated Lines 16.61 %

Importance

Changes 3
Bugs 0 Features 0
Metric Value
eloc 302
c 3
b 0
f 0
dl 104
loc 626
rs 3.04
wmc 67

22 Methods

Rating   Name   Duplication   Size   Complexity  
A export() 0 5 1
B getMakespan() 38 38 6
A getName() 0 2 1
A getRelations() 0 2 1
A setControllability(PlanControllabilityType) 0 2 1
A add(Relation) 0 2 1
B equals(Object) 0 15 7
A hashCode() 0 6 2
A getPlanControllabilityType() 0 2 1
A getSolvingTime() 0 2 1
A getHorizon() 0 2 1
A setSolutionNode(SearchSpaceNode) 0 2 1
B getMakespan(String) 45 45 5
A getSolutionNode() 0 2 1
A setSolvingTime(long) 0 2 1
B add(DomainComponent) 0 45 8
A getAllTimelines() 0 5 1
A SolutionPlan(String,long) 0 9 1
A getTimelines() 0 2 1
F generatePlanDescriptor() 0 198 15
A getObservations() 0 2 1
C toString() 21 92 9

How to fix   Duplicated Code    Complexity   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

Complexity

 Tip:   Before tackling complexity, make sure that you eliminate any duplication first. This often can reduce the size of classes significantly.

Complex classes like it.cnr.istc.pst.platinum.ai.framework.microkernel.lang.plan.SolutionPlan 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.lang.plan;
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.SearchSpaceNode;
11
import it.cnr.istc.pst.platinum.ai.framework.domain.component.DomainComponent;
12
import it.cnr.istc.pst.platinum.ai.framework.domain.component.DomainComponentType;
13
import it.cnr.istc.pst.platinum.ai.framework.domain.component.Token;
14
import it.cnr.istc.pst.platinum.ai.framework.domain.component.resource.Resource;
15
import it.cnr.istc.pst.platinum.ai.framework.domain.component.resource.ResourceEvent;
16
import it.cnr.istc.pst.platinum.ai.framework.domain.component.sv.StateVariable;
17
import it.cnr.istc.pst.platinum.ai.framework.microkernel.ConstraintCategory;
18
import it.cnr.istc.pst.platinum.ai.framework.microkernel.lang.relations.Relation;
19
import it.cnr.istc.pst.platinum.ai.framework.microkernel.lang.relations.temporal.TemporalRelation;
20
import it.cnr.istc.pst.platinum.ai.framework.parameter.lang.EnumerationParameter;
21
import it.cnr.istc.pst.platinum.ai.framework.parameter.lang.NumericParameter;
22
import it.cnr.istc.pst.platinum.ai.framework.parameter.lang.Parameter;
23
import it.cnr.istc.pst.platinum.ai.framework.parameter.lang.ParameterType;
24
import it.cnr.istc.pst.platinum.ai.framework.protocol.lang.ParameterTypeDescriptor;
25
import it.cnr.istc.pst.platinum.ai.framework.protocol.lang.PlanProtocolDescriptor;
26
import it.cnr.istc.pst.platinum.ai.framework.protocol.lang.ProtocolLanguageFactory;
27
import it.cnr.istc.pst.platinum.ai.framework.protocol.lang.TimelineProtocolDescriptor;
28
import it.cnr.istc.pst.platinum.ai.framework.protocol.lang.TokenProtocolDescriptor;
29
import it.cnr.istc.pst.platinum.ai.framework.protocol.lang.relation.RelationProtocolDescriptor;
30
31
/**
32
 * 
33
 * @author anacleto
34
 *
35
 */
36
public class SolutionPlan 
37
{
38
	private long horizion;
39
	private long solvingTime;
40
	private String name;
41
	private SearchSpaceNode solutionNode;
42
	private Set<Timeline> timelines;
43
	private Set<Timeline> observations;
44
	private List<Relation> relations;
45
	private PlanControllabilityType controllability;
46
	private Set<Profile> profiles;
47
	
48
	/**
49
	 * 
50
	 * @param name
51
	 * @param horizon
52
	 */
53
	public SolutionPlan(String name, long horizon) 
54
	{
55
		this.horizion = horizon;
56
		this.name = name;
57
		this.timelines = new HashSet<>();
58
		this.observations = new HashSet<>();
59
		this.relations = new ArrayList<>();
60
		this.profiles = new HashSet<>();
61
		this.controllability = PlanControllabilityType.UNKNOWN;
62
	}
63
	
64
	/**
65
	 * 
66
	 * @param node
67
	 */
68
	public void setSolutionNode(SearchSpaceNode node) {
69
		this.solutionNode = node;
70
	}
71
	
72
	/**
73
	 * 
74
	 * @return
75
	 */
76
	public SearchSpaceNode getSolutionNode() {
77
		return this.solutionNode;
78
	}
79
	
80
	/**
81
	 * 
82
	 * @return
83
	 */
84
	public String getName() {
85
		return name;
86
	}
87
	
88
	/**
89
	 * 
90
	 * @return
91
	 */
92
	public long getHorizon() {
93
		return this.horizion;
94
	}
95
	
96
	/**
97
	 * 
98
	 * @return
99
	 */
100 View Code Duplication
	public double[] getMakespan() 
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
101
	{
102
		// set makespan 
103
		double[] mk = new double[] {
104
				Double.MIN_VALUE + 1,  
105
				Double.MAX_VALUE - 1
106
		};
107
		
108
		// check timelines
109
		for (Timeline tl : this.timelines) 
110
		{
111
			// check primitive components only 
112
			if (tl.getComponent().getType().equals(DomainComponentType.SV_PRIMITIVE))
113
			{
114
				// check tokens
115
				if (!tl.getTokens().isEmpty()) {
116
					// get last token of the timeline
117
					Token last = tl.getTokens().get(0);
118
					for (int index = 1; index < tl.getTokens().size(); index++) {
119
						// get token 
120
						Token t = tl.getTokens().get(index);
121
						// check last token 
122
						if (t.getInterval().getEndTime().getLowerBound() > last.getInterval().getEndTime().getLowerBound()) {
123
							// update last token
124
							last = t;
125
						}
126
					}
127
					
128
					// update max end time
129
					mk[0] = Math.max(mk[0], last.getInterval().getEndTime().getLowerBound());
130
					mk[1] = Math.min(mk[1], last.getInterval().getEndTime().getUpperBound());
131
				}
132
			}
133
		}
134
		
135
		
136
		// get makespan
137
		return mk;
138
	}
139
140
	/**
141
	 * 
142
	 * @param compName
143
	 * @return
144
	 */
145 View Code Duplication
	public double[] getMakespan(String name) 
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
146
	{
147
		// set makespan 
148
		double[] mk = new double[] {
149
				0.0,
150
				0.0
151
		};
152
		
153
		// check timelines
154
		for (Timeline tl : this.timelines) 
155
		{
156
			// check primitive components only 
157
			if (tl.getComponent().getName().equals(name))
158
			{
159
				// preapre makespan
160
				mk = new double[] {
161
						Double.MIN_VALUE + 1,  
162
						Double.MAX_VALUE - 1
163
				};
164
				
165
				
166
				// get last token of the timeline
167
				Token last = tl.getTokens().get(0);
168
				for (int index = 1; index < tl.getTokens().size(); index++) {
169
					// get token 
170
					Token t = tl.getTokens().get(index);
171
					// check last token 
172
					if (t.getInterval().getEndTime().getLowerBound() > last.getInterval().getEndTime().getLowerBound()) {
173
						// update last token
174
						last = t;
175
					}
176
				}
177
				
178
				// update max end time
179
				mk[0] = Math.max(mk[0], last.getInterval().getEndTime().getLowerBound());
180
				mk[1] = Math.min(mk[1], last.getInterval().getEndTime().getUpperBound());
181
				
182
				// stop search
183
				break;
184
			}
185
		}
186
		
187
		
188
		// get makespan
189
		return mk;
190
	}
191
	
192
	/**
193
	 * 
194
	 * @param solvingTime
195
	 */
196
	public void setSolvingTime(long solvingTime) {
197
		this.solvingTime = solvingTime;
198
	}
199
	
200
	/**
201
	 * 
202
	 * @return
203
	 */
204
	public long getSolvingTime() {
205
		return solvingTime;
206
	}
207
	
208
	/**
209
	 * 
210
	 * @return
211
	 */
212
	public PlanControllabilityType getPlanControllabilityType() {
213
		return this.controllability;
214
	}
215
	
216
	/**
217
	 * 
218
	 * @param pseudo
219
	 */
220
	public void setControllability(PlanControllabilityType type) {
221
		this.controllability = type;
222
	}
223
	
224
	/**
225
	 * 
226
	 * @return
227
	 */
228
	public List<Timeline> getTimelines() {
229
		return new ArrayList<>(this.timelines);
230
	}
231
	
232
	/**
233
	 * 
234
	 * @return
235
	 */
236
	public List<Timeline> getObservations() {
237
		return new ArrayList<>(this.observations);
238
	}
239
	
240
	/**
241
	 * 
242
	 * @return
243
	 */
244
	public List<Timeline> getAllTimelines() {
245
		List<Timeline> list = new ArrayList<>();
246
		list.addAll(this.timelines);
247
		list.addAll(this.observations);
248
		return list;
249
	}
250
	
251
	/**
252
	 * 
253
	 * @param component
254
	 */
255
	public void add(DomainComponent component) 
256
	{
257
		// check component type
258
		switch (component.getType())
259
		{
260
			case SV_FUNCTIONAL : 
261
			case SV_PRIMITIVE : {
262
				// get the state variable
263
				StateVariable sv = (StateVariable) component;
264
				// get the timeline 
265
				Timeline tl = new Timeline(sv);
266
				// add to timeline
267
				this.timelines.add(tl);
268
			}
269
			break;
270
			
271
			case SV_EXTERNAL : {
272
				// get the state variable 
273
				StateVariable sv = (StateVariable) component;
274
				// get the timeline 
275
				Timeline tl = new Timeline(sv);
276
				// add to observations
277
				this.observations.add(tl);
278
			}
279
			break;
280
			
281
			case RESOURCE_DISCRETE : 
282
			case RESOURCE_RESERVOIR : {
283
				// get component as a resource
284
				Resource res = (Resource) component;
285
				// get profile
286
				Profile profile = new Profile(res);
287
				// add profile
288
				this.profiles.add(profile);
289
			}
290
			break;
291
			
292
			case PLAN_DATABASE : {
293
				// ignore this type of components
294
			}
295
			break;
296
			
297
			
298
			default : {
299
				throw new RuntimeException("Unknown component type " + component.getType() + "\n");
0 ignored issues
show
Best Practice introduced by
Dedicated exceptions should be preferred over throwing the generic Exception.
Loading history...
300
			}
301
		}
302
	}
303
	
304
	/**
305
	 * 
306
	 * @return
307
	 */
308
	public List<Relation> getRelations() {
309
		return relations;
310
	}
311
	
312
	/**
313
	 * 
314
	 * @param rel
315
	 */
316
	public void add(Relation rel) {
317
		this.relations.add(rel);
318
	}
319
	
320
	/**
321
	 * 
322
	 * @param plan
323
	 * @return
324
	 */
325
	public PlanProtocolDescriptor export() {
326
		// generate protocol plan descriptor
327
		PlanProtocolDescriptor exported = this.generatePlanDescriptor();
328
		// get exported plan
329
		return exported;
330
	}
331
	
332
	/**
333
	 * 
334
	 * @return
335
	 */
336
	protected PlanProtocolDescriptor generatePlanDescriptor() 
337
	{
338
		// get language factory
339
		ProtocolLanguageFactory factory = new ProtocolLanguageFactory(this.horizion);
340
		
341
		// create plan descriptor
342
		PlanProtocolDescriptor plan = factory.createPlanDescriptor(this.name, 0, this.horizion);
343
		// create an index
344
		Map<Token, TokenProtocolDescriptor> index = new HashMap<>();
345
		// create timeline descriptors
346
		for (Timeline tl : this.timelines) 
347
		{
348
			// get the state variable related to the timeline
349
			StateVariable comp = tl.getComponent();
350
			// initialize descriptor
351
			TimelineProtocolDescriptor timelineDescriptor = factory.createTimelineDescriptor(
352
					comp.getName(), 
353
					tl.getName(), 
354
					tl.isObservation());
355
			
356
			// get tokens of the timeline
357
			for (Token token : tl.getTokens()) 
358
			{
359
				// prepare the array of parameter names, values, and types
360
				String[] paramNames = new String[token.getPredicate().getParameters().length];
361
				ParameterTypeDescriptor[] paramTypes = new ParameterTypeDescriptor[token.getPredicate().getParameters().length];
362
				long[][] paramBounds = new long[token.getPredicate().getParameters().length][];
363
				String[][] paramValues = new String[token.getPredicate().getParameters().length][];
364
				for (int i = 0; i < token.getPredicate().getParameters().length; i++)
365
				{
366
					// get parameter
367
					Parameter<?> param = token.getPredicate().getParameterByIndex(i);
368
					// set parameter name
369
					paramNames[i] = param.getLabel();
370
					
371
					// check parameter type
372
					if (param.getType().equals(ParameterType.NUMERIC_PARAMETER_TYPE)) 
373
					{
374
						// get numeric parameter
375
						NumericParameter numPar = (NumericParameter) param;
376
						// set lower bound and upper bound
377
						paramBounds[i] = new long[] {
378
								numPar.getLowerBound(),
379
								numPar.getUpperBound()
380
						};
381
						// set default value to parameter values
382
						paramValues[i] = new String[] {};
383
						// set parameter type
384
						paramTypes[i] = ParameterTypeDescriptor.NUMERIC;
385
					}
386
					else if (param.getType().equals(ParameterType.ENUMERATION_PARAMETER_TYPE)) 
387
					{
388
						// enumeration parameter
389
						EnumerationParameter enuPar = (EnumerationParameter) param;
390
						// one single value is expected
391
						paramValues[i] = new String[] {
392
								enuPar.getValues()[0]
393
						};
394
						// set default value to parameter bounds
395
						paramBounds[i] = new long[] {};
396
						// set parameter type
397
						paramTypes[i] = ParameterTypeDescriptor.ENUMERATION;
398
					}
399
					else {
400
						throw new RuntimeException("Unknown parameter type:\n- type: " + param.getType() + "\n");
0 ignored issues
show
Best Practice introduced by
Dedicated exceptions should be preferred over throwing the generic Exception.
Loading history...
401
					}
402
				}
403
			
404
				// create token descriptor
405
				TokenProtocolDescriptor tokenDescriptor = factory.createTokenDescriptor(
406
						timelineDescriptor,
407
						token.getPredicate().getValue().getLabel(),
408
						new long [] {
409
								token.getInterval().getStartTime().getLowerBound(), 
410
								token.getInterval().getStartTime().getUpperBound()
411
						}, 
412
						new long[] {
413
								token.getInterval().getEndTime().getLowerBound(),
414
								token.getInterval().getEndTime().getUpperBound()
415
						}, 
416
						new long[] {
417
								token.getInterval().getDurationLowerBound(),
418
								token.getInterval().getDurationUpperBound()
419
						}, 
420
						paramNames, paramTypes, paramBounds, paramValues, token.getStartExecutionState());
421
422
				// update index
423
				index.put(token, tokenDescriptor);
424
			}
425
426
			// add timeline to plan
427
			plan.addTimeline(timelineDescriptor);
428
		}
429
		
430
		// create timeline descriptors
431
		for (Timeline tl : this.observations) 
432
		{
433
			// get the state variable related to the timeline
434
			StateVariable comp = tl.getComponent();
435
			// initialize descriptor
436
			TimelineProtocolDescriptor timelineDescriptor = factory.createTimelineDescriptor(
437
					comp.getName(), 
438
					tl.getName(), 
439
					tl.isObservation());
440
			
441
			// get tokens of the timeline
442
			for (Token token : tl.getTokens()) 
443
			{
444
				// prepare the array of parameter names, values, and types
445
				String[] paramNames = new String[token.getPredicate().getParameters().length];
446
				ParameterTypeDescriptor[] paramTypes = new ParameterTypeDescriptor[token.getPredicate().getParameters().length];
447
				long[][] paramBounds = new long[token.getPredicate().getParameters().length][];
448
				String[][] paramValues = new String[token.getPredicate().getParameters().length][];
449
				for (int i = 0; i < token.getPredicate().getParameters().length; i++)
450
				{
451
					// get parameter
452
					Parameter<?> param = token.getPredicate().getParameterByIndex(i);
453
					// check parameter type
454
					if (param.getType().equals(ParameterType.NUMERIC_PARAMETER_TYPE)) {
455
						// get numeric parameter
456
						NumericParameter numPar = (NumericParameter) param;
457
						// set lower bound and upper bound
458
						paramBounds[i] = new long[] {
459
								numPar.getLowerBound(),
460
								numPar.getUpperBound()
461
						};
462
						// set default value to parameter values
463
						paramValues[i] = new String[] {};
464
					}
465
					else if (param.getType().equals(ParameterType.ENUMERATION_PARAMETER_TYPE)) {
466
						// enumeration parameter
467
						EnumerationParameter enuPar = (EnumerationParameter) param;
468
						// one single value is expected
469
						paramValues[i] = new String[] {
470
								enuPar.getValues().toString()
0 ignored issues
show
Bug introduced by
Calling the toString on an array produces only the array's identity hashCode. Consider using the Arrays.toString instead.
Loading history...
471
						};
472
						// set default value to parameter bounds
473
						paramBounds[i] = new long[] {};
474
					}
475
					else {
476
						throw new RuntimeException("Unknown parameter type:\n- type: " + param.getType() + "\n");
0 ignored issues
show
Best Practice introduced by
Dedicated exceptions should be preferred over throwing the generic Exception.
Loading history...
477
					}
478
				}
479
			
480
				// create token descriptor
481
				TokenProtocolDescriptor tokenDescriptor = factory.createTokenDescriptor(
482
						timelineDescriptor, 
483
						token.getPredicate().getValue().getLabel(),
484
						new long [] {
485
								token.getInterval().getStartTime().getLowerBound(), 
486
								token.getInterval().getStartTime().getUpperBound()
487
						}, 
488
						new long[] {
489
								token.getInterval().getEndTime().getLowerBound(),
490
								token.getInterval().getEndTime().getUpperBound()
491
						}, 
492
						new long[] {
493
								token.getInterval().getDurationLowerBound(),
494
								token.getInterval().getDurationUpperBound()
495
						}, 
496
						paramNames, paramTypes, paramBounds, paramValues, token.getStartExecutionState());
497
498
				// update index
499
				index.put(token, tokenDescriptor);
500
			}
501
			
502
			// add timeline to plan
503
			plan.addTimeline(timelineDescriptor);
504
		}
505
		
506
		// create relation descriptors
507
		for (Relation relation : this.relations)
508
		{
509
			// export temporal relations only
510
			if (relation.getCategory().equals(ConstraintCategory.TEMPORAL_CONSTRAINT))
511
			{
512
				// consider only relations between values of state variables
513
				if (relation.getReference().getComponent() instanceof StateVariable && 
514
						relation.getTarget().getComponent() instanceof StateVariable)
515
				{
516
					// get temporal relation
517
					TemporalRelation trel = (TemporalRelation) relation;
518
					// create relation description 
519
					RelationProtocolDescriptor relDescriptor = factory.createRelationDescriptor(
520
							relation.getType().name().toUpperCase(), 
521
							index.get(relation.getReference().getToken()), 
522
							index.get(relation.getTarget().getToken()));
523
					
524
					// set bounds
525
					relDescriptor.setBounds(trel.getBounds());
526
					// add relation descriptor to plan
527
					plan.addRelation(relDescriptor);
528
				}
529
			}
530
		}
531
		
532
		// return plan descriptor
533
		return plan;
534
	}
535
536
	/**
537
	 * 
538
	 */
539
	@Override
540
	public int hashCode() {
541
		final int prime = 31;
542
		int result = 1;
543
		result = prime * result + ((name == null) ? 0 : name.hashCode());
544
		return result;
545
	}
546
547
	/**
548
	 * 
549
	 */
550
	@Override
551
	public boolean equals(Object obj) {
552
		if (this == obj)
553
			return true;
554
		if (obj == null)
555
			return false;
556
		if (getClass() != obj.getClass())
557
			return false;
558
		SolutionPlan other = (SolutionPlan) obj;
559
		if (name == null) {
560
			if (other.name != null)
561
				return false;
562
		} else if (!name.equals(other.name))
563
			return false;
564
		return true;
565
	}
566
	
567
	/**
568
	 * 
569
	 */
570
	@Override
571
	public String toString() 
572
	{
573
		// get plan makespan 
574
		double[] mk = this.getMakespan();
575
		// initialize solution plan description
576
		String description = "{\n"
577
				+ "\t\"horizon\": " + this.horizion + ",\n"
578
				+ "\t\"controllability\": \"" + this.controllability.toString().toLowerCase() + "\",\n"
579
				+ "\t\"makespan\": [" + mk[0] + ", " + mk[1] + "],\n"
580
				+ "\t\"solving_time\": " + solvingTime + ",\n";
581
		
582
		// check domain specific metric if any
583
		if (solutionNode.getDomainSpecificMetric() != null) {
584
			description += "\n";
585
			description += "\t\"metric\": " + solutionNode.getDomainSpecificMetric().toString() + ",\n";
586
			description += "\n";
587
		}
588
		
589
		// start description of timelines 
590
		description += "\t\"timelines\": [\n";
591 View Code Duplication
		for (Timeline tl : this.timelines) 
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
592
		{
593
			description += "\t\t{\n"
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...
594
					+ "\t\t\t\"name\": \"" + tl.getComponent().getName() + "\",\n"
595
					+ "\t\t\t\"tokens\": [\n";
596
			// get tokens
597
			for (Token token : tl.getTokens()) {
598
				description += "\t\t\t\t" + token + ",\n";
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...
599
			}
600
			description += "\t\t\t]\n"
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...
601
					+ "\t\t},\n";
602
 		}
603
		
604
		// end description of timelines
605
		description	+= "\t],\n\n";
606
		
607
		// print profiles
608
		description += "\t\"profiles\": [\n";
609
		for (Profile pro : this.profiles)
610
		{
611
			// open description
612
			description += "\t\t{\n"
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...
613
					+ "\t\t\t\"name\": \"" + pro.getName() + "\",\n"
614
					+ "\t\t\t\"initial-level\": " + pro.getInitCapacity() + ",\n"
615
					+ "\t\t\t\"min\": " + pro.getMinCapacity() + ",\n"
616
					+ "\t\t\t\"max\": " + pro.getMaxCapacity() + ",\n"
617
					+ "\t\t\t\"events\": [\n";
618
			
619
			// get events
620
			for (ResourceEvent<?> event : pro.getResourceEvents()) {
621
				description += "\t\t\t\t[\"update\": " + event.getAmount() + "  " + event.getEvent() + "],\n";
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...
622
			}
623
			
624
			// close description
625
			description += "\t\t\t]\n"
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...
626
					+ "\t\t},\n";
627
		}
628
		
629
		// description of profiles
630
		description += "\t],\n\n";
631
		
632
		// start description of observations
633
		description += "\t\"observations\": [\n";
634 View Code Duplication
		for (Timeline tl : this.observations) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
635
			description += "\t\t{\n"
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...
636
					+ "\t\t\tname: \"" + tl.getComponent().getName() + "\",\n"
637
					+ "\t\t\ttokens: [\n";
638
			// get tokens 
639
			for (Token token : tl.getTokens()) {
640
				description += "\t\t\t\t" + token + ",\n";
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...
641
			}
642
			description += "\t\t\t]\n"
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...
643
					+ "\t\t},\n";
644
		}
645
		
646
		// end description of observations
647
		description += "\t],\n\n";
648
		
649
		// start description of relations
650
		description += "\t\"relations\": [\n";
651
		for (Relation rel : this.relations) {
652
			description += "\t\t" + rel +  ",\n";
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...
653
		}
654
		
655
		// end description of relations
656
		description += "\t]\n\n";
657
		
658
		// close plan description
659
		description += "}\n\n";
660
		// get description
661
		return description;
662
	}
663
	
664
	
665
}
666