starting Xper with interfaces
[cdmlib-apps.git] / XperCdmIntegration / src / main / java / eu / etaxonomy / xper / AdaptaterCdmXper.java
1 package eu.etaxonomy.xper;
2
3 import java.util.ArrayList;
4 import java.util.Arrays;
5 import java.util.HashMap;
6 import java.util.List;
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.transaction.TransactionStatus;
13
14 import eu.etaxonomy.cdm.api.service.ITermService;
15 import eu.etaxonomy.cdm.api.service.IVocabularyService;
16 import eu.etaxonomy.cdm.api.service.pager.Pager;
17 import eu.etaxonomy.cdm.common.CdmUtils;
18 import eu.etaxonomy.cdm.model.common.CdmBase;
19 import eu.etaxonomy.cdm.model.common.DefinedTermBase;
20 import eu.etaxonomy.cdm.model.common.Language;
21 import eu.etaxonomy.cdm.model.common.Representation;
22 import eu.etaxonomy.cdm.model.common.TermVocabulary;
23 import eu.etaxonomy.cdm.model.description.CategoricalData;
24 import eu.etaxonomy.cdm.model.description.DescriptionElementBase;
25 import eu.etaxonomy.cdm.model.description.Feature;
26 import eu.etaxonomy.cdm.model.description.FeatureNode;
27 import eu.etaxonomy.cdm.model.description.FeatureTree;
28 import eu.etaxonomy.cdm.model.description.MeasurementUnit;
29 import eu.etaxonomy.cdm.model.description.QuantitativeData;
30 import eu.etaxonomy.cdm.model.description.State;
31 import eu.etaxonomy.cdm.model.description.StateData;
32 import eu.etaxonomy.cdm.model.description.TaxonDescription;
33 import eu.etaxonomy.cdm.model.description.WorkingSet;
34 import eu.etaxonomy.cdm.model.taxon.Taxon;
35 import eu.etaxonomy.cdm.model.taxon.TaxonBase;
36 import fr_jussieu_snv_lis.Xper;
37 import fr_jussieu_snv_lis.IO.ICdmAdapter;
38 import fr_jussieu_snv_lis.base.BaseObjectResource;
39 import fr_jussieu_snv_lis.base.IPersistenceSaveList;
40 import fr_jussieu_snv_lis.base.Individual;
41 import fr_jussieu_snv_lis.base.Mode;
42 import fr_jussieu_snv_lis.base.Variable;
43 import fr_jussieu_snv_lis.base.XPResource;
44 import fr_jussieu_snv_lis.utils.Utils;
45
46 public class AdaptaterCdmXper implements ICdmAdapter{
47 private static final Logger logger = Logger.getLogger(AdaptaterCdmXper.class);
48
49 TransactionStatus tx = Xper.getCdmApplicationController().startTransaction();
50
51 public AdaptaterCdmXper() {
52
53 }
54
55
56 public void load(){
57 loadFeatures();
58 loadTaxaAndDescription();
59
60 }
61
62 // Load the featureTree with the UUID
63 public void loadFeatures() {
64
65 UUID featureTreeUUID = UUID.fromString("1045f91b-6f1a-4a7d-8783-82a58a01ab25");
66 // UUID featureTreeUUID = UUID.fromString("43ab1efd-fa15-419a-8cd6-05477e4b37bc");
67 List<String> featureTreeInit = Arrays.asList(new String[]{"root.children.feature.representations"});
68
69 TransactionStatus tx = Xper.getCdmApplicationController().startTransaction();
70 FeatureTree featureTree = Xper.getCdmApplicationController().getFeatureTreeService().load(featureTreeUUID, featureTreeInit);
71 if (featureTree != null) {
72 loadFeatureNode(featureTree.getRoot(), -1);
73 }else{
74 logger.warn("Feature tree " + featureTreeUUID.toString() + " not found");
75 }
76 Xper.getCdmApplicationController().commitTransaction(tx);
77 }
78
79 /**
80 * Recursive methode to load FeatureNode and all its children
81 *
82 * @param featureNode
83 * @param indiceParent
84 */
85 public void loadFeatureNode(FeatureNode featureNode, int indiceParent){
86 List<FeatureNode> featureList = featureNode.getChildren();
87 for(FeatureNode child : featureList){
88 boolean alreadyExist = false;
89 Variable variable = new Variable(child.getFeature().getLabel());
90 variable.setUuid(child.getFeature().getUuid());
91 IPersistenceSaveList<Variable> vars = Utils.currentBase.getVariables();
92 for(Variable var : vars){
93 if(var.getName().equals(variable.getName()))
94 alreadyExist = true;
95 }
96
97 if(!alreadyExist && (child.getFeature().isSupportsCategoricalData() || child.getFeature().isSupportsQuantitativeData())){
98
99 Utils.currentBase.addVariable(variable);
100
101 if(child.getFeature().isSupportsCategoricalData()){
102 // Add states to the character
103 Set<TermVocabulary<State>> termVocabularySet = child.getFeature().getSupportedCategoricalEnumerations();
104 for(TermVocabulary<State> termVocabulary : termVocabularySet){
105 for(State state : termVocabulary.getTerms()){
106 Mode mode = new Mode(state.getLabel());
107 mode.setUuid(state.getUuid());
108 variable.addMode(mode);
109 }
110 }
111 }else if (child.getFeature().isSupportsQuantitativeData()) {
112 // Specify the character type (numerical)
113 variable.setType(Utils.numType);
114 }
115
116 if(indiceParent != -1 && Utils.currentBase.getVariableAt(indiceParent) != null){
117 variable.addMother(((Variable)Utils.currentBase.getVariableAt(indiceParent -1)));
118 }
119
120 loadFeatureNode(child, variable.getIndexInt());
121 }else{
122 loadFeatureNode(child, indiceParent);
123 }
124 }
125 }
126
127 // Load all the taxa and 1 description
128 public void loadTaxaAndDescription() {
129 TransactionStatus tx = Xper.getCdmApplicationController().startTransaction();
130 List<TaxonBase> taxonList = Xper.getCdmApplicationController().getTaxonService().list(Taxon.class , null, null, null, null);
131 for(TaxonBase taxonBase : taxonList){
132 if (Utils.currentBase != null) {
133 Individual individual = new Individual(taxonBase.getName().toString());
134 individual.setUuid(taxonBase.getUuid());
135
136 // Add a image to the taxon
137 BaseObjectResource bor = new BaseObjectResource(new XPResource("http://www.cheloniophilie.com/Images/Photos/Chelonia-mydas/tortue-marine.JPG"));
138 individual.addResource(bor);
139
140 // Add an empty description
141 IPersistenceSaveList<Variable> vars = Utils.currentBase.getVariables();
142 for(Variable var : vars){
143 individual.addMatrix(var, new ArrayList<Mode>());
144 }
145 loadDescription(individual, taxonBase);
146 Utils.currentBase.addIndividual(individual);
147 }
148 }
149 Xper.getCdmApplicationController().commitTransaction(tx);
150 }
151
152 // Load the first taxonDescription
153 public void loadDescription(Individual individual, TaxonBase taxonBase) {
154
155 Pager<TaxonDescription> taxonDescriptionPager = Xper.getCdmApplicationController().getDescriptionService().getTaxonDescriptions((Taxon)taxonBase, null, null, null, 0, Arrays.asList(new String[]{"elements.states", "elements.feature"} ));
156 List<TaxonDescription> taxonDescriptionList = taxonDescriptionPager.getRecords();
157 TaxonDescription taxonDescription = taxonDescriptionList.get(0);
158 Set<DescriptionElementBase> DescriptionElementBaseList = taxonDescription.getElements();
159 for(DescriptionElementBase descriptionElementBase : DescriptionElementBaseList){
160 if(descriptionElementBase instanceof CategoricalData){
161 // find the xper variable corresponding
162 Variable variable = null;
163 IPersistenceSaveList<Variable> vars = Utils.currentBase.getVariables();
164 for(Variable var : vars){
165 if(var.getUuid().equals(((CategoricalData)descriptionElementBase).getFeature().getUuid())){
166 variable = var;
167 }
168 }
169 if(variable != null){
170 // create a list of xper Mode corresponding
171 List<Mode> modesList = variable.getModes();
172 List<StateData> stateList = ((CategoricalData)descriptionElementBase).getStates();
173 for(StateData state : stateList){
174 for(Mode mode : modesList){
175 if(state.getState().getUuid().equals(mode.getUuid())){
176 // Add state to the Description
177 individual.addModeMatrix(variable, mode);
178 }
179 }
180 }
181 }
182 }else if(descriptionElementBase instanceof QuantitativeData){
183 // find the xper variable corresponding
184 Variable variable = null;
185 IPersistenceSaveList<Variable> vars = Utils.currentBase.getVariables();
186 for(Variable var : vars){
187 if(var.getUuid().equals(((QuantitativeData)descriptionElementBase).getFeature().getUuid())){
188 variable = var;
189 }
190 }
191 if(variable != null){
192 fr_jussieu_snv_lis.base.QuantitativeData qdXper = new fr_jussieu_snv_lis.base.QuantitativeData();
193 QuantitativeData qdCDM = ((QuantitativeData)descriptionElementBase);
194
195 if(qdCDM.getMax() != null)
196 qdXper.setMax(new Double(qdCDM.getMax()));
197 if(qdCDM.getMin() != null)
198 qdXper.setMin(new Double(qdCDM.getMin()));
199 if(qdCDM.getTypicalLowerBoundary() != null)
200 qdXper.setUmethLower(new Double(qdCDM.getTypicalLowerBoundary()));
201 if(qdCDM.getTypicalUpperBoundary() != null)
202 qdXper.setUmethUpper(new Double(qdCDM.getTypicalUpperBoundary()));
203
204 // Does not work
205 //qdXper.setMean(new Double(qdCDM.getAverage()));
206 //qdXper.setSd(new Double(qdCDM.getStandardDeviation()));
207 //qdXper.setNSample(new Double(qdCDM.getSampleSize()));
208
209 individual.addNumMatrix(variable, qdXper);
210 }
211
212 }
213 }
214 }
215
216 // Create a workingSet if not exist
217 public void createWorkingSet(){
218
219 if(Xper.getCdmApplicationController().getWorkingSetService().list(WorkingSet.class, null, null, null, null).size() <= 0){
220 WorkingSet ws = WorkingSet.NewInstance();
221
222 UUID featureTreeUUID = UUID.fromString("47eda782-89c7-4c69-9295-e4052ebe16c6");
223 List<String> featureTreeInit = Arrays.asList(new String[]{"root.children.feature.representations"});
224
225 FeatureTree featureTree = Xper.getCdmApplicationController().getFeatureTreeService().load(featureTreeUUID, featureTreeInit);
226 ws.setDescriptiveSystem(featureTree);
227
228 List<TaxonBase> taxonList = Xper.getCdmApplicationController().getTaxonService().list(Taxon.class , null, null, null, null);
229 for(TaxonBase taxonBase : taxonList){
230 Pager<TaxonDescription> taxonDescriptionPager = Xper.getCdmApplicationController().getDescriptionService().getTaxonDescriptions((Taxon)taxonBase, null, null, null, 0, Arrays.asList(new String[]{"elements.states", "elements.feature"} ));
231 List<TaxonDescription> taxonDescriptionList = taxonDescriptionPager.getRecords();
232 TaxonDescription taxonDescription = taxonDescriptionList.get(0);
233 ws.addDescription(taxonDescription);
234 System.out.println(taxonDescription.getUuid());
235 }
236
237 Xper.getCdmApplicationController().getWorkingSetService().save(ws);
238 }
239 }
240
241 @Override
242 public void save() {
243 IPersistenceSaveList<Variable> vars = Utils.currentBase.getVariables();
244 saveFeatureTree(vars);
245 saveFeatures(vars);
246 }
247
248
249 private void saveFeatureTree(IPersistenceSaveList<Variable> vars) {
250 logger.warn("Save feature tree not yet implemented");
251 }
252
253 /**
254 * @param vars
255 */
256 private void saveFeatures(IPersistenceSaveList<Variable> vars) {
257 tx = Xper.getCdmApplicationController().startTransaction();
258 for (Variable variable : vars){
259 Feature feature = getFeature(variable);
260 if (Utils.numType.equals(variable.getType())){
261 saveNumericalFeature(variable, feature);
262 }else if (Utils.catType.equals(variable.getType())){
263 saveCategoricalFeature(variable, feature);
264 }else{
265 logger.warn("variable type undefined");
266 }
267 }
268 Xper.getCdmApplicationController().commitTransaction(tx);
269 }
270
271
272 /**
273 * @param variable
274 * @return
275 */
276 private Feature getFeature(Variable variable) {
277 UUID uuid = variable.getUuid();
278 ITermService termService = Xper.getCdmApplicationController().getTermService();
279 DefinedTermBase<?> term = termService.find(uuid);
280 Feature feature = CdmBase.deproxy(term, Feature.class);
281 return feature;
282 }
283
284 private void saveCategoricalFeature(Variable variable, Feature feature) {
285 ITermService termService = Xper.getCdmApplicationController().getTermService();
286 IVocabularyService vocService = Xper.getCdmApplicationController().getVocabularyService();
287 if (feature == null){
288 saveNewFeature(variable, termService, vocService);
289 }else{
290 if (isChanged(feature, variable)){
291 feature.setLabel(variable.getName());
292 termService.save(feature);
293 }else{
294 logger.info("No change for variable: " + variable.getName());
295 }
296 int numberOfVocs = feature.getSupportedCategoricalEnumerations().size();
297 HashMap<UUID, State> allStates = getAllSupportedStates(feature);
298 for (Mode mode : variable.getModes()){
299 State state = allStates.get(mode.getUuid());
300 if (state == null){
301 saveNewState(mode, numberOfVocs, feature, termService, vocService);
302 }else{
303 allStates.remove(state.getUuid());
304 if (modeHasChanged(mode, state)){
305 String stateDescription = null;
306 String stateLabel = mode.getName();
307 String stateAbbrev = null;
308 Language lang = Language.DEFAULT();
309 Representation rep = state.getRepresentation(lang);
310 rep.setLabel(stateLabel);
311 termService.saveOrUpdate(state);
312 // State state = State.NewInstance(stateDescription, stateLabel, stateAbbrev);
313 // termService.save(state);
314 // voc.addTerm(state);
315 // vocService.save(voc);
316 }
317 }
318 }
319 for (State state : allStates.values()){
320 logger.warn("There is a state to delete: " + feature.getLabel() + "-" + state.getLabel());
321 for (TermVocabulary<State> voc :feature.getSupportedCategoricalEnumerations()){
322 voc.removeTerm(state);
323 }
324 }
325 }
326 }
327
328
329 private boolean modeHasChanged(Mode mode, State state) {
330 if (CdmUtils.nullSafeEqual(mode.getName(), state.getLabel())){
331 return false;
332 }else{
333 return true;
334 }
335 }
336
337
338 private void saveNewState(Mode mode, int numberOfVocs, Feature feature, ITermService termService, IVocabularyService vocService) {
339 TermVocabulary<State> voc;
340 if (numberOfVocs <= 0){
341 //new voc
342 String vocDescription = null;
343 String vocLabel = "Vocabulary for feature " + feature.getLabel();
344 String vocAbbrev = null;
345 String termSourceUri = null;
346 voc = TermVocabulary.NewInstance(vocDescription, vocLabel, vocAbbrev, termSourceUri);
347 }else if (numberOfVocs == 1){
348 voc = feature.getSupportedCategoricalEnumerations().iterator().next();
349 }else{
350 //numberOfVocs > 1
351 //FIXME preliminary
352 voc = feature.getSupportedCategoricalEnumerations().iterator().next();
353 }
354 saveNewModeToVoc(termService, vocService, voc, mode);
355 }
356
357
358 /**
359 * @param variable
360 * @param termService
361 * @param vocService
362 */
363 private void saveNewFeature(Variable variable, ITermService termService,
364 IVocabularyService vocService) {
365 Feature feature;
366 //new feature
367 String description = null;
368 String label = variable.getName();
369 String labelAbbrev = null;
370 feature = Feature.NewInstance(description, label, labelAbbrev);
371 variable.setUuid(feature.getUuid());
372 termService.save(feature);
373 //new voc
374 String vocDescription = null;
375 String vocLabel = "Vocabulary for feature " + label;
376 String vocAbbrev = null;
377 String termSourceUri = null;
378 TermVocabulary<State> voc = TermVocabulary.NewInstance(vocDescription, vocLabel, vocAbbrev, termSourceUri);
379 for (Mode mode:variable.getModes()){
380 saveNewModeToVoc(termService, vocService, voc, mode);
381 }
382 feature.addSupportedCategoricalEnumeration(voc);
383 termService.saveOrUpdate(feature);
384 }
385
386
387 /**
388 * @param termService
389 * @param vocService
390 * @param voc
391 * @param mode
392 */
393 private void saveNewModeToVoc(ITermService termService, IVocabularyService vocService, TermVocabulary<State> voc, Mode mode) {
394 String stateDescription = null;
395 String stateLabel = mode.getName();
396 String stateAbbrev = null;
397 State state = State.NewInstance(stateDescription, stateLabel, stateAbbrev);
398 mode.setUuid(state.getUuid());
399 termService.save(state);
400 voc.addTerm(state);
401 vocService.saveOrUpdate(voc);
402 }
403
404
405
406 private HashMap<UUID, State> getAllSupportedStates(Feature feature) {
407 HashMap<UUID, State> result = new HashMap<UUID,State>();
408 Set<TermVocabulary<State>> vocs = feature.getSupportedCategoricalEnumerations();
409 for (TermVocabulary<State> voc : vocs){
410 for (State state : voc.getTerms()){
411 result.put(state.getUuid(), state);
412 }
413 }
414 return result;
415 }
416
417
418 private boolean isChanged(Feature feature, Variable variable) {
419 //preliminary
420 return ! variable.getName().equals(feature.getLabel());
421 }
422
423
424
425 private void saveNumericalFeature(Variable variable, Feature feature) {
426 ITermService termService = Xper.getCdmApplicationController().getTermService();
427 IVocabularyService vocService = Xper.getCdmApplicationController().getVocabularyService();
428 String variableUnit = variable.getUnit();
429 Set<MeasurementUnit> units = feature.getRecommendedMeasurementUnits();
430 //preliminary
431 if (StringUtils.isBlank(variableUnit) ){
432 //unit is empty
433 if (!units.isEmpty()){
434 feature.getRecommendedMeasurementUnits().clear();
435 }
436 }else{
437 // unit is not empty
438 boolean unitExists = false;
439 for (MeasurementUnit measurementUnit: units){
440 //TODO ??
441 String labelOfUnit = measurementUnit.getLabel();
442 if (variableUnit.equals(labelOfUnit)){
443 unitExists = true;
444 break;
445 }
446 }
447 if (! unitExists){
448 units.clear();
449 MeasurementUnit existingUnit = findExistingUnit(variableUnit, termService);
450 if (existingUnit == null){
451 String unitDescription = null;
452 String unitLabel = variableUnit;
453 String labelAbbrev = null;
454 MeasurementUnit newUnit = MeasurementUnit.NewInstance(unitDescription, unitLabel, labelAbbrev);
455 termService.save(newUnit);
456 UUID defaultMeasurmentUnitVocabularyUuid = UUID.fromString("3b82c375-66bb-4636-be74-dc9cd087292a");
457 TermVocabulary voc = vocService.find(defaultMeasurmentUnitVocabularyUuid);
458 if (voc == null){
459 logger.warn("Could not find MeasurementService vocabulary");
460 }else{
461 voc.addTerm(newUnit);
462 vocService.saveOrUpdate(voc);
463 }
464 existingUnit = newUnit;
465 }
466 feature.addRecommendedMeasurementUnit(existingUnit);
467 }
468 }
469 }
470
471
472 private MeasurementUnit findExistingUnit(String variableUnit, ITermService termService) {
473 Pager<MeasurementUnit> existingUnits = termService.findByRepresentationText(variableUnit, MeasurementUnit.class, null, null);
474 for (MeasurementUnit exUnit : existingUnits.getRecords()){
475 if (variableUnit.equals(exUnit.getLabel())){
476 return exUnit;
477 }
478 }
479 return null;
480 }
481
482 }