Java tutorial
/* AWE - Amanzi Wireless Explorer * http://awe.amanzi.org * (C) 2008-2009, AmanziTel AB * * This library is provided under the terms of the Eclipse Public License * as described at http://www.eclipse.org/legal/epl-v10.html. Any use, * reproduction or distribution of the library constitutes recipient's * acceptance of this agreement. * * This library is distributed WITHOUT ANY WARRANTY; without even the * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. */ package org.amanzi.awe.statistics.model.impl; import java.text.MessageFormat; import java.util.ArrayList; import java.util.Arrays; import java.util.Date; import java.util.HashMap; import java.util.Iterator; import java.util.LinkedHashSet; import java.util.List; import java.util.Map; import java.util.Set; import org.amanzi.awe.statistics.dto.IStatisticsCell; import org.amanzi.awe.statistics.dto.IStatisticsGroup; import org.amanzi.awe.statistics.dto.IStatisticsLevel; import org.amanzi.awe.statistics.dto.IStatisticsRow; import org.amanzi.awe.statistics.dto.impl.StatisticsCell; import org.amanzi.awe.statistics.dto.impl.StatisticsGroup; import org.amanzi.awe.statistics.dto.impl.StatisticsLevel; import org.amanzi.awe.statistics.dto.impl.StatisticsRow; import org.amanzi.awe.statistics.filter.IStatisticsFilter; import org.amanzi.awe.statistics.model.DimensionType; import org.amanzi.awe.statistics.model.IStatisticsModel; import org.amanzi.awe.statistics.model.StatisticsNodeType; import org.amanzi.awe.statistics.nodeproperties.IStatisticsNodeProperties; import org.amanzi.awe.statistics.service.IStatisticsService; import org.amanzi.awe.statistics.service.impl.StatisticsService; import org.amanzi.awe.statistics.service.impl.StatisticsService.StatisticsRelationshipType; import org.amanzi.neo.dateformat.DateFormatManager; import org.amanzi.neo.dto.IDataElement; import org.amanzi.neo.impl.dto.DataElement; import org.amanzi.neo.impl.dto.SourcedElement.ICollectFunction; import org.amanzi.neo.impl.util.AbstractDataElementIterator; import org.amanzi.neo.models.exceptions.ModelException; import org.amanzi.neo.models.impl.internal.AbstractAnalyzisModel; import org.amanzi.neo.models.measurement.IMeasurementModel; import org.amanzi.neo.nodeproperties.IGeneralNodeProperties; import org.amanzi.neo.nodeproperties.IMeasurementNodeProperties; import org.amanzi.neo.nodeproperties.ITimePeriodNodeProperties; import org.amanzi.neo.nodetypes.NodeTypeNotExistsException; import org.amanzi.neo.services.INodeService; import org.amanzi.neo.services.exceptions.ServiceException; import org.amanzi.neo.services.impl.NodeService.NodeServiceRelationshipType; import org.apache.commons.lang3.ArrayUtils; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.tuple.ImmutablePair; import org.apache.commons.lang3.tuple.Pair; import org.apache.log4j.Logger; import org.neo4j.graphdb.Node; import org.neo4j.graphdb.RelationshipType; import com.google.common.collect.Iterables; import com.google.common.collect.Lists; /** * TODO Purpose of * <p> * </p> * * @author Nikolay Lagutko (nikolay.lagutko@amanzitel.com) * @since 1.0.0 */ public class StatisticsModel extends AbstractAnalyzisModel<IMeasurementModel> implements IStatisticsModel { private final static Logger LOGGER = Logger.getLogger(StatisticsModel.class); protected class StatisticsCellFilteredConverter extends DataElementConverter<IStatisticsCell> { private final IStatisticsFilter filter; /** * @param sourceCollection */ public StatisticsCellFilteredConverter(final Iterator<IStatisticsCell> sourceCollection, final IStatisticsFilter filter) { super(sourceCollection); this.filter = filter; } @Override protected IDataElement getNext(final IStatisticsCell element) { return filter == null ? element : filter.getCellName().equals(element.getName()) ? element : null; } } private abstract class AbstractStatisticsFilteredIterator<T extends IDataElement> extends AbstractDataElementIterator<T> { private final IStatisticsFilter filter; protected AbstractStatisticsFilteredIterator(final Iterator<Node> nodeIterator, final IStatisticsFilter filter) { super(nodeIterator); this.filter = filter; } @Override protected T createDataElement(final Node node) { final T result = createDataElementInternal(node); if (apply(result, filter)) { return result; } return null; } protected abstract T createDataElementInternal(Node node); protected abstract boolean apply(T element, IStatisticsFilter filter); } private class StatisticsLevelIterator extends AbstractStatisticsFilteredIterator<IStatisticsLevel> { private final DimensionType dimension; /** * @param nodeIterator */ protected StatisticsLevelIterator(final Iterator<Node> nodeIterator, final IStatisticsFilter filter, final DimensionType dimension) { super(nodeIterator, filter); this.dimension = dimension; } @Override protected IStatisticsLevel createDataElementInternal(final Node node) { return createStatisticsLevel(node, dimension); } @Override protected boolean apply(final IStatisticsLevel element, final IStatisticsFilter filter) { return filter == null || element.getName().equals(filter.getPeriod()); } } private class StatisticsRowIterator extends AbstractDataElementIterator<IStatisticsRow> { /** * @param nodeIterator */ protected StatisticsRowIterator(final Iterator<Node> nodeIterator) { super(nodeIterator); } @Override protected IStatisticsRow createDataElement(final Node node) { return createStatisticsRow(node); } } private class StatisticsCellIterator extends AbstractDataElementIterator<IStatisticsCell> { /** * @param nodeIterator */ protected StatisticsCellIterator(final Iterator<Node> nodeIterator) { super(nodeIterator); } @Override protected IStatisticsCell createDataElement(final Node node) { return createStatisticsCell(node); } } private class StatisticsGroupIterator extends AbstractStatisticsFilteredIterator<IStatisticsGroup> { /** * @param nodeIterator */ protected StatisticsGroupIterator(final Iterator<Node> nodeIterator, final IStatisticsFilter filter) { super(nodeIterator, filter); } @Override protected IStatisticsGroup createDataElement(final Node node) { return createStatisticsGroupFromNode(node); } @Override protected IStatisticsGroup createDataElementInternal(final Node node) { return createStatisticsGroupFromNode(node); } @Override protected boolean apply(final IStatisticsGroup element, final IStatisticsFilter filter) { return filter == null || filter.getGroupNames().contains(element.getPropertyValue()); } } private final ICollectFunction statisticsGroupSourcesCollectFunction = new ICollectFunction() { @Override public Iterable<IDataElement> collectSourceElements(final IDataElement element) { if (element instanceof IStatisticsGroup) { try { return getIteratorList((IStatisticsGroup) element); } catch (final ModelException e) { LOGGER.error("Error on collecting Sources of Statistics Group", e); } } return Iterables.emptyIterable(); } private Iterable<IDataElement> getIteratorList(final IStatisticsGroup group) throws ModelException { Iterable<IDataElement> result = Iterables.emptyIterable(); final Iterable<IStatisticsRow> rows = getStatisticsRows(group.getPeriod()); if (rows != null) { for (final IStatisticsRow sourceRow : rows) { if (sourceRow.getStatisticsGroup().equals(group)) { result = Iterables.concat(result, statisticsRowSourcesCollectFunction.collectSourceElements(sourceRow)); } } } return result; } }; private final ICollectFunction statisticsRowSourcesCollectFunction = new ICollectFunction() { @Override public Iterable<IDataElement> collectSourceElements(final IDataElement element) { if (element instanceof IStatisticsRow) { try { return getIterable((IStatisticsRow) element); } catch (final ModelException e) { LOGGER.error("Error on collecting Sources of Statistics Row", e); } } return Iterables.emptyIterable(); } private Iterable<IDataElement> getIterable(final IStatisticsRow row) throws ModelException { final Iterable<IStatisticsRow> rows = getSourceRows(row); final List<Iterable<IDataElement>> iterableList = new ArrayList<Iterable<IDataElement>>(); if (rows != null) { for (final IStatisticsRow sourceRow : rows) { iterableList.add(getIterable(sourceRow)); } } for (final IStatisticsCell cell : row.getStatisticsCells()) { iterableList.add(statisticsCellSourcesCollectFunction.collectSourceElements(cell)); } return Iterables.concat(iterableList); } }; private final ICollectFunction statisticsCellSourcesCollectFunction = new ICollectFunction() { @Override public Iterable<IDataElement> collectSourceElements(final IDataElement element) { if (element instanceof IStatisticsCell) { try { return getIterable((IStatisticsCell) element); } catch (final ModelException e) { LOGGER.error("Error on collecting Sources of Statistics Cell", e); } } return Iterables.emptyIterable(); } private Iterable<IDataElement> getIterable(final IStatisticsCell cell) throws ModelException { final Iterable<IStatisticsCell> cells = getSourceCells(cell); final List<Iterable<IDataElement>> iterableList = new ArrayList<Iterable<IDataElement>>(); if (cells != null) { for (final IStatisticsCell sourceCell : cells) { iterableList.add(getIterable(sourceCell)); } } iterableList.add(getSources(cell)); return Iterables.concat(iterableList); } }; private final ITimePeriodNodeProperties timePeriodNodeProperties; private final IStatisticsNodeProperties statisticsNodeProperties; private String templateName; private String aggregatedProperty; private final IStatisticsService statisticsService; private final Map<Pair<String, String>, IStatisticsGroup> statisticsGroupCache = new HashMap<Pair<String, String>, IStatisticsGroup>(); private final Map<DimensionType, Map<String, Node>> statisticsLevelCache = new HashMap<DimensionType, Map<String, Node>>(); private final Map<Pair<String, Long>, IStatisticsRow> statisticsRowCache = new HashMap<Pair<String, Long>, IStatisticsRow>(); private final Map<Pair<StatisticsRow, String>, Node> statisticsCellNodeCache = new HashMap<Pair<StatisticsRow, String>, Node>(); private final Map<StatisticsGroup, StatisticsRow> summuryCache = new HashMap<StatisticsGroup, StatisticsRow>(); private Set<String> columnNames = new LinkedHashSet<String>(); private final IMeasurementNodeProperties measurementNodeProperties; /** * @param nodeService * @param generalNodeProperties * @param measurementNodeProperties */ public StatisticsModel(final IStatisticsService statisticsService, final INodeService nodeService, final IGeneralNodeProperties generalNodeProperties, final ITimePeriodNodeProperties timePeriodNodeProperties, final IStatisticsNodeProperties statisticsNodeProperties, final IMeasurementNodeProperties measurementNodeProperties) { super(nodeService, generalNodeProperties); this.measurementNodeProperties = measurementNodeProperties; this.statisticsService = statisticsService; this.timePeriodNodeProperties = timePeriodNodeProperties; this.statisticsNodeProperties = statisticsNodeProperties; } @Override public void initialize(final Node rootNode) throws ModelException { if (LOGGER.isDebugEnabled()) { LOGGER.debug(getStartLogStatement("initialize", rootNode)); } try { super.initialize(rootNode); templateName = getNodeService().getNodeProperty(rootNode, statisticsNodeProperties.getTemplateNameProperty(), null, true); aggregatedProperty = getNodeService().getNodeProperty(rootNode, statisticsNodeProperties.getAggregationPropertyNameProperty(), null, true); columnNames = new LinkedHashSet<String>(Arrays.asList(getNodeService().getNodeProperty(rootNode, statisticsNodeProperties.getColumnNamesProperty(), ArrayUtils.EMPTY_STRING_ARRAY, false))); } catch (final Exception e) { processException("An error occured on Statistics Model Initialization", e); } if (LOGGER.isDebugEnabled()) { LOGGER.debug(getFinishLogStatement("initialize")); } } public void initialize(final Node parentNode, final String templateName, final String propertyName) throws ModelException { assert !StringUtils.isEmpty(templateName); assert !StringUtils.isEmpty(propertyName); if (LOGGER.isDebugEnabled()) { LOGGER.debug(getStartLogStatement("initialize", parentNode, templateName, propertyName)); } try { final String statisticsName = MessageFormat.format(StatisticsService.STATISTICS_NAME_PATTERN, templateName, propertyName); super.initialize(parentNode, statisticsName, StatisticsNodeType.STATISTICS); this.templateName = templateName; this.aggregatedProperty = propertyName; } catch (final Exception e) { processException("Exception on initializing Statistics Model", e); } if (LOGGER.isDebugEnabled()) { LOGGER.debug(getFinishLogStatement("initialize")); } } @Override public void finishUp() throws ModelException { try { getNodeService().updateProperty(getRootNode(), statisticsNodeProperties.getTemplateNameProperty(), templateName); getNodeService().updateProperty(getRootNode(), statisticsNodeProperties.getAggregationPropertyNameProperty(), aggregatedProperty); getNodeService().updateProperty(getRootNode(), statisticsNodeProperties.getColumnNamesProperty(), columnNames.toArray(new String[columnNames.size()])); } catch (final ServiceException e) { processException("Exception on finishin up Statistics Model", e); } } @Override protected RelationshipType getRelationToParent() { return StatisticsRelationshipType.STATISTICS; } @Override public IStatisticsGroup getStatisticsGroup(final String period, final String propertyKey) throws ModelException { if (LOGGER.isDebugEnabled()) { LOGGER.debug(getStartLogStatement("getGroup", period, propertyKey)); } // TODO: LN: 15.08.2012, validate input final Pair<String, String> groupKey = new ImmutablePair<String, String>(period, propertyKey); IStatisticsGroup result = statisticsGroupCache.get(groupKey); if (result == null) { result = getGroupFromDatabase(period, propertyKey); statisticsGroupCache.put(groupKey, result); } if (LOGGER.isDebugEnabled()) { LOGGER.debug(getFinishLogStatement("getGroup")); } return result; } protected IStatisticsGroup getGroupFromDatabase(final String period, final String propertyKey) throws ModelException { if (LOGGER.isDebugEnabled()) { LOGGER.debug(getStartLogStatement("getGroupFromDatabase", period, propertyKey)); } IStatisticsGroup result = null; try { final Node propertyLevel = getStatisticsLevelNode(DimensionType.PROPERTY, propertyKey); final Node periodLevel = getStatisticsLevelNode(DimensionType.TIME, period); final Node groupNode = statisticsService.getGroup(propertyLevel, periodLevel); result = createStatisticsGroup(groupNode, period, propertyKey); } catch (final ServiceException e) { processException("Error on getting StatisticsGroup from Database", e); } if (LOGGER.isDebugEnabled()) { LOGGER.debug(getFinishLogStatement("getGroupFromDatabase")); } return result; } protected IStatisticsGroup createStatisticsGroupFromNode(final Node node) { if (LOGGER.isDebugEnabled()) { LOGGER.debug(getStartLogStatement("createStatisticsGroup", node)); } IStatisticsGroup group = null; try { final String period = statisticsService.getStatisticsLevelName(node, DimensionType.TIME); final String propertyKey = statisticsService.getStatisticsLevelName(node, DimensionType.PROPERTY); group = createStatisticsGroup(node, period, propertyKey); } catch (final Exception e) { LOGGER.error("Error on getting StatisticsGroup instance from Node", e); return null; } if (LOGGER.isDebugEnabled()) { LOGGER.debug(getFinishLogStatement("createStatisticsGroup")); } return group; } protected IStatisticsGroup createStatisticsGroup(final Node node, final String period, final String propertyKey) throws ModelException { StatisticsGroup result = null; try { final String name = getNodeService().getNodeName(node); result = new StatisticsGroup(node, statisticsGroupSourcesCollectFunction); result.setNodeType(StatisticsNodeType.GROUP); result.setName(name); result.setPeriod(period); result.setPropertyValue(propertyKey); } catch (final ServiceException e) { processException("Error on converting node to StatisticsGroup", e); } return result; } @Override public IStatisticsRow getStatisticsRow(final IStatisticsGroup group, final long startDate, final long endDate) throws ModelException { if (LOGGER.isDebugEnabled()) { LOGGER.debug(getStartLogStatement("getStatisticsRow", group, startDate, endDate)); } final IStatisticsRow result = getStatisticsRow(group, null, startDate, endDate); if (LOGGER.isDebugEnabled()) { LOGGER.debug(getFinishLogStatement("getStatisticsRow")); } return result; } @Override public IStatisticsRow getStatisticsRow(final IStatisticsGroup group, final IStatisticsRow sourceRow, final long startDate, final long endDate) throws ModelException { if (LOGGER.isDebugEnabled()) { LOGGER.debug(getStartLogStatement("getStatisticsRow", group, sourceRow, startDate, endDate)); } // TODO: LN: 15.08.2012, validate input final Pair<String, Long> key = new ImmutablePair<String, Long>(group.getName(), startDate); IStatisticsRow result = statisticsRowCache.get(key); if (result == null) { result = getStatisticsRowFromDatabase((StatisticsGroup) group, sourceRow, startDate, endDate); statisticsRowCache.put(key, result); } if (sourceRow != null) { try { statisticsService.addSourceNode(((StatisticsRow) result).getNode(), ((DataElement) sourceRow).getNode()); } catch (final ServiceException e) { processException("Can't add source to row " + sourceRow, e); } } if (LOGGER.isDebugEnabled()) { LOGGER.debug(getFinishLogStatement("getStatisticsRow")); } return result; } protected IStatisticsRow getStatisticsRowFromDatabase(final StatisticsGroup statisticsGroup, final IStatisticsRow sourceRow, final long startDate, final long endDate) throws ModelException { if (LOGGER.isDebugEnabled()) { LOGGER.debug(getStartLogStatement("getStatisticsRowFromDatabase", statisticsGroup, sourceRow, startDate, endDate)); } final String name = Long.toString(startDate); IStatisticsRow result = null; try { Node sRowNode = getNodeService().getChildInChainByName(statisticsGroup.getNode(), name, StatisticsNodeType.S_ROW); if (sRowNode == null) { final Map<String, Object> properties = new HashMap<String, Object>(); addTimeProperty(properties, timePeriodNodeProperties.getStartDateProperty(), timePeriodNodeProperties.getStartDateTimestampProperty(), startDate); addTimeProperty(properties, timePeriodNodeProperties.getEndDateProperty(), timePeriodNodeProperties.getEndDateTimestampProperty(), endDate); sRowNode = getNodeService().createNodeInChain(statisticsGroup.getNode(), StatisticsNodeType.S_ROW, name, properties); updateSummury((StatisticsRow) getSummuryRow(statisticsGroup), startDate, endDate); } result = createStatisticsRow(sRowNode, startDate, endDate); } catch (final ServiceException e) { processException("Exception on getting Statistics Row from Database", e); } if (LOGGER.isDebugEnabled()) { LOGGER.debug(getFinishLogStatement("getStatisticsRowFromDatabase")); } return result; } protected StatisticsRow createStatisticsRow(final Node node, final long startDate, final long endDate) { final StatisticsRow row = new StatisticsRow(node, statisticsRowSourcesCollectFunction); row.setNodeType(StatisticsNodeType.S_ROW); row.setStartDate(startDate); row.setEndDate(endDate); return row; } protected IStatisticsRow createStatisticsRow(final Node node) { StatisticsRow row = null; try { final long startDate = getNodeService().getNodeProperty(node, timePeriodNodeProperties.getStartDateTimestampProperty(), null, true); final long endDate = getNodeService().getNodeProperty(node, timePeriodNodeProperties.getEndDateTimestampProperty(), null, true); row = createStatisticsRow(node, startDate, endDate); final boolean isSummury = getNodeService().getNodeProperty(node, statisticsNodeProperties.isSummuryProperty(), false, false); final Node groupNode = getNodeService().getChainParent(node); final IStatisticsGroup group = createStatisticsGroupFromNode(groupNode); row.setSummury(isSummury); row.setStatisticsGroup(group); row.setStatisticsCells(getStatisticsCells(node)); } catch (final Exception e) { LOGGER.error("Error on getting StatisticsRow Node from Database", e); return null; } return row; } protected IStatisticsCell createStatisticsCell(final Node node) { final StatisticsCell cell = new StatisticsCell(node, statisticsCellSourcesCollectFunction); try { cell.setName(getNodeService().getNodeName(node)); cell.setNodeType(getNodeService().getNodeType(node)); cell.setValue((Number) getNodeService().getNodeProperty(node, statisticsNodeProperties.getValueProperty(), null, false)); cell.setTotalValue(getNodeService().getNodeProperty(node, statisticsNodeProperties.getTotalValueProperty(), 0d, false)); cell.setSize( getNodeService().getNodeProperty(node, getGeneralNodeProperties().getSizeProperty(), 0, false)); } catch (final ServiceException e) { LOGGER.error("Error on getting StatisticsRow Node from Database", e); return null; } catch (final NodeTypeNotExistsException e) { LOGGER.error("Error on getting StatisticsRow Node from Database", e); return null; } return cell; } private void addTimeProperty(final Map<String, Object> properties, final String timeProperty, final String timestampProperty, final long time) { final Date date = new Date(time); final String dateString = DateFormatManager.getInstance().getDefaultFormat().format(date); properties.put(timeProperty, dateString); properties.put(timestampProperty, time); } protected Node getStatisticsLevelNode(final DimensionType dimensionType, final String key) throws ModelException { if (LOGGER.isDebugEnabled()) { LOGGER.debug(getStartLogStatement("getStatisticsLevelNode", dimensionType, key)); } Node result = getStatisticsLevelNodeFromCache(dimensionType, key); if (result == null) { try { result = statisticsService.getStatisticsLevel(getRootNode(), dimensionType, key); addStatisticsLevelNodeToCache(dimensionType, key, result); } catch (final ServiceException e) { processException("Exception on searching for Statistics Level", e); } } if (LOGGER.isDebugEnabled()) { LOGGER.debug(getFinishLogStatement("getStatisticsLevelNode")); } return result; } protected Node getStatisticsLevelNodeFromCache(final DimensionType dimensionType, final String key) { Map<String, Node> dimensionCache = statisticsLevelCache.get(dimensionType); if (dimensionCache == null) { dimensionCache = new HashMap<String, Node>(); statisticsLevelCache.put(dimensionType, dimensionCache); } return dimensionCache.get(key); } protected void addStatisticsLevelNodeToCache(final DimensionType dimensionType, final String key, final Node value) { Map<String, Node> dimensionCache = statisticsLevelCache.get(dimensionType); if (dimensionCache == null) { dimensionCache = new HashMap<String, Node>(); statisticsLevelCache.put(dimensionType, dimensionCache); } dimensionCache.put(key, value); } @Override public boolean updateStatisticsCell(final IStatisticsRow statisticsRow, final String name, final Object value, final Object totalValue, final IDataElement... sourceElement) throws ModelException { if (LOGGER.isDebugEnabled()) { LOGGER.debug(getStartLogStatement("updateStatisticsCell", statisticsRow, name, value)); } // TODO: LN: 17.08.2012, validate input // TODO: LN: 20.08.2012, value can be null boolean isCreated = false; ; Node statisticsCellNode = findStatisticsCellNode((StatisticsRow) statisticsRow, name); if (statisticsCellNode == null) { if (LOGGER.isDebugEnabled()) { LOGGER.debug("No Statistics Cell was found by name <" + name + "> in Row <" + statisticsRow + ">. Create new one."); } statisticsCellNode = createStatisticsCellNode((StatisticsRow) statisticsRow, name); isCreated = true; } try { if (value != null && totalValue != null) { int size = getNodeService().getNodeProperty(statisticsCellNode, getGeneralNodeProperties().getSizeProperty(), 0, false); getNodeService().updateProperty(statisticsCellNode, statisticsNodeProperties.getTotalValueProperty(), totalValue); getNodeService().updateProperty(statisticsCellNode, statisticsNodeProperties.getValueProperty(), value); for (final IDataElement singleElement : sourceElement) { final DataElement source = (DataElement) singleElement; statisticsService.addSourceNode(statisticsCellNode, source.getNode()); if (source instanceof StatisticsCell) { StatisticsCell cell = (StatisticsCell) source; size += cell.getSize(); } else { size++; } } getNodeService().updateProperty(statisticsCellNode, getGeneralNodeProperties().getSizeProperty(), size); } } catch (final ServiceException e) { processException( "Error on updating value of Statistics Cell <" + name + "> in Row <" + statisticsRow + ">", e); } if (LOGGER.isDebugEnabled()) { LOGGER.debug(getFinishLogStatement("updateStatisticsCell")); } return isCreated; } protected Node findStatisticsCellNode(final StatisticsRow statisticsRow, final String name) throws ModelException { if (LOGGER.isDebugEnabled()) { LOGGER.debug(getStartLogStatement("getStatisticsCellNode", statisticsRow, name)); } final Pair<StatisticsRow, String> key = new ImmutablePair<StatisticsRow, String>(statisticsRow, name); Node result = statisticsCellNodeCache.get(key); if (result == null) { result = getStatisticsCellNodeFromDatabase(statisticsRow, name); } if (LOGGER.isDebugEnabled()) { LOGGER.debug(getFinishLogStatement("getStatisticsCellNode")); } return result; } protected Node createStatisticsCellNode(final StatisticsRow statisticsRow, final String name) throws ModelException { if (LOGGER.isDebugEnabled()) { LOGGER.debug(getStartLogStatement("createStatisticsCellNode", statisticsRow, name)); } Node result = null; try { result = getNodeService().createNodeInChain(statisticsRow.getNode(), StatisticsNodeType.S_CELL, name); } catch (final ServiceException e) { processException( "Error on creating Statistics Cell Node by name <" + name + "> in Row <" + statisticsRow + ">.", e); } columnNames.add(name); if (LOGGER.isDebugEnabled()) { LOGGER.debug(getFinishLogStatement("createStatisticsCellNode")); } return result; } protected Node getStatisticsCellNodeFromDatabase(final StatisticsRow statisticsRow, final String name) throws ModelException { if (LOGGER.isDebugEnabled()) { LOGGER.debug(getStartLogStatement("getStatisticsCellNodeFromDatabase", statisticsRow, name)); } Node result = null; try { result = getNodeService().getChildInChainByName(statisticsRow.getNode(), name, StatisticsNodeType.S_CELL); } catch (final ServiceException e) { processException("Error on searching Statistics Cell Node by name <" + name + "> in Row <" + statisticsRow + ">.", e); } if (LOGGER.isDebugEnabled()) { LOGGER.debug(getFinishLogStatement("getStatisticsCellNodeFromDatabase")); } return result; } protected Iterable<IStatisticsCell> getStatisticsCells(final Node statisticsRowNode) throws ModelException { if (LOGGER.isDebugEnabled()) { LOGGER.debug(getStartLogStatement("getStatisticsCells", statisticsRowNode)); } // TODO: LN: 20.08.2012, validate input Iterable<IStatisticsCell> statisticsCells = null; try { final Iterator<Node> nodeIterator = getNodeService().getChildrenChain(statisticsRowNode); statisticsCells = new StatisticsCellIterator(nodeIterator).toIterable(); } catch (final ServiceException e) { processException("Error on getting chain of Statistics Cells", e); } if (LOGGER.isDebugEnabled()) { LOGGER.debug(getFinishLogStatement("getStatisticsCells")); } return statisticsCells; } @Override public Iterable<IStatisticsRow> getStatisticsRows(final String period) throws ModelException { return getStatisticsRowsInTimeRange(period, Long.MIN_VALUE, Long.MAX_VALUE); } @Override public Iterable<IStatisticsRow> getStatisticsRowsInTimeRange(final String period, final long startTime, final long endTime) throws ModelException { if (LOGGER.isDebugEnabled()) { LOGGER.debug(getStartLogStatement("getStatisticsRows", period)); } // TODO: LN: 20.08.2012, validate input Iterable<IStatisticsRow> statisticsRows = null; final Node periodNode = getStatisticsLevelNode(DimensionType.TIME, period); try { final Iterator<Node> groupNodeIterator = getNodeService().getChildren(periodNode, NodeServiceRelationshipType.CHILD); final List<Node> allRowsIterator = new ArrayList<Node>(); // TODO KV: seems like IteratorUtils.chaindedIterator() works badly, check this // solution. while (groupNodeIterator.hasNext()) { allRowsIterator.addAll(Lists.newArrayList( statisticsService.getRowsInTimeRange(groupNodeIterator.next(), startTime, endTime))); } statisticsRows = new StatisticsRowIterator(allRowsIterator.iterator()).toIterable(); } catch (final ServiceException e) { processException("Error on getting chain of Statistics Rows", e); } if (LOGGER.isDebugEnabled()) { LOGGER.debug(getFinishLogStatement("getStatisticsRows")); } return statisticsRows; } @Override public Set<String> getColumns() { return columnNames; } @Override public String getAggregatedProperty() { return aggregatedProperty; } @Override public boolean containsLevel(final DimensionType dimension, final String levelName) throws ModelException { if (LOGGER.isDebugEnabled()) { LOGGER.debug(getStartLogStatement("containsLevel", dimension, levelName)); } try { return statisticsService.findStatisticsLevel(getRootNode(), dimension, levelName) != null; } catch (final ServiceException e) { processException("Error on checking Statistics Level", e); } if (LOGGER.isDebugEnabled()) { LOGGER.debug(getFinishLogStatement("containsLevel")); } return false; } @Override public void flush() throws ModelException { statisticsCellNodeCache.clear(); statisticsRowCache.clear(); summuryCache.clear(); super.flush(); } @Override public void setLevelCount(final DimensionType dimension, final String levelName, final int count) throws ModelException { if (LOGGER.isDebugEnabled()) { LOGGER.debug(getStartLogStatement("setLevelCount", dimension, levelName, count)); } final Node levelNode = getStatisticsLevelNode(dimension, levelName); try { getNodeService().updateProperty(levelNode, getGeneralNodeProperties().getSizeProperty(), count); } catch (final ServiceException e) { processException("Error on updating count for level <" + dimension + ":" + levelName + ">.", e); } if (LOGGER.isDebugEnabled()) { LOGGER.debug(getFinishLogStatement("setLevelCount")); } } @Override public int getLevelCount(final DimensionType dimension, final String levelName) throws ModelException { if (LOGGER.isDebugEnabled()) { LOGGER.debug(getStartLogStatement("getLevelCount", dimension, levelName)); } int result = 0; final Node levelNode = getStatisticsLevelNode(dimension, levelName); try { result = getNodeService().getNodeProperty(levelNode, getGeneralNodeProperties().getSizeProperty(), 0, false); } catch (final ServiceException e) { processException("Error on getting count for level <" + dimension + ":" + levelName + ">.", e); } if (LOGGER.isDebugEnabled()) { LOGGER.debug(getFinishLogStatement("getLevelCount")); } return result; } @Override public IStatisticsRow getSummuryRow(final IStatisticsGroup statisticsGroup) throws ModelException { try { StatisticsRow row = summuryCache.get(statisticsGroup); if (row == null) { row = (StatisticsRow) getStatisticsRowFromDatabase((StatisticsGroup) statisticsGroup, null, Long.MAX_VALUE, Long.MIN_VALUE); final Node sRowNode = row.getNode(); row.setSummury(true); getNodeService().updateProperty(sRowNode, statisticsNodeProperties.isSummuryProperty(), true); row.setStatisticsGroup(statisticsGroup); summuryCache.put((StatisticsGroup) statisticsGroup, row); } return row; } catch (final ServiceException e) { processException("can't get syummury row from group" + statisticsGroup, e); } return null; } protected void updateSummury(final StatisticsRow summuryRow, final long startTime, final long endTime) throws ServiceException { if (endTime > summuryRow.getEndDate()) { updateSummuryRowDate(summuryRow, endTime, timePeriodNodeProperties.getEndDateProperty(), timePeriodNodeProperties.getEndDateTimestampProperty()); summuryRow.setEndDate(endTime); } if (startTime < summuryRow.getStartDate()) { updateSummuryRowDate(summuryRow, startTime, timePeriodNodeProperties.getStartDateProperty(), timePeriodNodeProperties.getStartDateTimestampProperty()); summuryRow.setStartDate(startTime); } } private void updateSummuryRowDate(final StatisticsRow row, final long currentDate, final String dateProperty, final String dateTimestampProperty) throws ServiceException { final Date date = new Date(currentDate); final String dateString = DateFormatManager.getInstance().getDefaultFormat().format(date); getNodeService().updateProperty(row.getNode(), dateProperty, dateString); getNodeService().updateProperty(row.getNode(), dateTimestampProperty, currentDate); } @Override public Iterable<IStatisticsGroup> getAllStatisticsGroups(final DimensionType type, final String levelName) throws ModelException { return getAllStatisticsGroups(type, levelName, null); } public Iterable<IStatisticsGroup> getAllStatisticsGroups(final DimensionType type, final String levelName, final IStatisticsFilter filter) throws ModelException { if (LOGGER.isDebugEnabled()) { LOGGER.debug(getStartLogStatement("getAllStatisticsGroups", type, levelName, filter)); } // TODO: LN: 20.08.2012, validate input final Node periodNode = getStatisticsLevelNode(type, levelName); Iterator<Node> groupNodeIterator = null; try { groupNodeIterator = getNodeService().getChildren(periodNode, NodeServiceRelationshipType.CHILD); } catch (final ServiceException e) { processException("can't find groups", e); } if (LOGGER.isDebugEnabled()) { LOGGER.debug(getFinishLogStatement("getAllStatisticsGroups")); } return new StatisticsGroupIterator(groupNodeIterator, filter).toIterable(); } @Override public Iterable<IStatisticsLevel> findAllStatisticsLevels(final DimensionType type) throws ModelException { if (LOGGER.isDebugEnabled()) { LOGGER.debug(getStartLogStatement("findAllStatisticsLevels", type)); } final Iterable<IStatisticsLevel> result = findAllStatisticsLevels(type, null); if (LOGGER.isDebugEnabled()) { LOGGER.debug(getFinishLogStatement("findAllStatisticsLevels")); } return result; } private boolean hasUnderlineSource(final IDataElement element) throws ModelException { if (LOGGER.isDebugEnabled()) { LOGGER.debug(getStartLogStatement("hasUnderlineSource", element)); } final DataElement statElement = (DataElement) element; Iterator<Node> sources = null; try { sources = statisticsService.getAllSources(statElement.getNode()); if (sources.hasNext() && element.getNodeType().equals(getNodeService().getNodeType(sources.next()))) { return true; } } catch (final ServiceException e) { processException("can't get sources from node " + statElement, e); } catch (final NodeTypeNotExistsException e) { LOGGER.error("can't get node type for", e); } return false; } @Override public Iterable<IStatisticsCell> getSourceCells(final IStatisticsCell cell) throws ModelException { if (!hasUnderlineSource(cell)) { return null; } final Iterator<Node> sources = getSourcesNodes(cell); return new StatisticsCellIterator(sources).toIterable(); } @Override public Iterable<IDataElement> getSources(final IDataElement cell) throws ModelException { final Iterator<Node> sources = getSourcesNodes(cell); if (cell.getNodeType().equals(StatisticsNodeType.S_CELL)) { return new DataElementIterator(sources, measurementNodeProperties.getEventProperty()).toIterable(); } return new DataElementIterator(sources).toIterable(); } @Override public Iterable<IStatisticsRow> getSourceRows(final IStatisticsRow row) throws ModelException { if (!hasUnderlineSource(row)) { return null; } final Iterator<Node> sources = getSourcesNodes(row); return new StatisticsRowIterator(sources).toIterable(); } private Iterator<Node> getSourcesNodes(final IDataElement element) throws ModelException { if (LOGGER.isDebugEnabled()) { LOGGER.debug(getStartLogStatement("getCellSources", element)); } final DataElement statCell = (DataElement) element; Iterator<Node> sources = null; try { sources = statisticsService.getAllSources(statCell.getNode()); } catch (final ServiceException e) { processException("can't get sources from node " + element, e); } if (LOGGER.isDebugEnabled()) { LOGGER.debug(getFinishLogStatement("getCellSources")); } return sources; } @Override public IDataElement getParent(final IDataElement childElement, final DimensionType dimension) throws ModelException { if (LOGGER.isDebugEnabled()) { LOGGER.debug(getStartLogStatement("getParent", childElement, dimension)); } IDataElement result = null; final DataElement child = (DataElement) childElement; if (child.getNodeType().equals(StatisticsNodeType.S_CELL)) { try { final Node parentNode = getNodeService().getChainParent(child.getNode()); result = createStatisticsRow(parentNode); } catch (final ServiceException e) { processException("Error on getting parent of SCell", e); } } else if (child instanceof IStatisticsRow) { final IStatisticsRow childRow = (IStatisticsRow) child; result = childRow.getStatisticsGroup(); } else if (child instanceof IStatisticsGroup) { final IStatisticsGroup childGroup = (IStatisticsGroup) child; String name = null; switch (dimension) { case PROPERTY: name = childGroup.getPropertyValue(); break; case TIME: name = childGroup.getPeriod(); break; } final Node periodNode = getStatisticsLevelNode(dimension, name); result = getDataElement(periodNode, StatisticsNodeType.LEVEL, name); } else if (child.getNodeType().equals(StatisticsNodeType.LEVEL)) { return asDataElement(); } if (LOGGER.isDebugEnabled()) { LOGGER.debug(getFinishLogStatement("getParent")); } return result; } @Override public IDataElement getParentElement(final IDataElement childElement) throws ModelException { return getParent(childElement, DimensionType.TIME); } @Override public Iterable<IDataElement> getChildren(final IDataElement parentElement) throws ModelException { if (LOGGER.isDebugEnabled()) { LOGGER.debug(getStartLogStatement("getChildren", parentElement)); } final Iterable<IDataElement> result = getChildren(parentElement, null); if (LOGGER.isDebugEnabled()) { LOGGER.debug(getFinishLogStatement("getChildren")); } return result; } @Override public String getName() { final StringBuilder builder = new StringBuilder(); builder.append(getSourceModel().getName() + " {" + super.getName() + "}"); return builder.toString(); } private StatisticsLevel createStatisticsLevel(final Node node, final DimensionType dimension) { final StatisticsLevel result = new StatisticsLevel(node, dimension); try { result.setNodeType(StatisticsNodeType.LEVEL); result.setName(getNodeService().getNodeName(node)); } catch (final ServiceException e) { LOGGER.error("Error on initializing Statistics Level", e); } return result; } @Override public Iterable<IDataElement> getChildren(final IDataElement parentElement, final IStatisticsFilter filter) throws ModelException { if (LOGGER.isDebugEnabled()) { LOGGER.debug(getStartLogStatement("getChildren", parentElement, filter)); } Iterable<IDataElement> result = null; if (parentElement.getNodeType().equals(StatisticsNodeType.LEVEL)) { final IStatisticsLevel level = (IStatisticsLevel) parentElement; result = new DataElementConverter<IStatisticsGroup>( getAllStatisticsGroups(level.getDimension(), level.getName(), filter).iterator()).toIterable(); } else if (parentElement.getNodeType().equals(StatisticsNodeType.GROUP)) { final IStatisticsGroup group = (IStatisticsGroup) parentElement; if (filter != null) { result = new DataElementConverter<IStatisticsRow>( getStatisticsRowsInTimeRange(group.getPeriod(), filter.getStartTime(), filter.getEndTime()) .iterator()).toIterable(); } else { result = new DataElementConverter<IStatisticsRow>(getStatisticsRows(group.getPeriod()).iterator()) .toIterable(); } } else if (parentElement.getNodeType().equals(StatisticsNodeType.S_ROW)) { final IStatisticsRow row = (IStatisticsRow) parentElement; result = new StatisticsCellFilteredConverter(row.getStatisticsCells().iterator(), filter).toIterable(); } else if (parentElement.getNodeType().equals(StatisticsNodeType.S_CELL)) { final IStatisticsCell cell = (IStatisticsCell) parentElement; final Iterable<IStatisticsCell> sourceCells = getSourceCells(cell); if (sourceCells != null) { result = new DataElementConverter<IStatisticsCell>(sourceCells.iterator()).toIterable(); } else { result = getSources(cell); } } if (LOGGER.isDebugEnabled()) { LOGGER.debug(getFinishLogStatement("getChildren")); } return result; } @Override public Iterable<IStatisticsLevel> findAllStatisticsLevels(final DimensionType type, final IStatisticsFilter filter) throws ModelException { if (LOGGER.isDebugEnabled()) { LOGGER.debug(getStartLogStatement("findAllStatisticsLevels", type, filter)); } Iterable<IStatisticsLevel> result = null; try { final Iterator<Node> levels = statisticsService.findAllStatisticsLevelNode(getRootNode(), type); result = new StatisticsLevelIterator(levels, filter, type).toIterable(); } catch (final ServiceException e) { processException("Error when try to find all levels nodes", e); } if (LOGGER.isDebugEnabled()) { LOGGER.debug(getFinishLogStatement("findAllStatisticsLevels")); } return result; } }