ref #6401 Refactor comparison of specimens in factual data view
[taxeditor.git] / eu.etaxonomy.taxeditor.editor / src / main / java / eu / etaxonomy / taxeditor / editor / view / descriptive / DescriptiveContentProvider.java
1 /**
2 *
3 */
4 package eu.etaxonomy.taxeditor.editor.view.descriptive;
5
6 import java.util.ArrayList;
7 import java.util.Collections;
8 import java.util.Comparator;
9 import java.util.List;
10 import java.util.Map;
11 import java.util.Set;
12
13 import org.eclipse.jface.viewers.ITreeContentProvider;
14 import org.eclipse.jface.viewers.Viewer;
15
16 import eu.etaxonomy.cdm.model.common.Marker;
17 import eu.etaxonomy.cdm.model.description.DescriptionBase;
18 import eu.etaxonomy.cdm.model.description.DescriptionElementBase;
19 import eu.etaxonomy.cdm.model.description.FeatureTree;
20 import eu.etaxonomy.cdm.model.description.IDescribable;
21 import eu.etaxonomy.cdm.model.description.IndividualsAssociation;
22 import eu.etaxonomy.taxeditor.editor.definedterm.input.TermEditorInput;
23 import eu.etaxonomy.taxeditor.model.FeatureNodeContainer;
24 import eu.etaxonomy.taxeditor.model.FeatureNodeContainerTree;
25 import eu.etaxonomy.taxeditor.preference.PreferencesUtil;
26 import eu.etaxonomy.taxeditor.store.UsageTermCollection;
27
28 /**
29 * <p>DescriptiveContentProvider class.</p>
30 *
31 * @author p.ciardelli
32 * @author n.hoffmann
33 * @version $Id: $
34 */
35 public class DescriptiveContentProvider implements ITreeContentProvider {
36
37 protected static final Object[] NO_CHILDREN = new Object[0];
38 protected Map<DescriptionBase<?>, FeatureNodeContainerTree> featureNodeContainerCache;
39 private boolean showOnlyIndividualAssociations;
40
41
42 public DescriptiveContentProvider(Map<DescriptionBase<?>, FeatureNodeContainerTree> featureNodeContainerCache) {
43 this(featureNodeContainerCache, false);
44 }
45 /**
46 * <p>Constructor for DescriptiveContentProvider.</p>
47 *
48 * @param featureNodeContainerCache a {@link java.util.Map} object.
49 */
50 public DescriptiveContentProvider(Map<DescriptionBase<?>, FeatureNodeContainerTree> featureNodeContainerCache, boolean showOnlyIndividualAssociations) {
51 this.featureNodeContainerCache = featureNodeContainerCache;
52 this.showOnlyIndividualAssociations = showOnlyIndividualAssociations;
53 }
54
55 /* (non-Javadoc)
56 * @see org.eclipse.jface.viewers.ITreeContentProvider#getChildren(java.lang.Object)
57 */
58 /** {@inheritDoc} */
59 @Override
60 public Object[] getChildren(Object parentElement) {
61 if (parentElement instanceof IDescribable<?>) {
62 return getDescriptions((IDescribable<?>) parentElement).toArray();
63 }
64 else if (parentElement instanceof DescriptionBase<?>) {
65 if ( ! ((DescriptionBase<?>) parentElement).isImageGallery()) {
66 DescriptionBase<?> description = (DescriptionBase<?>) parentElement;
67
68 FeatureNodeContainerTree containerTree = getContainerTreeForDesription(description);
69 List<FeatureNodeContainer> children = containerTree.getRoot().getChildren();
70 //filter out containers with no children
71 List<FeatureNodeContainer> childrenWithChildren = new ArrayList<FeatureNodeContainer>();
72 for (FeatureNodeContainer featureNodeContainer : children) {
73 if(getChildren(featureNodeContainer).length>0){
74 childrenWithChildren.add(featureNodeContainer);
75 }
76 }
77 return childrenWithChildren.toArray();
78 }
79 }
80 else if (parentElement instanceof FeatureNodeContainer){
81 FeatureNodeContainer container = (FeatureNodeContainer) parentElement;
82 if(container.isLeaf()){
83 List<DescriptionElementBase> descriptionElements = container.getDescriptionElements();
84 List<IndividualsAssociation> individualAssociations = new ArrayList<IndividualsAssociation>();
85 for (DescriptionElementBase descriptionElement : descriptionElements) {
86 if(descriptionElement instanceof IndividualsAssociation){
87 individualAssociations.add((IndividualsAssociation) descriptionElement);
88 }
89 }
90 //sort individual associations by title cache of associated specimens
91 Collections.sort(individualAssociations, new Comparator<IndividualsAssociation>() {
92
93 @Override
94 public int compare(IndividualsAssociation o1, IndividualsAssociation o2) {
95 if(o1==null){
96 if(o2==null){
97 return 0;
98 }
99 else{
100 return -1;
101 }
102 }
103 else if(o2==null){
104 return 1;
105 }
106
107 if(o1.getAssociatedSpecimenOrObservation()==null){
108 if(o2.getAssociatedSpecimenOrObservation()==null){
109 return 0;
110 }
111 else{
112 return -1;
113 }
114 }
115 else if(o2.getAssociatedSpecimenOrObservation()==null){
116 return 1;
117 }
118
119 String titleCache1 = o1.getAssociatedSpecimenOrObservation().getTitleCache();
120 String titleCache2 = o2.getAssociatedSpecimenOrObservation().getTitleCache();
121
122 if(titleCache1==null){
123 if(titleCache2==null){
124 return 0;
125 }
126 else{
127 return -1;
128 }
129 }
130 if(titleCache2==null){
131 return 1;
132 }
133
134 return titleCache1.compareTo(titleCache2);
135 }
136 });
137 if(showOnlyIndividualAssociations){
138 descriptionElements = new ArrayList<DescriptionElementBase>(individualAssociations);
139 }
140 return descriptionElements.toArray();
141 }else{
142 return container.getChildren().toArray();
143 }
144 }
145
146 return NO_CHILDREN;
147 }
148
149 private FeatureNodeContainerTree getContainerTreeForDesription(DescriptionBase<?> description){
150 if(! featureNodeContainerCache.containsKey(description)){
151 FeatureNodeContainerTree containerTree = new FeatureNodeContainerTree(description, getFeatureTree(description));
152 featureNodeContainerCache.put(description, containerTree);
153 }
154 return featureNodeContainerCache.get(description);
155 }
156
157 /** {@inheritDoc} */
158 @Override
159 public boolean hasChildren(Object element) {
160 if (element instanceof DescriptionBase<?>){
161 DescriptionBase<?> description = (DescriptionBase<?>) element;
162 FeatureNodeContainerTree containerTree = featureNodeContainerCache.get(description);
163 if(containerTree != null && containerTree.getRoot() != null){
164 return containerTree.getRoot().getChildren().size() != 0;
165 }
166 }
167 return getChildren(element).length != 0;
168 }
169
170 /**
171 * Retrieves the feature tree associated with the given description
172 *
173 * TODO as of now this is always the same thing because feature trees may not be associated
174 * to descriptions yet.
175 *
176 * @param description
177 * @return
178 */
179 private FeatureTree getFeatureTree(DescriptionBase description){
180
181 FeatureTree featureTree;
182 // TODO change this to the feature tree associated with this taxon description
183 if (description.hasStructuredData()){
184 featureTree = PreferencesUtil.getDefaultFeatureTreeForStructuredDescription();
185 }else{
186 featureTree = PreferencesUtil.getDefaultFeatureTreeForTextualDescription();
187 }
188
189 // create a transient tree with all features if none was selected
190 if(featureTree == null){
191 featureTree = TermEditorInput.getDefaultFeatureTree();
192 }
193
194 return featureTree;
195 }
196
197 /**
198 * Get all descriptions associated with the given object
199 * @param parentElement
200 * @return
201 */
202 protected List<DescriptionBase<?>> getDescriptions(IDescribable<?> parentElement) {
203 Set<? extends DescriptionBase<?>> elementDescriptions = parentElement.getDescriptions();
204 List<DescriptionBase<?>> resultDescriptions = new ArrayList<DescriptionBase<?>>();
205 for(DescriptionBase<?> description : elementDescriptions){
206 if(! description.isImageGallery()){
207 Set<Marker> descriptionMarkers = description.getMarkers();
208 if(descriptionMarkers != null && !descriptionMarkers.isEmpty()) {
209 for (Marker marker: descriptionMarkers) {
210 if(marker.getMarkerType() != null && !(marker.getMarkerType().getUuid().equals(UsageTermCollection.uuidUseMarkerType))) {
211 resultDescriptions.add(description);
212 }
213 }
214 }
215 else {
216 resultDescriptions.add(description);
217 }
218 }
219 }
220 return resultDescriptions;
221 }
222
223 /** {@inheritDoc} */
224 @Override
225 public Object getParent(Object element) {
226 return null;
227 }
228
229 /** {@inheritDoc} */
230 @Override
231 public Object[] getElements(Object inputElement) {
232 return getChildren(inputElement);
233 }
234
235 /**
236 * <p>dispose</p>
237 */
238 @Override
239 public void dispose() {
240 featureNodeContainerCache.clear();
241 }
242
243 /** {@inheritDoc} */
244 @Override
245 public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {}
246
247 public void toggleShowOnlyIndividualAssociations() {
248 showOnlyIndividualAssociations = !showOnlyIndividualAssociations;
249 }
250
251 }