private InternalMapLayer getSingleInternalMapLayer(MapView mapView, User user, Date date) { if (mapView == null) { return null; } List<OrganisationUnit> atLevels = new ArrayList<OrganisationUnit>(); List<OrganisationUnit> inGroups = new ArrayList<OrganisationUnit>(); if (mapView.hasOrganisationUnitLevels()) { atLevels.addAll( organisationUnitService.getOrganisationUnitsAtLevels( mapView.getOrganisationUnitLevels(), mapView.getOrganisationUnits())); } if (mapView.hasItemOrganisationUnitGroups()) { inGroups.addAll( organisationUnitService.getOrganisationUnits( mapView.getItemOrganisationUnitGroups(), mapView.getOrganisationUnits())); } date = date != null ? date : new Date(); mapView.init(user, date, null, atLevels, inGroups, null); List<OrganisationUnit> organisationUnits = mapView.getAllOrganisationUnits(); FilterUtils.filter(organisationUnits, new OrganisationUnitWithCoordinatesFilter()); java.util.Map<String, OrganisationUnit> uidOuMap = new HashMap<String, OrganisationUnit>(); for (OrganisationUnit ou : organisationUnits) { uidOuMap.put(ou.getUid(), ou); } String name = mapView.getName(); Period period = null; if (!mapView.getPeriods().isEmpty()) // TODO integrate with BaseAnalyticalObject { period = mapView.getPeriods().get(0); } else if (mapView.getRelatives() != null) { period = mapView.getRelatives().getRelativePeriods(date, null, false).get(0); } Integer radiusLow = mapView.getRadiusLow() != null ? mapView.getRadiusLow() : DEFAULT_RADIUS_LOW; Integer radiusHigh = mapView.getRadiusHigh() != null ? mapView.getRadiusHigh() : DEFAULT_RADIUS_HIGH; // Get the low and high colors, typically in hexadecimal form, e.g. #ff3200 Color colorLow = MapUtils.createColorFromString( StringUtils.trimToNull(mapView.getColorLow()) != null ? mapView.getColorLow() : DEFAULT_COLOR_LOW); Color colorHigh = MapUtils.createColorFromString( StringUtils.trimToNull(mapView.getColorHigh()) != null ? mapView.getColorHigh() : DEFAULT_COLOR_HIGH); Float opacity = mapView.getOpacity() != null ? mapView.getOpacity().floatValue() : DEFAULT_OPACITY; // TODO MapView should be extended to feature stroke color Color strokeColor = MapUtils.createColorFromString(DEFAULT_STROKE_COLOR); // TODO MapView might be extended to feature stroke width int strokeWidth = DEFAULT_STROKE_WIDTH; boolean hasLegendSet = mapView.hasLegendSet(); // Create and setup an internal layer InternalMapLayer mapLayer = new InternalMapLayer(); mapLayer.setName(name); mapLayer.setPeriod(period); mapLayer.setRadiusLow(radiusLow); mapLayer.setRadiusHigh(radiusHigh); mapLayer.setColorLow(colorLow); mapLayer.setColorHigh(colorHigh); mapLayer.setOpacity(opacity); mapLayer.setClasses(mapView.getClasses()); mapLayer.setStrokeColor(strokeColor); mapLayer.setStrokeWidth(strokeWidth); if (!mapView.isDataLayer()) // Boundary (and facility) layer { for (OrganisationUnit unit : organisationUnits) { mapLayer.addBoundaryMapObject(unit); } } else // Thematic layer { Collection<MapValue> mapValues = getAggregatedMapValues(mapView); if (mapValues.isEmpty()) { return null; } // Build and set the internal GeoTools map objects for the layer for (MapValue mapValue : mapValues) { OrganisationUnit orgUnit = uidOuMap.get(mapValue.getOu()); if (orgUnit != null) { mapLayer.addDataMapObject(mapValue.getValue(), orgUnit); } } if (!mapLayer.hasMapObjects()) { return null; } // Create an interval set for this map layer that distributes its map // objects into their respective intervals if (hasLegendSet) { mapLayer.setIntervalSetFromLegendSet(mapView.getLegendSet()); mapLayer.distributeAndUpdateMapObjectsInIntervalSet(); } else { mapLayer.setAutomaticIntervalSet( DistributionStrategy.STRATEGY_EQUAL_RANGE, mapLayer.getClasses()); mapLayer.distributeAndUpdateMapObjectsInIntervalSet(); } // Update the radius of each map object in this map layer according to // its map object's highest and lowest values mapLayer.applyInterpolatedRadii(); } return mapLayer; }
@Transactional public void export( Collection<Integer> dataElementIds, Collection<Integer> indicatorIds, Collection<Integer> periodIds, Collection<Integer> organisationUnitIds, Collection<Integer> organisationUnitGroupIds, TaskId id) { final int cpuCores = SystemUtils.getCpuCores(); Clock clock = new Clock() .startClock() .logTime( "Data mart export process started, number of CPU cores: " + cpuCores + ", " + SystemUtils.getMemoryString()); notifier.clear(id, DATAMART).notify(id, DATAMART, "Data mart export process started"); // --------------------------------------------------------------------- // Recreate temporary tables // --------------------------------------------------------------------- dataMartManager.dropTempAggregatedTables(); dataMartManager.createTempAggregatedTables(); clock.logTime("Recreated temporary tables"); // --------------------------------------------------------------------- // Replace null with empty collection // --------------------------------------------------------------------- dataElementIds = dataElementIds != null ? dataElementIds : new ArrayList<Integer>(); indicatorIds = indicatorIds != null ? indicatorIds : new ArrayList<Integer>(); periodIds = periodIds != null ? periodIds : new ArrayList<Integer>(); organisationUnitIds = organisationUnitIds != null ? organisationUnitIds : new ArrayList<Integer>(); organisationUnitGroupIds = organisationUnitGroupIds != null ? organisationUnitGroupIds : new ArrayList<Integer>(); clock.logTime( "Data elements: " + dataElementIds.size() + ", indicators: " + indicatorIds.size() + ", periods: " + periodIds.size() + ", org units: " + organisationUnitIds.size()); // --------------------------------------------------------------------- // Get objects // --------------------------------------------------------------------- final Collection<Indicator> indicators = indicatorService.getIndicators(indicatorIds); final Collection<Period> periods = periodService.getPeriods(periodIds); final List<OrganisationUnit> organisationUnits = new ArrayList<OrganisationUnit>( organisationUnitService.getOrganisationUnits(organisationUnitIds)); final Collection<OrganisationUnitGroup> organisationUnitGroups = organisationUnitGroupService.getOrganisationUnitGroups(organisationUnitGroupIds); final Collection<DataElement> dataElements = dataElementService.getDataElements(dataElementIds); clock.logTime("Retrieved meta-data objects"); notifier.notify(id, DATAMART, "Filtering meta-data"); // --------------------------------------------------------------------- // Filter objects // --------------------------------------------------------------------- organisationUnitService.filterOrganisationUnitsWithoutData(organisationUnits); FilterUtils.filter(dataElements, new AggregatableDataElementFilter()); FilterUtils.filter(dataElements, new DataElementWithAggregationFilter()); expressionService.filterInvalidIndicators(indicators); clock.logTime("Filtered objects"); notifier.notify(id, DATAMART, "Loading indicators"); // --------------------------------------------------------------------- // Explode indicator expressions // --------------------------------------------------------------------- for (Indicator indicator : indicators) { indicator.setExplodedNumerator(expressionService.explodeExpression(indicator.getNumerator())); indicator.setExplodedDenominator( expressionService.explodeExpression(indicator.getDenominator())); } clock.logTime("Exploded indicator expressions"); notifier.notify(id, DATAMART, "Loading data elements"); // --------------------------------------------------------------------- // Get operands // --------------------------------------------------------------------- final Collection<DataElementOperand> dataElementOperands = categoryService.getOperands(dataElements); final List<DataElementOperand> indicatorOperands = new ArrayList<DataElementOperand>( categoryService.populateOperands( expressionService.getOperandsInIndicators(indicators))); Set<DataElementOperand> allOperands = new HashSet<DataElementOperand>(); allOperands.addAll(dataElementOperands); allOperands.addAll(indicatorOperands); clock.logTime("Retrieved operands: " + allOperands.size()); notifier.notify(id, DATAMART, "Loading periods"); // --------------------------------------------------------------------- // Filter out future periods // --------------------------------------------------------------------- FilterUtils.filter(periods, new PastAndCurrentPeriodFilter()); clock.logTime("Number of periods: " + periods.size()); notifier.notify(id, DATAMART, "Filtering data elements without data"); // --------------------------------------------------------------------- // Remove operands without data // --------------------------------------------------------------------- allOperands = dataMartManager.getOperandsWithData(allOperands); indicatorOperands.retainAll(allOperands); clock.logTime( "Number of operands with data: " + allOperands.size() + ", " + SystemUtils.getMemoryString()); notifier.notify(id, DATAMART, "Populating crosstabulation table"); // --------------------------------------------------------------------- // Create crosstabtable // --------------------------------------------------------------------- final Collection<Integer> intersectingPeriodIds = ConversionUtils.getIdentifiers(Period.class, periodService.getIntersectionPeriods(periods)); final PeriodHierarchy periodHierarchy = periodService.getPeriodHierarchy(periods); final Set<Integer> orgUnitChildrenIds = organisationUnitService.getOrganisationUnitHierarchy().getChildren(organisationUnitIds); final List<Integer> crossTabOrgUnitIds = new ArrayList<Integer>(orgUnitChildrenIds); final String key = crossTabService.createCrossTabTable(crossTabOrgUnitIds); final List<DataElementOperand> operandList = new ArrayList<DataElementOperand>(allOperands); Collections.shuffle(operandList); final List<List<DataElementOperand>> operandPages = new PaginatedList<DataElementOperand>(operandList).setNumberOfPages(cpuCores).getPages(); List<Future<?>> crossTabFutures = new ArrayList<Future<?>>(); for (List<DataElementOperand> operandPage : operandPages) { crossTabFutures.add( crossTabService.populateCrossTabTable( operandPage, intersectingPeriodIds, crossTabOrgUnitIds, key)); } ConcurrentUtils.waitForCompletion(crossTabFutures); clock.logTime("Populated crosstab table, " + SystemUtils.getMemoryString()); notifier.notify(id, DATAMART, "Exporting data element data"); final boolean isDataElements = true; final boolean isIndicators = indicators != null && indicators.size() > 0; final int groupLevel = (Integer) systemSettingManager.getSystemSetting( KEY_ORGUNITGROUPSET_AGG_LEVEL, DEFAULT_ORGUNITGROUPSET_AGG_LEVEL); final boolean isGroups = organisationUnitGroups != null && organisationUnitGroups.size() > 0 && groupLevel > 0; if (isDataElements) { // ----------------------------------------------------------------- // 1. Export data element values // ----------------------------------------------------------------- if (operandList.size() > 0) { final OrganisationUnitHierarchy orgUnitHierarchy = organisationUnitService .getOrganisationUnitHierarchy() .prepareChildren(organisationUnits); List<Future<?>> futures = new ArrayList<Future<?>>(); for (List<DataElementOperand> operandPage : operandPages) { futures.add( dataElementDataMart.exportDataValues( operandPage, periods, organisationUnits, null, periodHierarchy, orgUnitHierarchy, AggregatedDataValueTempBatchHandler.class, key)); } ConcurrentUtils.waitForCompletion(futures); } clock.logTime( "Exported values for data element operands (" + operandList.size() + "), pages: " + operandPages.size() + ", " + SystemUtils.getMemoryString()); notifier.notify(id, DATAMART, "Dropping data element index"); // ----------------------------------------------------------------- // 2. Drop data element index // ----------------------------------------------------------------- dataMartManager.dropDataValueIndex(); clock.logTime("Dropped data element index"); notifier.notify(id, DATAMART, "Deleting existing data element data"); // ----------------------------------------------------------------- // 3. Delete existing aggregated data values // ----------------------------------------------------------------- dataMartManager.deleteAggregatedDataValues(periodIds); clock.logTime("Deleted existing data element data"); notifier.notify(id, DATAMART, "Copying data element data from temporary table"); // ----------------------------------------------------------------- // 4. Copy aggregated data values from temporary table // ----------------------------------------------------------------- dataMartManager.copyAggregatedDataValuesFromTemp(); clock.logTime("Copied data element data from temporary table"); notifier.notify(id, DATAMART, "Creating data element index"); // ----------------------------------------------------------------- // 5. Create data element index // ----------------------------------------------------------------- dataMartManager.createDataValueIndex(); clock.logTime("Created data element index"); } if (isGroups && isDataElements) { // ----------------------------------------------------------------- // 1. Export data element values // ----------------------------------------------------------------- notifier.notify(id, DATAMART, "Exporting data element org unit data"); Collection<OrganisationUnit> groupOrganisationUnits = new HashSet<OrganisationUnit>(organisationUnits); FilterUtils.filter( groupOrganisationUnits, new OrganisationUnitAboveOrEqualToLevelFilter(groupLevel)); if (operandList.size() > 0) { final OrganisationUnitHierarchy orgUnitHierarchy = organisationUnitService .getOrganisationUnitHierarchy() .prepareChildren(groupOrganisationUnits, organisationUnitGroups); List<Future<?>> futures = new ArrayList<Future<?>>(); for (List<DataElementOperand> operandPage : operandPages) { futures.add( dataElementDataMart.exportDataValues( operandPage, periods, groupOrganisationUnits, organisationUnitGroups, periodHierarchy, orgUnitHierarchy, AggregatedOrgUnitDataValueTempBatchHandler.class, key)); } ConcurrentUtils.waitForCompletion(futures); } clock.logTime( "Exported values for data element operands (" + operandList.size() + "), pages: " + operandPages.size() + ", " + SystemUtils.getMemoryString()); notifier.notify(id, DATAMART, "Dropping data element data indexes"); // ----------------------------------------------------------------- // 2. Drop data element index // ----------------------------------------------------------------- dataMartManager.dropOrgUnitDataValueIndex(); clock.logTime("Dropped org unit data element index"); notifier.notify(id, DATAMART, "Deleting existing org unit data element data"); // ----------------------------------------------------------------- // 3. Delete existing aggregated data values // ----------------------------------------------------------------- dataMartManager.deleteAggregatedOrgUnitDataValues(periodIds); clock.logTime("Deleted existing aggregated org unit datavalues"); notifier.notify(id, DATAMART, "Copying org unit data element data"); // ----------------------------------------------------------------- // 4. Copy aggregated org unit data values from temporary table // ----------------------------------------------------------------- dataMartManager.copyAggregatedOrgUnitDataValuesFromTemp(); clock.logTime("Copied org unit data element data from temporary table"); notifier.notify(id, DATAMART, "Creating org unit data element index"); // ----------------------------------------------------------------- // 5. Create org unit data element index // ----------------------------------------------------------------- dataMartManager.createOrgUnitDataValueIndex(); clock.logTime("Created org unit data element index"); notifier.notify(id, DATAMART, "Exporting data for org unit indicator data"); } crossTabService.dropCrossTabTable(key); List<List<OrganisationUnit>> organisationUnitPages = new PaginatedList<OrganisationUnit>(organisationUnits) .setNumberOfPages(cpuCores) .getPages(); if (isIndicators) { // ----------------------------------------------------------------- // 1. Create and populate aggregated data cache // ----------------------------------------------------------------- notifier.notify(id, DATAMART, "Populating aggregated data cache"); crossTabService.createAggregatedDataCache(indicatorOperands, key); List<Future<?>> aggregatedDataCacheFutures = new ArrayList<Future<?>>(); for (List<OrganisationUnit> organisationUnitPage : organisationUnitPages) { aggregatedDataCacheFutures.add( crossTabService.populateAggregatedDataCache( indicatorOperands, periods, organisationUnitPage, key)); } ConcurrentUtils.waitForCompletion(aggregatedDataCacheFutures); clock.logTime( "Created aggregated data cache, number of indicator operands: " + indicatorOperands.size()); notifier.notify(id, DATAMART, "Exporting indicator data"); // ----------------------------------------------------------------- // 2. Export indicator values // ----------------------------------------------------------------- List<Future<?>> futures = new ArrayList<Future<?>>(); for (List<OrganisationUnit> organisationUnitPage : organisationUnitPages) { futures.add( indicatorDataMart.exportIndicatorValues( indicators, periods, organisationUnitPage, null, indicatorOperands, AggregatedIndicatorValueTempBatchHandler.class, key)); } ConcurrentUtils.waitForCompletion(futures); clock.logTime( "Exported values for indicators (" + indicators.size() + "), pages: " + organisationUnitPages.size() + ", " + SystemUtils.getMemoryString()); notifier.notify(id, DATAMART, "Dropping indicator index"); // ----------------------------------------------------------------- // 3. Drop aggregated data cache and indicator index // ----------------------------------------------------------------- crossTabService.dropAggregatedDataCache(key); dataMartManager.dropIndicatorValueIndex(); clock.logTime("Dropped indicator index, " + SystemUtils.getMemoryString()); notifier.notify(id, DATAMART, "Deleting existing indicator data"); // ----------------------------------------------------------------- // 4. Delete existing aggregated indicator values // ----------------------------------------------------------------- dataMartManager.deleteAggregatedIndicatorValues(periodIds); clock.logTime("Deleted existing indicator data"); notifier.notify(id, DATAMART, "Copying indicator data from temporary table"); // ----------------------------------------------------------------- // 5. Copy aggregated data values from temporary table // ----------------------------------------------------------------- dataMartManager.copyAggregatedIndicatorValuesFromTemp(); clock.logTime("Copied indicator data from temporary table"); notifier.notify(id, DATAMART, "Creating indicator index"); // ----------------------------------------------------------------- // 6. Create indicator index // ----------------------------------------------------------------- dataMartManager.createIndicatorValueIndex(); clock.logTime("Created indicator index"); } if (isGroups && isIndicators) { // ----------------------------------------------------------------- // 1. Create aggregated data cache // ----------------------------------------------------------------- notifier.notify(id, DATAMART, "Populating aggregated data cache"); crossTabService.createAggregatedOrgUnitDataCache(indicatorOperands, key); List<Future<?>> aggregatedDataCacheFutures = new ArrayList<Future<?>>(); for (List<OrganisationUnit> organisationUnitPage : organisationUnitPages) { aggregatedDataCacheFutures.add( crossTabService.populateAggregatedOrgUnitDataCache( indicatorOperands, periods, organisationUnitPage, organisationUnitGroups, key)); } ConcurrentUtils.waitForCompletion(aggregatedDataCacheFutures); clock.logTime("Created aggregated org unit data cache"); notifier.notify(id, DATAMART, "Exporting org unit indicator data"); // ----------------------------------------------------------------- // 2. Export indicator values // ----------------------------------------------------------------- List<Future<?>> futures = new ArrayList<Future<?>>(); for (List<OrganisationUnit> organisationUnitPage : organisationUnitPages) { futures.add( indicatorDataMart.exportIndicatorValues( indicators, periods, organisationUnitPage, organisationUnitGroups, indicatorOperands, AggregatedOrgUnitIndicatorValueTempBatchHandler.class, key)); } ConcurrentUtils.waitForCompletion(futures); clock.logTime( "Exported values for indicators (" + indicators.size() + "), pages: " + organisationUnitPages.size() + ", " + SystemUtils.getMemoryString()); notifier.notify(id, DATAMART, "Dropping org unit indicator index"); // ----------------------------------------------------------------- // 3. Drop aggregated data cache and indicator index // ----------------------------------------------------------------- crossTabService.dropAggregatedOrgUnitDataCache(key); dataMartManager.dropOrgUnitIndicatorValueIndex(); clock.logTime("Dropped org unit indicator index, " + SystemUtils.getMemoryString()); notifier.notify(id, DATAMART, "Deleting existing org unit indicator data"); // ----------------------------------------------------------------- // 4. Delete existing aggregated indicator values // ----------------------------------------------------------------- dataMartManager.deleteAggregatedOrgUnitIndicatorValues(periodIds); clock.logTime("Deleted existing aggregated org unit indicatorvalues"); notifier.notify(id, DATAMART, "Copying org unit indicator data from temporary table"); // ----------------------------------------------------------------- // 5. Copy aggregated org unit indicator values from temp table // ----------------------------------------------------------------- dataMartManager.copyAggregatedOrgUnitIndicatorValuesFromTemp(); clock.logTime("Copied org unit indicator data from temporary table"); notifier.notify(id, DATAMART, "Creating org unit indicator indexes"); // ----------------------------------------------------------------- // 6. Create org unit indicator index // ----------------------------------------------------------------- dataMartManager.createOrgUnitIndicatorValueIndex(); clock.logTime("Created org unit indicator index"); } // --------------------------------------------------------------------- // Drop temporary tables // --------------------------------------------------------------------- dataMartManager.dropTempAggregatedTables(); clock.logTime("Dropped crosstab table"); clock.logTime("Data mart export process completed"); notifier.notify(id, DATAMART, INFO, "Data mart process completed", true); }