/*
* Copyright (C) 2010 Brockmann Consult GmbH (info@brockmann-consult.de)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation; either version 3 of the License, or (at your option)
* any later version.
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, see http://www.gnu.org/licenses/
*/
package org.esa.beam.smos.visat;
import com.bc.ceres.binio.CompoundData;
import com.bc.ceres.binio.CompoundType;
import com.bc.ceres.binio.Type;
import com.bc.ceres.binio.util.NumberUtils;
import com.bc.ceres.core.ProgressMonitor;
import com.bc.ceres.glayer.CollectionLayer;
import com.bc.ceres.glayer.Layer;
import com.bc.ceres.glayer.support.ImageLayer;
import com.bc.ceres.glayer.swing.LayerCanvas;
import com.bc.ceres.glevel.MultiLevelImage;
import com.bc.ceres.glevel.support.DefaultMultiLevelImage;
import com.bc.ceres.glevel.support.FileMultiLevelSource;
import com.bc.ceres.grender.Rendering;
import com.bc.ceres.grender.Viewport;
import org.esa.beam.dataio.smos.L1cScienceSmosFile;
import org.esa.beam.dataio.smos.L1cScienceValueProvider;
import org.esa.beam.dataio.smos.SmosConstants;
import org.esa.beam.dataio.smos.SmosFile;
import org.esa.beam.dataio.smos.SmosMultiLevelSource;
import org.esa.beam.dataio.smos.ValueProvider;
import org.esa.beam.framework.datamodel.Band;
import org.esa.beam.framework.datamodel.Product;
import org.esa.beam.framework.datamodel.RasterDataNode;
import org.esa.beam.framework.datamodel.VirtualBand;
import org.esa.beam.framework.help.HelpSys;
import org.esa.beam.framework.ui.product.ProductSceneView;
import org.esa.beam.glevel.TiledFileMultiLevelSource;
import org.esa.beam.smos.DateTimeUtils;
import org.esa.beam.smos.visat.swing.SnapshotSelectorCombo;
import org.esa.beam.smos.visat.swing.SnapshotSelectorComboModel;
import org.esa.beam.visat.VisatApp;
import org.jfree.layout.CenterLayout;
import javax.swing.AbstractButton;
import javax.swing.BorderFactory;
import javax.swing.ButtonGroup;
import javax.swing.ButtonModel;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JComponent;
import javax.swing.JInternalFrame;
import javax.swing.JLabel;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.JProgressBar;
import javax.swing.JRadioButton;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.SwingWorker;
import javax.swing.border.EmptyBorder;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.TableModel;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.ComponentOrientation;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.Shape;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.geom.AffineTransform;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.io.IOException;
import java.text.MessageFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import java.util.TimeZone;
import java.util.concurrent.ExecutionException;
public class SnapshotInfoToolView extends SmosToolView {
@SuppressWarnings({"UnusedDeclaration"})
public static final String ID = SnapshotInfoToolView.class.getName();
private static final SnapshotTableModel NULL_MODEL = new SnapshotTableModel(new Object[0][0]);
private SnapshotSelectorCombo snapshotSelectorCombo;
private JTable snapshotTable;
private ButtonModel locateSnapshotButtonModel;
private ButtonModel browseButtonModel;
private ButtonModel snapshotButtonModel;
private ButtonModel followModeButtonModel;
private ButtonModel synchronizeButtonModel;
@SuppressWarnings({"FieldCanBeLocal"})
private SnapshotIdListener snapshotIdListener;
@Override
protected JComponent createClientComponent() {
snapshotIdListener = new SnapshotIdListener();
JPanel mainPanel = new JPanel(new BorderLayout(4, 4));
mainPanel.setBorder(BorderFactory.createEmptyBorder(4, 4, 4, 4));
snapshotSelectorCombo = new SnapshotSelectorCombo();
snapshotSelectorCombo.addSliderChangeListener(snapshotIdListener);
snapshotSelectorCombo.addComboBoxActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
updateTable(snapshotSelectorCombo.getSnapshotId());
}
});
JComponent comboComponent = SnapshotSelectorCombo.createComponent(snapshotSelectorCombo, false);
mainPanel.add(comboComponent, BorderLayout.NORTH);
final JPanel snapshotTablePanel = createSnapshotTablePanel();
mainPanel.add(snapshotTablePanel, BorderLayout.CENTER);
final JPanel viewSettingsPanel = createViewSettingsPanel();
final JPanel southPanel = new JPanel(new BorderLayout(6, 0));
southPanel.add(viewSettingsPanel, BorderLayout.WEST);
final AbstractButton helpButton = createHelpButton();
southPanel.add(helpButton, BorderLayout.EAST);
mainPanel.add(southPanel, BorderLayout.SOUTH);
if (getDescriptor().getHelpId() != null) {
HelpSys.enableHelpOnButton(helpButton, getDescriptor().getHelpId());
HelpSys.enableHelpKey(mainPanel, getDescriptor().getHelpId());
}
return mainPanel;
}
@Override
protected void updateClientComponent(ProductSceneView smosView) {
final L1cScienceSmosFile smosFile = SmosBox.getL1cScienceSmosFile(smosView);
if (smosFile != null) {
if (!smosFile.hasSnapshotInfo()) {
startPolModeInitWaiting(smosView, smosFile);
return;
}
final long snapshotId = getSelectedSnapshotId(smosView.getRaster());
updateUI(smosView, snapshotId, true);
} else {
super.realizeSmosView(null);
}
}
private void updateTable(long snapshotId) {
final SmosFile selectedSmosFile = getSelectedSmosFile();
if (selectedSmosFile != null && selectedSmosFile instanceof L1cScienceSmosFile) {
final L1cScienceSmosFile l1cScienceSmosFile = (L1cScienceSmosFile) selectedSmosFile;
final int snapshotIndex = l1cScienceSmosFile.getSnapshotInfo().getSnapshotIndex(snapshotId);
if (snapshotIndex != -1) {
final SwingWorker<TableModel, Object> worker = new SwingWorker<TableModel, Object>() {
@Override
protected TableModel doInBackground() throws Exception {
final CompoundData data = l1cScienceSmosFile.getSnapshotData(snapshotIndex);
return createSnapshotTableModel(data);
}
@Override
protected void done() {
try {
final TableModel tableModel = get();
snapshotTable.setModel(tableModel);
} catch (InterruptedException | ExecutionException e) {
snapshotTable.setModel(NULL_MODEL);
}
}
};
worker.execute();
return;
}
}
snapshotTable.setModel(NULL_MODEL);
}
private TableModel createSnapshotTableModel(CompoundData data) {
final CompoundType compoundType = data.getType();
final int memberCount = data.getMemberCount();
final ArrayList<Object[]> list = new ArrayList<>(memberCount);
for (int i = 0; i < memberCount; i++) {
final Object[] entry = new Object[2];
entry[0] = compoundType.getMemberName(i);
final Type memberType = compoundType.getMemberType(i);
if (memberType.isSimpleType()) {
try {
entry[1] = NumberUtils.getNumericMember(data, i);
} catch (IOException e) {
entry[1] = "Failed reading data";
}
list.add(entry);
} else {
if ("Snapshot_Time".equals(compoundType.getMemberName(i))) {
try {
final Date date = DateTimeUtils.cfiDateToUtc(data);
final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSz",
Locale.ENGLISH);
dateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
entry[1] = dateFormat.format(date);
} catch (IOException e) {
entry[1] = "Failed reading data";
}
list.add(entry);
}
}
}
return new SnapshotTableModel(list.toArray(new Object[2][list.size()]));
}
private void updateSnapshotImage(RasterDataNode raster, long snapshotId) {
final MultiLevelImage sourceImage = raster.getSourceImage();
if (sourceImage instanceof DefaultMultiLevelImage) {
final DefaultMultiLevelImage multiLevelImage = (DefaultMultiLevelImage) sourceImage;
if (multiLevelImage.getSource() instanceof SmosMultiLevelSource) {
final SmosMultiLevelSource smosMultiLevelSource = (SmosMultiLevelSource) multiLevelImage.getSource();
final ValueProvider valueProvider = smosMultiLevelSource.getValueProvider();
if (valueProvider instanceof L1cScienceValueProvider) {
final L1cScienceValueProvider btDataValueProvider = (L1cScienceValueProvider) valueProvider;
if (btDataValueProvider.getSnapshotId() != snapshotId) {
btDataValueProvider.setSnapshotId(snapshotId);
resetRasterImages(raster);
}
}
}
}
}
private void locateSnapshotId(final ProductSceneView smosView, final long id) {
final L1cScienceSmosFile smosFile = SmosBox.getL1cScienceSmosFile(smosView);
if (smosFile != null) {
final Rectangle2D snapshotRegion = smosFile.getSnapshotInfo().getArea(id).getBounds2D();
if (snapshotRegion != null) {
final Viewport vp = smosView.getLayerCanvas().getViewport();
final AffineTransform m2v = vp.getModelToViewTransform();
final Point2D.Double center = new Point2D.Double(snapshotRegion.getCenterX(),
snapshotRegion.getCenterY());
m2v.transform(center, center);
final Rectangle viewBounds = vp.getViewBounds();
final double vx = viewBounds.getCenterX();
final double vy = viewBounds.getCenterY();
vp.moveViewDelta(vx - center.getX(), vy - center.getY());
} else {
JOptionPane.showMessageDialog(getPaneControl(), MessageFormat.format(
"No snapshot found with ID = {0}", id));
}
}
}
// package access for testing only tb 2014-04-10
static boolean isXPolarized(Band band) {
return band.getName().endsWith("_X");
}
// package access for testing only tb 2014-04-10
static boolean isYPolarized(Band band) {
return band.getName().endsWith("_Y");
}
// package access for testing only tb 2014-04-10
static boolean isXYPolarized(Band band) {
return band.getName().contains("_XY");
}
private class SnapshotIdListener implements ChangeListener {
private SnapshotRegionOverlay overlay = new SnapshotRegionOverlay();
private boolean overlayAdded;
@Override
public void stateChanged(ChangeEvent e) {
final long snapshotId = snapshotSelectorCombo.getSnapshotId();
updateTable(snapshotId);
if (snapshotSelectorCombo.isAdjusting()) {
if (snapshotButtonModel.isSelected()) {
overlay.setId(snapshotId);
if (!overlayAdded) {
overlayAdded = true;
getSelectedSmosView().getLayerCanvas().addOverlay(overlay);
} else {
getSelectedSmosView().getLayerCanvas().repaint();
}
}
return;
}
getSelectedSmosView().getLayerCanvas().removeOverlay(overlay);
overlayAdded = false;
if (synchronizeButtonModel.isSelected() && snapshotButtonModel.isSelected()) {
final ProductSceneView smosView = getSelectedSmosView();
if (smosView != null) {
if (followModeButtonModel.isSelected()) {
locateSnapshotId(smosView, snapshotId);
}
updateAllImagesAndViews(smosView.getProduct(), snapshotId);
}
}
}
}
private class SnapshotRegionOverlay implements LayerCanvas.Overlay {
private long snapshotId;
@Override
public void paintOverlay(LayerCanvas canvas, Rendering rendering) {
ProductSceneView view = getSelectedSmosView();
Graphics2D graphics = rendering.getGraphics();
L1cScienceSmosFile scienceSmosFile = SmosBox.getL1cScienceSmosFile(view);
if (scienceSmosFile != null) {
final Rectangle2D snapshotRegion = scienceSmosFile.getSnapshotInfo().getArea(snapshotId).getBounds2D();
if (snapshotRegion != null) {
final Viewport vp = view.getLayerCanvas().getViewport();
final AffineTransform m2v = vp.getModelToViewTransform();
Shape transformedShape = m2v.createTransformedShape(snapshotRegion);
Color color = graphics.getColor();
graphics.setColor(Color.WHITE);
graphics.draw(transformedShape);
graphics.setColor(color);
}
}
}
void setId(long snapshotId) {
this.snapshotId = snapshotId;
}
}
private class ToggleSnapshotModeAction implements ActionListener {
@Override
public void actionPerformed(ActionEvent event) {
final ProductSceneView smosView = getSelectedSmosView();
final long snapshotId;
if (snapshotButtonModel.isSelected()) {
snapshotId = snapshotSelectorCombo.getSnapshotId();
if (followModeButtonModel.isSelected()) {
locateSnapshotId(smosView, snapshotId);
}
} else {
snapshotId = -1;
}
updateAllImagesAndViews(smosView.getProduct(), snapshotId);
updateUI(smosView, snapshotId, false);
}
}
private void updateAllImagesAndViews(Product smosProduct, long snapshotId) {
final long xPolId;
final long yPolId;
final long crossPolId;
if (snapshotId != -1) {
final L1cScienceSmosFile smosFile = (L1cScienceSmosFile) getSelectedSmosFile();
xPolId = findSnapshotId(smosFile.getSnapshotInfo().getSnapshotIdsX(), snapshotId);
yPolId = findSnapshotId(smosFile.getSnapshotInfo().getSnapshotIdsY(), snapshotId);
crossPolId = findSnapshotId(smosFile.getSnapshotInfo().getSnapshotIdsXY(), snapshotId);
} else {
xPolId = -1;
yPolId = -1;
crossPolId = -1;
}
for (final Band band : smosProduct.getBands()) {
if (band.getName().equals(SmosConstants.LAND_SEA_MASK_NAME)) {
continue;
}
if (band instanceof VirtualBand) {
resetRasterImages(band);
} else if (isXPolarized(band)) {
updateSnapshotImage(band, xPolId);
} else if (isYPolarized(band)) {
updateSnapshotImage(band, yPolId);
} else if (isXYPolarized(band)) {
updateSnapshotImage(band, crossPolId);
} else if (band.isFlagBand()) {
updateSnapshotImage(band, snapshotId);
} else {
resetRasterImages(band);
}
}
for (final Band band : smosProduct.getBands()) {
if (band.getName().equals(SmosConstants.LAND_SEA_MASK_NAME)) {
continue;
}
if (band instanceof VirtualBand) {
updateViews(band, snapshotId);
} else if (isXPolarized(band)) {
updateViews(band, xPolId);
} else if (isYPolarized(band)) {
updateViews(band, yPolId);
} else if (isXYPolarized(band)) {
updateViews(band, crossPolId);
} else {
updateViews(band, snapshotId);
}
}
for (final Band band : smosProduct.getBands()) {
if (band.getName().equals(SmosConstants.LAND_SEA_MASK_NAME)) {
continue;
}
if (band instanceof VirtualBand) {
setSelectedSnapshotId(band, snapshotId);
} else if (isXPolarized(band)) {
setSelectedSnapshotId(band, xPolId);
} else if (isYPolarized(band)) {
setSelectedSnapshotId(band, yPolId);
} else if (isXYPolarized(band)) {
setSelectedSnapshotId(band, crossPolId);
} else {
setSelectedSnapshotId(band, snapshotId);
}
}
}
private void updateViews(RasterDataNode raster, long snapshotId) {
for (final JInternalFrame internalFrame : VisatApp.getApp().findInternalFrames(raster)) {
if (internalFrame != null) {
if (internalFrame.getContentPane() instanceof ProductSceneView) {
final ProductSceneView view = (ProductSceneView) internalFrame.getContentPane();
if (getSelectedSnapshotId(view.getRaster()) != snapshotId) {
regenerateImageLayers(view.getRootLayer());
}
}
}
}
}
private class LocateSnapshotAction implements ActionListener {
@Override
public void actionPerformed(ActionEvent event) {
final ProductSceneView smosView = getSelectedSmosView();
locateSnapshotId(smosView, getSelectedSnapshotId(smosView));
}
}
private JPanel createViewSettingsPanel() {
final JCheckBox synchroniseCheckBox = new JCheckBox("Synchronise with view", false);
synchronizeButtonModel = synchroniseCheckBox.getModel();
synchronizeButtonModel.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
final ProductSceneView smosView = getSelectedSmosView();
final long snapshotId = getSelectedSnapshotId(smosView);
updateUI(smosView, snapshotId, false);
}
});
final ToggleSnapshotModeAction toggleSnapshotModeAction = new ToggleSnapshotModeAction();
final JRadioButton browseButton = new JRadioButton("Browse", true);
browseButtonModel = browseButton.getModel();
browseButtonModel.addActionListener(toggleSnapshotModeAction);
final JRadioButton snapshotButton = new JRadioButton("Snapshot", false);
snapshotButtonModel = snapshotButton.getModel();
snapshotButtonModel.addActionListener(toggleSnapshotModeAction);
final ButtonGroup buttonGroup = new ButtonGroup();
buttonGroup.add(browseButton);
buttonGroup.add(snapshotButton);
final JCheckBox followModeCheckBox = new JCheckBox("Follow", false);
followModeButtonModel = followModeCheckBox.getModel();
final JButton locateSnapshotButton = new JButton("Locate in view");
locateSnapshotButton.addActionListener(new LocateSnapshotAction());
locateSnapshotButton.setToolTipText("Locate selected snapshot in view");
locateSnapshotButtonModel = locateSnapshotButton.getModel();
final JPanel viewSettingsPanel = new JPanel(new FlowLayout(FlowLayout.LEADING, 4, 4));
viewSettingsPanel.setComponentOrientation(ComponentOrientation.LEFT_TO_RIGHT);
viewSettingsPanel.add(synchroniseCheckBox);
viewSettingsPanel.add(browseButton);
viewSettingsPanel.add(snapshotButton);
viewSettingsPanel.add(followModeCheckBox);
viewSettingsPanel.add(locateSnapshotButton);
return viewSettingsPanel;
}
private void updateUI(ProductSceneView smosView, long snapshotId, boolean resetSelectorComboModel) {
if (resetSelectorComboModel) {
final L1cScienceSmosFile smosFile = SmosBox.getL1cScienceSmosFile(smosView);
snapshotSelectorCombo.setModel(new SnapshotSelectorComboModel(smosFile.getSnapshotInfo()));
}
final boolean sync = synchronizeButtonModel.isSelected();
if (sync) {
final String bandName = smosView.getRaster().getName();
if (bandName.endsWith("_X")) {
snapshotSelectorCombo.setComboBoxSelectedIndex(1);
} else if (bandName.endsWith("_Y")) {
snapshotSelectorCombo.setComboBoxSelectedIndex(2);
} else if (bandName.contains("_XY")) {
snapshotSelectorCombo.setComboBoxSelectedIndex(3);
} else {
snapshotSelectorCombo.setComboBoxSelectedIndex(0);
}
if (snapshotId != -1) {
snapshotSelectorCombo.setSnapshotId(snapshotId);
snapshotButtonModel.setSelected(true);
} else {
browseButtonModel.setSelected(true);
}
}
updateTable(snapshotSelectorCombo.getSnapshotId());
snapshotSelectorCombo.setComboBoxEnabled(!sync);
browseButtonModel.setEnabled(sync);
snapshotButtonModel.setEnabled(sync);
followModeButtonModel.setEnabled(sync && snapshotButtonModel.isSelected());
locateSnapshotButtonModel.setEnabled(sync && snapshotButtonModel.isSelected());
}
private JPanel createSnapshotTablePanel() {
snapshotTable = new JTable(NULL_MODEL);
snapshotTable.getColumnModel().getColumn(1).setCellRenderer(new DefaultTableCellRenderer() {
@Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected,
boolean hasFocus, int row, int column) {
super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
if (value instanceof Number) {
setHorizontalAlignment(RIGHT);
}
return this;
}
});
final JPopupMenu tablePopup = new JPopupMenu();
final JMenuItem exportItem = new JMenuItem("Export...");
exportItem.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
new TableModelExportRunner(getPaneWindow(),
getTitle(),
snapshotTable.getModel(),
snapshotTable.getColumnModel()).run();
}
});
tablePopup.add(exportItem);
snapshotTable.add(tablePopup);
MouseListener popupListener = new PopupListener(tablePopup);
snapshotTable.addMouseListener(popupListener);
final JPanel snapshotTablePanel = new JPanel(new BorderLayout());
final JLabel tableLabel = new JLabel("Snapshot Information:");
tableLabel.setBorder(new EmptyBorder(4, 0, 0, 0));
snapshotTablePanel.add(tableLabel, BorderLayout.NORTH);
snapshotTablePanel.add(new JScrollPane(snapshotTable), BorderLayout.CENTER);
return snapshotTablePanel;
}
private void startPolModeInitWaiting(ProductSceneView smosView, L1cScienceSmosFile smosFile) {
final JPanel centerPanel = new JPanel(new CenterLayout());
centerPanel.setPreferredSize(new Dimension(300, 200));
final JPanel panel = new JPanel(new BorderLayout());
final JProgressBar progressBar = new JProgressBar();
progressBar.setIndeterminate(true);
final JLabel message = new JLabel();
panel.add(message, BorderLayout.NORTH);
panel.add(progressBar, BorderLayout.CENTER);
centerPanel.add(panel);
setToolViewComponent(centerPanel);
final ProgressMonitor progressMonitor = new ProgressBarProgressMonitor(progressBar, message);
final SwingWorker worker = new PolModeWaiter(smosView, smosFile, progressMonitor);
progressMonitor.beginTask("Indexing snapshots and polarisation modes...", 100);
worker.execute();
}
private class PolModeWaiter extends SwingWorker {
private final ProductSceneView smosView;
private final L1cScienceSmosFile smosFile;
private final ProgressMonitor pm;
private PolModeWaiter(ProductSceneView smosView, L1cScienceSmosFile smosFile, ProgressMonitor pm) {
this.smosView = smosView;
this.smosFile = smosFile;
this.pm = pm;
}
@Override
protected Object doInBackground() throws InterruptedException {
try {
while (!smosFile.hasSnapshotInfo()) {
Thread.sleep(100);
}
} finally {
pm.done();
}
return null;
}
@Override
protected void done() {
setToolViewComponent(getClientComponent());
updateClientComponent(smosView);
}
}
private static class PopupListener extends MouseAdapter {
private final JPopupMenu popup;
PopupListener(JPopupMenu popup) {
this.popup = popup;
}
@Override
public void mousePressed(MouseEvent e) {
maybeShowPopup(e);
}
@Override
public void mouseReleased(MouseEvent e) {
maybeShowPopup(e);
}
private void maybeShowPopup(MouseEvent e) {
if (e.isPopupTrigger()) {
popup.show(e.getComponent(), e.getX(), e.getY());
}
}
}
private static long findSnapshotId(List<Long> snapshotIds, long requestedId) {
if (snapshotIds.size() == 0) {
return -1;
}
final int foundIndex = Collections.binarySearch(snapshotIds, requestedId);
if (foundIndex >= 0) {
return snapshotIds.get(foundIndex);
}
final int lowerIndex = -(foundIndex + 1) - 1;
final int upperIndex = -(foundIndex + 1);
final long lowerId;
if (lowerIndex < 0) {
lowerId = snapshotIds.get(0);
} else {
lowerId = snapshotIds.get(lowerIndex);
}
final long upperId;
if (upperIndex < snapshotIds.size()) {
upperId = snapshotIds.get(upperIndex);
} else {
upperId = snapshotIds.get(snapshotIds.size() - 1);
}
final long foundId;
if (requestedId - lowerId < upperId - requestedId) {
foundId = lowerId;
} else {
foundId = upperId;
}
return foundId;
}
private static void regenerateImageLayers(Layer layer) {
final List<Layer> children = layer.getChildren();
for (int i = children.size(); i-- > 0; ) {
final Layer child = children.get(i);
if (child instanceof ImageLayer) {
final ImageLayer imageLayer = (ImageLayer) child;
// skip static image layers
if (imageLayer.getMultiLevelSource() instanceof FileMultiLevelSource) {
continue;
}
if (imageLayer.getMultiLevelSource() instanceof TiledFileMultiLevelSource) {
continue;
}
imageLayer.regenerate();
} else {
if (child instanceof CollectionLayer) {
regenerateImageLayers(child);
}
}
}
}
private static void resetRasterImages(final RasterDataNode raster) {
raster.getSourceImage().reset();
if (raster.isValidMaskImageSet()) {
raster.resetValidMask();
raster.getValidMaskImage().reset();
}
if (raster.isGeophysicalImageSet()) {
raster.getGeophysicalImage().reset();
}
raster.setStx(null);
}
}