* and a {@link TaggedText} representation of the condensed distribution string.
*/
public static CondensedDistribution getCondensedDistribution(Collection<Distribution> filteredDistributions,
- SetMap<NamedArea, NamedArea> parentAreaMap, CondensedDistributionConfiguration config, List<Language> languages) {
+ SetMap<NamedArea,TermNode<NamedArea>> area2TermNodesMap, CondensedDistributionConfiguration config, List<Language> languages) {
CondensedDistributionComposer composer = new CondensedDistributionComposer();
CondensedDistribution condensedDistribution = composer.createCondensedDistribution(
- filteredDistributions, parentAreaMap, languages, config);
+ filteredDistributions, area2TermNodesMap, languages, config);
return condensedDistribution;
}
* @param distribution
* @param area
*/
- private static void addAreaToLayerMap(Map<String, Map<Integer,
- Set<Distribution>>> layerMap,
+ private static void addAreaToLayerMap(Map<String,
+ Map<Integer,Set<Distribution>>> layerMap,
List<PresenceAbsenceTerm> statusList,
Distribution distribution,
NamedArea area,
private static void addDistributionToStyleMap(Distribution distribution, Map<Integer, Set<Distribution>> styleMap,
List<PresenceAbsenceTerm> statusList) {
+
PresenceAbsenceTerm status = distribution.getStatus();
if (status != null) {
int style = statusList.indexOf(status);
Set<Distribution> distributionSet = styleMap.get(style);
if (distributionSet == null) {
- distributionSet = new HashSet<Distribution>();
+ distributionSet = new HashSet<>();
styleMap.put(style, distributionSet);
}
distributionSet.add(distribution);
*
* <li><b>Prefer aggregated rule</b>: if this flag is set to <code>true</code> aggregated
* distributions are preferred over non-aggregated elements.
- * (Aggregated description elements are identified by the description having type
- * {@link DescriptionType.AGGREGATED_DISTRIBUTION}). This means if an non-aggregated status
+ * (Aggregated descriptions are identified by their description having type
+ * {@link DescriptionType.AGGREGATED_DISTRIBUTION}). This means if a non-aggregated status
* information exists for the same area for which aggregated data is available,
* the aggregated data has to be given preference over other data.
- * see parameter <code>preferAggregated</code></li>
+ * See parameter <code>preferAggregated</code></li>
*
* <li><b>Status order preference rule</b>: In case of multiple distribution
* status ({@link PresenceAbsenceTermBase}) for the same area the status
* with the highest order is preferred, see
* {@link DefinedTermBase#compareTo(DefinedTermBase)}. This rule is
* optional, see parameter <code>statusOrderPreference</code></li>
+ *
* <li><b>Sub area preference rule</b>: If there is an area with a <i>direct
* sub area</i> and both areas have the same status only the
* information on the sub area should be reported, whereas the super area
* should be ignored. This rule is optional, see parameter
* <code>subAreaPreference</code>. Can be run separately from the other filters.
* This rule affects any distribution,
- * that is to computed and edited equally. For more details see
+ * that is to be computed and edited equally. For more details see
* {@link https://dev.e-taxonomy.eu/redmine/issues/5050})</li>
* </ol>
*
* @return the filtered collection of distribution elements.
*/
public static Set<Distribution> filterDistributions(Collection<Distribution> distributions,
- TermTree<NamedArea> areaTree,
- Set<MarkerType> fallbackAreaMarkerTypes, boolean preferAggregated, boolean statusOrderPreference,
- boolean subAreaPreference, boolean keepFallBackOnlyIfNoSubareaDataExists, boolean ignoreDistributionStatusUndefined) {
-
- SetMap<NamedArea, Distribution> filteredDistributions = new SetMap<>(distributions.size());
+ TermTree<NamedArea> areaTree, TermTree<PresenceAbsenceTerm> statusTree,
+ Set<MarkerType> fallbackAreaMarkerTypes,
+ boolean preferAggregated, boolean statusOrderPreference,
+ boolean subAreaPreference, boolean keepFallBackOnlyIfNoSubareaDataExists) {
+
+ SetMap<NamedArea, Distribution> filteredDistributionsPerArea = new SetMap<>(distributions.size());
+ Set<UUID> statusPositiveSet = null;
+ if (statusTree != null) {
+ statusPositiveSet = new HashSet<>();
+ for (PresenceAbsenceTerm status : statusTree.asTermList()) {
+ statusPositiveSet.add(status.getUuid());
+ }
+ }
- // sort Distributions by the area and filter undefinedStatus
+ // assign distributions to the area and filter undefined status
for(Distribution distribution : distributions){
NamedArea area = distribution.getArea();
if(area == null) {
logger.debug("skipping distribution with NULL area");
continue;
}
- boolean filterUndefined = ignoreDistributionStatusUndefined && distribution.getStatus() != null
- && distribution.getStatus().getUuid().equals(PresenceAbsenceTerm.uuidUndefined);
- if (!filterUndefined){
- filteredDistributions.putItem(area, distribution);
+ boolean filterOutStatus = statusPositiveSet != null &&
+ (distribution.getStatus() == null
+ || !statusPositiveSet.contains(distribution.getStatus().getUuid()));
+ if (!filterOutStatus){
+ filteredDistributionsPerArea.putItem(area, distribution);
}
}
}
// -------------------------------------------------------------------
- // 1) skip distributions having an area with markers matching hiddenAreaMarkerTypes
+ // 1) skip distributions having an area with markers matching fallbackAreaMarkerTypes
// but keep distributions for fallback areas (areas with hidden marker, but with visible sub-areas)
//TODO since using area tree this is only relevant if keepFallBackOnlyIfNoSubareaDataExists = true
// as the area tree should also exclude real hidden areas
// if(!CdmUtils.isNullSafeEmpty(fallbackAreaMarkerTypes)) {
- removeHiddenAndKeepFallbackAreas(areaTree, fallbackAreaMarkerTypes, filteredDistributions, keepFallBackOnlyIfNoSubareaDataExists);
+ removeHiddenAndKeepFallbackAreas(areaTree, fallbackAreaMarkerTypes, filteredDistributionsPerArea, keepFallBackOnlyIfNoSubareaDataExists);
// }
// -------------------------------------------------------------------
// 2) remove not computed distributions for areas for which computed
// distributions exists
if(preferAggregated) {
- handlePreferAggregated(filteredDistributions);
+ handlePreferAggregated(filteredDistributionsPerArea);
}
// -------------------------------------------------------------------
// 3) status order preference rule
if (statusOrderPreference) {
- SetMap<NamedArea, Distribution> tmpMap = new SetMap<>(filteredDistributions.size());
- for(NamedArea key : filteredDistributions.keySet()){
- tmpMap.put(key, filterByHighestDistributionStatusForArea(filteredDistributions.get(key)));
+ SetMap<NamedArea, Distribution> tmpMap = new SetMap<>(filteredDistributionsPerArea.size());
+ for(NamedArea key : filteredDistributionsPerArea.keySet()){
+ tmpMap.put(key, filterByHighestDistributionStatusForArea(filteredDistributionsPerArea.get(key)));
}
- filteredDistributions = tmpMap;
+ filteredDistributionsPerArea = tmpMap;
}
// -------------------------------------------------------------------
// 4) Sub area preference rule
if(subAreaPreference){
- handleSubAreaPreferenceRule(filteredDistributions, areaTree);
+ handleSubAreaPreferenceRule(filteredDistributionsPerArea, areaTree);
}
- return valuesOfAllInnerSets(filteredDistributions.values());
+ return valuesOfAllInnerSets(filteredDistributionsPerArea.values());
}
static TermTree<NamedArea> getAreaTree(Collection<Distribution> distributions,
- Set<MarkerType> hiddenAreaMarkerTypes) {
+ Set<MarkerType> fallbackAreaMarkerTypes) {
//TODO see comment in below method
// List<TermVocabulary<NamedArea>> vocs = getVocabualries(distributions);
- TermTree<NamedArea> areaTree = createAreaTreeByDistributions(distributions, hiddenAreaMarkerTypes);
+ TermTree<NamedArea> areaTree = createAreaTreeByDistributions(distributions, fallbackAreaMarkerTypes);
return areaTree;
}
* Removes hidden areas marked as such if they have no children.
*/
private static TermTree<NamedArea> createAreaTreeByDistributions(Collection<Distribution> distributions,
- Set<MarkerType> hiddenAreaMarkerTypes) {
+ Set<MarkerType> fallbackAreaMarkerTypes) {
- hiddenAreaMarkerTypes = hiddenAreaMarkerTypes == null ? new HashSet<>() : hiddenAreaMarkerTypes;
+ fallbackAreaMarkerTypes = fallbackAreaMarkerTypes == null ? new HashSet<>() : fallbackAreaMarkerTypes;
TermTree<NamedArea> result = TermTree.NewInstance(TermType.NamedArea, NamedArea.class);
//create area list
Set<NamedArea> relevantAreas = new HashSet<>();
for (Distribution distribution : distributions) {
- NamedArea area = distribution.getArea();
+ NamedArea area = HibernateProxyHelper.deproxy(distribution.getArea(), NamedArea.class) ;
if (area != null && !relevantAreas.contains(area)) {
- boolean isHidden = isMarkedHidden(area, hiddenAreaMarkerTypes);
+ boolean isHidden = isMarkedAs(area, fallbackAreaMarkerTypes);
if (isHidden) {
//if is hidden area either ignore (hidden area) or add unhidden children (fallback area)
- Set<NamedArea> unhiddenChildren = getUnhiddenChildren(area, hiddenAreaMarkerTypes);
+ Set<NamedArea> unhiddenChildren = getUnhiddenChildren(area, fallbackAreaMarkerTypes);
if (!unhiddenChildren.isEmpty()) {
relevantAreas.addAll(unhiddenChildren);
}
return areaNode;
}
- private static Set<NamedArea> getUnhiddenChildren(NamedArea area, Set<MarkerType> hiddenAreaMarkerTypes) {
+ private static Set<NamedArea> getUnhiddenChildren(NamedArea area, Set<MarkerType> fallbackAreaMarkerTypes) {
Set<NamedArea> result = new HashSet<>();
for (NamedArea child : area.getIncludes()) {
- if (!isMarkedHidden(child, hiddenAreaMarkerTypes)) {
+ if (!isMarkedAs(child, fallbackAreaMarkerTypes)) {
result.add(child);
}
- result.addAll(getUnhiddenChildren(child, hiddenAreaMarkerTypes));
+ result.addAll(getUnhiddenChildren(child, fallbackAreaMarkerTypes));
}
return result;
}
-
+ /**
+ * Removes all distributions that have an area being a parent of
+ * another distribution area. E.g. removes distribution for "Europe"
+ * if a distribution for "France" exists in the list, where Europe
+ * is a direct parent for France.
+ */
private static void handleSubAreaPreferenceRule(SetMap<NamedArea, Distribution> filteredDistributions,
TermTree<NamedArea> areaTree) {
- SetMap<NamedArea, NamedArea> parentMap = areaTree.getParentMap();
+ SetMap<NamedArea, NamedArea> childToParentsMap = areaTree.getParentMap();
Set<NamedArea> removeCandidatesArea = new HashSet<>();
for(NamedArea area : filteredDistributions.keySet()){
if(removeCandidatesArea.contains(area)){
continue;
}
- //xx;
- NamedArea parent = parentMap.getFirstValue(area);
- if(parent != null && filteredDistributions.containsKey(parent)){
- removeCandidatesArea.add(parent);
- }
+ childToParentsMap.get(area).forEach(parent->{
+ if(parent != null && filteredDistributions.containsKey(parent)){
+ removeCandidatesArea.add(parent);
+ }
+ });
}
for(NamedArea removeKey : removeCandidatesArea){
filteredDistributions.remove(removeKey);
/**
* Remove areas not in area tree but keep fallback areas.
*/
- private static void removeHiddenAndKeepFallbackAreas(TermTree<NamedArea> areaTree, Set<MarkerType> hiddenAreaMarkerTypes,
+ private static void removeHiddenAndKeepFallbackAreas(TermTree<NamedArea> areaTree, Set<MarkerType> fallbackAreaMarkerTypes,
SetMap<NamedArea,Distribution> filteredDistributionsPerArea, boolean keepFallBackOnlyIfNoSubareaDataExists) {
Set<NamedArea> areasHiddenByMarker = new HashSet<>();
for(NamedArea area : filteredDistributionsPerArea.keySet()) {
if (! availableAreas.contains(area)) {
areasHiddenByMarker.add(area);
- }else if(isMarkedHidden(area, hiddenAreaMarkerTypes)) {
+ }else if(isMarkedAs(area, fallbackAreaMarkerTypes)) {
Set<TermNode<NamedArea>> nodes = areaTree.getNodesForTerm(area);
// if at least one sub area is not hidden by a marker
// the given area is a fall-back area for this sub area
SetMap<NamedArea, Distribution> distributionsForSubareaCheck = keepFallBackOnlyIfNoSubareaDataExists ? filteredDistributionsPerArea : null;
- boolean isFallBackArea = isRemainingFallBackArea(nodes, hiddenAreaMarkerTypes, distributionsForSubareaCheck);
+ boolean isFallBackArea = isRemainingFallBackArea(nodes, fallbackAreaMarkerTypes, distributionsForSubareaCheck);
if (!isFallBackArea) {
// this area does not need to be shown as
// fall-back for another area so it will be hidden.
}
//if filteredDistributions == null it can be ignored if data exists or not
- private static boolean isRemainingFallBackArea(Set<TermNode<NamedArea>> areaNode, Set<MarkerType> hiddenAreaMarkerTypes,
+ private static boolean isRemainingFallBackArea(Set<TermNode<NamedArea>> areaNode, Set<MarkerType> fallbackAreaMarkerTypes,
SetMap<NamedArea, Distribution> filteredDistributions) {
Set<TermNode<NamedArea>> childNodes = new HashSet<>();
Set<TermNode<NamedArea>> childNodeAsSet = new HashSet<>();
childNodeAsSet.add(included);
//if subarea is not hidden and data exists return true
- if (isMarkedHidden(subArea, hiddenAreaMarkerTypes)){
- boolean subAreaIsFallback = isRemainingFallBackArea(childNodeAsSet, hiddenAreaMarkerTypes, filteredDistributions);
+ if (isMarkedAs(subArea, fallbackAreaMarkerTypes)){
+ boolean subAreaIsFallback = isRemainingFallBackArea(childNodeAsSet, fallbackAreaMarkerTypes, filteredDistributions);
if (subAreaIsFallback && noOrIgnoreData){
return true;
}else{
// if (isNotHidden_AndHasNoData_OrDataCanBeIgnored) {
// return true;
// }
-// if (!isMarkedHidden(subArea, hiddenAreaMarkerTypes) ){
+// if (!isMarkedHidden(subArea, fallbackAreaMarkerTypes) ){
//
// }
//
// //do the same recursively
-// boolean hasVisibleSubSubarea = isRemainingFallBackArea(subArea, hiddenAreaMarkerTypes, filteredDistributions, areasHiddenByMarker);
+// boolean hasVisibleSubSubarea = isRemainingFallBackArea(subArea, fallbackAreaMarkerTypes, filteredDistributions, areasHiddenByMarker);
// if (hasVisibleSubSubarea){
// return true;
// }
return false;
}
- public static boolean isMarkedHidden(NamedArea area, Set<MarkerType> hiddenAreaMarkerTypes) {
- if(hiddenAreaMarkerTypes != null) {
- for(MarkerType markerType : hiddenAreaMarkerTypes){
+ public static boolean isMarkedAs(NamedArea area, Set<MarkerType> markerTypes) {
+ if(markerTypes != null) {
+ for(MarkerType markerType : markerTypes){
if(area.hasMarker(markerType, true)){
return true;
}
Collection<Distribution> distributions,
SetMap<NamedArea, NamedArea> parentAreaMap,
Set<MarkerType> fallbackAreaMarkerTypes,
+ Set<MarkerType> alternativeRootAreaMarkerTypes,
boolean neverUseFallbackAreaAsParent,
DistributionOrder distributionOrder,
IDefinedTermDao termDao) {
if (logger.isDebugEnabled()){logger.debug("order tree ...");}
//order by areas
- tree.orderAsTree(distributions, parentAreaMap, omitLevels, fallbackAreaMarkerTypes, neverUseFallbackAreaAsParent);
+ tree.orderAsTree(distributions, parentAreaMap, omitLevels, fallbackAreaMarkerTypes,
+ neverUseFallbackAreaAsParent);
+ tree.handleAlternativeRootArea(alternativeRootAreaMarkerTypes);
tree.recursiveSortChildren(distributionOrder); // TODO respect current locale for sorting
if (logger.isDebugEnabled()){logger.debug("create tree - DONE");}
return tree;
public static DistributionTreeDto buildOrderedTreeDto(Set<NamedAreaLevel> omitLevels,
Collection<DistributionDto> distributions,
SetMap<NamedArea, NamedArea> parentAreaMap,
- Set<MarkerType> fallbackAreaMarkerTypes,
+ TermTree<NamedArea> areaTree, Set<MarkerType> fallbackAreaMarkerTypes,
+ Set<MarkerType> alternativeRootAreaMarkerType,
boolean neverUseFallbackAreaAsParent,
DistributionOrder distributionOrder,
- IDefinedTermDao termDao) {
+ IDefinedTermDao termDao,
+ boolean useSecondMethod) {
//TODO loader needed?
DistributionTreeDtoLoader loader = new DistributionTreeDtoLoader(termDao);
- DistributionTreeDto dto = loader.load();
+ DistributionTreeDto distributionTreeDto = loader.load();
if (logger.isDebugEnabled()){logger.debug("order tree ...");}
+
//order by areas
- loader.orderAsTree(dto, distributions, parentAreaMap, omitLevels, fallbackAreaMarkerTypes, neverUseFallbackAreaAsParent);
- loader.recursiveSortChildren(dto, distributionOrder); // TODO respect current locale for sorting
+ if (!useSecondMethod) {
+ loader.orderAsTree(distributionTreeDto, distributions, parentAreaMap, omitLevels,
+ fallbackAreaMarkerTypes, neverUseFallbackAreaAsParent);
+ }else {
+ loader.orderAsTree2(distributionTreeDto, distributions, areaTree, omitLevels,
+ fallbackAreaMarkerTypes, neverUseFallbackAreaAsParent);
+ }
+ loader.handleAlternativeRootArea(distributionTreeDto, alternativeRootAreaMarkerType);
+ loader.recursiveSortChildren(distributionTreeDto, distributionOrder); // TODO respect current locale for sorting
+
if (logger.isDebugEnabled()){logger.debug("create tree - DONE");}
- return dto;
+ return distributionTreeDto;
}
/**