/*
* Copyright 1998-2015 University Corporation for Atmospheric Research/Unidata
*
* Portions of this software were developed by the Unidata Program at the
* University Corporation for Atmospheric Research.
*
* Access and use of this software shall impose the following obligations
* and understandings on the user. The user is granted the right, without
* any fee or cost, to use, copy, modify, alter, enhance and distribute
* this software, and any derivative works thereof, and its supporting
* documentation for any purpose whatsoever, provided that this entire
* notice appears in all copies of the software, derivative works and
* supporting documentation. Further, UCAR requests that the user credit
* UCAR/Unidata in any publications that result from the use of this
* software or in any product that includes this software. The names UCAR
* and/or Unidata, however, may not be used in any advertising or publicity
* to endorse or promote any products or commercial entity unless specific
* written permission is obtained from UCAR/Unidata. The user also
* understands that UCAR/Unidata is not obligated to provide the user with
* any support, consulting, training or assistance of any kind with regard
* to the use, operation and performance of this software nor to provide
* the user with any updates, revisions, new versions or "bug fixes."
*
* THIS SOFTWARE IS PROVIDED BY UCAR/UNIDATA "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL UCAR/UNIDATA BE LIABLE FOR ANY SPECIAL,
* INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
* FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
* NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
* WITH THE ACCESS, USE OR PERFORMANCE OF THIS SOFTWARE.
*/
package thredds.core;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Formatter;
import java.util.HashMap;
import java.util.List;
import javax.annotation.PostConstruct;
import javax.servlet.http.HttpServletRequest;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import thredds.client.catalog.*;
import thredds.server.wms.Godiva2Viewer;
import ucar.nc2.constants.FeatureType;
import ucar.nc2.util.IO;
import ucar.unidata.util.StringUtil2;
// @Service
public class ViewerServiceImpl implements ViewerService {
private static Logger logger = LoggerFactory.getLogger(ViewerServiceImpl.class);
public static ViewerLinkProvider getStaticView() {
return new StaticView();
}
private List<Viewer> viewers = new ArrayList<>();
private HashMap<String, String> templates = new HashMap<>();
@Override
public List<Viewer> getViewers() {
return null;
}
@Override
public Viewer getViewer(String viewer) {
return null;
}
@Override
public boolean registerViewer(Viewer v) {
return viewers.add(v);
}
@Override
public String getViewerTemplate(String path) {
String template = templates.get(path);
if (template != null)
return template;
try {
template = IO.readFile(path);
} catch (IOException ioe) {
return null;
}
templates.put(path, template);
return template;
}
@Override
public void showViewers(Formatter out, Dataset dataset, HttpServletRequest req) {
int count = 0;
for (Viewer viewer : viewers) {
if (viewer.isViewable(dataset)) count++;
}
if (count == 0) return;
out.format("<h3>Viewers:</h3><ul>\r\n");
for (Viewer viewer : viewers) {
if (viewer.isViewable(dataset)) {
if (viewer instanceof ViewerLinkProvider) {
List<ViewerLinkProvider.ViewerLink> sp = ((ViewerLinkProvider) viewer).getViewerLinks(dataset, req);
for (ViewerLinkProvider.ViewerLink vl : sp) {
if (vl.getUrl() != null && !vl.getUrl().equals(""))
out.format("<li><a href='%s'>%s</a></li>\r\n", vl.getUrl(), vl.getTitle() != null ? vl.getTitle() : vl.getUrl());
}
} else {
String viewerLinkHtml = viewer.getViewerLinkHtml(dataset, req);
if (viewerLinkHtml != null) {
out.format(" <li> ");
out.format(viewerLinkHtml);
out.format("</li>\n");
}
}
}
}
out.format("</ul>\r\n");
}
@SuppressWarnings("unused")
@PostConstruct
private void registerViewers() {
registerViewer(new ViewerGodiva());
registerViewer(new ToolsUI());
registerViewer(new IDV());
registerViewer(new StaticView());
}
// Viewers...
// ToolsUI
private static class ToolsUI implements Viewer {
public boolean isViewable(Dataset ds) {
String id = ds.getID();
return ((id != null) && ds.hasAccess());
}
public String getViewerLinkHtml(Dataset ds, HttpServletRequest req) {
String base = ds.getParentCatalog().getUriString();
if (base.endsWith(".html"))
base = base.substring(0, base.length() - 5) + ".xml";
Formatter query = new Formatter();
query.format("<a href='%s/view/ToolsUI.jnlp?", req.getContextPath());
query.format("catalog=%s&dataset=%s'>NetCDF-Java ToolsUI (webstart)</a>", base, ds.getID());
return query.toString();
}
}
// IDV
private static class IDV implements Viewer {
public boolean isViewable(Dataset ds) {
Access access = getOpendapAccess(ds);
if (access == null)
return false;
FeatureType dt = ds.getFeatureType();
return dt == FeatureType.GRID;
}
public String getViewerLinkHtml(Dataset ds, HttpServletRequest req) {
Access access = getOpendapAccess(ds);
if (access == null)
return null;
URI dataURI = access.getStandardUri();
if (dataURI == null) {
logger.warn("IDVViewer access URL failed on {}", ds.getName());
return null;
}
if (!dataURI.isAbsolute()) {
try {
URI base = new URI(req.getRequestURL().toString());
dataURI = base.resolve(dataURI);
// System.out.println("Resolve URL with "+req.getRequestURL()+" got= "+dataURI.toString());
} catch (URISyntaxException e) {
logger.error("Resolve URL with " + req.getRequestURL(), e);
}
}
return "<a href='" + req.getContextPath() + "/view/idv.jnlp?url="
+ dataURI.toString()
+ "'>Integrated Data Viewer (IDV) (webstart)</a>";
}
private Access getOpendapAccess(Dataset ds) {
Access access = ds.getAccess(ServiceType.DODS);
if (access == null)
access = ds.getAccess(ServiceType.OPENDAP);
return access;
}
}
// LOOK whats this for ??
private static final String propertyNamePrefix = "viewer";
private static class StaticView implements ViewerLinkProvider {
public boolean isViewable(Dataset ds) {
return hasViewerProperties(ds);
}
public String getViewerLinkHtml(Dataset ds, HttpServletRequest req) {
List<ViewerLink> viewerLinks = getViewerLinks(ds, req);
if (viewerLinks.isEmpty())
return null;
ViewerLink firstLink = viewerLinks.get(0);
return "<a href='" + firstLink.getUrl() + "'>" + firstLink.getTitle() + "</a>";
}
@Override
public List<ViewerLink> getViewerLinks(Dataset ds, HttpServletRequest req) {
List<Property> viewerProperties = findViewerProperties(ds);
if (viewerProperties.isEmpty())
return Collections.emptyList();
List<ViewerLink> result = new ArrayList<>();
for (Property p : viewerProperties) {
ViewerLink viewerLink = parseViewerPropertyValue(p.getName(), p.getValue(), ds);
if (viewerLink != null)
result.add(viewerLink);
}
return result;
}
private ViewerLink parseViewerPropertyValue(String viewerName, String viewerValue, Dataset ds) {
String viewerUrl;
String viewerTitle;
int lastCommaLocation = viewerValue.lastIndexOf(",");
if (lastCommaLocation != -1) {
viewerUrl = viewerValue.substring(0, lastCommaLocation);
viewerTitle = viewerValue.substring(lastCommaLocation + 1);
if (viewerUrl.equals(""))
return null;
if (viewerTitle.equals(""))
viewerTitle = viewerName;
} else {
viewerUrl = viewerValue;
viewerTitle = viewerName;
}
viewerUrl = StringUtil2.quoteHtmlContent(sub(viewerUrl, ds));
return new ViewerLink(viewerTitle, viewerUrl);
}
private boolean hasViewerProperties(Dataset ds) {
for (Property p : ds.getProperties())
if (p.getName().startsWith(propertyNamePrefix))
return true;
return false;
}
private List<Property> findViewerProperties(Dataset ds) {
List<Property> result = new ArrayList<>();
for (Property p : ds.getProperties())
if (p.getName().startsWith(propertyNamePrefix))
result.add(p);
return result;
}
private String sub(String org, Dataset ds) {
List<Access> access = ds.getAccess();
if (access.size() == 0)
return org;
// look through all access for {serviceName}
for (Access acc : access) {
String sname = "{" + acc.getService().getType() + "}";
if (org.contains(sname)) {
URI uri = acc.getStandardUri();
if (uri != null)
return StringUtil2.substitute(org, sname, uri.toString());
}
}
String sname = "{url}";
if ((org.contains(sname)) && (access.size() > 0)) {
Access acc = access.get(0); // just use the first one
URI uri = acc.getStandardUri();
if (uri != null)
return StringUtil2.substitute(org, sname, uri.toString());
}
return org;
}
}
}