Issue #2954 fall back to existing map scales if map scale is missing

Change-Id: I75083325edec689c38f2fe7661c635ddf3e0f527

Former-commit-id: c07802a208 [formerly 6e21526fd2] [formerly c07802a208 [formerly 6e21526fd2] [formerly ed9bee5533 [formerly c7167ad2f59ba02edc842f321d12cd36cd6da8bb]]]
Former-commit-id: ed9bee5533
Former-commit-id: 12aa82ee3f [formerly d07ec00b92]
Former-commit-id: 61b8abe589
This commit is contained in:
Nate Jensen 2014-07-15 15:24:58 -05:00
parent fa9cc74703
commit a559ae9796
2 changed files with 203 additions and 48 deletions

View file

@ -30,6 +30,9 @@ import org.eclipse.ui.IWorkbenchWindow;
import com.raytheon.uf.common.localization.AutoUpdatingLocalizationFile; import com.raytheon.uf.common.localization.AutoUpdatingLocalizationFile;
import com.raytheon.uf.common.localization.AutoUpdatingLocalizationFile.AutoUpdatingFileChangedListener; import com.raytheon.uf.common.localization.AutoUpdatingLocalizationFile.AutoUpdatingFileChangedListener;
import com.raytheon.uf.common.localization.IPathManager; import com.raytheon.uf.common.localization.IPathManager;
import com.raytheon.uf.common.localization.LocalizationContext;
import com.raytheon.uf.common.localization.LocalizationContext.LocalizationLevel;
import com.raytheon.uf.common.localization.LocalizationContext.LocalizationType;
import com.raytheon.uf.common.localization.LocalizationFile; import com.raytheon.uf.common.localization.LocalizationFile;
import com.raytheon.uf.common.localization.PathManagerFactory; import com.raytheon.uf.common.localization.PathManagerFactory;
import com.raytheon.uf.common.localization.exception.LocalizationException; import com.raytheon.uf.common.localization.exception.LocalizationException;
@ -41,6 +44,7 @@ import com.raytheon.uf.common.status.UFStatus;
import com.raytheon.uf.common.status.UFStatus.Priority; import com.raytheon.uf.common.status.UFStatus.Priority;
import com.raytheon.uf.viz.core.drawables.AbstractRenderableDisplay; import com.raytheon.uf.viz.core.drawables.AbstractRenderableDisplay;
import com.raytheon.uf.viz.core.exception.VizException; import com.raytheon.uf.viz.core.exception.VizException;
import com.raytheon.uf.viz.core.maps.display.VizMapEditor;
import com.raytheon.uf.viz.core.maps.scales.MapScales.MapScale; import com.raytheon.uf.viz.core.maps.scales.MapScales.MapScale;
import com.raytheon.uf.viz.core.maps.scales.MapScales.PartId; import com.raytheon.uf.viz.core.maps.scales.MapScales.PartId;
import com.raytheon.uf.viz.core.procedures.Bundle; import com.raytheon.uf.viz.core.procedures.Bundle;
@ -61,7 +65,8 @@ import com.raytheon.viz.ui.actions.LoadSerializedXml;
* Oct 08, 2013 mschenke Initial creation * Oct 08, 2013 mschenke Initial creation
* Oct 22, 2013 2491 bsteffen Change from SerializationUtil to * Oct 22, 2013 2491 bsteffen Change from SerializationUtil to
* ProcedureXmlManager * ProcedureXmlManager
* Mar 24, 2014 2954 mpduff Check for missing map scale files and handle the situation. * Mar 24, 2014 2954 mpduff Log when missing map scale files
* Jul 15, 2014 2954 njensen Added fallbacks when missing map scale files
* *
* </pre> * </pre>
* *
@ -79,6 +84,11 @@ public class MapScalesManager {
private static final String DEFAULT_SCALES_FILE = "scalesInfo.xml"; private static final String DEFAULT_SCALES_FILE = "scalesInfo.xml";
// TODO would be better to fall back to a worldwide display
private static final String LAST_RESORT_NAME = "Northern Hemisphere";
private static final String LAST_RESORT_FILENAME = "NHemisphere.xml";
/** /**
* Manager class for a single {@link MapScale}. Is able to create a Bundle * Manager class for a single {@link MapScale}. Is able to create a Bundle
* for the scale. May provide functions for modifying/saving scales * for the scale. May provide functions for modifying/saving scales
@ -94,7 +104,7 @@ public class MapScalesManager {
private final String displayName; private final String displayName;
private final PartId[] partIds; private PartId[] partIds;
private final AutoUpdatingLocalizationFile scaleFile; private final AutoUpdatingLocalizationFile scaleFile;
@ -103,13 +113,15 @@ public class MapScalesManager {
private final boolean isCustom; private final boolean isCustom;
private ManagedMapScale(String baseDir, MapScale scale) private ManagedMapScale(String baseDir, MapScale scale)
throws SerializationException { throws IllegalStateException, SerializationException {
this.isCustom = false; this.isCustom = false;
this.partIds = scale.getPartIds();
this.displayName = scale.getDisplayName();
LocalizationFile file = PathManagerFactory.getPathManager() LocalizationFile file = PathManagerFactory.getPathManager()
.getStaticLocalizationFile( .getStaticLocalizationFile(
baseDir + IPathManager.SEPARATOR baseDir + IPathManager.SEPARATOR
+ scale.getFileName()); + scale.getFileName());
if (file == null || !file.exists()) { if (file == null || !file.exists()) {
throw new IllegalStateException( throw new IllegalStateException(
"scalesInfo.xml references missing file " "scalesInfo.xml references missing file "
@ -117,9 +129,18 @@ public class MapScalesManager {
} }
this.scaleFile = new AutoUpdatingLocalizationFile(file); this.scaleFile = new AutoUpdatingLocalizationFile(file);
this.scaleFile.addListener(listener); this.scaleFile.addListener(listener);
this.partIds = scale.getPartIds();
this.displayName = scale.getDisplayName();
loadBundleXml(); loadBundleXml();
/*
* TODO this is inefficient to unmarshal it eagerly for no purpose
* other than to validate, but it ensures that if the files exist
* but have bad XML, then the thrown exception from getScaleBundle()
* will cause the fallback code to be triggered, leading to no blank
* panes
*/
// validate the XML is good
getScaleBundle();
} }
private ManagedMapScale(String displayName, Bundle scaleBundle) private ManagedMapScale(String displayName, Bundle scaleBundle)
@ -190,7 +211,9 @@ public class MapScalesManager {
@Override @Override
public void fileChanged(AutoUpdatingLocalizationFile file) { public void fileChanged(AutoUpdatingLocalizationFile file) {
try { try {
loadMapScales(); MapScales scales = file.loadObject(getJAXBManager(),
MapScales.class);
loadMapScales(scales);
} catch (SerializationException e) { } catch (SerializationException e) {
statusHandler.handle(Priority.PROBLEM, e.getLocalizedMessage(), statusHandler.handle(Priority.PROBLEM, e.getLocalizedMessage(),
e); e);
@ -198,7 +221,7 @@ public class MapScalesManager {
} }
}; };
private final AutoUpdatingLocalizationFile scalesFile; private AutoUpdatingLocalizationFile scalesFile;
private final String scaleBundleDir; private final String scaleBundleDir;
@ -223,36 +246,106 @@ public class MapScalesManager {
*/ */
public MapScalesManager(String scalesDir, String scalesFile) public MapScalesManager(String scalesDir, String scalesFile)
throws SerializationException { throws SerializationException {
this(scalesDir, PathManagerFactory.getPathManager() String filename = scalesDir + IPathManager.SEPARATOR + scalesFile;
LocalizationFile locFile = PathManagerFactory.getPathManager()
.getStaticLocalizationFile( .getStaticLocalizationFile(
scalesDir + IPathManager.SEPARATOR + scalesFile)); filename);
MapScales scales = null;
try {
this.scalesFile = new AutoUpdatingLocalizationFile(locFile);
scales = this.scalesFile.loadObject(getJAXBManager(),
MapScales.class);
} catch (SerializationException e) {
/*
* failed to load scalesInfo file, try and fall back to BASE
*/
if (!locFile.getContext().getLocalizationLevel()
.equals(LocalizationLevel.BASE)) {
locFile = PathManagerFactory.getPathManager()
.getLocalizationFile(
new LocalizationContext(
LocalizationType.CAVE_STATIC,
LocalizationLevel.BASE), filename);
this.scalesFile = new AutoUpdatingLocalizationFile(locFile);
scales = this.scalesFile.loadObject(getJAXBManager(),
MapScales.class);
} else {
throw e;
}
}
this.scaleBundleDir = scalesDir;
this.scalesFile.addListener(listener);
loadMapScales(scales);
}
private synchronized void loadMapScales(MapScales scales)
{
List<ManagedMapScale> storedScales = new ArrayList<ManagedMapScale>();
List<PartId> failedParts = new ArrayList<PartId>();
for (MapScale scale : scales.getScales()) {
try {
storedScales.add(new ManagedMapScale(scaleBundleDir, scale));
} catch (Exception e) {
StringBuilder sb = new StringBuilder();
sb.append("Error loading " + scale.getDisplayName()
+ " scale. ");
if (scale.getPartIds() != null && scale.getPartIds().length > 0) {
sb.append(scale.getDisplayName()
+ " pane will attempt to revert to working scale. ");
}
sb.append(scale.getDisplayName()
+ " will not appear in the menu. ");
statusHandler.error(sb.toString(), e);
if (scale.getPartIds() != null) {
for (PartId p : scale.getPartIds()) {
failedParts.add(p);
}
}
}
}
this.storedScales = storedScales;
// storedScales must be set before handleMissingParts()
if (!failedParts.isEmpty()) {
handleMissingParts(failedParts);
}
} }
/** /**
* Construct a MapScalesManager for the given scales file. File must be * Handles the parts that referenced scales files that couldn't be found.
* deserializable into a {@link MapScales} object
* *
* @param bundleDir * @param missingParts
* directory bundle files are relative to * the parts that were missing
* @param scalesFile * @param goodScales
* @throws SerializationException * the scales that successfully loaded
*/ */
public MapScalesManager(String bundleDir, LocalizationFile scalesFile) protected void handleMissingParts(List<PartId> missingParts) {
throws SerializationException { /*
this.scaleBundleDir = bundleDir; * if the missing part was a side view, fall back to the main pane
this.scalesFile = new AutoUpdatingLocalizationFile(scalesFile); */
this.scalesFile.addListener(listener); ManagedMapScale mainPane = findEditorScale();
loadMapScales();
}
private synchronized void loadMapScales() throws SerializationException { if (mainPane == null) {
List<ManagedMapScale> storedScales = new ArrayList<ManagedMapScale>(); /*
MapScales scales = this.scalesFile.loadObject(getJAXBManager(), * main pane is missing too, so fall back to a base scale that is
MapScales.class); * guaranteed to be there
for (MapScale scale : scales.getScales()) { */
storedScales.add(new ManagedMapScale(scaleBundleDir, scale)); mainPane = getLastResortScale();
storedScales.add(mainPane);
} }
this.storedScales = storedScales;
/*
* Set all the missing parts to the scale in the main pane
*/
List<PartId> combinedParts = new ArrayList<PartId>(
mainPane.partIds.length + missingParts.size());
for (PartId p : mainPane.getPartIds()) {
combinedParts.add(p);
}
for (PartId p : missingParts) {
combinedParts.add(p);
}
mainPane.partIds = combinedParts.toArray(new PartId[0]);
} }
/** /**
@ -336,12 +429,12 @@ public class MapScalesManager {
} }
/** /**
* Gets the {@link ManagedMapScale}s defined for the partId * Gets the Bundle defined for the partId.
* *
* @param partId * @param partId
* @return * @return
*/ */
public ManagedMapScale[] getScalesForPart(String partId) { public Bundle getScaleBundleForPart(String partId) {
List<ManagedMapScale> scalesForPart = new ArrayList<ManagedMapScale>(); List<ManagedMapScale> scalesForPart = new ArrayList<ManagedMapScale>();
for (ManagedMapScale scale : storedScales) { for (ManagedMapScale scale : storedScales) {
for (PartId part : scale.getPartIds()) { for (PartId part : scale.getPartIds()) {
@ -351,7 +444,26 @@ public class MapScalesManager {
} }
} }
} }
return scalesForPart.toArray(new ManagedMapScale[0]);
Bundle b = null;
for (ManagedMapScale scale : scalesForPart) {
try {
b = scale.getScaleBundle();
} catch (SerializationException e) {
statusHandler.error("Error deserializing bundle for scale: "
+ scale, e);
}
if (b != null) {
break;
}
}
if (b != null) {
b.setView(partId);
}
return b;
} }
/** /**
@ -408,4 +520,54 @@ public class MapScalesManager {
} }
return jaxbManager; return jaxbManager;
} }
/**
* Gets a base scale that should always be there and should always work.
* Used to prevent blank panes if scale overrides are misconfigured.
*
* @return
*/
protected ManagedMapScale getLastResortScale() {
ManagedMapScale scale = null;
PartId fallbackPartId = new PartId();
fallbackPartId.setId(VizMapEditor.EDITOR_ID);
fallbackPartId.setView(false);
MapScale fallback = new MapScale();
fallback.setPartIds(new PartId[] { fallbackPartId });
fallback.setDisplayName(LAST_RESORT_NAME);
fallback.setFileName(LAST_RESORT_FILENAME);
try {
scale = new ManagedMapScale(scaleBundleDir, fallback);
} catch (Exception e) {
statusHandler.fatal("Error loading the last resort scale "
+ LAST_RESORT_FILENAME, e);
// things will null pointer if this ever hits, but come on
}
return scale;
}
/**
* Finds the editor pane (ie VizMapEditor.EDITOR_ID) associated with a list
* of scales
*
* @return the first scale tied to a VizMapEditor, or null if none are found
*/
public ManagedMapScale findEditorScale() {
ManagedMapScale editorScale = null;
for (ManagedMapScale scale : storedScales) {
PartId[] parts = scale.partIds;
if (parts != null) {
for (PartId p : parts) {
if (VizMapEditor.EDITOR_ID.equals(p.getId())) {
editorScale = scale;
break;
}
}
}
if (editorScale != null) {
break;
}
}
return editorScale;
}
} }

