Revision 4fbf8f87
Added by Patrick Plitzner over 6 years ago
eu.etaxonomy.taxeditor.editor/src/main/java/eu/etaxonomy/taxeditor/editor/workingSet/matrix/CharacterMatrix.java | ||
---|---|---|
11 | 11 |
import java.util.ArrayList; |
12 | 12 |
import java.util.Collection; |
13 | 13 |
import java.util.Collections; |
14 |
import java.util.HashMap; |
|
14 | 15 |
import java.util.List; |
16 |
import java.util.Map; |
|
15 | 17 |
import java.util.Set; |
16 | 18 |
import java.util.UUID; |
17 | 19 |
|
... | ... | |
19 | 21 |
import javax.annotation.PreDestroy; |
20 | 22 |
import javax.inject.Inject; |
21 | 23 |
|
24 |
import org.apache.commons.collections4.map.LinkedMap; |
|
22 | 25 |
import org.eclipse.core.runtime.IProgressMonitor; |
23 | 26 |
import org.eclipse.e4.ui.di.Focus; |
24 | 27 |
import org.eclipse.e4.ui.di.Persist; |
... | ... | |
79 | 82 |
import eu.etaxonomy.cdm.model.description.DescriptionBase; |
80 | 83 |
import eu.etaxonomy.cdm.model.description.Feature; |
81 | 84 |
import eu.etaxonomy.cdm.model.description.FeatureTree; |
85 |
import eu.etaxonomy.cdm.model.description.MeasurementUnit; |
|
82 | 86 |
import eu.etaxonomy.cdm.model.description.SpecimenDescription; |
83 | 87 |
import eu.etaxonomy.cdm.model.description.State; |
84 | 88 |
import eu.etaxonomy.cdm.model.description.WorkingSet; |
... | ... | |
89 | 93 |
import eu.etaxonomy.taxeditor.editor.workingSet.matrix.quantitative.QuantitativeDataDisplayConverter; |
90 | 94 |
import eu.etaxonomy.taxeditor.model.IDirtyMarkable; |
91 | 95 |
import eu.etaxonomy.taxeditor.model.IPartContentHasDetails; |
96 |
import eu.etaxonomy.taxeditor.model.MessagingUtils; |
|
92 | 97 |
import eu.etaxonomy.taxeditor.store.CdmStore; |
93 | 98 |
import eu.etaxonomy.taxeditor.workbench.part.IE4SavablePart; |
94 | 99 |
|
... | ... | |
99 | 104 |
*/ |
100 | 105 |
public class CharacterMatrix implements IE4SavablePart, IPartContentHasDetails, IConversationEnabled, IDirtyMarkable{ |
101 | 106 |
|
107 |
private static final int LEADING_COLUMN_COUNT = 4; |
|
108 |
private static final String TAXON_COLUMN = "taxon_column"; |
|
109 |
private static final String COLLECTOR_COLUMN = "collector_column"; |
|
110 |
private static final String IDENTIFIER_COLUMN = "identifier_column"; |
|
111 |
private static final String COUNTRY_COLUMN = "country_column"; |
|
112 |
|
|
102 | 113 |
private WorkingSet workingSet; |
103 | 114 |
|
104 | 115 |
private Composite parent; |
... | ... | |
116 | 127 |
|
117 | 128 |
private NatTable natTable; |
118 | 129 |
|
119 |
private List<Feature> features; |
|
130 |
private Map<Integer, Feature> indexToFeatureMap = new HashMap<>(); |
|
131 |
|
|
132 |
private LinkedMap<String, String> propertyToLabelMap = new LinkedMap<>(); |
|
120 | 133 |
|
121 | 134 |
@PostConstruct |
122 | 135 |
public void create(Composite parent) { |
... | ... | |
137 | 150 |
|
138 | 151 |
//get features/columns stored in working set |
139 | 152 |
FeatureTree tree = workingSet.getDescriptiveSystem(); |
140 |
features = new ArrayList<>(tree.getDistinctFeatures()); |
|
153 |
List<Feature> features = new ArrayList<>(tree.getDistinctFeatures());
|
|
141 | 154 |
Collections.sort(features); |
142 | 155 |
|
143 | 156 |
|
... | ... | |
147 | 160 |
/** |
148 | 161 |
* data provider |
149 | 162 |
*/ |
150 |
SpecimenColumnPropertyAccessor columnPropertyAccessor = new SpecimenColumnPropertyAccessor(features);
|
|
163 |
SpecimenColumnPropertyAccessor columnPropertyAccessor = new SpecimenColumnPropertyAccessor(this);
|
|
151 | 164 |
IDataProvider bodyDataProvider = new ListDataProvider<SpecimenDescription>(sortedList, columnPropertyAccessor); |
152 | 165 |
|
153 | 166 |
/** |
... | ... | |
156 | 169 |
DataLayer bodyDataLayer = new DataLayer(bodyDataProvider); |
157 | 170 |
final ColumnOverrideLabelAccumulator columnLabelAccumulator =new ColumnOverrideLabelAccumulator(bodyDataLayer); |
158 | 171 |
bodyDataLayer.setConfigLabelAccumulator(columnLabelAccumulator); |
159 |
registerColumnLabels(columnLabelAccumulator); |
|
172 |
for(int i=0;i<features.size();i++){ |
|
173 |
Feature feature = features.get(i); |
|
174 |
initLabels(features, columnLabelAccumulator, i, feature); |
|
175 |
} |
|
160 | 176 |
GlazedListsEventLayer<SpecimenDescription> eventLayer = new GlazedListsEventLayer<>(bodyDataLayer, sortedList); |
161 | 177 |
|
162 | 178 |
RowReorderLayer rowReorderLayer = new RowReorderLayer(eventLayer); |
... | ... | |
168 | 184 |
* column header layer |
169 | 185 |
*/ |
170 | 186 |
IDataProvider columnHeaderDataProvider = new DefaultColumnHeaderDataProvider( |
171 |
columnPropertyAccessor.getPropertyToLabelMap().values().toArray(new String[] {}), columnPropertyAccessor.getPropertyToLabelMap());
|
|
187 |
propertyToLabelMap.values().toArray(new String[] {}), propertyToLabelMap);
|
|
172 | 188 |
DataLayer columnHeaderDataLayer = new DataLayer(columnHeaderDataProvider); |
173 | 189 |
ILayer columnHeaderLayer = new ColumnHeaderLayer(columnHeaderDataLayer, viewportLayer, selectionLayer); |
174 | 190 |
|
... | ... | |
221 | 237 |
natTable.addConfiguration(new SingleClickSortConfiguration()); |
222 | 238 |
|
223 | 239 |
|
224 |
// add custom configuration for data conversion |
|
240 |
// add custom configuration for data conversion and add column labels for each feature
|
|
225 | 241 |
viewportLayer.addConfiguration(new AbstractRegistryConfiguration() { |
226 | 242 |
@Override |
227 | 243 |
public void configureRegistry(IConfigRegistry configRegistry) { |
228 |
features.forEach(feature -> registerColumnConfiguration(feature, configRegistry)); |
|
229 |
} |
|
244 |
features.forEach(feature->registerColumnConfiguration(feature, configRegistry)); |
|
230 | 245 |
} |
231 |
); |
|
246 |
|
|
247 |
}); |
|
232 | 248 |
|
233 | 249 |
// add the ExportCommandHandler to the ViewportLayer in order to make |
234 | 250 |
// exporting work |
... | ... | |
269 | 285 |
parent.layout(); |
270 | 286 |
} |
271 | 287 |
|
272 |
private void registerColumnLabels(ColumnOverrideLabelAccumulator columnLabelAccumulator) { |
|
273 |
for(int i=0;i<features.size();i++){ |
|
274 |
columnLabelAccumulator.registerColumnOverrides(i, getProperty(features.get(i))); |
|
288 |
private void initLabels(List<Feature> features, final ColumnOverrideLabelAccumulator columnLabelAccumulator, |
|
289 |
int index, Feature feature) { |
|
290 |
|
|
291 |
propertyToLabelMap.put(TAXON_COLUMN, "Taxon"); |
|
292 |
propertyToLabelMap.put(COLLECTOR_COLUMN, "Collector + No"); |
|
293 |
propertyToLabelMap.put(IDENTIFIER_COLUMN, "Identifier"); |
|
294 |
propertyToLabelMap.put(COUNTRY_COLUMN, "Country"); |
|
295 |
|
|
296 |
columnLabelAccumulator.registerColumnOverrides(index+LEADING_COLUMN_COUNT, getProperty(features.get(index))); |
|
297 |
indexToFeatureMap.put(index+LEADING_COLUMN_COUNT, feature); |
|
298 |
|
|
299 |
String featureLabel = feature.getLabel(); |
|
300 |
String property = featureLabel; |
|
301 |
//show unit for quantitative data |
|
302 |
if(feature.isSupportsQuantitativeData()){ |
|
303 |
Set<MeasurementUnit> recommendedMeasurementUnits = feature.getRecommendedMeasurementUnits(); |
|
304 |
if(recommendedMeasurementUnits.size()!=1){ |
|
305 |
MessagingUtils.error(SpecimenColumnPropertyAccessor.class, "Only one unit is allowed for quantitative data", null); |
|
306 |
return; |
|
307 |
} |
|
308 |
MeasurementUnit unit = recommendedMeasurementUnits.iterator().next(); |
|
309 |
featureLabel += " ["+unit.getLabel()+"]"; |
|
275 | 310 |
} |
311 |
propertyToLabelMap.put(property, featureLabel); |
|
276 | 312 |
} |
277 | 313 |
|
278 | 314 |
private void registerColumnConfiguration(Feature feature, IConfigRegistry configRegistry) { |
... | ... | |
311 | 347 |
@Override |
312 | 348 |
public List<?> getValues(int columnIndex, int rowIndex) { |
313 | 349 |
List<State> states = new ArrayList<>(); |
314 |
Feature feature = features.get(columnIndex);
|
|
350 |
Feature feature = indexToFeatureMap.get(columnIndex);
|
|
315 | 351 |
if(feature.isSupportsCategoricalData()){ |
316 | 352 |
Set<TermVocabulary<State>> stateVocs = feature.getSupportedCategoricalEnumerations(); |
317 | 353 |
for (TermVocabulary<State> voc : stateVocs) { |
... | ... | |
342 | 378 |
return descriptions; |
343 | 379 |
} |
344 | 380 |
|
345 |
public List<Feature> getFeatures() { |
|
346 |
return features; |
|
347 |
} |
|
348 |
|
|
349 | 381 |
private String getProperty(Feature feature){ |
350 | 382 |
return feature.getLabel(); |
351 | 383 |
} |
352 | 384 |
|
385 |
public Map<Integer, Feature> getIndexToFeatureMap() { |
|
386 |
return indexToFeatureMap; |
|
387 |
} |
|
388 |
|
|
389 |
public LinkedMap<String, String> getPropertyToLabelMap() { |
|
390 |
return propertyToLabelMap; |
|
391 |
} |
|
392 |
|
|
353 | 393 |
public void setDirty() { |
354 | 394 |
this.dirty.setDirty(true); |
355 | 395 |
} |
eu.etaxonomy.taxeditor.editor/src/main/java/eu/etaxonomy/taxeditor/editor/workingSet/matrix/SpecimenColumnPropertyAccessor.java | ||
---|---|---|
11 | 11 |
import java.util.ArrayList; |
12 | 12 |
import java.util.Collection; |
13 | 13 |
import java.util.List; |
14 |
import java.util.Map; |
|
15 | 14 |
import java.util.Set; |
16 | 15 |
|
17 |
import org.apache.commons.collections4.map.LinkedMap; |
|
18 | 16 |
import org.eclipse.nebula.widgets.nattable.data.IColumnPropertyAccessor; |
19 | 17 |
|
18 |
import eu.etaxonomy.cdm.api.service.IOccurrenceService; |
|
19 |
import eu.etaxonomy.cdm.hibernate.HibernateProxyHelper; |
|
20 | 20 |
import eu.etaxonomy.cdm.model.description.CategoricalData; |
21 | 21 |
import eu.etaxonomy.cdm.model.description.DescriptionElementBase; |
22 | 22 |
import eu.etaxonomy.cdm.model.description.Feature; |
23 |
import eu.etaxonomy.cdm.model.description.MeasurementUnit; |
|
24 | 23 |
import eu.etaxonomy.cdm.model.description.SpecimenDescription; |
25 | 24 |
import eu.etaxonomy.cdm.model.description.State; |
26 | 25 |
import eu.etaxonomy.cdm.model.description.StateData; |
27 |
import eu.etaxonomy.taxeditor.model.MessagingUtils; |
|
26 |
import eu.etaxonomy.cdm.model.occurrence.DerivedUnit; |
|
27 |
import eu.etaxonomy.cdm.model.occurrence.FieldUnit; |
|
28 |
import eu.etaxonomy.cdm.model.occurrence.SpecimenOrObservationBase; |
|
29 |
import eu.etaxonomy.taxeditor.store.CdmStore; |
|
28 | 30 |
|
29 | 31 |
/** |
30 | 32 |
* @author pplitzner |
... | ... | |
33 | 35 |
*/ |
34 | 36 |
public class SpecimenColumnPropertyAccessor implements IColumnPropertyAccessor<SpecimenDescription>{ |
35 | 37 |
|
36 |
private final List<Feature> features; |
|
37 |
private LinkedMap<String, String> propertyToLabelMap = new LinkedMap<>(); |
|
38 |
|
|
39 |
|
|
40 |
public SpecimenColumnPropertyAccessor(final List<Feature> features) { |
|
41 |
this.features = features; |
|
42 |
for (Feature feature : features) { |
|
43 |
String featureLabel = feature.getLabel(); |
|
44 |
String property = featureLabel; |
|
45 |
//show unit for quantitative data |
|
46 |
if(feature.isSupportsQuantitativeData()){ |
|
47 |
Set<MeasurementUnit> recommendedMeasurementUnits = feature.getRecommendedMeasurementUnits(); |
|
48 |
if(recommendedMeasurementUnits.size()!=1){ |
|
49 |
MessagingUtils.error(SpecimenColumnPropertyAccessor.class, "Only one unit is allowed for quantitative data", null); |
|
50 |
continue; |
|
51 |
} |
|
52 |
MeasurementUnit unit = recommendedMeasurementUnits.iterator().next(); |
|
53 |
featureLabel += " ["+unit.getLabel()+"]"; |
|
54 |
} |
|
55 |
propertyToLabelMap.put(property, featureLabel); |
|
56 |
} |
|
57 |
} |
|
38 |
private CharacterMatrix matrix; |
|
58 | 39 |
|
59 |
public Map<String, String> getPropertyToLabelMap() {
|
|
60 |
return propertyToLabelMap;
|
|
40 |
public SpecimenColumnPropertyAccessor(CharacterMatrix matrix) {
|
|
41 |
this.matrix = matrix;
|
|
61 | 42 |
} |
62 | 43 |
|
44 |
|
|
63 | 45 |
/** |
64 | 46 |
* {@inheritDoc} |
65 | 47 |
*/ |
66 | 48 |
@Override |
67 |
public DescriptionElementBase getDataValue(SpecimenDescription rowObject, int columnIndex) { |
|
68 |
Feature feature = features.get(columnIndex); |
|
49 |
public Object getDataValue(SpecimenDescription rowObject, int columnIndex) { |
|
50 |
IOccurrenceService occurrenceService = CdmStore.getService(IOccurrenceService.class); |
|
51 |
SpecimenOrObservationBase<?> specimen = rowObject.getDescribedSpecimenOrObservation(); |
|
52 |
Collection<FieldUnit> fieldUnits = occurrenceService.getFieldUnits(specimen.getUuid()); |
|
53 |
switch (columnIndex) { |
|
54 |
case 0: |
|
55 |
return occurrenceService.listAssociatedTaxa(specimen, null, null, null, null); |
|
56 |
case 1: |
|
57 |
if(fieldUnits.size()!=1){ |
|
58 |
return "More than one or no field unit found for specimen"; |
|
59 |
} |
|
60 |
return fieldUnits.iterator().next(); |
|
61 |
case 2: |
|
62 |
if(specimen instanceof DerivedUnit){ |
|
63 |
return occurrenceService.getMostSignificantIdentifier(HibernateProxyHelper.deproxy(specimen, DerivedUnit.class)); |
|
64 |
} |
|
65 |
return null; |
|
66 |
case 3: |
|
67 |
if(fieldUnits.size()!=1){ |
|
68 |
return "More than one or no field unit found for specimen"; |
|
69 |
} |
|
70 |
FieldUnit fieldUnit = fieldUnits.iterator().next(); |
|
71 |
if(fieldUnit.getGatheringEvent()!=null){ |
|
72 |
return fieldUnit.getGatheringEvent().getCountry(); |
|
73 |
} |
|
74 |
return null; |
|
75 |
|
|
76 |
default: |
|
77 |
break; |
|
78 |
} |
|
79 |
Feature feature = matrix.getIndexToFeatureMap().get(columnIndex); |
|
69 | 80 |
Set<DescriptionElementBase> elements = rowObject.getElements(); |
70 | 81 |
for (DescriptionElementBase descriptionElementBase : elements) { |
71 | 82 |
if(descriptionElementBase.getFeature().equals(feature)){ |
... | ... | |
80 | 91 |
*/ |
81 | 92 |
@Override |
82 | 93 |
public void setDataValue(SpecimenDescription rowObject, int columnIndex, Object newValue) { |
83 |
Feature feature = features.get(columnIndex);
|
|
94 |
Feature feature = matrix.getIndexToFeatureMap().get(columnIndex);
|
|
84 | 95 |
Set<DescriptionElementBase> elements = rowObject.getElements(); |
85 | 96 |
for (DescriptionElementBase descriptionElementBase : elements) { |
86 | 97 |
if(descriptionElementBase.getFeature().equals(feature)){ |
87 |
setDescriptionElement(rowObject, descriptionElementBase, feature, newValue);
|
|
98 |
setDescriptionElement(descriptionElementBase, feature, newValue); |
|
88 | 99 |
} |
89 | 100 |
} |
90 | 101 |
} |
91 | 102 |
|
92 | 103 |
|
93 |
private void setDescriptionElement(SpecimenDescription description, DescriptionElementBase descriptionElementBase, Feature feature, Object newValue) {
|
|
104 |
private void setDescriptionElement(DescriptionElementBase descriptionElementBase, Feature feature, Object newValue) { |
|
94 | 105 |
//FIXME move this to cdmlib service layer |
95 | 106 |
if(feature.isSupportsCategoricalData() && descriptionElementBase instanceof CategoricalData && newValue instanceof Collection){ |
96 | 107 |
CategoricalData categoricalData = (CategoricalData)descriptionElementBase; |
... | ... | |
110 | 121 |
*/ |
111 | 122 |
@Override |
112 | 123 |
public int getColumnCount() { |
113 |
return features.size();
|
|
124 |
return matrix.getPropertyToLabelMap().size();
|
|
114 | 125 |
} |
115 | 126 |
|
116 | 127 |
/** |
... | ... | |
118 | 129 |
*/ |
119 | 130 |
@Override |
120 | 131 |
public String getColumnProperty(int columnIndex) { |
121 |
return features.get(columnIndex).getLabel();
|
|
132 |
return matrix.getPropertyToLabelMap().get(columnIndex);
|
|
122 | 133 |
} |
123 | 134 |
|
124 | 135 |
/** |
... | ... | |
126 | 137 |
*/ |
127 | 138 |
@Override |
128 | 139 |
public int getColumnIndex(String propertyName){ |
129 |
return propertyToLabelMap.indexOf(propertyName);
|
|
140 |
return matrix.getPropertyToLabelMap().indexOf(propertyName);
|
|
130 | 141 |
} |
131 | 142 |
|
132 | 143 |
} |
eu.etaxonomy.taxeditor.editor/src/main/java/eu/etaxonomy/taxeditor/editor/workingSet/matrix/categorical/CategoricalDataDisplayConverter.java | ||
---|---|---|
32 | 32 |
else if(canonicalValue instanceof State){ |
33 | 33 |
return ((State) canonicalValue).getLabel(); |
34 | 34 |
} |
35 |
return canonicalValue.toString(); |
|
35 |
else if(canonicalValue!=null){ |
|
36 |
return canonicalValue.toString(); |
|
37 |
} |
|
38 |
return null; |
|
36 | 39 |
} |
37 | 40 |
|
38 | 41 |
/** |
Also available in: Unified diff
ref #7095 Add non-editable additional columns with extra info to matrix