This is an automated email from the ASF dual-hosted git repository.
desruisseaux pushed a commit to branch geoapi-4.0
in repository https://gitbox.apache.org/repos/asf/sis.git
The following commit(s) were added to refs/heads/geoapi-4.0 by this push:
new 55f5813 Make native (implementation-dependent) NetCDF metadata
available.
55f5813 is described below
commit 55f58134462e0619a21fe05dd692c64eb8e34d5a
Author: Martin Desruisseaux <[email protected]>
AuthorDate: Mon Feb 3 20:26:23 2020 +0100
Make native (implementation-dependent) NetCDF metadata available.
---
.../apache/sis/gui/dataset/ResourceExplorer.java | 32 ++-
.../apache/sis/gui/metadata/MetadataSummary.java | 41 +++-
.../org/apache/sis/gui/metadata/MetadataTree.java | 206 ++---------------
...MetadataTree.java => StandardMetadataTree.java} | 253 +--------------------
.../org/apache/sis/util/resources/Vocabulary.java | 5 +
.../sis/util/resources/Vocabulary.properties | 1 +
.../sis/util/resources/Vocabulary_fr.properties | 1 +
.../org/apache/sis/internal/netcdf/Decoder.java | 10 +-
.../sis/internal/netcdf/impl/ChannelDecoder.java | 22 ++
.../sis/internal/netcdf/ucar/DecoderWrapper.java | 46 ++++
.../org/apache/sis/storage/netcdf/NetcdfStore.java | 25 +-
.../apache/sis/storage/netcdf/package-info.java | 2 +-
.../java/org/apache/sis/storage/DataStore.java | 31 ++-
13 files changed, 228 insertions(+), 447 deletions(-)
diff --git
a/application/sis-javafx/src/main/java/org/apache/sis/gui/dataset/ResourceExplorer.java
b/application/sis-javafx/src/main/java/org/apache/sis/gui/dataset/ResourceExplorer.java
index 68a8e7c..d7672b8 100644
---
a/application/sis-javafx/src/main/java/org/apache/sis/gui/dataset/ResourceExplorer.java
+++
b/application/sis-javafx/src/main/java/org/apache/sis/gui/dataset/ResourceExplorer.java
@@ -16,6 +16,7 @@
*/
package org.apache.sis.gui.dataset;
+import java.util.Objects;
import java.util.Collection;
import javafx.beans.property.ReadOnlyProperty;
import javafx.beans.property.SimpleObjectProperty;
@@ -32,10 +33,13 @@ import org.apache.sis.storage.Resource;
import org.apache.sis.storage.FeatureSet;
import org.apache.sis.gui.metadata.MetadataSummary;
import org.apache.sis.gui.metadata.MetadataTree;
+import org.apache.sis.gui.metadata.StandardMetadataTree;
import org.apache.sis.gui.coverage.GridView;
import org.apache.sis.gui.coverage.ImageRequest;
import org.apache.sis.internal.gui.Resources;
import org.apache.sis.storage.GridCoverageResource;
+import org.apache.sis.util.collection.TableColumn;
+import org.apache.sis.util.resources.Vocabulary;
/**
@@ -59,12 +63,6 @@ public class ResourceExplorer extends WindowManager {
private final ResourceTree resources;
/**
- * The tab where to show {@link #features} or {@link #coverage}, depending
on the kind of resource.
- * The data will be set only if this tab is visible, because their loading
may be costly.
- */
- private final Tab dataTab;
-
- /**
* The data as a table, created when first needed.
*/
private FeatureTable features;
@@ -88,6 +86,12 @@ public class ResourceExplorer extends WindowManager {
private final SplitPane content;
/**
+ * The tab where to show {@link #features} or {@link #coverage}, depending
on the kind of resource.
+ * The data will be set only if this tab is visible, because their loading
may be costly.
+ */
+ private final Tab dataTab;
+
+ /**
* The currently selected resource.
*/
public final ReadOnlyProperty<Resource> selectedResourceProperty;
@@ -110,9 +114,21 @@ public class ResourceExplorer extends WindowManager {
final Resources localized = localized();
dataTab = new Tab(localized.getString(Resources.Keys.Data));
dataTab.setContextMenu(new ContextMenu(createNewWindowMenu()));
+
+ final String nativeTabText =
Vocabulary.getResources(localized.getLocale()).getString(Vocabulary.Keys.Format);
+ final MetadataTree nativeMetadata = new MetadataTree(metadata);
+ final Tab nativeTab = new Tab(nativeTabText, nativeMetadata);
+ nativeTab.setDisable(true);
+ nativeMetadata.contentProperty.addListener((p,o,n) -> {
+ nativeTab.setDisable(n == null);
+ Object label = (n != null) ?
n.getRoot().getValue(TableColumn.NAME) : null;
+ nativeTab.setText(Objects.toString(label, nativeTabText));
+ });
+
final TabPane tabs = new TabPane(
new Tab(localized.getString(Resources.Keys.Summary),
metadata.getView()), dataTab,
- new Tab(localized.getString(Resources.Keys.Metadata), new
MetadataTree(metadata)));
+ new Tab(localized.getString(Resources.Keys.Metadata), new
StandardMetadataTree(metadata)),
+ nativeTab);
tabs.setTabClosingPolicy(TabPane.TabClosingPolicy.UNAVAILABLE);
tabs.setTabDragPolicy(TabPane.TabDragPolicy.REORDER);
@@ -121,7 +137,7 @@ public class ResourceExplorer extends WindowManager {
resources.getSelectionModel().getSelectedItems().addListener(this::selectResource);
SplitPane.setResizableWithParent(resources, Boolean.FALSE);
SplitPane.setResizableWithParent(tabs, Boolean.TRUE);
- content.setDividerPosition(0, 300);
+ resources.setPrefWidth(400);
selectedResourceProperty = new SimpleObjectProperty<>(this,
"selectedResource");
dataTab.selectedProperty().addListener(this::dataTabShown);
diff --git
a/application/sis-javafx/src/main/java/org/apache/sis/gui/metadata/MetadataSummary.java
b/application/sis-javafx/src/main/java/org/apache/sis/gui/metadata/MetadataSummary.java
index a90e99d..f4f3f42 100644
---
a/application/sis-javafx/src/main/java/org/apache/sis/gui/metadata/MetadataSummary.java
+++
b/application/sis-javafx/src/main/java/org/apache/sis/gui/metadata/MetadataSummary.java
@@ -19,6 +19,7 @@ package org.apache.sis.gui.metadata;
import java.text.DateFormat;
import java.text.NumberFormat;
import java.util.Collection;
+import java.util.ArrayList;
import java.util.Locale;
import java.util.StringJoiner;
import javafx.application.Platform;
@@ -43,9 +44,11 @@ import org.apache.sis.internal.gui.ExceptionReporter;
import org.apache.sis.internal.gui.Resources;
import org.apache.sis.internal.gui.Styles;
import org.apache.sis.internal.util.Strings;
+import org.apache.sis.storage.DataStore;
import org.apache.sis.storage.DataStoreException;
import org.apache.sis.storage.Resource;
import org.apache.sis.util.ArgumentChecks;
+import org.apache.sis.util.collection.TreeTable;
import org.apache.sis.util.iso.Types;
@@ -134,6 +137,13 @@ public class MetadataSummary {
private final TitledPane[] information;
/**
+ * The listeners to notify about native metadata. We define those
listeners in this {@link MetadataSummary}
+ * for taking advantage of the background loading mechanism. We do not
provide public API for such listeners
+ * because a future version may want to provide those listeners in a more
appropriate (not yet defined) class.
+ */
+ final ArrayList<MetadataTree> nativeMetadataViews;
+
+ /**
* Creates an initially empty metadata overview.
*/
public MetadataSummary() {
@@ -147,6 +157,7 @@ public class MetadataSummary {
content.setFitToWidth(true);
metadataProperty = new SimpleObjectProperty<>(this, "metadata");
metadataProperty.addListener(MetadataSummary::applyChange);
+ nativeMetadataViews = new ArrayList<>();
}
/**
@@ -202,19 +213,31 @@ public class MetadataSummary {
setMetadata((Metadata) null);
} else {
final class Getter extends Task<Metadata> {
- /**
- * Invoked in a background thread for fetching metadata,
- * eventually with other information like grid geometry.
- */
+ /** The native metadata, or {@code null} if none or not
requested. */
+ private TreeTable nativeMetadata;
+
+ /** Invoked in a background thread for fetching metadata. */
@Override protected Metadata call() throws DataStoreException {
+ if (resource instanceof DataStore &&
!nativeMetadataViews.isEmpty()) {
+ nativeMetadata = ((DataStore)
resource).getNativeMetadata().orElse(null);
+ }
return resource.getMetadata();
}
- /**
- * Shows the result, unless another {@link
#setMetadata(Resource)} has been invoked.
- */
- @Override protected void succeeded() {super.succeeded();
setMetadata(getValue());}
- @Override protected void failed() {super.failed();
setError(getException());}
+ /** Shows the result in JavaFX thread. */
+ @Override protected void succeeded() {
+ super.succeeded();
+ setMetadata(getValue());
+ for (final MetadataTree view : nativeMetadataViews) {
+ view.setContent(nativeMetadata);
+ }
+ }
+
+ /** Invoked in JavaFX thread if metadata loading failed. */
+ @Override protected void failed() {
+ super.failed();
+ setError(getException());
+ }
}
BackgroundThreads.execute(new Getter());
}
diff --git
a/application/sis-javafx/src/main/java/org/apache/sis/gui/metadata/MetadataTree.java
b/application/sis-javafx/src/main/java/org/apache/sis/gui/metadata/MetadataTree.java
index 397303c..9b964b2 100644
---
a/application/sis-javafx/src/main/java/org/apache/sis/gui/metadata/MetadataTree.java
+++
b/application/sis-javafx/src/main/java/org/apache/sis/gui/metadata/MetadataTree.java
@@ -20,9 +20,6 @@ import java.util.Locale;
import java.util.List;
import java.util.ArrayList;
import java.util.Collection;
-import java.util.Collections;
-import java.io.StringWriter;
-import javax.xml.transform.stream.StreamResult;
import javafx.beans.DefaultProperty;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.ReadOnlyObjectWrapper;
@@ -30,40 +27,23 @@ import javafx.beans.property.ReadOnlyStringWrapper;
import javafx.beans.property.SimpleObjectProperty;
import javafx.beans.value.ObservableValue;
import javafx.collections.ObservableList;
-import javafx.event.ActionEvent;
-import javafx.event.EventHandler;
-import javafx.scene.control.ContextMenu;
-import javafx.scene.control.Menu;
-import javafx.scene.control.MenuItem;
import javafx.scene.control.TreeItem;
import javafx.scene.control.TreeTableView;
import javafx.scene.control.TreeTableColumn;
import javafx.scene.control.TreeTableColumn.CellDataFeatures;
-import javafx.scene.control.TreeTableRow;
-import javafx.scene.input.Clipboard;
-import javafx.scene.input.ClipboardContent;
-import org.opengis.metadata.Metadata;
import org.opengis.util.InternationalString;
import org.opengis.util.ControlledVocabulary;
import org.opengis.referencing.IdentifiedObject;
-import org.apache.sis.metadata.AbstractMetadata;
-import org.apache.sis.metadata.MetadataStandard;
-import org.apache.sis.metadata.ValueExistencePolicy;
import org.apache.sis.referencing.IdentifiedObjects;
-import org.apache.sis.internal.xml.LegacyNamespaces;
-import org.apache.sis.internal.gui.ExceptionReporter;
-import org.apache.sis.internal.gui.DataFormats;
-import org.apache.sis.internal.gui.Resources;
import org.apache.sis.util.collection.TreeTable;
import org.apache.sis.util.collection.TableColumn;
import org.apache.sis.util.iso.Types;
-import org.apache.sis.io.wkt.WKTFormat;
-import org.apache.sis.xml.XML;
/**
- * A view of {@link Metadata} properties organized as a tree table.
- * The content of each row in this tree table is represented by a {@link
TreeTable.Node}.
+ * A view of metadata represented by a {@link TreeTable}. This base class can
represent
+ * {@linkplain org.apache.sis.storage.DataStore#getNativeMetadata() native
metadata} or
+ * {@linkplain org.apache.sis.storage.DataStore#getMetadata() standard
metadata}.
* The tree table shows the following columns:
*
* <ul>
@@ -71,8 +51,8 @@ import org.apache.sis.xml.XML;
* <li>{@link TableColumn#VALUE} — the property value typically as a string,
number or date.</li>
* </ul>
*
- * While this view is designed mostly for metadata, it can actually be used
- * for other kinds of data provided by the {@link TreeTable} interface.
+ * In the particular case of metadata from ISO 19115 standard,
+ * the {@link StandardMetadataTree} specialization should be used instead than
this base class.
*
* <h2>Limitations</h2>
* <ul>
@@ -80,9 +60,7 @@ import org.apache.sis.xml.XML;
* For changing content, use the {@link #contentProperty} instead.</li>
* </ul>
*
- * @todo Add contextual menu for showing a node in the summary pane (we would
store in memory the path,
- * including sequence number for multi-values property, and apply it to
all opened resources).
- * Add a panel for controlling the number/date/angle format pattern.
+ * @todo Add a panel for controlling the number/date/angle format pattern.
*
* @author Siddhesh Rane (GSoC)
* @author Martin Desruisseaux (Geomatys)
@@ -137,7 +115,7 @@ public class MetadataTree extends
TreeTableView<TreeTable.Node> {
/**
* The locale to use for texts.
*/
- private final Locale textLocale;
+ final Locale textLocale;
/**
* The locale to use for dates/numbers.
@@ -146,26 +124,30 @@ public class MetadataTree extends
TreeTableView<TreeTable.Node> {
private final Locale dataLocale;
/**
- * The "copy" and "copy as" localized string, used for contextual menus.
- */
- private final String copy, copyAs;
-
- /**
* Creates a new initially empty metadata tree.
*/
public MetadataTree() {
- this(null);
+ this(null, false);
}
/**
* Creates a new initially empty metadata tree which will be automatically
updated
- * when the given widget shows new metadata. This constructor registers a
listener
- * to {@link MetadataSummary#metadataProperty} which forwards the metadata
changes
- * to {@link #setContent(Metadata)}.
+ * when the given widget is given a {@linkplain
org.apache.sis.storage.DataStore}.
*
* @param controller the widget to watch, or {@code null} if none.
*/
public MetadataTree(final MetadataSummary controller) {
+ this(controller, false);
+ }
+
+ /**
+ * For {@link MetadataTree} and {@link StandardMetadataTree} constructors.
+ *
+ * @param controller the widget to watch, or {@code null} if none.
+ * @param standard {@code true} for showing standard metadata, or
{@code false} for native metadata.
+ */
+ @SuppressWarnings("ThisEscapedInObjectConstruction")
+ MetadataTree(final MetadataSummary controller, final boolean standard) {
if (controller != null) {
textLocale = controller.localized.getLocale();
dataLocale = controller.dataLocale;
@@ -173,47 +155,24 @@ public class MetadataTree extends
TreeTableView<TreeTable.Node> {
textLocale = Locale.getDefault(Locale.Category.DISPLAY);
dataLocale = Locale.getDefault(Locale.Category.FORMAT);
}
- final Resources localized = Resources.forLocale(textLocale);
- copy = localized.getString(Resources.Keys.Copy);
- copyAs = localized.getString(Resources.Keys.CopyAs);
-
contentProperty = new ContentProperty(this);
nameColumn = new TreeTableColumn<>(TableColumn.NAME
.getHeader().toString(textLocale));
valueColumn = new
TreeTableColumn<>(TableColumn.VALUE.getHeader().toString(textLocale));
nameColumn .setCellValueFactory(MetadataTree::getPropertyName);
valueColumn.setCellValueFactory(MetadataTree::getPropertyValue);
- setRowFactory(Row::new);
setColumnResizePolicy(CONSTRAINED_RESIZE_POLICY);
getColumns().setAll(nameColumn, valueColumn);
contentProperty.addListener(MetadataTree::applyChange);
- if (controller != null) {
- controller.metadataProperty.addListener((p,o,n) -> setContent(n));
- }
- }
-
- /**
- * Returns the given metadata as a tree table.
- */
- private static TreeTable toTree(final Object metadata) {
- if (metadata instanceof AbstractMetadata) {
- return ((AbstractMetadata) metadata).asTreeTable();
- } else {
- return MetadataStandard.ISO_19115.asTreeTable(metadata, null,
ValueExistencePolicy.COMPACT);
+ if (!standard) {
+ setShowRoot(false);
+ if (controller != null) {
+ controller.nativeMetadataViews.add(this);
+ }
}
}
/**
- * Sets the metadata to show in this tree table. This method gets a {@link
TreeTable} view
- * of the given metadata, then delegates to {@link #setContent(TreeTable)}.
- *
- * @param metadata the metadata to show in this tree table view, or
{@code null} if none.
- */
- public void setContent(final Metadata metadata) {
- setContent(metadata == null ? null : toTree(metadata));
- }
-
- /**
* Sets the data to show.
* This is a convenience method for setting {@link #contentProperty} value.
* The given {@link TreeTable} shall contain at least the following
columns:
@@ -263,121 +222,6 @@ public class MetadataTree extends
TreeTableView<TreeTable.Node> {
}
/**
- * A row in a metadata tree view, used for adding contextual menu on a
row-by-row basis.
- */
- private static final class Row extends TreeTableRow<TreeTable.Node>
implements EventHandler<ActionEvent> {
- /**
- * The context menu, to be added only if this row is non-empty.
- */
- private final ContextMenu menu;
-
- /**
- * The menu items for XML or WKT formats.
- */
- private final MenuItem copyAsXML, copyAsLegacy, copyAsWKT;
-
- /**
- * The menu items for copying in XML formats, to be disabled if we can
not do this export.
- */
- private final Menu copyAs;
-
- /**
- * Creates a new row for the given tree table.
- */
- @SuppressWarnings("ThisEscapedInObjectConstruction")
- Row(final TreeTableView<TreeTable.Node> view) {
- final MetadataTree md = (MetadataTree) view;
- final MenuItem copy;
- copy = new MenuItem(md.copy);
- copyAsXML = new MenuItem();
- copyAsWKT = new MenuItem("WKT — Well Known Text");
- copyAsLegacy = new MenuItem("XML — Metadata (2007)");
- copyAs = new Menu(md.copyAs, null, copyAsWKT, copyAsXML,
copyAsLegacy);
- menu = new ContextMenu(copy, copyAs);
- copyAsLegacy.setOnAction(this);
- copyAsXML .setOnAction(this);
- copy .setOnAction(this);
- }
-
- /**
- * Invoked when a new row is selected. This method enable or disable
the "copy as" menu
- * depending on whether or not we can format XML document for
currently selected row.
- */
- @Override
- protected void updateItem(final TreeTable.Node item, final boolean
empty) {
- super.updateItem(item, empty);
- if (!empty) {
- boolean disabled = true;
- final TreeTable.Node node = getItem();
- if (node != null) {
- final Object obj = node.getUserObject();
- if (obj != null) {
- if
(MetadataStandard.ISO_19115.isMetadata(obj.getClass())) {
- copyAsXML.setText("XML — Metadata (2016)");
- copyAsWKT.setDisable(true);
- copyAsLegacy.setDisable(false);
- disabled = false;
- } else if (obj instanceof IdentifiedObject) {
- copyAsXML.setText("XML — Geographic Markup
Language");
- copyAsWKT.setDisable(false);
- copyAsLegacy.setDisable(true);
- disabled = false;
- }
- }
- }
- copyAs.setDisable(disabled);
- }
- setContextMenu(empty ? null : menu);
- }
-
- /**
- * Invoked when user requested to copy metadata. The requested format
(ISO 19115 versus ISO 19139)
- * will be determined by comparing the event source with {@link
#copyAsLegacy} and {@link #copyAsXML}
- * menu items.
- */
- @Override
- public void handle(final ActionEvent event) {
- final TreeTable.Node node = getItem();
- if (node != null) {
- final Object obj = node.getUserObject();
- if (obj != null) {
- final Object source = event.getSource();
- final ClipboardContent content = new ClipboardContent();
- final String text;
- try {
- if (source == copyAsWKT) {
// Well Known Text.
- final WKTFormat f = new WKTFormat(null, null);
- text = f.format(obj);
- } else if (source == copyAsXML) {
// GML or ISO 19115-3:2016.
- text = XML.marshal(obj);
- content.put(DataFormats.XML, text);
- } else if (source == copyAsLegacy) {
// ISO 19139:2007.
- final StringWriter output = new StringWriter();
- XML.marshal(obj, new StreamResult(output),
-
Collections.singletonMap(XML.METADATA_VERSION, LegacyNamespaces.VERSION_2007));
- text = output.toString();
- content.put(DataFormats.ISO_19139, text);
- } else if
(MetadataStandard.ISO_19115.isMetadata(obj.getClass())) {
- text = toTree(obj).toString();
- } else {
- final Object value =
node.getValue(TableColumn.VALUE);
- if (value == null) return;
- text = value.toString();
- }
- } catch (Exception e) {
- final Resources localized =
Resources.forLocale(((MetadataTree) getTreeTableView()).textLocale);
-
ExceptionReporter.show(localized.getString(Resources.Keys.ErrorExportingData),
-
localized.getString(Resources.Keys.CanNotCreateXML), e);
- return;
- }
- content.putString(text);
- Clipboard.getSystemClipboard().setContent(content);
- }
- }
- }
- }
-
- /**
* A simple node encapsulating a {@link TreeTable.Node} in a view.
* The list of children is fetched when first needed.
*/
diff --git
a/application/sis-javafx/src/main/java/org/apache/sis/gui/metadata/MetadataTree.java
b/application/sis-javafx/src/main/java/org/apache/sis/gui/metadata/StandardMetadataTree.java
similarity index 50%
copy from
application/sis-javafx/src/main/java/org/apache/sis/gui/metadata/MetadataTree.java
copy to
application/sis-javafx/src/main/java/org/apache/sis/gui/metadata/StandardMetadataTree.java
index 397303c..77d280d 100644
---
a/application/sis-javafx/src/main/java/org/apache/sis/gui/metadata/MetadataTree.java
+++
b/application/sis-javafx/src/main/java/org/apache/sis/gui/metadata/StandardMetadataTree.java
@@ -16,47 +16,29 @@
*/
package org.apache.sis.gui.metadata;
-import java.util.Locale;
-import java.util.List;
-import java.util.ArrayList;
-import java.util.Collection;
import java.util.Collections;
import java.io.StringWriter;
import javax.xml.transform.stream.StreamResult;
-import javafx.beans.DefaultProperty;
-import javafx.beans.property.ObjectProperty;
-import javafx.beans.property.ReadOnlyObjectWrapper;
-import javafx.beans.property.ReadOnlyStringWrapper;
-import javafx.beans.property.SimpleObjectProperty;
-import javafx.beans.value.ObservableValue;
-import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.control.ContextMenu;
import javafx.scene.control.Menu;
import javafx.scene.control.MenuItem;
-import javafx.scene.control.TreeItem;
import javafx.scene.control.TreeTableView;
-import javafx.scene.control.TreeTableColumn;
-import javafx.scene.control.TreeTableColumn.CellDataFeatures;
import javafx.scene.control.TreeTableRow;
import javafx.scene.input.Clipboard;
import javafx.scene.input.ClipboardContent;
import org.opengis.metadata.Metadata;
-import org.opengis.util.InternationalString;
-import org.opengis.util.ControlledVocabulary;
import org.opengis.referencing.IdentifiedObject;
import org.apache.sis.metadata.AbstractMetadata;
import org.apache.sis.metadata.MetadataStandard;
import org.apache.sis.metadata.ValueExistencePolicy;
-import org.apache.sis.referencing.IdentifiedObjects;
import org.apache.sis.internal.xml.LegacyNamespaces;
import org.apache.sis.internal.gui.ExceptionReporter;
import org.apache.sis.internal.gui.DataFormats;
import org.apache.sis.internal.gui.Resources;
import org.apache.sis.util.collection.TreeTable;
import org.apache.sis.util.collection.TableColumn;
-import org.apache.sis.util.iso.Types;
import org.apache.sis.io.wkt.WKTFormat;
import org.apache.sis.xml.XML;
@@ -71,8 +53,8 @@ import org.apache.sis.xml.XML;
* <li>{@link TableColumn#VALUE} — the property value typically as a string,
number or date.</li>
* </ul>
*
- * While this view is designed mostly for metadata, it can actually be used
- * for other kinds of data provided by the {@link TreeTable} interface.
+ * This class still supports the {@link #setContent(TreeTable)} method,
+ * but {@link #setContent(Metadata)} should be used instead.
*
* <h2>Limitations</h2>
* <ul>
@@ -82,7 +64,6 @@ import org.apache.sis.xml.XML;
*
* @todo Add contextual menu for showing a node in the summary pane (we would
store in memory the path,
* including sequence number for multi-values property, and apply it to
all opened resources).
- * Add a panel for controlling the number/date/angle format pattern.
*
* @author Siddhesh Rane (GSoC)
* @author Martin Desruisseaux (Geomatys)
@@ -90,61 +71,7 @@ import org.apache.sis.xml.XML;
* @since 1.1
* @module
*/
-@DefaultProperty("content")
-public class MetadataTree extends TreeTableView<TreeTable.Node> {
- /**
- * The column for metadata property name.
- */
- private final TreeTableColumn<TreeTable.Node, String> nameColumn;
-
- /**
- * The column for metadata property value.
- * Values are typically {@link InternationalString}, {@link Number} or
dates.
- */
- private final TreeTableColumn<TreeTable.Node, Object> valueColumn;
-
- /**
- * The data shown in this tree table. The {@link
ObjectProperty#set(Object)} method requires
- * that the given value obey to the constraints documented in {@link
#setContent(TreeTable)}.
- *
- * @see #getContent()
- * @see #setContent(TreeTable)
- */
- public final ObjectProperty<TreeTable> contentProperty;
-
- /**
- * Implementation of {@link MetadataTree#contentProperty} as a named class
for more readable stack trace.
- * This class verifies the constraints documented in {@link
MetadataTree#setContent(TreeTable)}.
- */
- private static final class ContentProperty extends
SimpleObjectProperty<TreeTable> {
- /** Creates a new property. */
- ContentProperty(final MetadataTree bean) {
- super(bean, "content");
- }
-
- /** Invoked when the user wants to set new data. */
- @Override public void set(final TreeTable data) {
- if (data != null) {
- final List<TableColumn<?>> columns = data.getColumns();
- if (!(columns.contains(TableColumn.NAME) &&
columns.contains(TableColumn.VALUE))) {
- throw new IllegalArgumentException();
- }
- }
- super.set(data);
- }
- }
-
- /**
- * The locale to use for texts.
- */
- private final Locale textLocale;
-
- /**
- * The locale to use for dates/numbers.
- * This is often the same than {@link #textLocale}.
- */
- private final Locale dataLocale;
-
+public class StandardMetadataTree extends MetadataTree {
/**
* The "copy" and "copy as" localized string, used for contextual menus.
*/
@@ -153,7 +80,7 @@ public class MetadataTree extends
TreeTableView<TreeTable.Node> {
/**
* Creates a new initially empty metadata tree.
*/
- public MetadataTree() {
+ public StandardMetadataTree() {
this(null);
}
@@ -165,28 +92,12 @@ public class MetadataTree extends
TreeTableView<TreeTable.Node> {
*
* @param controller the widget to watch, or {@code null} if none.
*/
- public MetadataTree(final MetadataSummary controller) {
- if (controller != null) {
- textLocale = controller.localized.getLocale();
- dataLocale = controller.dataLocale;
- } else {
- textLocale = Locale.getDefault(Locale.Category.DISPLAY);
- dataLocale = Locale.getDefault(Locale.Category.FORMAT);
- }
+ public StandardMetadataTree(final MetadataSummary controller) {
+ super(controller, true);
final Resources localized = Resources.forLocale(textLocale);
copy = localized.getString(Resources.Keys.Copy);
copyAs = localized.getString(Resources.Keys.CopyAs);
-
- contentProperty = new ContentProperty(this);
- nameColumn = new TreeTableColumn<>(TableColumn.NAME
.getHeader().toString(textLocale));
- valueColumn = new
TreeTableColumn<>(TableColumn.VALUE.getHeader().toString(textLocale));
- nameColumn .setCellValueFactory(MetadataTree::getPropertyName);
- valueColumn.setCellValueFactory(MetadataTree::getPropertyValue);
setRowFactory(Row::new);
-
- setColumnResizePolicy(CONSTRAINED_RESIZE_POLICY);
- getColumns().setAll(nameColumn, valueColumn);
- contentProperty.addListener(MetadataTree::applyChange);
if (controller != null) {
controller.metadataProperty.addListener((p,o,n) -> setContent(n));
}
@@ -214,55 +125,6 @@ public class MetadataTree extends
TreeTableView<TreeTable.Node> {
}
/**
- * Sets the data to show.
- * This is a convenience method for setting {@link #contentProperty} value.
- * The given {@link TreeTable} shall contain at least the following
columns:
- *
- * <ul>
- * <li>{@link TableColumn#NAME}</li>
- * <li>{@link TableColumn#VALUE}</li>
- * </ul>
- *
- * @param data the data to show, or {@code null} if none.
- * @throws IllegalArgumentException if the data is non-null but does not
contains the required columns.
- */
- public final void setContent(final TreeTable data) {
- contentProperty.setValue(data);
- }
-
- /**
- * Returns the data currently shown, or {@code null} if none.
- * This is a convenience method for fetching {@link #contentProperty}
value.
- *
- * @return the table currently shown, or {@code null} if none.
- *
- * @see #contentProperty
- * @see #setContent(TreeTable)
- */
- public final TreeTable getContent() {
- return contentProperty.getValue();
- }
-
- /**
- * Invoked when {@link #contentProperty} value changed.
- *
- * @param property the property which has been modified.
- * @param oldValue the old tree table.
- * @param content the tree table to use for building new content.
- */
- private static void applyChange(final ObservableValue<? extends TreeTable>
property,
- final TreeTable oldValue, final TreeTable
content)
- {
- final MetadataTree s = (MetadataTree) ((ContentProperty)
property).getBean();
- TreeItem<TreeTable.Node> root = null;
- if (content != null) {
- root = new Item(content.getRoot());
- root.setExpanded(true);
- }
- s.setRoot(root);
- }
-
- /**
* A row in a metadata tree view, used for adding contextual menu on a
row-by-row basis.
*/
private static final class Row extends TreeTableRow<TreeTable.Node>
implements EventHandler<ActionEvent> {
@@ -286,7 +148,7 @@ public class MetadataTree extends
TreeTableView<TreeTable.Node> {
*/
@SuppressWarnings("ThisEscapedInObjectConstruction")
Row(final TreeTableView<TreeTable.Node> view) {
- final MetadataTree md = (MetadataTree) view;
+ final StandardMetadataTree md = (StandardMetadataTree) view;
final MenuItem copy;
copy = new MenuItem(md.copy);
copyAsXML = new MenuItem();
@@ -306,7 +168,7 @@ public class MetadataTree extends
TreeTableView<TreeTable.Node> {
@Override
protected void updateItem(final TreeTable.Node item, final boolean
empty) {
super.updateItem(item, empty);
- if (!empty) {
+ if (!empty && copyAs != null) {
boolean disabled = true;
final TreeTable.Node node = getItem();
if (node != null) {
@@ -365,7 +227,7 @@ public class MetadataTree extends
TreeTableView<TreeTable.Node> {
text = value.toString();
}
} catch (Exception e) {
- final Resources localized =
Resources.forLocale(((MetadataTree) getTreeTableView()).textLocale);
+ final Resources localized =
Resources.forLocale(((StandardMetadataTree) getTreeTableView()).textLocale);
ExceptionReporter.show(localized.getString(Resources.Keys.ErrorExportingData),
localized.getString(Resources.Keys.CanNotCreateXML), e);
return;
@@ -376,101 +238,4 @@ public class MetadataTree extends
TreeTableView<TreeTable.Node> {
}
}
}
-
- /**
- * A simple node encapsulating a {@link TreeTable.Node} in a view.
- * The list of children is fetched when first needed.
- */
- private static final class Item extends TreeItem<TreeTable.Node> {
- /**
- * Whether this node is a leaf.
- */
- private final boolean isLeaf;
-
- /**
- * Creates a new node.
- */
- Item(final TreeTable.Node node) {
- super(node);
- isLeaf = node.isLeaf() || node.getChildren().isEmpty();
- }
-
- /**
- * Returns whether the node can not have children.
- */
- @Override
- public boolean isLeaf() {
- return isLeaf;
- }
-
- /**
- * Returns the items for all sub-nodes contained in this node.
- */
- @Override
- public ObservableList<TreeItem<TreeTable.Node>> getChildren() {
- final ObservableList<TreeItem<TreeTable.Node>> children =
super.getChildren();
- if (children.isEmpty()) {
- final Collection<TreeTable.Node> data =
getValue().getChildren();
- final List<Item> wrappers = new ArrayList<>(data.size());
- for (final TreeTable.Node child : data) {
- wrappers.add(new Item(child));
- }
- children.setAll(wrappers); // Fire a single event instead
of multiple `add`.
- }
- return children;
- }
- }
-
- /**
- * Returns the value for the specified column.
- * The generic type in this method signature reduces the risk that we
confuse columns.
- *
- * @param <T> the type of values in the column.
- * @param cell a wrapper around the {@link TreeTable.Node} from which
to get the value.
- * @param column column of the desired value.
- * @return value in the specified column. May be {@code null}.
- */
- private static <T> T getValue(final CellDataFeatures<TreeTable.Node, ?
extends T> cell, final TableColumn<T> column) {
- final TreeTable.Node node = cell.getValue().getValue();
- return node.getValue(column);
- }
-
- /**
- * Returns the name of the metadata property wrapped by the given argument.
- * This method is invoked by JavaFX when a new cell needs to be rendered.
- */
- private static ObservableValue<String> getPropertyName(final
CellDataFeatures<TreeTable.Node, String> cell) {
- final CharSequence value = getValue(cell, TableColumn.NAME);
- final String text;
- if (value instanceof InternationalString) {
- final MetadataTree view = (MetadataTree) cell.getTreeTableView();
- text = ((InternationalString) value).toString(view.textLocale);
- } else {
- text = (value != null) ? value.toString() : null;
- }
- return new ReadOnlyStringWrapper(text);
- }
-
- /**
- * Returns the value of the metadata property wrapped by the given
argument.
- * This method is invoked by JavaFX when a new cell needs to be rendered.
- *
- * @todo Format other kinds of objects (numbers, dates, timezones, etc.).
- * See {@link org.apache.sis.util.collection.TreeTableFormat},
- * if possible by putting some code in common.
- */
- private static ObservableValue<Object> getPropertyValue(final
CellDataFeatures<TreeTable.Node, Object> cell) {
- final MetadataTree view = (MetadataTree) cell.getTreeTableView();
- Object value = getValue(cell, TableColumn.VALUE);
- if (value instanceof IdentifiedObject) {
- value = IdentifiedObjects.getDisplayName((IdentifiedObject) value,
view.textLocale);
- }
- if (value instanceof ControlledVocabulary) {
- value = Types.getCodeTitle((ControlledVocabulary) value);
- }
- if (value instanceof InternationalString) {
- value = ((InternationalString) value).toString(view.textLocale);
- }
- return new ReadOnlyObjectWrapper<>(value);
- }
}
diff --git
a/core/sis-utility/src/main/java/org/apache/sis/util/resources/Vocabulary.java
b/core/sis-utility/src/main/java/org/apache/sis/util/resources/Vocabulary.java
index 2afc5b3..4d0f30c 100644
---
a/core/sis-utility/src/main/java/org/apache/sis/util/resources/Vocabulary.java
+++
b/core/sis-utility/src/main/java/org/apache/sis/util/resources/Vocabulary.java
@@ -410,6 +410,11 @@ public final class Vocabulary extends
IndexedResourceBundle {
public static final short FillValue = 63;
/**
+ * Format
+ */
+ public static final short Format = 196;
+
+ /**
* Geocentric
*/
public static final short Geocentric = 64;
diff --git
a/core/sis-utility/src/main/java/org/apache/sis/util/resources/Vocabulary.properties
b/core/sis-utility/src/main/java/org/apache/sis/util/resources/Vocabulary.properties
index 21688a3..df7d99c 100644
---
a/core/sis-utility/src/main/java/org/apache/sis/util/resources/Vocabulary.properties
+++
b/core/sis-utility/src/main/java/org/apache/sis/util/resources/Vocabulary.properties
@@ -85,6 +85,7 @@ EntryCount_1 = {0} entr{0,choice,0#y|2#ies}
Envelope = Envelope
Errors = Errors
FillValue = Fill value
+Format = Format
Geocentric = Geocentric
GeocentricRadius = Geocentric radius
GeocentricConversion = Geocentric conversion
diff --git
a/core/sis-utility/src/main/java/org/apache/sis/util/resources/Vocabulary_fr.properties
b/core/sis-utility/src/main/java/org/apache/sis/util/resources/Vocabulary_fr.properties
index 62f4c5a..e5bef50 100644
---
a/core/sis-utility/src/main/java/org/apache/sis/util/resources/Vocabulary_fr.properties
+++
b/core/sis-utility/src/main/java/org/apache/sis/util/resources/Vocabulary_fr.properties
@@ -92,6 +92,7 @@ EndPoint = Point d\u2019arriv\u00e9
Envelope = Enveloppe
Errors = Erreurs
FillValue = Valeur de remplissage
+Format = Format
Geocentric = G\u00e9ocentrique
GeocentricRadius = Rayon g\u00e9ocentrique
GeocentricConversion = Conversion g\u00e9ocentrique
diff --git
a/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/Decoder.java
b/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/Decoder.java
index 95e3046..d3dc0e0 100644
---
a/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/Decoder.java
+++
b/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/Decoder.java
@@ -41,6 +41,7 @@ import org.apache.sis.util.Utilities;
import org.apache.sis.util.ComparisonMode;
import org.apache.sis.util.logging.Logging;
import org.apache.sis.util.logging.PerformanceLevel;
+import org.apache.sis.util.collection.TreeTable;
import org.apache.sis.internal.util.StandardDateFormat;
import org.apache.sis.internal.system.DefaultFactories;
import org.apache.sis.internal.system.Modules;
@@ -54,7 +55,7 @@ import
org.apache.sis.internal.referencing.ReferencingFactoryContainer;
* Synchronizations are caller's responsibility.</p>
*
* @author Martin Desruisseaux (Geomatys)
- * @version 1.0
+ * @version 1.1
* @since 0.3
* @module
*/
@@ -179,6 +180,13 @@ public abstract class Decoder extends
ReferencingFactoryContainer implements Clo
}
/**
+ * Adds netCDF attributes to the given node.
+ *
+ * @param root the node where to add netCDF attributes.
+ */
+ public abstract void addNativeMetadata(TreeTable.Node root);
+
+ /**
* Returns a filename for formatting error message and for information
purpose.
* The filename should not contain path, but may contain file extension.
*
diff --git
a/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/impl/ChannelDecoder.java
b/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/impl/ChannelDecoder.java
index c7e5481..bac80a7 100644
---
a/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/impl/ChannelDecoder.java
+++
b/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/impl/ChannelDecoder.java
@@ -60,6 +60,8 @@ import org.apache.sis.storage.event.StoreListeners;
import org.apache.sis.util.ArraysExt;
import org.apache.sis.util.resources.Errors;
import org.apache.sis.util.resources.Vocabulary;
+import org.apache.sis.util.collection.TreeTable;
+import org.apache.sis.util.collection.TableColumn;
import org.apache.sis.setup.GeometryLibrary;
import org.apache.sis.measure.Units;
import org.apache.sis.math.Vector;
@@ -1036,6 +1038,26 @@ nextVar: for (final VariableInfo variable :
variables) {
}
/**
+ * Adds netCDF attributes to the given node.
+ *
+ * @param root the node where to add netCDF attributes.
+ */
+ @Override
+ public void addNativeMetadata(final TreeTable.Node root) {
+ for (final Map.Entry<String,Object> entry : attributeMap.entrySet()) {
+ final TreeTable.Node node = root.newChild();
+ node.setValue(TableColumn.NAME, entry.getKey());
+ Object value = entry.getValue();
+ if (value != null) {
+ if (value instanceof Vector) {
+ value = ((Vector) value).toArray();
+ }
+ node.setValue(TableColumn.VALUE, value);
+ }
+ }
+ }
+
+ /**
* Returns a string representation to be inserted in {@link
org.apache.sis.storage.netcdf.NetcdfStore#toString()}
* result. This is for debugging purpose only any may change in any future
SIS version.
*
diff --git
a/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/ucar/DecoderWrapper.java
b/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/ucar/DecoderWrapper.java
index d9c6306..d2766ec 100644
---
a/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/ucar/DecoderWrapper.java
+++
b/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/ucar/DecoderWrapper.java
@@ -40,6 +40,8 @@ import ucar.nc2.ft.FeatureDatasetPoint;
import ucar.nc2.ft.FeatureDatasetFactoryManager;
import ucar.nc2.ft.FeatureCollection;
import org.apache.sis.util.ArraysExt;
+import org.apache.sis.util.collection.TreeTable;
+import org.apache.sis.util.collection.TableColumn;
import org.apache.sis.internal.netcdf.Convention;
import org.apache.sis.internal.netcdf.Decoder;
import org.apache.sis.internal.netcdf.Variable;
@@ -500,6 +502,50 @@ public final class DecoderWrapper extends Decoder
implements CancelTask {
}
/**
+ * Adds netCDF attributes to the given node.
+ *
+ * @param root the node where to add netCDF attributes.
+ */
+ @Override
+ public void addNativeMetadata(final TreeTable.Node root) {
+ addNativeMetadata(root, file.getRootGroup());
+ }
+
+ /**
+ * Adds all attributes of the given group, then create nodes for
sub-groups (if any).
+ * This method invokes itself recursively.
+ */
+ private void addNativeMetadata(final TreeTable.Node branch, final Group
group) {
+ for (final Attribute attribute : group.getAttributes()) {
+ final TreeTable.Node node = branch.newChild();
+ node.setValue(TableColumn.NAME, attribute.getShortName());
+ final int length = attribute.getLength();
+ final Object value;
+ switch (length) {
+ case 0: continue;
+ case 1: {
+ value = attribute.getValue(0);
+ break;
+ }
+ default: {
+ final Object[] values = new Object[length];
+ for (int i=0; i<length; i++) {
+ values[i] = attribute.getValue(i);
+ }
+ value = values;
+ break;
+ }
+ }
+ node.setValue(TableColumn.VALUE, value);
+ }
+ for (final Group sub : group.getGroups()) {
+ final TreeTable.Node node = branch.newChild();
+ node.setValue(TableColumn.NAME, sub.getShortName());
+ addNativeMetadata(node, sub);
+ }
+ }
+
+ /**
* Invoked by the UCAR netCDF library for checking if the reading process
has been canceled.
* This method returns the {@link #canceled} flag.
*
diff --git
a/storage/sis-netcdf/src/main/java/org/apache/sis/storage/netcdf/NetcdfStore.java
b/storage/sis-netcdf/src/main/java/org/apache/sis/storage/netcdf/NetcdfStore.java
index f5b8db7..4844f61 100644
---
a/storage/sis-netcdf/src/main/java/org/apache/sis/storage/netcdf/NetcdfStore.java
+++
b/storage/sis-netcdf/src/main/java/org/apache/sis/storage/netcdf/NetcdfStore.java
@@ -42,6 +42,9 @@ import org.apache.sis.storage.Resource;
import org.apache.sis.storage.event.StoreEvent;
import org.apache.sis.storage.event.StoreListener;
import org.apache.sis.storage.event.WarningEvent;
+import org.apache.sis.util.collection.DefaultTreeTable;
+import org.apache.sis.util.collection.TableColumn;
+import org.apache.sis.util.collection.TreeTable;
import org.apache.sis.util.CharSequences;
import org.apache.sis.util.Version;
import ucar.nc2.constants.ACDD;
@@ -53,7 +56,7 @@ import ucar.nc2.constants.CDM;
* Instances of this data store are created by {@link
NetcdfStoreProvider#open(StorageConnector)}.
*
* @author Martin Desruisseaux (Geomatys)
- * @version 1.0
+ * @version 1.1
*
* @see NetcdfStoreProvider
*
@@ -191,6 +194,26 @@ public class NetcdfStore extends DataStore implements
Aggregate {
}
/**
+ * Returns netCDF attributes. The meaning of those attributes may vary
depending on data provider.
+ * The {@linkplain #getMetadata() standard metadata} should be preferred
since they allow abstraction of
+ * data format details, but those native metadata are sometime useful when
an information is not provided
+ * by the standard metadata.
+ *
+ * @return resources information structured in an implementation-specific
way.
+ * @throws DataStoreException if an error occurred while reading the
metadata.
+ *
+ * @since 1.1
+ */
+ @Override
+ public Optional<TreeTable> getNativeMetadata() throws DataStoreException {
+ final DefaultTreeTable table = new DefaultTreeTable(TableColumn.NAME,
TableColumn.VALUE);
+ final TreeTable.Node root = table.getRoot();
+ root.setValue(TableColumn.NAME, NetcdfStoreProvider.NAME);
+ decoder.addNativeMetadata(root);
+ return Optional.of(table);
+ }
+
+ /**
* Returns the resources (features or coverages) in this netCDF store.
*
* @return children resources that are components of this netCDF store.
diff --git
a/storage/sis-netcdf/src/main/java/org/apache/sis/storage/netcdf/package-info.java
b/storage/sis-netcdf/src/main/java/org/apache/sis/storage/netcdf/package-info.java
index fc4605e..468b167 100644
---
a/storage/sis-netcdf/src/main/java/org/apache/sis/storage/netcdf/package-info.java
+++
b/storage/sis-netcdf/src/main/java/org/apache/sis/storage/netcdf/package-info.java
@@ -48,7 +48,7 @@
* Care must be taken for avoiding confusion when using SIS and UCAR libraries
together.
*
* @author Martin Desruisseaux (IRD, Geomatys)
- * @version 1.0
+ * @version 1.1
* @since 0.3
* @module
*/
diff --git
a/storage/sis-storage/src/main/java/org/apache/sis/storage/DataStore.java
b/storage/sis-storage/src/main/java/org/apache/sis/storage/DataStore.java
index dcf983c..e4368b1 100644
--- a/storage/sis-storage/src/main/java/org/apache/sis/storage/DataStore.java
+++ b/storage/sis-storage/src/main/java/org/apache/sis/storage/DataStore.java
@@ -29,6 +29,8 @@ import org.opengis.metadata.identification.Identification;
import org.opengis.parameter.ParameterValueGroup;
import org.apache.sis.util.Localized;
import org.apache.sis.util.ArgumentChecks;
+import org.apache.sis.util.collection.TreeTable;
+import org.apache.sis.util.collection.TableColumn;
import org.apache.sis.internal.storage.StoreUtilities;
import org.apache.sis.internal.storage.Resources;
import org.apache.sis.internal.util.Strings;
@@ -63,7 +65,7 @@ import org.apache.sis.storage.event.StoreListeners;
*
* @author Johann Sorel (Geomatys)
* @author Martin Desruisseaux (Geomatys)
- * @version 1.0
+ * @version 1.1
*
* @see DataStores#open(Object)
*
@@ -351,7 +353,7 @@ public abstract class DataStore implements Resource,
Localized, AutoCloseable {
* file format and more.
*
* @return information about resources in the data store. Should not be
{@code null}.
- * @throws DataStoreException if an error occurred while reading the data.
+ * @throws DataStoreException if an error occurred while reading the
metadata.
*
* @see #getIdentifier()
*/
@@ -359,6 +361,31 @@ public abstract class DataStore implements Resource,
Localized, AutoCloseable {
public abstract Metadata getMetadata() throws DataStoreException;
/**
+ * Returns implementation-specific metadata. The structure of those
metadata varies for each file format.
+ * The {@linkplain #getMetadata() standard metadata} should be preferred
since they allow abstraction of
+ * format details, but those native metadata are sometime useful when an
information is not provided by
+ * the standard metadata.
+ *
+ * <p>The tree table should contain at least the following columns:</p>
+ * <ul>
+ * <li>{@link TableColumn#NAME} — a name for the metadata property,
e.g. "Title".</li>
+ * <li>{@link TableColumn#VALUE} — the property value typically as a
string, number or date.</li>
+ * </ul>
+ *
+ * The {@link TableColumn#NAME} of the root node should be a format name
such as "NetCDF" or "GeoTIFF".
+ * That name should be short since it may be used in widget as a
designation of implementation-specific
+ * details.
+ *
+ * @return resources information structured in an implementation-specific
way.
+ * @throws DataStoreException if an error occurred while reading the
metadata.
+ *
+ * @since 1.1
+ */
+ public Optional<TreeTable> getNativeMetadata() throws DataStoreException {
+ return Optional.empty();
+ }
+
+ /**
* Searches for a resource identified by the given identifier. The given
identifier should be the string
* representation of the return value of {@link Resource#getIdentifier()}
on the desired resource.
* Implementation may also accept aliases for convenience. For example if
the full name of a resource