Project

General

Profile

Download (25.2 KB) Statistics
| Branch: | Revision:
1
package eu.etaxonomy.cdm.io.xper;
2

    
3
import java.util.HashMap;
4
import java.util.HashSet;
5
import java.util.List;
6
import java.util.Map;
7
import java.util.Set;
8
import java.util.UUID;
9

    
10
import org.apache.commons.lang.StringUtils;
11
import org.apache.log4j.Logger;
12
import org.springframework.stereotype.Component;
13
import org.springframework.transaction.TransactionStatus;
14

    
15
import eu.etaxonomy.cdm.api.service.ITermService;
16
import eu.etaxonomy.cdm.api.service.IVocabularyService;
17
import eu.etaxonomy.cdm.api.service.pager.Pager;
18
import eu.etaxonomy.cdm.common.CdmUtils;
19
import eu.etaxonomy.cdm.io.common.CdmIoBase;
20
import eu.etaxonomy.cdm.io.common.IoStateBase;
21
import eu.etaxonomy.cdm.model.common.CdmBase;
22
import eu.etaxonomy.cdm.model.common.DefinedTermBase;
23
import eu.etaxonomy.cdm.model.common.Language;
24
import eu.etaxonomy.cdm.model.common.Representation;
25
import eu.etaxonomy.cdm.model.common.TermVocabulary;
26
import eu.etaxonomy.cdm.model.common.UuidAndTitleCache;
27
import eu.etaxonomy.cdm.model.description.CategoricalData;
28
import eu.etaxonomy.cdm.model.description.Feature;
29
import eu.etaxonomy.cdm.model.description.FeatureNode;
30
import eu.etaxonomy.cdm.model.description.FeatureTree;
31
import eu.etaxonomy.cdm.model.description.MeasurementUnit;
32
import eu.etaxonomy.cdm.model.description.QuantitativeData;
33
import eu.etaxonomy.cdm.model.description.State;
34
import eu.etaxonomy.cdm.model.description.StateData;
35
import eu.etaxonomy.cdm.model.description.TaxonDescription;
36
import eu.etaxonomy.cdm.model.description.WorkingSet;
37
import eu.etaxonomy.cdm.model.taxon.Taxon;
38
import eu.etaxonomy.cdm.model.taxon.TaxonBase;
39
import fr_jussieu_snv_lis.XPApp;
40
import fr_jussieu_snv_lis.Xper;
41
import fr_jussieu_snv_lis.IO.IExternalAdapter;
42
import fr_jussieu_snv_lis.base.Individual;
43
import fr_jussieu_snv_lis.base.Mode;
44
import fr_jussieu_snv_lis.base.Variable;
45
import fr_jussieu_snv_lis.utils.Utils;
46

    
47
@Component
48
public class CdmXperAdapter extends CdmIoBase implements IExternalAdapter{
49
	private static final Logger logger = Logger.getLogger(CdmXperAdapter.class);
50
	
51
	private CdmXperAdapter  adapter = this;
52

    
53
//	private CdmApplicationController cdmApplicationController;
54
	private CdmXperBaseControler baseController;
55
	private UUID uuidWorkingSet;
56
//	private WorkingSet workingSet; 
57
	
58
	//TODO preliminary
59
	//CONFIGURATION
60
	private boolean isLazyModes = false;
61
	private boolean isLazyIndMatrix = true;
62
	private boolean useSecInTaxonName = false;
63
	
64
	public CdmXperAdapter(){
65
		BaseCdm base = new BaseCdm();
66
		CdmXperBaseControler baseController = new CdmXperBaseControler(base, this);
67
		setBaseController(baseController);
68
	}
69
	
70
	public boolean startXper(UUID uuidWorkingSet){
71
		this.uuidWorkingSet = uuidWorkingSet;
72
		Thread t = new Thread() {
73
			public void run() {
74
				new Xper(adapter);
75
			}
76
			
77
		};
78
		System.out.println("xper2 start");
79
		t.start();
80
//		while(!XPApp.xperReady){
81
//			//TODO
82
//		}
83
//		System.out.println("xper2 started :::");
84
		return true;
85
	}
86

    
87
	
88
//************************* GETTER /SETTER **********************/	
89

    
90
	public void setBaseController(CdmXperBaseControler baseController) {
91
		this.baseController = baseController;
92
	}
93

    
94
	/* (non-Javadoc)
95
	 * @see fr_jussieu_snv_lis.IO.IExternalAdapter#getBaseController()
96
	 */
97
	public CdmXperBaseControler getBaseController() {
98
		return baseController;
99
	}
100

    
101
	public WorkingSet getWorkingSet() {
102
//		if (this.workingSet == null){
103
			WorkingSet workingSet = getWorkingSetService().find(uuidWorkingSet);
104
//		}
105
		return workingSet;
106
	}
107
	
108
	public WorkingSet getLanguage() {
109
		
110
//		if (this.workingSet == null){
111
			WorkingSet workingSet = getWorkingSetService().find(uuidWorkingSet);
112
//		}
113
		return workingSet;
114
	}
115
	
116
	
117
	
118
//*********************** METHODS **********************/	
119
	
120
	public void load(){
121
		loadFeatures();
122
		loadTaxa();
123
	}
124

    
125
	// Load the featureTree with the UUID
126
	public void loadFeatures() {
127
		logger.warn("load features start");
128
		TransactionStatus tx = startTransaction();
129
		
130
		FeatureTree featureTree = getWorkingSet().getDescriptiveSystem();
131
		getFeatureTreeService().saveOrUpdate(featureTree);
132
		
133
		if (featureTree != null) {
134
			loadFeatureNode(featureTree.getRoot(), -1);
135
		}else{
136
			logger.warn("No feature tree available");
137
		}
138
		commitTransaction(tx);
139
		logger.warn("load features end :::");
140
	}
141

    
142

    
143
	
144
	/**
145
	 * Recursive methode to load FeatureNode and all its children
146
	 * 
147
	 * @param featureNode
148
	 * @param indiceParent
149
	 */
150
	public void loadFeatureNode(FeatureNode featureNode, int indiceParent){
151
		List<FeatureNode> featureList = featureNode.getChildren();
152
		
153
		adaptFeatureListToVariableList(indiceParent, featureList);
154
	}
155

    
156
	/**
157
	 * @param indiceParent
158
	 * @param featureList
159
	 */
160
	public void adaptFeatureListToVariableList(int indiceParent, List<FeatureNode> featureList) {
161
//		List<Variable> result = new ArrayList<Variable>(featureList.size()); 
162
		for(FeatureNode child : featureList){
163
			boolean alreadyExist = false;
164
			Variable variable = adaptFeatureNodeToVariable(child);
165
			
166
			//?? TODO
167
			List<Variable> vars = XPApp.getCurrentBase().getVariables();
168
			
169
			for(Variable var : vars){
170
				if(var.getName().equals(variable.getName()))
171
					alreadyExist = true;
172
			}
173
			
174
			if(!alreadyExist && (child.getFeature().isSupportsCategoricalData() || child.getFeature().isSupportsQuantitativeData())){
175
				
176
				XPApp.getCurrentBase().addVariable(variable);
177
//				result.add(variable);
178
				
179
				if(child.getFeature().isSupportsCategoricalData()){
180
					// Add states to the feature
181
					if (! isLazyModes){
182
						addModesToVariable(child, variable);
183
					}
184
				}
185
				
186
				if(indiceParent != -1 && XPApp.getCurrentBase().getVariableAt(indiceParent) != null){
187
//				if(indiceParent != -1 && result.get(indiceParent) != null){
188
					variable.addMother((XPApp.getCurrentBase().getVariableAt(indiceParent -1)));
189
//					variable.addMother(result.get(indiceParent -1 ));
190
				}
191
				
192
				adaptFeatureListToVariableList(variable.getIndexInt(), child.getChildren());
193
			}else{
194
				adaptFeatureListToVariableList(indiceParent, child.getChildren());
195
			}
196
		}
197
		return;
198
	}
199

    
200
	/**
201
	 * @param child
202
	 * @param variable
203
	 */
204
	private void addModesToVariable(FeatureNode child, Variable variable) {
205
		Set<TermVocabulary<State>> termVocabularySet = child.getFeature().getSupportedCategoricalEnumerations();
206
		for(TermVocabulary<State> termVocabulary : termVocabularySet){
207
			for(State state : termVocabulary.getTerms()){
208
				Mode mode = adaptStateToMode(state);
209
				variable.addMode(mode);
210
			}
211
		}
212
	}
213

    
214
	/**
215
	 * @param child
216
	 * @return
217
	 */
218
	private Variable adaptFeatureNodeToVariable(FeatureNode child) {
219
		Variable variable = new Variable(child.getFeature().getLabel());
220
		variable.setUuid(child.getFeature().getUuid());
221
		if (child.getFeature().isSupportsQuantitativeData()){
222
			// Specify the character type (numerical)
223
			variable.setType(Utils.numType);
224
		}else if (child.getFeature().isSupportsCategoricalData()){
225
			variable.setType(Utils.catType);
226
		}
227
		return variable;
228
	}
229
	
230
// ******************** STATE - MODE ***********************************/
231
	private Mode adaptStateToMode(State state) {
232
		Mode result =  new Mode(state.getLabel());
233
		result.setUuid(state.getUuid());
234
		return result;	
235
	}
236
	
237

    
238
	public State adaptModeToState(Mode mode) {
239
		State state = State.NewInstance(mode.getDescription(), mode.getName(), null);
240
		mode.setUuid(state.getUuid());
241
		return state;
242
	}
243
	
244
// ******************** TAXON - INDIVIDUAL ***********************************/
245

    
246
	/**
247
	 * @param taxonBase
248
	 * @return
249
	 */
250
	public Individual adaptTaxonToIndividual(TaxonBase taxonBase) {
251
		String name = useSecInTaxonName? taxonBase.getTitleCache() : taxonBase.getName().getTitleCache();
252
		Individual individual = new Individual(name);
253
		individual.setUuid(taxonBase.getUuid());
254
		return individual;
255
	}
256
	
257
// ******************************** ******************************************/	
258
//    // OLD
259
//	// Load all the taxa and 1 description
260
//	public void loadTaxaAndDescription() {
261
//		logger.warn("load taxa start");
262
//		//fill all variables with empty lists
263
//
264
//		
265
//		TransactionStatus tx = startTransaction();
266
//		
267
//		getWorkingSet().getDescriptions();
268
//		
269
//		logger.warn("load taxa from CDM");
270
//		List<TaxonBase> taxonList = getTaxonService().list(Taxon.class , null, null, null, null);
271
//		
272
//		for(TaxonBase taxonBase : taxonList){
273
//			if (XPApp.getCurrentBase() != null) {
274
//				
275
//				// Add a image to the taxon
276
//				BaseObjectResource bor = new BaseObjectResource(new XPResource("http://www.cheloniophilie.com/Images/Photos/Chelonia-mydas/tortue-marine.JPG"));
277
//                individual.addResource(bor); 
278
//                
279
//				// Add an empty description
280
//                
281
//                loadDescription(individual, taxonBase);
282
//                
283
//			}
284
//		}
285
//		commitTransaction(tx);
286
//		logger.warn("load taxa end :::");
287
//	}
288

    
289

    
290
	/**
291
	 * Load taxa and convert to individuals.
292
	 * Loads the 
293
	 *  - uuid
294
	 *  - name
295
	 *  - varModMatrix, 
296
	 *  - varNumValuesMatrix
297
	 *  - varComment (TODO)
298
	 *  - varUnknown (TODO)
299
	 */
300
	public void loadTaxa(){
301
		//categorical data
302
		logger.warn("load categorical data");
303
		Map<UuidAndTitleCache, Map<UUID, Set<CategoricalData>>> categoricalData = getCategoricalData();
304
		handleCategoricalData(categoricalData);
305
		logger.warn("load categorical data :::");
306
		
307
		//quantitative data
308
		logger.warn("load quantitative data");
309
		Map<UuidAndTitleCache, Map<UUID, Set<QuantitativeData>>> quantitativeData = getQuantitativeData();
310
		handleQuantitativeData(quantitativeData);
311
		logger.warn("load quantitative data :::");
312
		
313
		//TODO
314
		//descriptions with no data
315
		
316
		//TODO varComment
317
		
318
		//TODO varUnknown
319
		
320
		//TODO Resources
321
		
322
//		TODO private String index;
323
//		TODO private String description;
324

    
325
		
326
		
327
	}
328

    
329
	/**
330
	 * @return
331
	 */
332
	private Map<UuidAndTitleCache, Map<UUID, Set<CategoricalData>>> getCategoricalData() {
333
		Map<UuidAndTitleCache, Map<UUID, Set<CategoricalData>>> data = getWorkingSetService().getTaxonFeatureDescriptionElementMap(
334
				CategoricalData.class, uuidWorkingSet, null);
335
		return data;
336
	}
337

    
338
	private Map<UuidAndTitleCache, Map<UUID, Set<QuantitativeData>>> getQuantitativeData() {
339
		Map<UuidAndTitleCache, Map<UUID, Set<QuantitativeData>>> data = getWorkingSetService().getTaxonFeatureDescriptionElementMap(
340
				QuantitativeData.class, uuidWorkingSet, null);
341
		return data;
342
	}
343

    
344

    
345

    
346
	private void handleCategoricalData(Map<UuidAndTitleCache, Map<UUID, Set<CategoricalData>>> categoricalData) {
347
		for (UuidAndTitleCache taxon : categoricalData.keySet()){
348
			Map<UUID, Set<CategoricalData>> variableMap = categoricalData.get(taxon);
349
			Individual individual = getIndividualByUuidAndTitleCache(taxon);
350
			
351
			handleCategoricalData(variableMap, individual);
352
		}
353
	}
354
	
355
	private void handleQuantitativeData(Map<UuidAndTitleCache, Map<UUID, Set<QuantitativeData>>> quantitativeData) {
356
		for (UuidAndTitleCache taxon : quantitativeData.keySet()){
357
			Map<UUID, Set<QuantitativeData>> variableMap = quantitativeData.get(taxon);
358
			Individual individual = getIndividualByUuidAndTitleCache(taxon);
359
			handleQuantitativeData(variableMap, individual);
360
		}
361
	}
362

    
363

    
364
	private void handleCategoricalData(Map<UUID, Set<CategoricalData>> variableMap, Individual individual) {
365
		for (UUID featureUuid : variableMap.keySet()){
366
			Variable variable = baseController.findVariableByUuid(featureUuid);
367
			if (variable != null){
368
				for (CategoricalData categorical : variableMap.get(featureUuid)) {
369
					// create a list of xper Mode corresponding
370
					List<Mode> modesList = variable.getModes();
371
					List<StateData> stateDataList = categorical.getStates();
372
					for (StateData stateData : stateDataList) {
373
						for (Mode mode : modesList) {
374
							if (stateData.getState().getUuid().equals(mode.getUuid())) {
375
								// Add state to the Description
376
								individual.addModeMatrix(variable, mode);
377
							}
378
						}
379
					}
380
				}
381
			}else{
382
				logger.warn("Variable not found for uuid " +  featureUuid.toString());
383
			}
384
		}
385
	}
386
	
387
	
388
	private void handleQuantitativeData(Map<UUID, Set<QuantitativeData>> variableMap, Individual individual) {
389
		for (UUID featureUuid : variableMap.keySet()){
390
			Variable variable = baseController.findVariableByUuid(featureUuid);
391
			if (variable != null){
392
				for (QuantitativeData qdCDM : variableMap.get(featureUuid)){
393
					fr_jussieu_snv_lis.base.QuantitativeData qdXper = adaptQdCdm2QdXper(qdCDM);
394
					individual.addNumMatrix(variable, qdXper);
395
				}
396
			}else{
397
				logger.warn("Variable not found for uuid " +  featureUuid.toString());
398
			}
399
		}
400
	}
401

    
402
	/**
403
	 * @param qdCDM
404
	 * @return
405
	 */
406
	private fr_jussieu_snv_lis.base.QuantitativeData adaptQdCdm2QdXper(
407
			QuantitativeData qdCDM) {
408
		fr_jussieu_snv_lis.base.QuantitativeData qdXper = new fr_jussieu_snv_lis.base.QuantitativeData();
409
		
410
		if (qdCDM.getMax() != null){
411
			qdXper.setMax(new Double(qdCDM.getMax()));
412
		}
413
		if (qdCDM.getMin() != null){
414
			qdXper.setMin(new Double(qdCDM.getMin()));
415
		}
416
		if (qdCDM.getTypicalLowerBoundary() != null){
417
			qdXper.setUmethLower(new Double(qdCDM
418
					.getTypicalLowerBoundary()));
419
		}
420
		if (qdCDM.getTypicalUpperBoundary() != null){
421
			qdXper.setUmethUpper(new Double(qdCDM
422
					.getTypicalUpperBoundary()));
423
		}
424
		if (qdCDM.getAverage() != null){
425
			qdXper.setMean(new Double(qdCDM.getAverage()));
426
		}
427
		if (qdCDM.getStandardDeviation() != null){
428
			qdXper.setSd(new Double(qdCDM.getStandardDeviation()));
429
		}
430
		if (qdCDM.getSampleSize() != null){
431
			qdXper.setNSample(new Integer(Math.round(qdCDM.getSampleSize())));
432
		}
433
		return qdXper;
434
	}
435
	
436
	
437
	private Individual getIndividualByUuidAndTitleCache(UuidAndTitleCache taxon) {
438
		Individual result = this.getBaseController().findIndividualByName(taxon.getTitleCache());
439
		if (result == null){
440
			result= new Individual(taxon.getTitleCache());
441
			result.setUuid(taxon.getUuid());
442
			this.getBaseController().addIndividual(result);
443
		}
444
		return result;
445
	}
446

    
447

    
448
//	// Create a workingSet if not exist
449
//	public void createWorkingSet(){
450
//		
451
//		if(getWorkingSetService().list(WorkingSet.class, null, null, null, null).size() <= 0){
452
//			WorkingSet ws = WorkingSet.NewInstance();
453
//			
454
//			UUID featureTreeUUID = UUID.fromString("47eda782-89c7-4c69-9295-e4052ebe16c6");
455
//			List<String> featureTreeInit = Arrays.asList(new String[]{"root.children.feature.representations"});
456
//			
457
//			FeatureTree featureTree = getFeatureTreeService().load(featureTreeUUID, featureTreeInit);
458
//			ws.setDescriptiveSystem(featureTree);
459
//			
460
//			List<TaxonBase> taxonList = getTaxonService().list(Taxon.class , null, null, null, null);
461
//			for(TaxonBase taxonBase : taxonList){
462
//				Pager<TaxonDescription> taxonDescriptionPager = getDescriptionService().getTaxonDescriptions((Taxon)taxonBase, null, null, null, 0, Arrays.asList(new String[]{"elements.states", "elements.feature"} ));
463
//				List<TaxonDescription> taxonDescriptionList = taxonDescriptionPager.getRecords();
464
//				TaxonDescription taxonDescription = taxonDescriptionList.get(0);
465
//				ws.addDescription(taxonDescription);
466
//				System.out.println(taxonDescription.getUuid());
467
//			}
468
//			
469
//			getWorkingSetService().save(ws);
470
//		}
471
//	}
472

    
473
// ************************************ SAVE *************************************/	
474
	
475
	@Override
476
	public void save() {
477
		List<Variable> vars = XPApp.getCurrentBase().getVariables();
478
		saveFeatureTree(vars);
479
		saveFeatures(vars);
480
	}
481

    
482

    
483
	private void saveFeatureTree(List<Variable> vars) {
484
		logger.warn("Save feature tree  not yet implemented");
485
	}
486

    
487
	/**
488
	 * @param vars
489
	 */
490
	private void saveFeatures(List<Variable> vars) {
491
		TransactionStatus tx = startTransaction();
492
		for (Variable variable : vars){
493
			Feature feature = getFeature(variable);
494
			if (variable.isNumType()){
495
				saveNumericalFeature(variable, feature);
496
			}else if (Utils.catType.equals(variable.getType())){
497
				saveCategoricalFeature(variable, feature);
498
			}else{
499
				logger.warn("variable type undefined");
500
			}
501
		}
502
		commitTransaction(tx);
503
	}
504

    
505

    
506
	/**
507
	 * @param variable
508
	 * @return
509
	 */
510
	public Feature getFeature(Variable variable) {
511
		UUID uuid = variable.getUuid();
512
		ITermService termService = getTermService();
513
		DefinedTermBase<?> term = termService.find(uuid);
514
		Feature feature = CdmBase.deproxy(term, Feature.class);
515
		return feature;
516
	}
517

    
518
	private void saveCategoricalFeature(Variable variable, Feature feature) {
519
		ITermService termService = getTermService();
520
		IVocabularyService vocService = getVocabularyService();
521
		if (feature == null){
522
			saveNewFeature(variable, termService, vocService);
523
		}else{
524
			if (isChanged(feature, variable)){
525
				feature.setLabel(variable.getName());
526
				termService.save(feature);
527
			}else{
528
				logger.info("No change for variable: " + variable.getName());
529
			}
530
			
531
			HashMap<UUID, State> allStates = getAllSupportedStates(feature);
532
			for (Mode mode : variable.getModes()){
533
				State state = allStates.get(mode.getUuid());
534
				if (state == null){
535
					saveNewState(mode, feature);
536
				}else{
537
					allStates.remove(state.getUuid());
538
					if (modeHasChanged(mode, state)){
539
						String stateDescription = null;
540
						String stateLabel = mode.getName();
541
						String stateAbbrev = null;
542
						Language lang = Language.DEFAULT();
543
						Representation rep = state.getRepresentation(lang);
544
						rep.setLabel(stateLabel);
545
						termService.saveOrUpdate(state);
546
//						State state = State.NewInstance(stateDescription, stateLabel, stateAbbrev);
547
//						termService.save(state);
548
//						voc.addTerm(state);
549
//						vocService.save(voc);
550
					}
551
				}
552
			}
553
			for (State state : allStates.values()){
554
				logger.warn("There is a state to delete: " + feature.getLabel() + "-" + state.getLabel());
555
				for (TermVocabulary<State> voc :feature.getSupportedCategoricalEnumerations()){
556
					voc.removeTerm(state);
557
				}
558
			}
559
		}
560
	}
561

    
562

    
563
	private boolean modeHasChanged(Mode mode, State state) {
564
		if (CdmUtils.nullSafeEqual(mode.getName(), state.getLabel())){
565
			return false;
566
		}else{
567
			return true;
568
		}
569
	}
570

    
571

    
572
	public void saveNewState(Mode mode, Feature feature) {
573
		TransactionStatus ta = startTransaction();
574
		ITermService termService = getTermService();
575
		IVocabularyService vocService = getVocabularyService();
576
		
577
		termService.saveOrUpdate(feature);
578
		int numberOfVocs = feature.getSupportedCategoricalEnumerations().size();
579
		
580
		TermVocabulary<State> voc;
581
		if (numberOfVocs <= 0){
582
			//new voc
583
			String vocLabel = "Vocabulary for feature " + feature.getLabel();
584
			String vocDescription = vocLabel + ". Automatically created by Xper.";
585
			String vocAbbrev = null;
586
			String termSourceUri = null;
587
			voc = TermVocabulary.NewInstance(vocDescription, vocLabel, vocAbbrev, termSourceUri);
588
		}else if (numberOfVocs == 1){
589
			voc = feature.getSupportedCategoricalEnumerations().iterator().next();
590
		}else{
591
			//numberOfVocs > 1
592
			//FIXME preliminary
593
			logger.warn("Multiple supported vocabularies not yet correctly implemented");
594
			voc = feature.getSupportedCategoricalEnumerations().iterator().next();
595
		}
596
		saveNewModeToVoc(termService, vocService, voc, mode);
597
		commitTransaction(ta);
598
	}
599
	
600

    
601
	/**
602
	 * @param variable
603
	 * @param termService
604
	 * @param vocService
605
	 */
606
	private void saveNewFeature(Variable variable, ITermService termService,
607
			IVocabularyService vocService) {
608
		Feature feature;
609
		//new feature
610
		String description = null;
611
		String label = variable.getName();
612
		String labelAbbrev = null;
613
		feature = Feature.NewInstance(description, label, labelAbbrev);
614
		variable.setUuid(feature.getUuid());
615
		termService.save(feature);
616
		//new voc
617
		String vocDescription = null;
618
		String vocLabel = "Vocabulary for feature " + label;
619
		String vocAbbrev = null;
620
		String termSourceUri = null;
621
		TermVocabulary<State> voc = TermVocabulary.NewInstance(vocDescription, vocLabel, vocAbbrev, termSourceUri);
622
		for (Mode mode:variable.getModes()){
623
			saveNewModeToVoc(termService, vocService, voc, mode);
624
		}
625
		feature.addSupportedCategoricalEnumeration(voc);
626
		termService.saveOrUpdate(feature);
627
	}
628

    
629

    
630
	/**
631
	 * @param termService
632
	 * @param vocService
633
	 * @param voc
634
	 * @param mode
635
	 */
636
	private void saveNewModeToVoc(ITermService termService, IVocabularyService vocService, TermVocabulary<State> voc, Mode mode) {
637
		State state = adaptModeToState(mode);
638
		termService.save(state);
639
		voc.addTerm(state);
640
		vocService.saveOrUpdate(voc);
641
	}
642

    
643

    
644

    
645
	private HashMap<UUID, State> getAllSupportedStates(Feature feature) {
646
		HashMap<UUID, State> result = new HashMap<UUID,State>();
647
		Set<TermVocabulary<State>> vocs = feature.getSupportedCategoricalEnumerations();
648
		for (TermVocabulary<State> voc : vocs){
649
			for (State state : voc.getTerms()){
650
				result.put(state.getUuid(), state);
651
			}
652
		}
653
		return result;
654
	}
655

    
656

    
657
	private boolean isChanged(Feature feature, Variable variable) {
658
		//preliminary
659
		return ! variable.getName().equals(feature.getLabel());
660
	}
661

    
662

    
663

    
664
	private void saveNumericalFeature(Variable variable, Feature feature) {
665
//		IVocabularyService vocService = getVocabularyService();
666
		String variableUnit = variable.getUnit();
667
		Set<MeasurementUnit> units = feature.getRecommendedMeasurementUnits();
668
		//preliminary
669
		if (StringUtils.isBlank(variableUnit) ){
670
			//unit is empty
671
			if (!units.isEmpty()){
672
				feature.getRecommendedMeasurementUnits().clear();
673
			}
674
		}else{
675
			// unit is not empty
676
			boolean unitExists = false;
677
			for (MeasurementUnit measurementUnit: units){
678
				//TODO ??
679
				String labelOfUnit = measurementUnit.getLabel();
680
				if (variableUnit.equals(labelOfUnit)){
681
					unitExists = true;
682
					break;
683
				}
684
			}
685
			if (! unitExists){
686
				units.clear();
687
				MeasurementUnit existingUnit = findExistingUnit(variableUnit);
688
				if (existingUnit == null){
689
					String unitDescription = null;
690
					String unitLabel = variableUnit;
691
					String labelAbbrev = null;
692
					MeasurementUnit newUnit = MeasurementUnit.NewInstance(unitDescription, unitLabel, labelAbbrev);
693
					getTermService().save(newUnit);
694
					UUID defaultMeasurmentUnitVocabularyUuid = UUID.fromString("3b82c375-66bb-4636-be74-dc9cd087292a");
695
					TermVocabulary voc = getVocabularyService().find(defaultMeasurmentUnitVocabularyUuid);
696
					if (voc == null){
697
						logger.warn("Could not find MeasurementService vocabulary");
698
					}else{
699
						voc.addTerm(newUnit);
700
						getVocabularyService().saveOrUpdate(voc);
701
					}
702
					existingUnit = newUnit;
703
				}
704
				feature.addRecommendedMeasurementUnit(existingUnit);
705
			}
706
		}
707
	}
708

    
709

    
710
	private MeasurementUnit findExistingUnit(String variableUnit) {
711
		Pager<MeasurementUnit> existingUnits = getTermService().findByRepresentationText(variableUnit, MeasurementUnit.class, null, null);
712
		for (MeasurementUnit exUnit : existingUnits.getRecords()){
713
			if (variableUnit.equals(exUnit.getLabel())){
714
				return exUnit;
715
			}
716
		}
717
		return null;
718
	}
719

    
720

    
721
// ************************** Override ********************************/	
722
	
723
	@Override
724
	protected boolean doInvoke(IoStateBase state) {
725
		//not needed
726
		return false;
727
	}
728

    
729
	@Override
730
	protected boolean doCheck(IoStateBase state) {
731
		//not needed
732
		return false;
733
	}
734

    
735
	@Override
736
	protected boolean isIgnore(IoStateBase state) {
737
		//not needed
738
		return false;
739
	}
740

    
741
	@Override
742
	public String toString() {
743
		String ws = uuidWorkingSet == null ?"-" : uuidWorkingSet.toString();
744
		return "CdmXperAdapter (" + ws + ")";
745
	}
746

    
747
	public void controlModeIndVar(boolean selected, Variable v, Individual i, Mode m) {
748
//		(boolean selected, Variable v, Individual i, Mode m);
749
		TransactionStatus txStatus = startTransaction();
750
		Taxon taxon = (Taxon)getTaxonService().find(i.getUuid());
751
		Feature feature = (Feature)getTermService().find(v.getUuid());
752
		Set<Feature> features = new HashSet<Feature>();
753
		features.add(feature);
754
		List<CategoricalData> catData = getDescriptionService().getDescriptionElementsForTaxon(taxon, features, CategoricalData.class, null, null, null);
755
		if (catData.size()>1){
756
			logger.warn("There is more than one categorical data for the same taxon and the same feature");
757
		}
758
		if (selected && catData.size() == 0 ){
759
			CategoricalData data = CategoricalData.NewInstance();
760
			data.setFeature(feature);
761
			TaxonDescription desc = taxon.getDescriptions().iterator().next();
762
			desc.addElement(data);
763
			addModeToCategoricalData(m, data);
764
			getDescriptionService().saveDescriptionElement(data);
765
		}else{
766
			for (CategoricalData data: catData){
767
				State tmpState = adaptModeToState(m);
768
				StateData existingState = null;
769
				//test data exists
770
				for (StateData sd : data.getStates()){
771
					if (tmpState.equals(sd.getState())){
772
						existingState = sd;
773
						break;
774
					}
775
				}
776
				if (selected && existingState == null){
777
					//selected
778
					addModeToCategoricalData(m, data);
779
				}else if (!selected && existingState != null){
780
					//unselected
781
					data.getStates().remove(existingState);
782
				}
783
				getDescriptionService().saveDescriptionElement(data);
784
			}
785
		}
786
		commitTransaction(txStatus);
787
		
788
	}
789

    
790
	/**
791
	 * @param m
792
	 * @param data
793
	 */
794
	private void addModeToCategoricalData(Mode m, CategoricalData data) {
795
		StateData sd =  StateData.NewInstance();
796
		State state = (State)getTermService().find(m.getUuid());
797
		sd.setState(state);
798
		data.getStates().add(sd);
799
	}
800
	
801
	
802
	
803

    
804
}
(2-2/3)