/* * Constellation - An open source and standard compliant SDI * http://www.constellation-sdi.org * * Copyright 2014 Geomatys. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.constellation.gui; import juzu.Action; import juzu.Path; import juzu.Resource; import juzu.Response; import juzu.Route; import juzu.View; import juzu.plugin.ajax.Ajax; import juzu.template.Template; import org.apache.commons.fileupload.FileItem; import org.apache.commons.lang3.StringUtils; import org.constellation.ServiceDef.Specification; import org.constellation.configuration.ConfigDirectory; import org.constellation.configuration.Layer; import org.constellation.configuration.LayerList; import org.constellation.dto.AccessConstraint; import org.constellation.dto.AddLayer; import org.constellation.dto.Contact; import org.constellation.dto.DataInformation; import org.constellation.dto.Service; import org.constellation.gui.service.ConstellationService; import org.constellation.gui.service.InstanceSummary; import org.constellation.gui.service.MapManager; import org.constellation.gui.service.ProviderManager; import org.constellation.gui.service.ServicesManager; import org.constellation.gui.service.bean.LayerData; import org.constellation.gui.templates.webservices; import org.constellation.gui.util.LayerComparator; import org.constellation.gui.util.LayerDataComparator; import javax.inject.Inject; import java.io.File; import java.io.IOException; import java.nio.file.Files; import java.nio.file.StandardCopyOption; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.ResourceBundle; import java.util.logging.Level; import java.util.logging.Logger; import org.apache.sis.util.logging.Logging; import static org.apache.commons.lang3.StringUtils.containsIgnoreCase; import static org.apache.commons.lang3.StringUtils.isBlank; /** * Constellation web client main Juzu controller. Manage linkage with other controller and homepages * * @author Benjamin Garcia (Geomatys) * @version 0.9 * @since 0.9 */ public class Controller { private static final Logger LOGGER = Logging.getLogger("org.constellation.gui"); /** * Manager used to call constellation server side. */ @Inject protected ServicesManager servicesManager; @Inject protected MapManager mapManager; @Inject protected ProviderManager providerManager; @Inject private ConstellationService cstl; // @Inject protected DataInformationContainer informationContainer; /** * Home page juzu template. */ @Inject @Path("index.gtmpl") protected Template index; @Inject @Path("data_dashboard.gtmpl") protected Template dataDashboard; @Inject @Path("data_listing.gtmpl") protected Template dataListing; @Inject @Path("add_data.gtmpl") protected Template addData; @Inject @Path("local_file_modal.gtmpl") protected Template localFileModal; @Inject @Path("server_modal.gtmpl") protected Template serverModal; /** * {@link java.util.ResourceBundle} used on this application */ @Inject protected ResourceBundle bundle; /** * Webservice main page juzu template. */ @Inject @Path("webservices.gtmpl") webservices webServices; /** * End service creation page juzu tempate */ @Inject @Path("success.gtmpl") org.constellation.gui.templates.success success; @Inject @Path("add_data_alias.gtmpl") Template addDataAlias; @Inject @Path("layer.gtmpl") Template dataElement; /** * Generate homepage * * @return a {@link juzu.Response} with right mime type */ @View @Route("/") public Response index() { return index.ok().withMimeType("text/html"); } /** * Generate webservice main page * * @return a {@link juzu.Response} with right mime type */ @View @Route("/webservices") public Response webservices() { List<InstanceSummary> services = servicesManager.getServiceList(); return webServices.with().services(services).ok().withMimeType("text/html"); } @View @Route("/data") public Response dataDashboard(final String errorInformation) { final List<LayerData> list = providerManager.getDataListing(Arrays.asList("vector")); final int nbResults = list.size(); // Truncate the list. final List<LayerData> providers; if (!list.isEmpty()) { final int endIndex = Math.min(list.size(), 10); providers = list.subList(0, endIndex); } else { providers = new ArrayList<>(0); } final Map<String, Object> parameters = new HashMap<>(0); parameters.put("providers", providers); parameters.put("nbResults", nbResults); parameters.put("startIndex", 0); parameters.put("nbPerPage", 10); parameters.put("selected", null); parameters.put("errorInformation", errorInformation); String url = cstl.getUrlWithEndSlash() + "api/1/portrayal/portray"; parameters.put("portrayalUrl", url); return dataDashboard.ok(parameters).withMimeType("text/html"); } /** * Action to create a WMS Service. * * @param createdService main {@link org.constellation.dto.Service} generated by web form * @param serviceContact service contact which set after on {@link org.constellation.dto.Service} * @param serviceConstraint service constraint which set after on {@link org.constellation.dto.Service} * @param versions service versions list * @param keywords service keyword list * @param transactional {@code true} if in transactional mode. * @param serviceType service type (WMS, etc...) * @return a {@link juzu.Response} to create view */ @Action @Route("/{serviceType}/success") public Response createService(Service createdService, Contact serviceContact, AccessConstraint serviceConstraint, String versions, String keywords, String transactional, String serviceType) throws IOException { //build versions list final List<String> versionsList; if (versions.contains(",")) { final String[] versionsArray = versions.split(","); versionsList = Arrays.asList(versionsArray); } else { versionsList = new ArrayList<>(); versionsList.add(versions); } createdService.setVersions(versionsList); //build keywords list final List<String> keywordsList; if (keywords.contains(",")) { final String[] keywordsArray = keywords.split(","); keywordsList = Arrays.asList(keywordsArray); } else { keywordsList = new ArrayList<>(); keywordsList.add(keywords); } createdService.setKeywords(keywordsList); //set other object on service createdService.setServiceConstraints(serviceConstraint); serviceContact.setFullname(); createdService.setServiceContact(serviceContact); if(transactional!=null && !transactional.isEmpty()){ createdService.setTransactional(true); } //call service try { servicesManager.createServices(createdService, Specification.fromShortName(serviceType)); if (serviceType.equalsIgnoreCase("csw")) { return CswController_.chooseSource(createdService.getName(), createdService.getDescription(), createdService.getIdentifier(), serviceType, versionsList); } else { return Controller_.succeeded(createdService.getName(), createdService.getDescription(), createdService.getIdentifier(), serviceType, versionsList, "true"); } } catch (IOException ex) { return Controller_.succeeded(createdService.getName(), createdService.getDescription(), createdService.getIdentifier(), serviceType, versionsList, "false"); } } /** * View after service creation * * @param name * @param description * @param identifier * @param type service type * @param versionList service version available * @param created {@link String} {@link boolean} mirror to no if service is created * @return a {@link juzu.Response} to create view */ @View @Route("/succeeded") public Response succeeded(final String name, final String description, final String identifier, final String type, final List<String> versionList, final String created) { Boolean create = Boolean.parseBoolean(created); InstanceSummary is = new InstanceSummary(); is.setIdentifier(identifier); is.setName(name); is.set_abstract(description); is.setType(type); servicesManager.buildServiceUrl(type, identifier, versionList, is); return success.with().service(is).versions(versionList).created(create).ok().withMimeType("text/html"); } /** * Generate datalist to show it in ajax * * @param serviceId Service where we want to see data * @param start First element list counter * @param count Element number by page * @param orderBy String to order by this attribute * @param filter String to filter list * @throws java.io.IOException on communication error with Constellation server */ @Ajax @Resource @Route("/dataList") public Response generateDataList(final String serviceId, final String serviceType, final String start, final String count, final String orderBy, final String direction, final String filter) throws IOException { final LayerList listBean = mapManager.getLayers(serviceId, Specification.fromShortName(serviceType)); // Search layers by name. if (!isBlank(filter)) { final List<Layer> toRemove = new ArrayList<>(); for (final Layer bean : listBean.getLayer()) { if (!containsIgnoreCase(bean.getName().getLocalPart(), filter)) { toRemove.add(bean); } } listBean.getLayer().removeAll(toRemove); } final int nbResults = listBean.getLayer().size(); // Sort layers by criteria. if (!StringUtils.isBlank(orderBy) && !StringUtils.isBlank(direction)) { Collections.sort(listBean.getLayer(), new LayerComparator(orderBy, direction)); } // Truncate the list. final List<Layer> layers; final int intStart = Integer.parseInt(start); final int intCount = Integer.parseInt(count); if (!listBean.getLayer().isEmpty() && intStart < listBean.getLayer().size()) { final int endIndex = Math.min(listBean.getLayer().size(), intStart + intCount); layers = listBean.getLayer().subList(intStart, endIndex); } else { layers = new ArrayList<>(0); } final Map<String, Object> parameters = new HashMap<>(); parameters.put("layers", layers); parameters.put("nbResults", nbResults); parameters.put("startIndex", intStart); parameters.put("nbPerPage", intCount); return dataElement.with(parameters).ok(); } @Ajax @Resource @Route("/providerList") public Response getAvailableData(List<String> dataTypes, final String start, final String count, final String orderBy, final String direction, final String filter) { for (int i = 0; i < dataTypes.size(); i++) { String current = dataTypes.get(i); if(current.equalsIgnoreCase("coverage")){ dataTypes.set(i, "raster"); } } final List<LayerData> list = providerManager.getDataListing(dataTypes); // Search layers by name. if (!isBlank(filter)) { final List<LayerData> toRemove = new ArrayList<>(); for (final LayerData bean : list) { if (!containsIgnoreCase(bean.getName(), filter)) { toRemove.add(bean); } } list.removeAll(toRemove); } final int nbResults = list.size(); // Sort layers by criteria. if (!StringUtils.isBlank(orderBy) && !StringUtils.isBlank(direction)) { Collections.sort(list, new LayerDataComparator(orderBy, direction)); } // Truncate the list. final List<LayerData> providers; final int intStart = (start == null) ? 0 : Integer.parseInt(start); final int intCount = (count == null) ? 10 : Integer.parseInt(count); if (!list.isEmpty() && intStart < list.size()) { final int endIndex = Math.min(list.size(), intStart + intCount); providers = list.subList(intStart, endIndex); } else { providers = new ArrayList<>(0); } final Map<String, Object> parameters = new HashMap<>(); parameters.put("providers", providers); parameters.put("nbResults", nbResults); parameters.put("startIndex", intStart); parameters.put("nbPerPage", intCount); return dataListing.with(parameters).ok(); } /** * juzu Upload utilisation. Save file on temp directory before create a thread to send it on server. * * @param file file set by client for constellation server * @return a {@link juzu.Response} to redirect on another page */ @Resource @Route("/upload") public Response upload(final FileItem file, final FileItem metadataFile, final String dataType, final String returnURL) { boolean metadataUploaded = false; if (!metadataFile.getName().isEmpty()) { metadataUploaded = true; } if (file != null) { DataInformation di; try { File dataDirectory = ConfigDirectory.getDataDirectory(); final File newFile = new File(dataDirectory, file.getName()); Files.copy(file.getInputStream(), newFile.toPath(), StandardCopyOption.REPLACE_EXISTING); if (metadataUploaded) { File newMetadataFile = new File(dataDirectory.getAbsolutePath() + "/metadata/" + metadataFile.getName()); Files.copy(metadataFile.getInputStream(), newMetadataFile.toPath(), StandardCopyOption.REPLACE_EXISTING); } di = providerManager.loadData(file.getName(), metadataFile.getName(), dataType); informationContainer.setInformation(di); } catch (IOException ex) { LOGGER.log(Level.WARNING, ex.getLocalizedMessage(), ex); } Response aResponse = Response.error("response not initialized"); switch (dataType) { case "raster": aResponse = RasterController_.showRaster(returnURL, metadataUploaded + "", "true"); break; case "vector": aResponse = VectorController_.showVector(returnURL, metadataUploaded + "", "true"); } return aResponse; } else { return Response.error("error when saving file on server"); } } @Action @Route("layer/add") public Response addLayer(final String layerAlias, final String dataName, final String dataProvider, final String serviceId, final String serviceType) { AddLayer toAddLayer = new AddLayer(layerAlias, serviceType, serviceId, dataProvider, dataName); providerManager.addLayer(toAddLayer); return MapController_.dashboard(serviceId, serviceType); } /** * Reloads the WMS service with the specified identifier. * * @param serviceId the service identifier * @return a status {@link juzu.Response} */ @Ajax @Resource @Route("service/reload") public Response restartService(final String serviceType, final String serviceId) { try { servicesManager.restartService(serviceId, Specification.fromShortName(serviceType)); return Response.ok(); } catch (IOException ex) { return Response.error(ex.getLocalizedMessage()); } } /** * Stops the WMS service with the specified identifier. * * @param serviceId the service identifier * @return a status {@link juzu.Response} */ @Ajax @Resource @Route("service/stop") public Response stopService(final String serviceType, final String serviceId) { try { servicesManager.stopService(serviceId, Specification.fromShortName(serviceType)); return Response.ok(); } catch (IOException ex) { return Response.error(ex.getLocalizedMessage()); } } /** * Deletes the WMS service with the specified identifier. * * @param serviceId the service identifier * @return a status {@link juzu.Response} */ @Ajax @Resource @Route("service/delete") public Response deleteService(final String serviceType, final String serviceId) { try { servicesManager.deleteService(serviceId, Specification.fromShortName(serviceType)); return Response.ok(); } catch (IOException ex) { return Response.error(ex.getLocalizedMessage()); } } /** * Stars the WMS service with the specified identifier. * * @param serviceId the service identifier * @return a status {@link juzu.Response} */ @Ajax @Resource @Route("service/start") public Response startService(final String serviceType, final String serviceId) { try { servicesManager.startService(serviceId, Specification.fromShortName(serviceType)); return Response.ok(); } catch (IOException ex) { return Response.error(ex.getLocalizedMessage()); } } /** * Updates the WMS service general description. * * @param identifier the service identifier * @param name the (new) service name * @param keywords the (new) service keywords * @param description the (new) service description * @param v111 the (new) service v111 state * @param v130 the (new) service v130 state * @return a status {@link juzu.Response} * @throws java.io.IOException on communication error with Constellation server */ @Ajax @Resource @Route("service/description") public Response setServiceDescription(final String serviceType, final String identifier, final String name, final String keywords, final String description, final String v111, final String v130) throws IOException { final Service metadata = servicesManager.getMetadata(identifier, Specification.WMS); metadata.setName(name); metadata.setKeywords(!isBlank(keywords) ? Arrays.asList(keywords.split(",")) : null); metadata.setDescription(description); metadata.setVersions(new ArrayList<String>()); if (v111 != null) metadata.getVersions().add(v111); if (v130 != null) metadata.getVersions().add(v130); try { servicesManager.setMetadata(metadata, Specification.fromShortName(serviceType)); return Response.ok(); } catch (IOException ex) { return Response.error(ex.getLocalizedMessage()); } } /** * Update the WMS service constraint and contact. * * @param identifier the service identifier * @param contact the (new) service contact * @param constraint the (new) service constraint * @return a status {@link juzu.Response} * @throws java.io.IOException on communication error with Constellation server */ @Ajax @Resource @Route("service/metadata") public Response setServiceMetadata(final String serviceType, final String identifier, final Contact contact, final AccessConstraint constraint) throws IOException { final Service metadata = servicesManager.getMetadata(identifier, Specification.WMS); metadata.setServiceContact(contact); metadata.setServiceConstraints(constraint); try { servicesManager.setMetadata(metadata, Specification.fromShortName(serviceType)); return Response.ok(); } catch (IOException ex) { return Response.error(ex.getLocalizedMessage()); } } }