View file

@ -35,7 +35,6 @@ import org.eclipse.ui.PartInitException;
import org.eclipse.ui.PlatformUI; import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.part.ViewPart; import org.eclipse.ui.part.ViewPart;
import com.raytheon.uf.common.serialization.SerializationException;
import com.raytheon.uf.common.status.IUFStatusHandler; import com.raytheon.uf.common.status.IUFStatusHandler;
import com.raytheon.uf.common.status.UFStatus; import com.raytheon.uf.common.status.UFStatus;
import com.raytheon.uf.common.status.UFStatus.Priority; import com.raytheon.uf.common.status.UFStatus.Priority;
@ -52,7 +51,6 @@ import com.raytheon.uf.viz.core.drawables.ResourcePair;
import com.raytheon.uf.viz.core.exception.VizException; import com.raytheon.uf.viz.core.exception.VizException;
import com.raytheon.uf.viz.core.globals.VizGlobalsManager; import com.raytheon.uf.viz.core.globals.VizGlobalsManager;
import com.raytheon.uf.viz.core.maps.scales.MapScalesManager; import com.raytheon.uf.viz.core.maps.scales.MapScalesManager;
import com.raytheon.uf.viz.core.maps.scales.MapScalesManager.ManagedMapScale;
import com.raytheon.uf.viz.core.procedures.Bundle; import com.raytheon.uf.viz.core.procedures.Bundle;
import com.raytheon.uf.viz.core.rsc.AbstractVizResource; import com.raytheon.uf.viz.core.rsc.AbstractVizResource;
import com.raytheon.uf.viz.core.rsc.IInputHandler; import com.raytheon.uf.viz.core.rsc.IInputHandler;
@ -96,7 +94,8 @@ import com.vividsolutions.jts.geom.Coordinate;
* Mar 21, 2013 1638 mschenke Changed map scales not tied to d2d * Mar 21, 2013 1638 mschenke Changed map scales not tied to d2d
* Aug 9, 2013 DR 16427 D. Friedman Swap additional input handlers. * Aug 9, 2013 DR 16427 D. Friedman Swap additional input handlers.
* Oct 10, 2013 #2104 mschenke Switched to use MapScalesManager * Oct 10, 2013 #2104 mschenke Switched to use MapScalesManager
* * Jul 15, 2014 2954 njensen Updated init() for MapScalesManager change
*
* </pre> * </pre>
* *
* @author chammack * @author chammack
@ -141,18 +140,8 @@ public class SideView extends ViewPart implements IMultiPaneEditor,
String myId = site.getId() + UiUtil.SECONDARY_ID_SEPARATOR String myId = site.getId() + UiUtil.SECONDARY_ID_SEPARATOR
+ site.getSecondaryId(); + site.getSecondaryId();
for (ManagedMapScale scale : MapScalesManager.getInstance() bundleToLoad = MapScalesManager.getInstance().getScaleBundleForPart(
.getScalesForPart(myId)) { myId);
try {
Bundle b = scale.getScaleBundle();
b.setView(myId);
bundleToLoad = b;
} catch (SerializationException e) {
statusHandler.handle(Priority.PROBLEM,
"Error deserializing bundle for scale: " + scale, e);
}
break;
}
} }
@Override @Override
@ -284,6 +273,7 @@ public class SideView extends ViewPart implements IMultiPaneEditor,
* *
* @see com.raytheon.viz.core.IDisplayPaneContainer#getActiveDisplayPane() * @see com.raytheon.viz.core.IDisplayPaneContainer#getActiveDisplayPane()
*/ */
@Override
public IDisplayPane getActiveDisplayPane() { public IDisplayPane getActiveDisplayPane() {
return paneManager.getActiveDisplayPane(); return paneManager.getActiveDisplayPane();
} }
@ -774,15 +764,18 @@ public class SideView extends ViewPart implements IMultiPaneEditor,
ISelectedPanesChangedListener listener) { ISelectedPanesChangedListener listener) {
} }
@Override
public void registerMouseHandler(IInputHandler handler, public void registerMouseHandler(IInputHandler handler,
InputPriority priority) { InputPriority priority) {
paneManager.registerMouseHandler(handler, priority); paneManager.registerMouseHandler(handler, priority);
} }
@Override
public void registerMouseHandler(IInputHandler handler) { public void registerMouseHandler(IInputHandler handler) {
paneManager.registerMouseHandler(handler); paneManager.registerMouseHandler(handler);
} }
@Override
public void unregisterMouseHandler(IInputHandler handler) { public void unregisterMouseHandler(IInputHandler handler) {
paneManager.unregisterMouseHandler(handler); paneManager.unregisterMouseHandler(handler);
} }