/* * gvNIX is an open source tool for rapid application development (RAD). * Copyright (C) 2010 Generalitat Valenciana * * 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.gvnix.addon.geo.addon; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.PrintWriter; import java.lang.reflect.Modifier; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Locale; import java.util.Map; import java.util.Map.Entry; import java.util.Set; import java.util.logging.Level; import java.util.logging.Logger; import org.apache.commons.io.IOUtils; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.Validate; import org.apache.felix.scr.annotations.Component; import org.apache.felix.scr.annotations.Reference; import org.apache.felix.scr.annotations.Service; import org.gvnix.addon.geo.addon.listeners.GeoDependencyListener; import org.gvnix.addon.geo.annotations.GvNIXGeoConversionService; import org.gvnix.addon.geo.annotations.GvNIXMapViewer; import org.gvnix.support.MessageBundleUtils; import org.gvnix.support.OperationUtils; import org.gvnix.support.WebProjectUtils; import org.gvnix.web.i18n.roo.addon.ValencianCatalanLanguage; import org.osgi.framework.InvalidSyntaxException; import org.osgi.framework.ServiceReference; import org.osgi.service.component.ComponentContext; import org.springframework.roo.addon.propfiles.PropFileOperations; import org.springframework.roo.addon.web.mvc.controller.annotations.converter.RooConversionService; import org.springframework.roo.addon.web.mvc.controller.annotations.scaffold.RooWebScaffold; import org.springframework.roo.addon.web.mvc.jsp.i18n.I18n; import org.springframework.roo.addon.web.mvc.jsp.i18n.I18nSupport; import org.springframework.roo.addon.web.mvc.jsp.i18n.languages.SpanishLanguage; import org.springframework.roo.addon.web.mvc.jsp.menu.MenuOperations; import org.springframework.roo.classpath.PhysicalTypeCategory; import org.springframework.roo.classpath.PhysicalTypeIdentifier; import org.springframework.roo.classpath.TypeLocationService; import org.springframework.roo.classpath.TypeManagementService; import org.springframework.roo.classpath.details.ClassOrInterfaceTypeDetails; import org.springframework.roo.classpath.details.ClassOrInterfaceTypeDetailsBuilder; import org.springframework.roo.classpath.details.FieldMetadata; import org.springframework.roo.classpath.details.MemberFindingUtils; import org.springframework.roo.classpath.details.annotations.AnnotationMetadata; import org.springframework.roo.classpath.details.annotations.AnnotationMetadataBuilder; import org.springframework.roo.classpath.details.annotations.ArrayAttributeValue; import org.springframework.roo.classpath.details.annotations.ClassAttributeValue; import org.springframework.roo.classpath.details.annotations.StringAttributeValue; import org.springframework.roo.classpath.operations.AbstractOperations; import org.springframework.roo.metadata.MetadataService; import org.springframework.roo.model.JavaPackage; import org.springframework.roo.model.JavaSymbolName; import org.springframework.roo.model.JavaType; import org.springframework.roo.model.JdkJavaType; import org.springframework.roo.model.SpringJavaType; import org.springframework.roo.process.manager.MutableFile; import org.springframework.roo.project.LogicalPath; import org.springframework.roo.project.Path; import org.springframework.roo.project.PathResolver; import org.springframework.roo.project.ProjectOperations; import org.springframework.roo.support.logging.HandlerUtils; import org.springframework.roo.support.util.FileUtils; import org.springframework.roo.support.util.XmlRoundTripUtils; import org.springframework.roo.support.util.XmlUtils; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.NamedNodeMap; import org.w3c.dom.Node; import org.w3c.dom.NodeList; /** * Implementation of GEO Addon operations * * @author <a href="http://www.disid.com">DISID Corporation S.L.</a> made for <a * href="http://www.dgti.gva.es">General Directorate for Information * Technologies (DGTI)</a> * @since 1.4 */ @Component @Service public class GeoOperationsImpl extends AbstractOperations implements GeoOperations { private static final Logger LOGGER = HandlerUtils .getLogger(GeoOperationsImpl.class); private static final String LABEL = "label"; private static final String INDEX_ATTR = "index"; private static final String SHOW = "show"; private static final String SHOW_VIEW = "WEB-INF/views/%s/show.jspx"; private static final String VALUE = "value"; private static final String ERR_N_TO_CREATE_NEW_MAP = "ERROR. Is necesary to create new map element using \"web mvc geo controller\" command before generate geo web layer"; private static final JavaType GVNIX_ENTITY_MAP_LAYER_ANNOTATION = new JavaType( "org.gvnix.addon.jpa.annotations.geo.providers.hibernatespatial.GvNIXEntityMapLayer"); private static final JavaType GVNIX_WEB_ENTITY_MAP_LAYER_ANNOTATION = new JavaType( "org.gvnix.addon.geo.annotations.GvNIXWebEntityMapLayer"); private static final JavaType ROO_WEB_SCAFFOLD_ANNOTATION = new JavaType( "org.springframework.roo.addon.web.mvc.controller.annotations.scaffold.RooWebScaffold"); private static final String WEBMCV_DATABINDER_BEAN_ID = "dataBinderRequestMappingHandlerAdapter"; private static final String JACKSON2_RM_HANDLER_ADAPTER = "org.gvnix.web.json.Jackson2RequestMappingHandlerAdapter"; private static final String OBJECT_MAPPER = "org.gvnix.web.json.ConversionServiceObjectMapper"; private ComponentContext cContext; private PathResolver pathResolver; private TypeLocationService typeLocationService; private MetadataService metadataService; private I18nSupport i18nSupport; private PropFileOperations propFileOperations; private ProjectOperations projectOperations; private MenuOperations menuOperations; private TypeManagementService typeManagementService; private WebProjectUtils webProjectUtils; private OperationUtils operationUtils; private MessageBundleUtils messageBundleUtils; private static final JavaType SCAFFOLD_ANNOTATION = new JavaType( RooWebScaffold.class.getName()); private static final JavaType CONVERSION_SERVICE_ANNOTATION = new JavaType( RooConversionService.class.getName()); private static final JavaType GEO_CONVERSION_SERVICE_ANNOTATION = new JavaType( GvNIXGeoConversionService.class.getName()); private static final JavaType MAP_VIEWER_ANNOTATION = new JavaType( GvNIXMapViewer.class.getName()); /** * Uses to ensure that dependencyListener will be loaded */ @Reference private GeoDependencyListener dependencyListener; protected void activate(final ComponentContext componentContext) { cContext = componentContext; context = cContext.getBundleContext(); } /** * This method checks if setup command is available * * @return true if setup command is available */ @Override public boolean isSetupCommandAvailable() { return getProjectOperations().isFeatureInstalledInFocusedModule( "gvnix-geo-persistence") && getProjectOperations().isFeatureInstalledInFocusedModule( "gvnix-jquery"); } /** * This method checks if add map command is available * * @return true if add map command is available */ @Override public boolean isMapCommandAvailable() { return isSetupCommandAvailable(); } /** * This method checks if web mvc geo all command is available * * @return true if web nvc geo all command is available */ @Override public boolean isAllCommandAvailable() { return isSetupCommandAvailable(); } /** * This method checks if web mvc geo add command is available * * @return true if web nvc geo add command is available */ @Override public boolean isAddCommandAvailable() { return isSetupCommandAvailable(); } @Override public boolean isFieldCommandAvailable() { return isSetupCommandAvailable(); } @Override public boolean isLayerCommandAvailable() { return isSetupCommandAvailable(); } @Override public boolean isToolCommandAvailable() { return isSetupCommandAvailable(); } /** * This method imports all necessary element to build a gvNIX GEO * application */ @Override public void setup() { // Adding project dependencies updatePomDependencies(); // Update web-mvc config updateWebMvcConfig(); // Locate all ApplicationConversionServiceFactoryBean and annotate it annotateApplicationConversionService(); // Installing all necessary components installComponents(); // Install Bootstrap if necessary if (getProjectOperations().isFeatureInstalledInFocusedModule( "gvnix-bootstrap")) { updateGeoAddonToBootstrap(); } } /** * This method adds all necessary components to display a map view */ @Override public void addMap(JavaType controller, JavaSymbolName path, ProjectionCRSTypes projection) { String filePackage = controller.getPackage() .getFullyQualifiedPackageName(); // Doing a previous setup to install necessary components and annotate // ApplicationConversionService if (!getProjectOperations().isFeatureInstalledInFocusedModule( FEATURE_NAME_GVNIX_GEO_WEB_MVC)) { setup(); } // Adding new controller with annotated class addMapViewerController(controller, path, projection); // Adding new show.jspx and views.xml createViews(filePackage, path, projection); // Add new component labels to application.properties addI18nComponentsProperties(); // Add new mapController view to application.properties addI18nControllerProperties(filePackage, path.getReadableSymbolName() .toLowerCase()); // Add new menu entry for this new map view String finalPath = path.getReadableSymbolName().toLowerCase(); getMenuOperations().addMenuItem( new JavaSymbolName("map_menu_category"), new JavaSymbolName(path.getReadableSymbolName() + "_map_menu_entry"), path.getReadableSymbolName(), "global_generic", "/" + finalPath, null, getWebappPath()); } /** * This method adds all GEO entities to all available maps or specific map */ @Override public void all(JavaSymbolName path) { // Checking if exists map element before to generate geo web layer if (!checkExistsMapElement()) { throw new RuntimeException(ERR_N_TO_CREATE_NEW_MAP); } List<String> paths = new ArrayList<String>(); // Checks if path is null or not. If is null, add all entities to all // available maps, if not, add all entities to specified map. if (path != null) { String pathList = path.toString(); String[] pathsToAdd = pathList.split(","); for (String currentPath : pathsToAdd) { currentPath = currentPath.replaceAll("/", "").trim(); // Getting map controller ClassOrInterfaceTypeDetails mapController = GeoUtils .getMapControllerByPath(getTypeLocationService(), currentPath); // If mapController is null show an error Validate.notNull( mapController, String.format( "Controller annotated with @GvNIXMapViewer and with path \"%s\" doesn't found. Use \"web mvc geo controller\" to generate new map view.", currentPath)); paths.add(currentPath); } } else { // If path is null, entity will be added to all maps paths.add(""); } // Looking for entities with GEO components and annotate his // controllers annotateAllGeoEntityControllers(paths); } /** * This method adds specific GEO entities to all available maps or specific * map */ @Override public void add(JavaType controller, JavaSymbolName path) { // Checking if exists map element before to generate geo web layer if (!checkExistsMapElement()) { throw new RuntimeException(ERR_N_TO_CREATE_NEW_MAP); } Validate.notNull(controller, "Controller is necessary to execute this operation"); // Checking that the specified controller is a valid controller ClassOrInterfaceTypeDetails controllerDetails = getTypeLocationService() .getTypeDetails(controller); // Getting scaffold annotation AnnotationMetadata scaffoldAnnotation = controllerDetails .getAnnotation(ROO_WEB_SCAFFOLD_ANNOTATION); Validate.notNull( scaffoldAnnotation, String.format( "%s is not a valid controller. Controller must be annotated with @RooWebScaffold", controller.getFullyQualifiedTypeName())); // Check if is valid GEO Entity boolean isValidEntity = GeoUtils.isGeoEntity(scaffoldAnnotation, getTypeLocationService()); Validate.isTrue(isValidEntity, String .format("Specified entity \"%s\" has not GEO fields", scaffoldAnnotation.getAttribute("formBackingObject") .getValue())); // Checking if entity has geo finder JavaType entity = (JavaType) scaffoldAnnotation.getAttribute( new JavaSymbolName("formBackingObject")).getValue(); ClassOrInterfaceTypeDetails entityDetails = getTypeLocationService() .getTypeDetails(entity); AnnotationMetadata gvNIXEntityMapLayerAnnotation = entityDetails .getAnnotation(GVNIX_ENTITY_MAP_LAYER_ANNOTATION); Validate.notNull( gvNIXEntityMapLayerAnnotation, String.format( "Specified entity \"%s\" is not annotated with @GvNIXEntityMapLayer. Use \"finder geo add\" command to generate necessary methods", entity.getSimpleTypeName())); List<String> paths = new ArrayList<String>(); // Add annotation to controller if (path != null) { String pathList = path.toString(); String[] pathsToAdd = pathList.split(","); for (String currentPath : pathsToAdd) { currentPath = currentPath.replaceAll("/", "").trim(); // Getting map controller ClassOrInterfaceTypeDetails mapController = GeoUtils .getMapControllerByPath(getTypeLocationService(), currentPath); // If mapController is null show an error Validate.notNull( mapController, String.format( "Controller annotated with @GvNIXMapViewer doesn't found. Use \"web mvc geo controller\" to generate new map view.", currentPath)); paths.add(currentPath); } } else { // If path is null, entity will be added to all maps paths.add(""); } annotateGeoEntityController(controller, paths); } /** * This method transform an input element to map controller on CRU views * * @param controller * @param fieldName * @param color * @param weight * @param center * @param zoom * @param maxZoom */ @Override public void field(JavaType controller, JavaSymbolName fieldName, String color, String weight, String center, String zoom, String maxZoom) { // Doing a previous setup to install necessary components and annotate // ApplicationConversionService if (!getProjectOperations().isFeatureInstalledInFocusedModule( FEATURE_NAME_GVNIX_GEO_WEB_MVC)) { setup(); } Validate.notNull(controller, "Valid controller is necessary"); // Getting controller Details ClassOrInterfaceTypeDetails controllerDetails = getTypeLocationService() .getTypeDetails(controller); // Getting roo web scaffold annotation AnnotationMetadata rooWebScaffoldAnnotation = controllerDetails .getAnnotation(ROO_WEB_SCAFFOLD_ANNOTATION); Validate.notNull( rooWebScaffoldAnnotation, "Controller annotated with @RooWebScaffold is necessary. Generate controller for your entity using 'web mvc scaffold'"); // Getting @RequestMapping annotation AnnotationMetadata requestMappingAnnotation = controllerDetails .getAnnotation(SpringJavaType.REQUEST_MAPPING); Validate.notNull( requestMappingAnnotation, "Controller annotated with @RequestMapping is necessary. Generate controller for your entity using 'web mvc scaffold'"); // Getting path String path = requestMappingAnnotation.getAttribute(VALUE).getValue() .toString(); // Getting entity JavaType relatedEntity = (JavaType) rooWebScaffoldAnnotation .getAttribute("formBackingObject").getValue(); // Checking if current entity has Geo fields Validate.isTrue(GeoUtils.isGeoEntity(rooWebScaffoldAnnotation, getTypeLocationService()), String.format( "Current entity '%s' doesn't have GEO fields.", relatedEntity.getSimpleTypeName())); // Getting entity details ClassOrInterfaceTypeDetails entityDetails = getTypeLocationService() .getTypeDetails(relatedEntity); // Getting declared fields FieldMetadata field = entityDetails.getDeclaredField(fieldName); Validate.notNull(field, String.format( "Field '%s' not exists on entity '%s'", fieldName, relatedEntity.getSimpleTypeName())); // Getting field type to get package JavaType fieldType = field.getFieldType(); JavaPackage fieldPackage = fieldType.getPackage(); boolean isGeoField = fieldPackage.toString().equals( "com.vividsolutions.jts.geom"); Validate.isTrue(isGeoField, String.format( "Current field '%s' is not a valid GEO field", fieldName)); // Getting create.jspx final String createPath = getPathResolver().getFocusedIdentifier( Path.SRC_MAIN_WEBAPP, String.format("WEB-INF/views/%s/create.jspx", path)); // Getting update.jspx final String updatePath = getPathResolver().getFocusedIdentifier( Path.SRC_MAIN_WEBAPP, String.format("WEB-INF/views/%s/update.jspx", path)); // Getting show.jspx final String showPath = getPathResolver().getFocusedIdentifier( Path.SRC_MAIN_WEBAPP, String.format(SHOW_VIEW, path)); updateCRU(path, createPath, fieldName, fieldType, color, weight, center, zoom, maxZoom, "create"); updateCRU(path, updatePath, fieldName, fieldType, color, weight, center, zoom, maxZoom, "update"); updateCRU(path, showPath, fieldName, fieldType, color, weight, center, zoom, maxZoom, SHOW); } /** * This method add new base tile layers on selected map * * @param name * @param url * @param path * @param index * @param opacity */ @Override public void tileLayer(String name, String url, JavaSymbolName path, String index, String opacity) { // Checking if exists map element before to generate geo tile layer if (!checkExistsMapElement()) { throw new RuntimeException(ERR_N_TO_CREATE_NEW_MAP); } // Creating map with params to send Map<String, String> tileLayerAttr = new HashMap<String, String>(); tileLayerAttr.put(INDEX_ATTR, index); tileLayerAttr.put("url", url); tileLayerAttr.put("opacity", opacity); name = name.replaceAll(" ", "_"); createBaseLayer(name, tileLayerAttr, path, "tile"); } /** * * This method add new base wms layers on selected map * * @param name * @param url * @param path * @param index * @param opacity * @param layers * @param format * @param transparent * @param styles * @param version * @param crs */ @Override public void wmsLayer(String name, String url, JavaSymbolName path, String index, String opacity, String layers, String format, boolean transparent, String styles, String version, String crs) { // Checking if exists map element before to generate geo tile layer if (!checkExistsMapElement()) { throw new RuntimeException(ERR_N_TO_CREATE_NEW_MAP); } // Creating map with params to send Map<String, String> wmsLayerAttr = new HashMap<String, String>(); wmsLayerAttr.put(INDEX_ATTR, index); wmsLayerAttr.put("url", url); wmsLayerAttr.put("opacity", opacity); wmsLayerAttr.put("layers", layers); wmsLayerAttr.put("format", format); wmsLayerAttr.put("transparent", transparent ? "true" : "false"); wmsLayerAttr.put("styles", styles); wmsLayerAttr.put("version", version); wmsLayerAttr.put("crs", crs); name = name.replaceAll(" ", "_"); createBaseLayer(name, wmsLayerAttr, path, "wms"); } /** * * This method add new measure tool on selected map * * @param name * @param path * @param preventExitMessageCode */ @Override public void addMeasureTool(String name, JavaSymbolName path, String preventExitMessageCode) { // Checking if exists map element before to generate geo tool if (!checkExistsMapElement()) { throw new RuntimeException(ERR_N_TO_CREATE_NEW_MAP); } // Creating map with params to send Map<String, String> toolAttr = new HashMap<String, String>(); toolAttr.put("preventExitMessage", preventExitMessageCode); createTool(name, toolAttr, path, "measure"); } /** * * This method add new custom tool on selected map * * @param name * @param path * @param preventExitMessageCode */ @Override public void addCustomTool(String name, JavaSymbolName path, String preventExitMessageCode, String icon, String iconLibrary, boolean actionTool, String activateFunction, String deactivateFunction, String cursorIcon) { // Checking if exists map element before to generate geo tool if (!checkExistsMapElement()) { throw new RuntimeException(ERR_N_TO_CREATE_NEW_MAP); } // Creating map with params to send Map<String, String> toolAttr = new HashMap<String, String>(); toolAttr.put("preventExitMessage", preventExitMessageCode); toolAttr.put("icon", icon); toolAttr.put("iconLibrary", iconLibrary); toolAttr.put("actionTool", actionTool ? "true" : "false"); toolAttr.put("activateFunction", activateFunction); toolAttr.put("deactivateFunction", deactivateFunction); toolAttr.put("cursorIcon", cursorIcon); createTool(name, toolAttr, path, "custom"); LOGGER.log( Level.INFO, String.format( "**NOTE: Remember that you need to create %s and %s JavaScript functions with your custom tool implementation.", activateFunction, deactivateFunction)); } /** * This method generate a Map with map path and new tool id * * @param toolAttr * @param path * @param string */ private void createTool(String name, Map<String, String> toolAttr, JavaSymbolName path, String type) { String mapId = ""; // Adding id base layer to application.properties Map<String, String> propertyList = new HashMap<String, String>(); // Getting paths to add base layer Map<String, String> pathsMap = new HashMap<String, String>(); Set<ClassOrInterfaceTypeDetails> controllerDetails = getTypeLocationService() .findClassesOrInterfaceDetailsWithAnnotation( MAP_VIEWER_ANNOTATION); for (ClassOrInterfaceTypeDetails controller : controllerDetails) { String controllerPath = (String) controller .getAnnotation(SpringJavaType.REQUEST_MAPPING) .getAttribute(VALUE).getValue(); if (path != null) { if (controllerPath.replaceAll("/", "").equals( path.getSymbolName())) { // Getting mapId mapId = String.format("ps_%s_%s", controller.getType() .getPackage().getFullyQualifiedPackageName() .replaceAll("[.]", "_"), new JavaSymbolName(path .getSymbolName().replaceAll("/", "")) .getSymbolNameCapitalisedFirstLetter()); pathsMap.put(path.getSymbolName(), mapId + "_" + name); // Add to application.properties propertyList.put(LABEL + mapId.substring(2).toLowerCase() + "_" + name, name); } } else { // Getting mapId mapId = String.format("ps_%s_%s", controller.getType() .getPackage().getFullyQualifiedPackageName() .replaceAll("[.]", "_"), new JavaSymbolName( controllerPath.replaceAll("/", "")) .getSymbolNameCapitalisedFirstLetter()); pathsMap.put(controllerPath.replaceAll("/", ""), mapId + "_" + name); // Add to application.properties propertyList.put(LABEL + mapId.substring(2).toLowerCase() + "_" + name, name); } } addToolToMaps(name, pathsMap, toolAttr, type); getPropFileOperations().addProperties(getWebappPath(), "WEB-INF/i18n/application.properties", propertyList, true, false); } /** * * This method uses id map and id base layer to generate new base layer * using baseLayerAttr * * @param name * @param pathsMap * @param toolAttr * @param type */ private void addToolToMaps(String name, Map<String, String> pathsMap, Map<String, String> toolAttr, String type) { boolean exists = false; // Getting all maps for (Entry mapPath : pathsMap.entrySet()) { String viewPath = getPathResolver().getFocusedIdentifier( Path.SRC_MAIN_WEBAPP, String.format(SHOW_VIEW, mapPath.getKey())); if (fileManager.exists(viewPath)) { Document docXml = getWebProjectUtils().loadXmlDocument( viewPath, fileManager); // Getting current tools Element docRoot = docXml.getDocumentElement(); NodeList tools = docRoot.getElementsByTagName("tool:" + type); // If exists tools, check if current name exists if (tools.getLength() > 0) { for (int i = 0; i < tools.getLength(); i++) { Node tool = tools.item(i); NamedNodeMap currentToolAttr = tool.getAttributes(); if (currentToolAttr.getNamedItem("id") != null) { String id = currentToolAttr.getNamedItem("id") .getNodeValue().toString(); String newId = (String) mapPath.getValue(); if (id.equals(newId)) { LOGGER.log(Level.INFO, String.format( "Tool %s exists on '%s'", type, viewPath)); exists = true; break; } } } } // If not exists, add tool if (!exists) { // If not existstool, create new one Element tool = docXml.createElement("tool:" + type); tool.setAttribute("id", (String) mapPath.getValue()); for (Entry attr : toolAttr.entrySet()) { String key = (String) attr.getKey(); String value = (String) attr.getValue(); if (StringUtils.isNotBlank(value)) { tool.setAttribute(key, value); } } // Generating z attr tool.setAttribute("z", XmlRoundTripUtils.calculateUniqueKeyFor(tool)); Node toolbarElement = docRoot.getElementsByTagName( "geo:toolbar").item(0); toolbarElement.appendChild(tool); fileManager.createOrUpdateTextFileIfRequired(viewPath, XmlUtils.nodeToString(docXml), true); } } else { throw new RuntimeException(String.format( " Error getting 'WEB-INF/views/%s/show.jspx' view", mapPath.getKey())); } } } /** * * This method generate a Map with map path and new base layer id * * @param name * @param baseLayerAttr * @param path * @param type */ private void createBaseLayer(String name, Map<String, String> baseLayerAttr, JavaSymbolName path, String type) { String mapId = ""; // Adding id base layer to application.properties Map<String, String> propertyList = new HashMap<String, String>(); // Getting paths to add base layer Map<String, String> pathsMap = new HashMap<String, String>(); Set<ClassOrInterfaceTypeDetails> controllerDetails = getTypeLocationService() .findClassesOrInterfaceDetailsWithAnnotation( MAP_VIEWER_ANNOTATION); for (ClassOrInterfaceTypeDetails controller : controllerDetails) { String controllerPath = (String) controller .getAnnotation(SpringJavaType.REQUEST_MAPPING) .getAttribute(VALUE).getValue(); if (path != null) { if (controllerPath.replaceAll("/", "").equals( path.getSymbolName())) { // Getting mapId mapId = String.format("ps_%s_%s", controller.getType() .getPackage().getFullyQualifiedPackageName() .replaceAll("[.]", "_"), new JavaSymbolName(path .getSymbolName().replaceAll("/", "")) .getSymbolNameCapitalisedFirstLetter()); pathsMap.put(path.getSymbolName(), mapId + "_" + name); // Add to application.properties propertyList.put(LABEL + mapId.substring(2).toLowerCase() + "_" + name, name); } } else { // Getting mapId mapId = String.format("ps_%s_%s", controller.getType() .getPackage().getFullyQualifiedPackageName() .replaceAll("[.]", "_"), new JavaSymbolName( controllerPath.replaceAll("/", "")) .getSymbolNameCapitalisedFirstLetter()); pathsMap.put(controllerPath.replaceAll("/", ""), mapId + "_" + name); // Add to application.properties propertyList.put(LABEL + mapId.substring(2).toLowerCase() + "_" + name, name); } } addBaseLayerToMaps(name, pathsMap, baseLayerAttr, type); getPropFileOperations().addProperties(getWebappPath(), "WEB-INF/i18n/application.properties", propertyList, true, false); } /** * * This method uses id map and id base layer to generate new base layer * using baseLayerAttr * * @param name * @param pathsMap * @param baseLayerAttr * @param type */ private void addBaseLayerToMaps(String name, Map<String, String> pathsMap, Map<String, String> baseLayerAttr, String type) { boolean exists = false; // Getting all maps for (Entry mapPath : pathsMap.entrySet()) { String viewPath = getPathResolver().getFocusedIdentifier( Path.SRC_MAIN_WEBAPP, String.format(SHOW_VIEW, mapPath.getKey())); if (fileManager.exists(viewPath)) { Document docXml = getWebProjectUtils().loadXmlDocument( viewPath, fileManager); // Getting current base layers Element docRoot = docXml.getDocumentElement(); NodeList baseLayers = docRoot.getElementsByTagName("layer:" + type); // If exists baselayers, check if current name exists if (baseLayers.getLength() > 0) { for (int i = 0; i < baseLayers.getLength(); i++) { Node baseLayer = baseLayers.item(i); NamedNodeMap currentBaseLayerAttr = baseLayer .getAttributes(); if (currentBaseLayerAttr.getNamedItem("id") != null) { String id = currentBaseLayerAttr.getNamedItem("id") .getNodeValue().toString(); String newId = (String) mapPath.getValue(); if (id.equals(newId)) { LOGGER.log(Level.INFO, String.format( "Base %s layer exists on '%s'", type, viewPath)); exists = true; break; } } } } // If not exists, add new base layer if (!exists) { // If not exists base layers, create new one Element baseLayer = docXml.createElement("layer:" + type); baseLayer.setAttribute("id", (String) mapPath.getValue()); for (Entry attr : baseLayerAttr.entrySet()) { String key = (String) attr.getKey(); String value = (String) attr.getValue(); if (StringUtils.isNotBlank(value)) { baseLayer.setAttribute(key, value); } } // Checks if exists index if (StringUtils.isBlank(baseLayer.getAttribute(INDEX_ATTR))) { baseLayer.setAttribute(INDEX_ATTR, Integer .toString(getNewBaseLayerPosition(docRoot))); } // Generating z attr baseLayer.setAttribute("z", XmlRoundTripUtils.calculateUniqueKeyFor(baseLayer)); Node tocElement = docRoot.getElementsByTagName("geo:toc") .item(0); tocElement.appendChild(baseLayer); fileManager.createOrUpdateTextFileIfRequired(viewPath, XmlUtils.nodeToString(docXml), true); } } else { throw new RuntimeException(String.format( " Error getting 'WEB-INF/views/%s/show.jspx' view", mapPath.getKey())); } } } /** * Method to update JSPX CRU views with map controls * * @param path * @param fieldName * @param fieldType * @param color * @param weight * @param center * @param zoom * @param maxZoom * @param type */ private void updateCRU(String path, String viewPath, JavaSymbolName fieldName, JavaType fieldType, String color, String weight, String center, String zoom, String maxZoom, String type) { Map<String, String> uriMap = new HashMap<String, String>(1); uriMap.put("xmlns:geofield", "urn:jsptagdir:/WEB-INF/tags/geo/form/fields"); getWebProjectUtils().addTagxUriInJspx(path, type, uriMap, getProjectOperations(), fileManager); // Updating file if (fileManager.exists(viewPath)) { Document createDoc = getWebProjectUtils().loadXmlDocument(viewPath, fileManager); Element docRoot = createDoc.getDocumentElement(); // Getting createForm element Node form = null; if (type.equals("create")) { form = docRoot.getElementsByTagName("form:create").item(0); } else if (type.equals("update")) { form = docRoot.getElementsByTagName("form:update").item(0); } else if (type.equals(SHOW)) { form = docRoot.getElementsByTagName("page:show").item(0); } // Getting all input elements NodeList inputs = null; if (type.equals("create") || type.equals("update")) { inputs = docRoot.getElementsByTagName("field:input"); } else { inputs = docRoot.getElementsByTagName("field:display"); } for (int i = 0; i < inputs.getLength(); i++) { Node input = inputs.item(i); NamedNodeMap inputAttr = input.getAttributes(); Node attr = inputAttr.getNamedItem("field"); // If field equals current field if (attr != null && attr.getNodeValue().equals(fieldName.toString())) { // Save id attribute Node idAttr = inputAttr.getNamedItem("id"); // Create element depens of type Element mapControl = null; if (type.equals(SHOW)) { mapControl = createDoc .createElement("geofield:map-display"); } else if (fieldType.equals(new JavaType( "com.vividsolutions.jts.geom.Point"))) { mapControl = createDoc .createElement("geofield:map-point"); } else if (fieldType.equals(new JavaType( "com.vividsolutions.jts.geom.LineString"))) { mapControl = createDoc .createElement("geofield:map-line"); if (StringUtils.isNotBlank(color)) { mapControl.setAttribute("color", color); } if (StringUtils.isNotBlank(weight)) { mapControl.setAttribute("weight", weight); } } else if (fieldType.equals(new JavaType( "com.vividsolutions.jts.geom.Polygon")) || fieldType.equals(new JavaType( "com.vividsolutions.jts.geom.Geometry"))) { mapControl = createDoc .createElement("geofield:map-polygon"); if (StringUtils.isNotBlank(color)) { mapControl.setAttribute("color", color); } if (StringUtils.isNotBlank(weight)) { mapControl.setAttribute("weight", weight); } } else if (fieldType.equals(new JavaType( "com.vividsolutions.jts.geom.MultiLineString"))) { mapControl = createDoc .createElement("geofield:map-multiline"); if (StringUtils.isNotBlank(color)) { mapControl.setAttribute("color", color); } if (StringUtils.isNotBlank(weight)) { mapControl.setAttribute("weight", weight); } } else { throw new RuntimeException(String.format( "Cannot convert field type %s to map control", fieldType)); } // Adding general attributes mapControl.setAttribute("field", fieldName.toString()); if (StringUtils.isNotBlank(center)) { String validCenter = "[" + center + "]"; mapControl.setAttribute("center", validCenter); } if (StringUtils.isNotBlank(zoom)) { mapControl.setAttribute("zoom", zoom); } if (StringUtils.isNotBlank(maxZoom)) { mapControl.setAttribute("maxZoom", maxZoom); } // Adding saved attr mapControl.setAttribute("id", idAttr.getNodeValue()); // Adding object if (type.equals(SHOW)) { mapControl.setAttribute("object", inputAttr .getNamedItem("object").getNodeValue()); } mapControl.setAttribute("z", "user-managed"); // Remove input geo field form.removeChild(input); // Add new element form.appendChild(mapControl); fileManager.createOrUpdateTextFileIfRequired(viewPath, XmlUtils.nodeToString(createDoc), true); break; } } } } /** * This method annotate controller with @GvNIXEntityMapLayer * * @param controller * @param paths */ public void annotateGeoEntityController(JavaType controller, List<String> paths) { // Obtain all map controllers List<JavaType> mapControllers = GeoUtils .getAllMapsControllers(getTypeLocationService()); ClassOrInterfaceTypeDetails controllerDetails = getTypeLocationService() .getTypeDetails(controller); // Generating annotation ClassOrInterfaceTypeDetailsBuilder detailsBuilder = new ClassOrInterfaceTypeDetailsBuilder( controllerDetails); AnnotationMetadataBuilder annotationBuilder = new AnnotationMetadataBuilder( GVNIX_WEB_ENTITY_MAP_LAYER_ANNOTATION); // Add annotation to target type detailsBuilder.updateTypeAnnotation(annotationBuilder.build()); // Save changes to disk getTypeManagementService().createOrUpdateTypeOnDisk( detailsBuilder.build()); // / Update necessary map controllers with current entity // If developer specify map path add on it if (!(paths.size() == 1 && paths.get(0).equals(""))) { Iterator<String> pathIterator = paths.iterator(); while (pathIterator.hasNext()) { // Getting path String currentPath = pathIterator.next(); // Getting map controller for current path JavaType mapController = GeoUtils.getMapControllerByPath( currentPath, getTypeLocationService()); // Annotate map controllers adding current entity annotateMapController(mapController, getTypeLocationService(), getTypeManagementService(), controllerDetails.getType()); } } else { // If no path selected, annotate all mapControllers with // current entityController for (JavaType mapController : mapControllers) { // Annotate map controllers adding current entity annotateMapController(mapController, getTypeLocationService(), getTypeManagementService(), controllerDetails.getType()); } } } /** * This method annotate all controllers if has Geo Fields * * @param path */ public void annotateAllGeoEntityControllers(List<String> paths) { // Getting all entity controllers annotated with @RooWebScaffold Set<ClassOrInterfaceTypeDetails> entityControllers = getTypeLocationService() .findClassesOrInterfaceDetailsWithAnnotation( ROO_WEB_SCAFFOLD_ANNOTATION); Validate.notNull(entityControllers, "Controllers with @RooWebScaffold annotation doesn't found"); // Obtain all map controllers List<JavaType> mapControllers = GeoUtils .getAllMapsControllers(getTypeLocationService()); Iterator<ClassOrInterfaceTypeDetails> it = entityControllers.iterator(); while (it.hasNext()) { ClassOrInterfaceTypeDetails entityController = it.next(); // Getting scaffold annotation AnnotationMetadata scaffoldAnnotation = entityController .getAnnotation(ROO_WEB_SCAFFOLD_ANNOTATION); // Getting entity asociated Object entity = scaffoldAnnotation .getAttribute("formBackingObject").getValue(); ClassOrInterfaceTypeDetails entityDetails = getTypeLocationService() .getTypeDetails((JavaType) entity); // Checking if geo finders are added to entity AnnotationMetadata gvNIXEntityMapLayerAnnotation = entityDetails .getAnnotation(GVNIX_ENTITY_MAP_LAYER_ANNOTATION); if (gvNIXEntityMapLayerAnnotation != null) { // Getting all fields of current entity List<? extends FieldMetadata> entityFields = entityDetails .getDeclaredFields(); Iterator<? extends FieldMetadata> fieldsIterator = entityFields .iterator(); while (fieldsIterator.hasNext()) { // Getting field FieldMetadata field = fieldsIterator.next(); // Getting field type to get package JavaType fieldType = field.getFieldType(); JavaPackage fieldPackage = fieldType.getPackage(); // If has jts field, annotate controller if (fieldPackage.toString().equals( "com.vividsolutions.jts.geom")) { // Generating annotation ClassOrInterfaceTypeDetailsBuilder detailsBuilder = new ClassOrInterfaceTypeDetailsBuilder( entityController); AnnotationMetadataBuilder annotationBuilder = new AnnotationMetadataBuilder( GVNIX_WEB_ENTITY_MAP_LAYER_ANNOTATION); // Add annotation to target type detailsBuilder.updateTypeAnnotation(annotationBuilder .build()); // Save changes to disk getTypeManagementService().createOrUpdateTypeOnDisk( detailsBuilder.build()); // Update necessary map controllers with current entity // If developer specify map path add on it if (!(paths.size() == 1 && paths.get(0).equals(""))) { Iterator<String> pathIterator = paths.iterator(); while (pathIterator.hasNext()) { // Getting path String currentPath = pathIterator.next(); // Getting map controller for current path JavaType mapController = GeoUtils .getMapControllerByPath(currentPath, getTypeLocationService()); // Annotate map controllers adding current // entity annotateMapController(mapController, getTypeLocationService(), getTypeManagementService(), entityController.getType()); } } else { // If no path selected, annotate all mapControllers // with // current entityController for (JavaType mapController : mapControllers) { // Annotate map controllers adding current // entity annotateMapController(mapController, getTypeLocationService(), getTypeManagementService(), entityController.getType()); } } break; } } } } } /** * This method create necessary views to visualize map * * @param path */ public void createViews(String controllerPackage, JavaSymbolName path, ProjectionCRSTypes projection) { PathResolver pathResolver = getProjectOperations().getPathResolver(); String finalPath = path.getReadableSymbolName().toLowerCase(); // Modifying views.xml to add show.jspx view final String viewsPath = pathResolver.getFocusedIdentifier( Path.SRC_MAIN_WEBAPP, String.format("WEB-INF/views/%s/views.xml", finalPath)); final String showPath = getPathResolver().getFocusedIdentifier( Path.SRC_MAIN_WEBAPP, String.format(SHOW_VIEW, finalPath)); // Copying views.xml if (!fileManager.exists(viewsPath)) { InputStream inputStream = null; OutputStream outputStream = null; try { inputStream = FileUtils.getInputStream(getClass(), "views/views.xml"); outputStream = fileManager.createFile(viewsPath) .getOutputStream(); // Doing this to solve problems with <!DOCTYPE element // //////////////////////////////////////////////// PrintWriter writer = new PrintWriter(outputStream); writer.println("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>"); writer.println("<!DOCTYPE tiles-definitions PUBLIC \"-//Apache Software Foundation//DTD Tiles Configuration 2.1//EN\" \"http://tiles.apache.org/dtds/tiles-config_2_1.dtd\">"); writer.println("<tiles-definitions>"); // Depens of Bootstrap change extends layout if (getProjectOperations().isFeatureInstalledInFocusedModule( "gvnix-bootstrap")) { writer.println(String .format(" <definition extends=\"default-map\" name=\"%s/show\">", finalPath)); } else { writer.println(String .format(" <definition extends=\"default\" name=\"%s/show\">", finalPath)); } writer.println(String .format(" <put-attribute name=\"body\" value=\"/WEB-INF/views/%s/show.jspx\"/>", finalPath)); writer.println(" </definition>"); writer.println("</tiles-definitions>"); writer.flush(); writer.close(); // //////////////////////////////////////////// IOUtils.copy(inputStream, outputStream); } catch (final IOException ioe) { throw new IllegalStateException(ioe); } finally { IOUtils.closeQuietly(inputStream); IOUtils.closeQuietly(outputStream); } } // Copying show.jspx if (!fileManager.exists(showPath)) { InputStream inputStream = null; OutputStream outputStream = null; try { inputStream = FileUtils.getInputStream(getClass(), "views/show.jspx"); outputStream = fileManager.createFile(showPath) .getOutputStream(); IOUtils.copy(inputStream, outputStream); } catch (final IOException ioe) { throw new IllegalStateException(ioe); } finally { IOUtils.closeQuietly(inputStream); IOUtils.closeQuietly(outputStream); } } // If show.jspx file doesn't exists, show an error if (!fileManager.exists(showPath)) { throw new RuntimeException(String.format( "ERROR. Not exists show.jspx file on 'views/%s' folder", finalPath)); } else { // Getting document and adding definition Document docXml = getWebProjectUtils().loadXmlDocument(showPath, fileManager); Element docRoot = docXml.getDocumentElement(); // Creating geo:map element String mapId = String.format("ps_%s_%s", controllerPackage.replaceAll("[.]", "_"), path.getSymbolNameCapitalisedFirstLetter()); Element map = docXml.createElement("geo:map"); map.setAttribute("id", mapId); map.setAttribute("projection", projection != null ? projection.toString() : "EPSG3857"); map.setAttribute("z", XmlRoundTripUtils.calculateUniqueKeyFor(map)); // Creating geo:toc element and adding to map Element toc = docXml.createElement("geo:toc"); toc.setAttribute("id", String.format("%s_toc", mapId)); toc.setAttribute("z", XmlRoundTripUtils.calculateUniqueKeyFor(toc)); map.appendChild(toc); // Creating geo:toolbar element and adding to map Element toolbar = docXml.createElement("geo:toolbar"); toolbar.setAttribute("id", String.format("%s_toolbar", mapId)); toolbar.setAttribute("z", XmlRoundTripUtils.calculateUniqueKeyFor(toolbar)); map.appendChild(toolbar); // Adding childs to mainDiv docRoot.appendChild(map); fileManager.createOrUpdateTextFileIfRequired(showPath, XmlUtils.nodeToString(docXml), true); } } /** * This method generates a new class annotated with @GvNIXMapViewer * * @param controller * @param path */ public void addMapViewerController(JavaType controller, JavaSymbolName path, ProjectionCRSTypes projection) { // Getting all classes with @GvNIXMapViewer annotation // and checking that not exists another with the specified path for (JavaType mapViewer : getTypeLocationService() .findTypesWithAnnotation(MAP_VIEWER_ANNOTATION)) { Validate.notNull(mapViewer, "@GvNIXMapViewer required"); ClassOrInterfaceTypeDetails mapViewerController = getTypeLocationService() .getTypeDetails(mapViewer); // Getting RequestMapping annotations final AnnotationMetadata requestMappingAnnotation = MemberFindingUtils .getAnnotationOfType(mapViewerController.getAnnotations(), SpringJavaType.REQUEST_MAPPING); Validate.notNull(mapViewer, String.format( "Error on %s getting @RequestMapping value", mapViewer)); String requestMappingPath = requestMappingAnnotation .getAttribute(VALUE).getValue().toString(); // If exists some path like the selected, shows an error String finalPath = String.format("/%s", path.toString()); if (finalPath.equals(requestMappingPath)) { throw new RuntimeException( String.format( "ERROR. There's other class annotated with @GvNIXMapViewer and path \"%s\"", finalPath)); } } // Create new class createNewController(controller, generateJavaType(controller), path, projection); } /** * This method creates a controller using specified configuration * * @param controller * @param target * @param path */ public void createNewController(JavaType controller, JavaType target, JavaSymbolName path, ProjectionCRSTypes projection) { Validate.notNull(controller, "Entity required"); if (target == null) { target = generateJavaType(controller); } Validate.isTrue( !JdkJavaType.isPartOfJavaLang(target.getSimpleTypeName()), "Target name '%s' must not be part of java.lang", target.getSimpleTypeName()); int modifier = Modifier.PUBLIC; final String declaredByMetadataId = PhysicalTypeIdentifier .createIdentifier(target, getPathResolver().getFocusedPath(Path.SRC_MAIN_JAVA)); File targetFile = new File(getTypeLocationService() .getPhysicalTypeCanonicalPath(declaredByMetadataId)); Validate.isTrue(!targetFile.exists(), "Type '%s' already exists", target); // Prepare class builder final ClassOrInterfaceTypeDetailsBuilder cidBuilder = new ClassOrInterfaceTypeDetailsBuilder( declaredByMetadataId, modifier, target, PhysicalTypeCategory.CLASS); // Prepare annotations array List<AnnotationMetadataBuilder> annotations = new ArrayList<AnnotationMetadataBuilder>( 2); // Add @Controller annotations annotations .add(new AnnotationMetadataBuilder(SpringJavaType.CONTROLLER)); // Add @RequestMapping annotation AnnotationMetadataBuilder requestMappingAnnotation = new AnnotationMetadataBuilder( SpringJavaType.REQUEST_MAPPING); requestMappingAnnotation.addStringAttribute(VALUE, String.format("/%s", path.toString())); annotations.add(requestMappingAnnotation); // Add @GvNIXMapViewer annotation with list of all entities annotated // with @GvNIXEntityMapLayer AnnotationMetadataBuilder mapViewerAnnotation = new AnnotationMetadataBuilder( MAP_VIEWER_ANNOTATION); // Generating empty class attribute value final List<ClassAttributeValue> entityAttributes = new ArrayList<ClassAttributeValue>(); // Looking for all entities annotated with @GvNIXEntityMapLayer for (ClassOrInterfaceTypeDetails entity : getTypeLocationService() .findClassesOrInterfaceDetailsWithAnnotation( GVNIX_WEB_ENTITY_MAP_LAYER_ANNOTATION)) { // Getting map layer annotation AnnotationMetadata mapLayerAnnotation = entity .getAnnotation(GVNIX_WEB_ENTITY_MAP_LAYER_ANNOTATION); // Getting maps where will be displayed @SuppressWarnings({ "unchecked", "rawtypes" }) ArrayAttributeValue<StringAttributeValue> mapLayerAttributes = (ArrayAttributeValue) mapLayerAnnotation .getAttribute("maps"); boolean addEntityToMap = false; if (mapLayerAttributes == null) { addEntityToMap = true; } else { List<StringAttributeValue> mapLayerAttributesValues = mapLayerAttributes .getValue(); for (StringAttributeValue map : mapLayerAttributesValues) { if (map.getValue() == path.toString()) { addEntityToMap = true; break; } } } if (addEntityToMap) { final ClassAttributeValue entityAttribute = new ClassAttributeValue( new JavaSymbolName(VALUE), entity.getType()); entityAttributes.add(entityAttribute); } } // Create "entityLayers" attributes array from string attributes // list ArrayAttributeValue<ClassAttributeValue> entityLayersArray = new ArrayAttributeValue<ClassAttributeValue>( new JavaSymbolName("entityLayers"), entityAttributes); // Adding controller class list to MapViewer Controller mapViewerAnnotation.addAttribute(entityLayersArray); // Adding projection to MapViewer annotation StringAttributeValue projectionAttribute = new StringAttributeValue( new JavaSymbolName("projection"), projection != null ? projection.toString() : "EPSG3857"); mapViewerAnnotation.addAttribute(projectionAttribute); annotations.add(mapViewerAnnotation); // Set annotations cidBuilder.setAnnotations(annotations); getTypeManagementService().createOrUpdateTypeOnDisk(cidBuilder.build()); } /** * Generates new JavaType based on <code>controller</code> class name. * * @param controller * @param targetPackage if null uses <code>controller</code> package * @return */ private JavaType generateJavaType(JavaType controller) { return new JavaType( String.format("%s.%s", controller.getPackage() .getFullyQualifiedPackageName(), controller .getSimpleTypeName())); } /** * This method annotate ApplicationConversionServices classes to transform * GEO elements */ public void annotateApplicationConversionService() { // Validate that exists web layer Set<JavaType> controllers = getTypeLocationService() .findTypesWithAnnotation(SCAFFOLD_ANNOTATION); Validate.notEmpty( controllers, "There's not exists any web layer on this gvNIX application. Execute 'web mvc all --package ~.web' to create web layer."); // Getting all classes with @RooConversionService annotation for (JavaType conversorService : getTypeLocationService() .findTypesWithAnnotation(CONVERSION_SERVICE_ANNOTATION)) { Validate.notNull(conversorService, "RooConversionService required"); ClassOrInterfaceTypeDetails applicationConversionService = getTypeLocationService() .getTypeDetails(conversorService); // Only for @RooConversionService annotated controllers final AnnotationMetadata rooConversionServiceAnnotation = MemberFindingUtils .getAnnotationOfType( applicationConversionService.getAnnotations(), CONVERSION_SERVICE_ANNOTATION); Validate.isTrue(rooConversionServiceAnnotation != null, "Operation for @RooConversionService annotated classes only."); final boolean isGeoConversionServiceAnnotated = MemberFindingUtils .getAnnotationOfType( applicationConversionService.getAnnotations(), GEO_CONVERSION_SERVICE_ANNOTATION) != null; // If annotation already exists on the target type do nothing if (isGeoConversionServiceAnnotated) { return; } ClassOrInterfaceTypeDetailsBuilder detailsBuilder = new ClassOrInterfaceTypeDetailsBuilder( applicationConversionService); AnnotationMetadataBuilder annotationBuilder = new AnnotationMetadataBuilder( GEO_CONVERSION_SERVICE_ANNOTATION); // Add annotation to target type detailsBuilder.addAnnotation(annotationBuilder.build()); // Save changes to disk getTypeManagementService().createOrUpdateTypeOnDisk( detailsBuilder.build()); } } /** * This method updates Pom dependencies and repositories */ public void updatePomDependencies() { final Element configuration = XmlUtils.getConfiguration(getClass()); GeoUtils.updatePom(configuration, getProjectOperations(), getMetadataService()); } /** * This method install necessary components on correct folders */ public void installComponents() { PathResolver pathResolver = getProjectOperations().getPathResolver(); LogicalPath webappPath = getWebappPath(); // Copy Javascript files and related resources getOperationUtils().updateDirectoryContents("scripts/leaflet/*.js", pathResolver.getIdentifier(webappPath, "/scripts/leaflet"), fileManager, cContext, getClass()); getOperationUtils().updateDirectoryContents( "scripts/leaflet/images/*.png", pathResolver.getIdentifier(webappPath, "/scripts/leaflet/images"), fileManager, cContext, getClass()); // Copy Styles files and related resources getOperationUtils().updateDirectoryContents("styles/leaflet/*.css", pathResolver.getIdentifier(webappPath, "/styles/leaflet"), fileManager, cContext, getClass()); getOperationUtils().updateDirectoryContents( "styles/leaflet/images/*.png", pathResolver .getIdentifier(webappPath, "/styles/leaflet/images"), fileManager, cContext, getClass()); // Copy necessary fonts getOperationUtils().updateDirectoryContents("styles/fonts/*.*", pathResolver.getIdentifier(webappPath, "/styles/fonts"), fileManager, cContext, getClass()); // Copy images into images folder getOperationUtils().updateDirectoryContents("images/*.*", pathResolver.getIdentifier(webappPath, "/images"), fileManager, cContext, getClass()); // Copy tags into tags folder getOperationUtils().updateDirectoryContents("tags/geo/*.tagx", pathResolver.getIdentifier(webappPath, "/WEB-INF/tags/geo"), fileManager, cContext, getClass()); getOperationUtils().updateDirectoryContents( "tags/geo/layers/*.tagx", pathResolver.getIdentifier(webappPath, "/WEB-INF/tags/geo/layers"), fileManager, cContext, getClass()); getOperationUtils().updateDirectoryContents( "tags/geo/tools/*.tagx", pathResolver.getIdentifier(webappPath, "/WEB-INF/tags/geo/tools"), fileManager, cContext, getClass()); getOperationUtils().updateDirectoryContents( "tags/geo/form/fields/*.tagx", pathResolver.getIdentifier(webappPath, "/WEB-INF/tags/geo/form/fields"), fileManager, cContext, getClass()); // Copy necessary layouts files getOperationUtils().updateDirectoryContents("layouts/*.jspx", pathResolver.getIdentifier(webappPath, "/WEB-INF/layouts"), fileManager, cContext, getClass()); getOperationUtils().updateDirectoryContents("layouts/*.xml", pathResolver.getIdentifier(webappPath, "/WEB-INF/layouts"), fileManager, cContext, getClass()); // Add JS sources to loadScripts if (getProjectOperations().isFeatureInstalledInFocusedModule( "gvnix-bootstrap")) { addToLoadScripts("js_leaflet_geo_js", "/resources/scripts/leaflet/leaflet_bootstrap.js", false); } else { addToLoadScripts("js_leaflet_geo_js", "/resources/scripts/leaflet/leaflet.js", false); } addToLoadScripts("js_leaflet_ext_gvnix_url", "/resources/scripts/leaflet/leaflet.ext.gvnix.map.js", false); addToLoadScripts( "js_leaflet_ext_gvnix_measure_tool_url", "/resources/scripts/leaflet/leaflet.ext.gvnix.map.measure.tool.js", false); addToLoadScripts( "js_leaflet_ext_gvnix_generic_tool_url", "/resources/scripts/leaflet/leaflet.ext.gvnix.map.generic.tool.js", false); addToLoadScripts("js_leaflet_geo_omnivore_js", "/resources/scripts/leaflet/leaflet-omnivore.min.js", false); addToLoadScripts("js_leaflet_geo_awesome_markers_js", "/resources/scripts/leaflet/leaflet.awesome-markers.min.js", false); addToLoadScripts("js_leaflet_geo_marker_cluster_js", "/resources/scripts/leaflet/leaflet.markercluster-src.js", false); addToLoadScripts("js_leaflet_zoom_slider_js", "/resources/scripts/leaflet/L.Control.Zoomslider.js", false); addToLoadScripts("js_leaflet_measuring_tool_js", "/resources/scripts/leaflet/L.MeasuringTool.js", false); addToLoadScripts("js_leaflet_html_layers_control", "/resources/scripts/leaflet/leaflet.htmllayercontrol.js", false); addToLoadScripts("js_leaflet_html_toolbar_control", "/resources/scripts/leaflet/leaflet.htmltoolbarcontrol.js", false); addToLoadScripts("js_leaflet_draw", "/resources/scripts/leaflet/leaflet.draw-src.js", false); // Add CSS Sources to Load Scripts if (getProjectOperations().isFeatureInstalledInFocusedModule( "gvnix-bootstrap")) { addToLoadScripts("styles_leaflet_geo_css", "/resources/styles/leaflet/leaflet.bootstrap.css", true); addToLoadScripts("styles_gvnix_leaflet_geo_css", "/resources/styles/leaflet/gvnix.leaflet.bootstrap.css", true); } else { addToLoadScripts("styles_leaflet_geo_css", "/resources/styles/leaflet/leaflet.css", true); addToLoadScripts("styles_gvnix_leaflet_geo_css", "/resources/styles/leaflet/gvnix.leaflet.css", true); } addToLoadScripts("styles_leaflet_font_css", "/resources/styles/leaflet/font-awesome.min.css", true); addToLoadScripts("styles_leaflet_markers_css", "/resources/styles/leaflet/leaflet.awesome-markers.css", true); addToLoadScripts("styles_marker_cluster_css", "/resources/styles/leaflet/MarkerCluster.css", true); addToLoadScripts("styles_marker_cluster_default_css", "/resources/styles/leaflet/MarkerCluster.Default.css", true); addToLoadScripts("styles_zoom_slider_css", "/resources/styles/leaflet/L.Control.Zoomslider.css", true); addToLoadScripts("styles_leaflet_html_layers_control", "/resources/styles/leaflet/leaflet.htmllayercontrol.css", true); addToLoadScripts("styles_leaflet_html_toolbar_control", "/resources/styles/leaflet/leaflet.htmltoolbarcontrol.css", true); addToLoadScripts("styles_leaflet_drawl", "/resources/styles/leaflet/leaflet.draw.css", true); } /** * This method adds reference in laod-script.tagx to use * jquery.loupeField.ext.gvnix.js */ public void addToLoadScripts(String varName, String url, boolean isCSS) { // Modify Roo load-scripts.tagx String docTagxPath = getPathResolver().getIdentifier(getWebappPath(), "WEB-INF/tags/util/load-scripts.tagx"); Validate.isTrue(fileManager.exists(docTagxPath), "load-script.tagx not found: ".concat(docTagxPath)); MutableFile docTagxMutableFile = null; Document docTagx; try { docTagxMutableFile = fileManager.updateFile(docTagxPath); docTagx = XmlUtils.getDocumentBuilder().parse( docTagxMutableFile.getInputStream()); } catch (Exception e) { throw new IllegalStateException(e); } Element root = docTagx.getDocumentElement(); boolean modified = false; if (isCSS) { modified = getWebProjectUtils().addCssToTag(docTagx, root, varName, url) || modified; } else { modified = getWebProjectUtils().addJSToTag(docTagx, root, varName, url) || modified; } if (modified) { XmlUtils.writeXml(docTagxMutableFile.getOutputStream(), docTagx); } } /** * This method add necessary properties to messages.properties */ public void addI18nComponentsProperties() { // Check if Valencian_Catalan language is supported and add properties // if so Set<I18n> supportedLanguages = getI18nSupport().getSupportedLanguages(); for (I18n i18n : supportedLanguages) { if (i18n.getLocale().equals(new Locale("ca"))) { getMessageBundleUtils().installI18nMessages( new ValencianCatalanLanguage(), getProjectOperations(), fileManager); getMessageBundleUtils().addPropertiesToMessageBundle("ca", getClass(), getPropFileOperations(), getProjectOperations(), fileManager); break; } } // Add properties to Spanish messageBundle getMessageBundleUtils().installI18nMessages(new SpanishLanguage(), getProjectOperations(), fileManager); getMessageBundleUtils().addPropertiesToMessageBundle("es", getClass(), getPropFileOperations(), getProjectOperations(), fileManager); // Add properties to default messageBundle getMessageBundleUtils().addPropertiesToMessageBundle("en", getClass(), getPropFileOperations(), getProjectOperations(), fileManager); } /** * This method add necessary properties to application.properties for * Controller */ public void addI18nControllerProperties(String controllerPackage, String path) { Map<String, String> propertyList = new HashMap<String, String>(); propertyList.put("menu_category_map_menu_category_label", "Maps"); propertyList.put( String.format("label_%s_%s", controllerPackage.replaceAll("[.]", "_"), path), "Entity Map Viewer"); propertyList.put( String.format("label_%s_%s_toc", controllerPackage.replaceAll("[.]", "_"), path), "Layers"); getPropFileOperations().addProperties(getWebappPath(), "WEB-INF/i18n/application.properties", propertyList, true, false); } /** * This method annotate MapControllers with entities to represent * * @param mapControllersToAnnotate * @param typeLocationService * @param typeManagementService * @param entity */ private void annotateMapController(JavaType mapController, TypeLocationService typeLocationService, TypeManagementService typeManagementService, JavaType controller) { ClassOrInterfaceTypeDetails mapControllerDetails = typeLocationService .getTypeDetails(mapController); // Getting @GvNIXMapViewer Annotation AnnotationMetadata mapViewerAnnotation = mapControllerDetails .getAnnotation(MAP_VIEWER_ANNOTATION); // Generating new annotation ClassOrInterfaceTypeDetailsBuilder classOrInterfaceTypeDetailsBuilder = new ClassOrInterfaceTypeDetailsBuilder( mapControllerDetails); AnnotationMetadataBuilder annotationBuilder = new AnnotationMetadataBuilder( MAP_VIEWER_ANNOTATION); // Getting current entities @SuppressWarnings({ "unchecked", "rawtypes" }) ArrayAttributeValue<ClassAttributeValue> mapViewerAttributesOld = (ArrayAttributeValue) mapViewerAnnotation .getAttribute("entityLayers"); // Initialize class attributes list for detail fields final List<ClassAttributeValue> entityAttributes = new ArrayList<ClassAttributeValue>(); boolean notIncluded = true; if (mapViewerAttributesOld != null) { // Adding by default old entities entityAttributes.addAll(mapViewerAttributesOld.getValue()); // Checking that current entity is not included yet List<ClassAttributeValue> mapViewerAttributesOldValues = mapViewerAttributesOld .getValue(); for (ClassAttributeValue currentEntity : mapViewerAttributesOldValues) { if (currentEntity.getValue().equals(controller)) { notIncluded = false; break; } } } // If current entity is not included in old values, include to new // annotation if (notIncluded) { // Create a class attribute for property final ClassAttributeValue entityAttribute = new ClassAttributeValue( new JavaSymbolName(VALUE), controller); entityAttributes.add(entityAttribute); } // Create "entityLayers" attributes array from string attributes // list ArrayAttributeValue<ClassAttributeValue> entityLayersArray = new ArrayAttributeValue<ClassAttributeValue>( new JavaSymbolName("entityLayers"), entityAttributes); annotationBuilder.addAttribute(entityLayersArray); annotationBuilder.build(); // Update annotation into controller classOrInterfaceTypeDetailsBuilder .updateTypeAnnotation(annotationBuilder); // Save controller changes to disk getTypeManagementService().createOrUpdateTypeOnDisk( classOrInterfaceTypeDetailsBuilder.build()); } /** * Update the webmvc-config.xml file in order to register * Jackson2RequestMappingHandlerAdapter * * @param targetPackage */ private void updateWebMvcConfig() { LogicalPath webappPath = getWebProjectUtils().getWebappPath( getProjectOperations()); String webMvcXmlPath = getProjectOperations().getPathResolver() .getIdentifier(webappPath, "WEB-INF/spring/webmvc-config.xml"); Validate.isTrue(fileManager.exists(webMvcXmlPath), "webmvc-config.xml not found"); MutableFile webMvcXmlMutableFile = null; Document webMvcXml; try { webMvcXmlMutableFile = fileManager.updateFile(webMvcXmlPath); webMvcXml = XmlUtils.getDocumentBuilder().parse( webMvcXmlMutableFile.getInputStream()); } catch (Exception e) { throw new IllegalStateException(e); } Element root = webMvcXml.getDocumentElement(); Element dataBinder = XmlUtils.findFirstElement("bean[@id='" + WEBMCV_DATABINDER_BEAN_ID + "']", root); if (dataBinder != null) { root.removeChild(dataBinder); } // add bean tag to argument-resolvers Element bean = webMvcXml.createElement("bean"); bean.setAttribute("id", WEBMCV_DATABINDER_BEAN_ID); bean.setAttribute("p:order", "1"); bean.setAttribute("class", JACKSON2_RM_HANDLER_ADAPTER); Element property = webMvcXml.createElement("property"); property.setAttribute("name", "objectMapper"); Element objectMapperBean = webMvcXml.createElement("bean"); objectMapperBean.setAttribute("class", OBJECT_MAPPER); property.appendChild(objectMapperBean); bean.appendChild(property); root.appendChild(bean); boolean writeFile = false; // Register querydslUtilsGeoBean bean Element querydslUtilBeanElement = XmlUtils.findFirstElement( "bean[@id='querydslUtilsBean']", root); if (querydslUtilBeanElement == null) { throw new IllegalStateException( "querydslUtilsBean element cannot be found"); } else { if (!querydslUtilBeanElement.getAttribute("class").equals( "org.gvnix.web.datatables.util.impl.QuerydslUtilsBeanImpl")) { // Bean exists but was modified manually LOGGER.warning("Cannot add geo implementations because querydslUtilsBean was modified manually"); writeFile = false; } else { // Replace bean querydslUtilBeanElement.setAttribute("class", "org.gvnix.web.geo.util.impl.QuerydslUtilsBeanGeoImpl"); writeFile = true; } } // Register datatablesUtilsGeoBean bean Element datatablesUtilBeanElement = XmlUtils.findFirstElement( "bean[@id='datatableUtilsBean']", root); if (datatablesUtilBeanElement == null) { throw new IllegalStateException( "datatablesUtilsBean element cannot be found"); } else { if (!datatablesUtilBeanElement .getAttribute("class") .equals("org.gvnix.web.datatables.util.impl.DatatablesUtilsBeanImpl")) { // Bean exists but was modified manually LOGGER.warning("Cannot add geo implementations because datatableUtilsBean was modified manually"); writeFile = false; } else { // Replace bean datatablesUtilBeanElement .setAttribute("class", "org.gvnix.web.geo.util.impl.DatatablesUtilsBeanGeoImpl"); writeFile = true; } } if (writeFile) { XmlUtils.writeXml(webMvcXmlMutableFile.getOutputStream(), webMvcXml); } } /** * This method checks if exists some map element * * @return */ public boolean checkExistsMapElement() { // If not exists any class with @GvNIXMapViewer annotation, return false return !getTypeLocationService() .findClassesOrInterfaceDetailsWithAnnotation( MAP_VIEWER_ANNOTATION).isEmpty(); } /** * This method returns position of new base layer * * @param docRoot * @return */ public int getNewBaseLayerPosition(Element docRoot) { NodeList tileLayers = docRoot.getElementsByTagName("layer:tile"); NodeList wmsLayers = docRoot.getElementsByTagName("layer:wms"); return tileLayers.getLength() + wmsLayers.getLength() + 1; } /** * Creates an instance with the {@code src/main/webapp} path in the current * module * * @return */ public LogicalPath getWebappPath() { return getWebProjectUtils().getWebappPath(getProjectOperations()); } // Feature methods ----- /** * Gets the feature name managed by this operations class. * * @return feature name */ @Override public String getName() { return FEATURE_NAME_GVNIX_GEO_WEB_MVC; } /** * Returns true if GEO is installed */ @Override public boolean isInstalledInModule(String moduleName) { String dirPath = getPathResolver().getIdentifier(getWebappPath(), "scripts/leaflet/leaflet.js"); return fileManager.exists(dirPath); } /** * This method updates geo addon to use Bootstrap components */ @Override public void updateGeoAddonToBootstrap() { updateLoadScripts("js_leaflet_geo_js", "/resources/scripts/leaflet/leaflet_bootstrap.js", false); updateLoadScripts("styles_leaflet_geo_css", "/resources/styles/leaflet/leaflet.bootstrap.css", true); updateLoadScripts("styles_gvnix_leaflet_geo_css", "/resources/styles/leaflet/gvnix.leaflet.bootstrap.css", true); // Getting all maps and update layouts to use Bootstrap layout Set<ClassOrInterfaceTypeDetails> mapViews = getTypeLocationService() .findClassesOrInterfaceDetailsWithAnnotation( new JavaType("org.gvnix.addon.geo.GvNIXMapViewer")); PathResolver pathResolver = getProjectOperations().getPathResolver(); for (ClassOrInterfaceTypeDetails mapView : mapViews) { // Getting current map path AnnotationMetadata requestMapping = mapView .getAnnotation(new JavaType( "org.springframework.web.bind.annotation.RequestMapping")); String path = (String) requestMapping.getAttribute("value") .getValue(); path = path.substring(1); String finalPath = new JavaSymbolName(path).getReadableSymbolName() .toLowerCase(); // Modifying views.xml to add default-map final String viewsPath = pathResolver.getFocusedIdentifier( Path.SRC_MAIN_WEBAPP, String.format("WEB-INF/views/%s/views.xml", finalPath)); // Checking if has default-map yet boolean isMapLayout = false; Document docXml = getWebProjectUtils().loadXmlDocument(viewsPath, fileManager); // Getting current layout Element docRoot = docXml.getDocumentElement(); Element definitionElement = (Element) docRoot.getElementsByTagName( "definition").item(0); if (definitionElement != null) { String currentLayout = definitionElement .getAttribute("extends"); isMapLayout = "default-map".equals(currentLayout); } if (!isMapLayout) { // Copying views.xml InputStream inputStream = null; OutputStream outputStream = null; try { inputStream = FileUtils.getInputStream(getClass(), "views/views.xml"); if (fileManager.exists(viewsPath)) { outputStream = fileManager.updateFile(viewsPath) .getOutputStream(); } else { outputStream = fileManager.createFile(viewsPath) .getOutputStream(); } // Doing this to solve problems with <!DOCTYPE element // //////////////////////////////////////////////// PrintWriter writer = new PrintWriter(outputStream); writer.println("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>"); writer.println("<!DOCTYPE tiles-definitions PUBLIC \"-//Apache Software Foundation//DTD Tiles Configuration 2.1//EN\" \"http://tiles.apache.org/dtds/tiles-config_2_1.dtd\">"); writer.println("<tiles-definitions>"); writer.println(String .format(" <definition extends=\"default-map\" name=\"%s/show\">", finalPath)); writer.println(String .format(" <put-attribute name=\"body\" value=\"/WEB-INF/views/%s/show.jspx\"/>", finalPath)); writer.println(" </definition>"); writer.println("</tiles-definitions>"); writer.flush(); writer.close(); IOUtils.copy(inputStream, outputStream); } catch (final IOException ioe) { throw new IllegalStateException(ioe); } finally { IOUtils.closeQuietly(inputStream); IOUtils.closeQuietly(outputStream); } } } } /** * This method adds reference in laod-script.tagx */ public void updateLoadScripts(String varName, String url, boolean isCSS) { // Modify Roo load-scripts.tagx String docTagxPath = getPathResolver().getIdentifier(getWebappPath(), "WEB-INF/tags/util/load-scripts.tagx"); Validate.isTrue(fileManager.exists(docTagxPath), "load-script.tagx not found: ".concat(docTagxPath)); MutableFile docTagxMutableFile = null; Document docTagx; try { docTagxMutableFile = fileManager.updateFile(docTagxPath); docTagx = XmlUtils.getDocumentBuilder().parse( docTagxMutableFile.getInputStream()); } catch (Exception e) { throw new IllegalStateException(e); } Element root = docTagx.getDocumentElement(); boolean modified = false; Element urlElement = XmlUtils.findFirstElement( "url[@var='".concat(varName) + "']", root); if (urlElement != null) { // Getting current url value String currentUrlValue = urlElement.getAttribute("value"); if (!url.equals(currentUrlValue)) { urlElement.setAttribute("var", varName); urlElement.setAttribute(VALUE, url); modified = true; } } if (isCSS) { // Add link Element cssElement = XmlUtils.findFirstElement( String.format("link[@href='${%s}']", varName), root); if (cssElement == null) { cssElement = docTagx.createElement("link"); cssElement.setAttribute("rel", "stylesheet"); cssElement.setAttribute("type", "text/css"); cssElement.setAttribute("media", "screen"); cssElement.setAttribute("href", "${".concat(varName) .concat("}")); root.appendChild(cssElement); modified = true; } } else { // Add script Element scriptElement = XmlUtils.findFirstElement( String.format("script[@src='${%s}']", varName), root); if (scriptElement == null) { scriptElement = docTagx.createElement("script"); scriptElement.setAttribute("src", "${".concat(varName).concat("}")); scriptElement.setAttribute("type", "text/javascript"); scriptElement.appendChild(docTagx .createComment("required for FF3 and Opera")); root.appendChild(scriptElement); modified = true; } } if (modified) { XmlUtils.writeXml(docTagxMutableFile.getOutputStream(), docTagx); } } public PathResolver getPathResolver() { if (pathResolver == null) { // Get all Services implement PathResolver interface try { ServiceReference<?>[] references = this.context .getAllServiceReferences(PathResolver.class.getName(), null); for (ServiceReference<?> ref : references) { return (PathResolver) this.context.getService(ref); } return null; } catch (InvalidSyntaxException e) { LOGGER.warning("Cannot load PathResolver on GeoOperationsImpl."); return null; } } else { return pathResolver; } } public TypeLocationService getTypeLocationService() { if (typeLocationService == null) { // Get all Services implement TypeLocationService interface try { ServiceReference<?>[] references = this.context .getAllServiceReferences( TypeLocationService.class.getName(), null); for (ServiceReference<?> ref : references) { return (TypeLocationService) this.context.getService(ref); } return null; } catch (InvalidSyntaxException e) { LOGGER.warning("Cannot load TypeLocationService on GeoOperationsImpl."); return null; } } else { return typeLocationService; } } public MetadataService getMetadataService() { if (metadataService == null) { // Get all Services implement MetadataService interface try { ServiceReference<?>[] references = this.context .getAllServiceReferences( MetadataService.class.getName(), null); for (ServiceReference<?> ref : references) { return (MetadataService) this.context.getService(ref); } return null; } catch (InvalidSyntaxException e) { LOGGER.warning("Cannot load MetadataService on GeoOperationsImpl."); return null; } } else { return metadataService; } } public I18nSupport getI18nSupport() { if (i18nSupport == null) { // Get all Services implement I18nSupport interface try { ServiceReference<?>[] references = this.context .getAllServiceReferences(I18nSupport.class.getName(), null); for (ServiceReference<?> ref : references) { return (I18nSupport) this.context.getService(ref); } return null; } catch (InvalidSyntaxException e) { LOGGER.warning("Cannot load I18nSupport on GeoOperationsImpl."); return null; } } else { return i18nSupport; } } public PropFileOperations getPropFileOperations() { if (propFileOperations == null) { // Get all Services implement PropFileOperations interface try { ServiceReference<?>[] references = this.context .getAllServiceReferences( PropFileOperations.class.getName(), null); for (ServiceReference<?> ref : references) { return (PropFileOperations) this.context.getService(ref); } return null; } catch (InvalidSyntaxException e) { LOGGER.warning("Cannot load PropFileOperations on GeoOperationsImpl."); return null; } } else { return propFileOperations; } } public ProjectOperations getProjectOperations() { if (projectOperations == null) { // Get all Services implement ProjectOperations interface try { ServiceReference<?>[] references = this.context .getAllServiceReferences( ProjectOperations.class.getName(), null); for (ServiceReference<?> ref : references) { return (ProjectOperations) this.context.getService(ref); } return null; } catch (InvalidSyntaxException e) { LOGGER.warning("Cannot load ProjectOperations on GeoOperationsImpl."); return null; } } else { return projectOperations; } } public MenuOperations getMenuOperations() { if (menuOperations == null) { // Get all Services implement MenuOperations interface try { ServiceReference<?>[] references = this.context .getAllServiceReferences( MenuOperations.class.getName(), null); for (ServiceReference<?> ref : references) { return (MenuOperations) this.context.getService(ref); } return null; } catch (InvalidSyntaxException e) { LOGGER.warning("Cannot load MenuOperations on GeoOperationsImpl."); return null; } } else { return menuOperations; } } public TypeManagementService getTypeManagementService() { if (typeManagementService == null) { // Get all Services implement TypeManagementService interface try { ServiceReference<?>[] references = this.context .getAllServiceReferences( TypeManagementService.class.getName(), null); for (ServiceReference<?> ref : references) { return (TypeManagementService) this.context.getService(ref); } return null; } catch (InvalidSyntaxException e) { LOGGER.warning("Cannot load TypeManagementService on GeoOperationsImpl."); return null; } } else { return typeManagementService; } } public WebProjectUtils getWebProjectUtils() { if (webProjectUtils == null) { // Get all Services implement WebProjectUtils interface try { ServiceReference<?>[] references = this.context .getAllServiceReferences( WebProjectUtils.class.getName(), null); for (ServiceReference<?> ref : references) { webProjectUtils = (WebProjectUtils) this.context .getService(ref); return webProjectUtils; } return null; } catch (InvalidSyntaxException e) { LOGGER.warning("Cannot load WebProjectUtils on GeoOperationsImpl."); return null; } } else { return webProjectUtils; } } public OperationUtils getOperationUtils() { if (operationUtils == null) { // Get all Services implement OperationUtils interface try { ServiceReference<?>[] references = this.context .getAllServiceReferences( OperationUtils.class.getName(), null); for (ServiceReference<?> ref : references) { operationUtils = (OperationUtils) this.context .getService(ref); return operationUtils; } return null; } catch (InvalidSyntaxException e) { LOGGER.warning("Cannot load OperationUtils on GeoOperationsImpl."); return null; } } else { return operationUtils; } } public MessageBundleUtils getMessageBundleUtils() { if (messageBundleUtils == null) { // Get all Services implement MessageBundleUtils interface try { ServiceReference<?>[] references = this.context .getAllServiceReferences( MessageBundleUtils.class.getName(), null); for (ServiceReference<?> ref : references) { messageBundleUtils = (MessageBundleUtils) this.context .getService(ref); return messageBundleUtils; } return null; } catch (InvalidSyntaxException e) { LOGGER.warning("Cannot load MessageBundleUtils on GeoOperationsImpl."); return null; } } else { return messageBundleUtils; } } }