Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,13 @@ In it's current form, it doesn't provide any html/javascript scaffolding, only s

## Icons

The main mechanism to use icons is to have a spring bean named "leaflet-icon-provider-XXX" implement the interface fr.paris.lutece.plugins.leaflet.service.IIconProvider. The implementor must return an icon name. The Java code for pages displaying the map can then call fr.paris.lutece.plugins.leaflet.service.IconService.getIcon() to retrieve the icon name from the resource.
The main mechanism to use icons is to have a CDI bean named "leaflet-icon-provider-XXX" implement the interface fr.paris.lutece.plugins.leaflet.service.IIconProvider. The implementor must return an icon name. The Java code for pages displaying the map can then call fr.paris.lutece.plugins.leaflet.service.IconService.getIcon() to retrieve the icon name from the resource.

fr.paris.lutece.plugins.leaflet.service.IconService.getList() can be used to get a List of available icons, for example to build GUIs for users to choose an icon. To add icons to this list, add an entry in the datastore in the form ('leaflet.icon.icons.ICON_NAME.installed', 'true').

## Popups

The main mechanism to use popups is to have a spring bean named "leaflet-rest-popup-provider-XXX" implement the interface fr.paris.lutece.plugins.leaflet.rest.service.IPopupContentProvider. The implementor must produce html snippets. They will be automatically accessible at the URL rest/leaflet/popup/{XXX}/{docid}/{code} and can be loaded when the user clicks a marker with AJAX.
The main mechanism to use popups is to have a CDI bean named "leaflet-rest-popup-provider-XXX" implement the interface fr.paris.lutece.plugins.leaflet.rest.service.IPopupContentProvider. The implementor must produce html snippets. They will be automatically accessible at the URL rest/leaflet/popup/{XXX}/{docid}/{code} and can be loaded when the user clicks a marker with AJAX.

CORS headers can be enabled with the following properties:

Expand Down
27 changes: 21 additions & 6 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,14 @@
<parent>
<artifactId>lutece-global-pom</artifactId>
<groupId>fr.paris.lutece.tools</groupId>
<version>7.0.2</version>
<version>8.0.0-SNAPSHOT</version>
</parent>

<modelVersion>4.0.0</modelVersion>
<groupId>fr.paris.lutece.plugins</groupId>
<artifactId>plugin-leaflet</artifactId>
<packaging>lutece-plugin</packaging>
<version>1.0.5-SNAPSHOT</version>
<version>2.0.0-SNAPSHOT</version>
<name>Lutece leaflet plugin</name>

<repositories>
Expand All @@ -20,27 +20,42 @@
<url>https://dev.lutece.paris.fr/maven_repository</url>
<layout>default</layout>
</repository>
<repository>
<id>luteceSnapshot</id>
<name>luteceSnapshot</name>
<url>https://dev.lutece.paris.fr/snapshot_repository</url>
<snapshots>
<enabled>true</enabled>
</snapshots>
<releases>
<enabled>false</enabled>
</releases>
</repository>
</repositories>

<dependencies>
<dependency>
<groupId>fr.paris.lutece</groupId>
<artifactId>lutece-core</artifactId>
<version>[7.0.0,7.9.9)</version>
<version>[8.0.0-SNAPSHOT,)</version>
<type>lutece-core</type>
</dependency>
<dependency>
<groupId>fr.paris.lutece.plugins</groupId>
<artifactId>plugin-rest</artifactId>
<version>[3.1.1,3.9.9)</version>
<version>[4.0.0-SNAPSHOT,)</version>
<type>lutece-plugin</type>
</dependency>
<dependency>
<groupId>fr.paris.lutece.plugins</groupId>
<artifactId>library-lutece-unit-testing</artifactId>
<type>jar</type>
<scope>test</scope>
</dependency>
</dependencies>

<properties>
<componentName>leaflet</componentName>
<jiraProjectName>LEAFLET</jiraProjectName>
<jiraComponentId />
</properties>

<scm>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,6 @@
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.DeserializationFeature;

Expand Down Expand Up @@ -143,7 +141,7 @@ public String getType( )
@JsonProperty( PATH_PROPERTIES )
public Map<String, Object> getProperties( )
{
HashMap<String, Object> properties = new HashMap<String, Object>( );
Map<String, Object> properties = new HashMap<>( );

if ( _address != null )
{
Expand Down Expand Up @@ -171,7 +169,7 @@ public Map<String, Object> getProperties( )
@JsonProperty( PATH_GEOMETRY )
public Map<String, Object> getGeometry( )
{
HashMap<String, Object> geometry = new HashMap<String, Object>( );
Map<String, Object> geometry = new HashMap<>( );
geometry.put( PATH_GEOMETRY_TYPE, _typegeometry );
if ( _typegeometry.equals( VALUE_GEOMETRY_TYPE ) )
{
Expand Down Expand Up @@ -311,7 +309,7 @@ public String toXML( )
* @return The geolocItem object
*/
public static GeolocItem fromJSON( String strJson )
throws JsonParseException, JsonMappingException, IOException
throws IOException
{
return _objectMapper.readValue( strJson, GeolocItem.class );
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,21 +35,10 @@

import fr.paris.lutece.util.xml.XmlUtil;

/*
import org.codehaus.jackson.JsonParseException;
import org.codehaus.jackson.annotate.JsonAutoDetect;
import org.codehaus.jackson.annotate.JsonAutoDetect.Visibility;
import org.codehaus.jackson.annotate.JsonProperty;
import org.codehaus.jackson.map.DeserializationConfig;
import org.codehaus.jackson.map.JsonMappingException;
import org.codehaus.jackson.map.ObjectMapper;
*/

import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.DeserializationFeature;

Expand Down Expand Up @@ -86,7 +75,6 @@ public class GeolocItemPolygon
static
{
_objectMapper = new ObjectMapper( );
//_objectMapper.configure( DeserializationConfig.Feature.FAIL_ON_UNKNOWN_PROPERTIES, false );
_objectMapper.configure( DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false );
}

Expand Down Expand Up @@ -144,7 +132,7 @@ public String getType( )
@JsonProperty( PATH_PROPERTIES )
public Map<String, Object> getProperties( )
{
HashMap<String, Object> properties = new HashMap<String, Object>( );
Map<String, Object> properties = new HashMap<>( );

if ( _icon != null )
{
Expand All @@ -167,7 +155,7 @@ public Map<String, Object> getProperties( )
@JsonProperty( PATH_GEOMETRY )
public Map<String, Object> getGeometry( )
{
HashMap<String, Object> geometry = new HashMap<String, Object>( );
Map<String, Object> geometry = new HashMap<>( );
//geometry.put( PATH_GEOMETRY_TYPE, VALUE_GEOMETRY_TYPE_POLYGON );
geometry.put( PATH_GEOMETRY_TYPE, _typegeometry );
//geometry.put( PATH_GEOMETRY_COORDINATES, _lonlat );
Expand Down Expand Up @@ -287,7 +275,7 @@ public String toXML( )
* @return The geolocItem object
*/
public static GeolocItemPolygon fromJSON( String strJson )
throws JsonParseException, JsonMappingException, IOException
throws IOException
{
return _objectMapper.readValue( strJson, GeolocItemPolygon.class );
}
Expand Down
114 changes: 69 additions & 45 deletions src/java/fr/paris/lutece/plugins/leaflet/rest/rs/LeafletRest.java
Original file line number Diff line number Diff line change
Expand Up @@ -33,29 +33,33 @@
*/
package fr.paris.lutece.plugins.leaflet.rest.rs;

import javax.servlet.http.HttpServletRequest;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.ResponseBuilder;

import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.enterprise.inject.Instance;
import jakarta.enterprise.inject.literal.NamedLiteral;
import jakarta.inject.Inject;
import jakarta.inject.Named;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.PathParam;
import jakarta.ws.rs.WebApplicationException;
import jakarta.ws.rs.core.Context;
import jakarta.ws.rs.core.Response;
import jakarta.ws.rs.core.Response.ResponseBuilder;

import fr.paris.lutece.plugins.leaflet.rest.service.IPopupContentProvider;
import fr.paris.lutece.plugins.leaflet.service.CorsUtils;
import fr.paris.lutece.plugins.rest.service.RestConstants;
import fr.paris.lutece.portal.service.i18n.I18nService;
import fr.paris.lutece.portal.service.spring.SpringContextService;
import fr.paris.lutece.portal.service.util.AppLogService;
import fr.paris.lutece.portal.service.util.AppPropertiesService;


/**
* LeafletRest
*/
@ApplicationScoped
@Named( "leaflet-rest.leafletRest" )
@Path( RestConstants.BASE_PATH + "leaflet" )
public class LeafletRest
{
Expand All @@ -69,12 +73,14 @@ public class LeafletRest
private static final String PROPERTY_CORS_ENABLED_KEY = "leaflet.cors.enabled";
private static final boolean PROPERTY_CORS_ENABLED_DEFAULT = false;


private static final String HEADER_ORIGIN = "origin";

private static final String PROPERTY_CORS_METHODS_KEY = "leaflet.cors.methods";
private static final String PROPERTY_CORS_METHODS_DEFAULT = "GET, POST, DELETE, PUT";

@Inject
private Instance<IPopupContentProvider> _popupContentProviderInstance;

/**
* Get an html snippet representing a leaflet popup
* @param request the httpServletRequest
Expand All @@ -85,47 +91,65 @@ public class LeafletRest
*/
@GET
@Path( PATH_POPUP )
public Response getDocument( @Context
HttpServletRequest request, @PathParam( PARAMETER_PROVIDER )
String strProvider, @PathParam( PARAMETER_ID_DOCUMENT )
String strIdDocument, @PathParam( PARAMETER_CODE )
String strCode )
public Response getDocument( @Context HttpServletRequest request,
@PathParam( PARAMETER_PROVIDER ) String strProvider,
@PathParam( PARAMETER_ID_DOCUMENT ) String strIdDocument,
@PathParam( PARAMETER_CODE ) String strCode )
{
try
Instance<IPopupContentProvider> selectedProviderInstance = _popupContentProviderInstance.select( NamedLiteral.of( BEAN_PREFIX + strProvider ) );

String popup = getPopupContentProvider( selectedProviderInstance, strProvider, strIdDocument ).getPopup( request, strIdDocument, strCode );

if ( popup != null )
{

IPopupContentProvider popupContentProvider = (IPopupContentProvider) SpringContextService.getBean( BEAN_PREFIX +
strProvider );

String popup = popupContentProvider.getPopup( request, strIdDocument, strCode );

if ( popup != null )
{
String popupLocalized = I18nService.localize( popup, request.getLocale( ) );

ResponseBuilder responseBuilder = Response.ok();
if ( AppPropertiesService.getPropertyBoolean( PROPERTY_CORS_ENABLED_KEY, PROPERTY_CORS_ENABLED_DEFAULT ) ) {

String strHeaderOrigin = request.getHeader( HEADER_ORIGIN );
String strAccessControlAllowOrigin = CorsUtils.isValidOrigin( strHeaderOrigin ) ? strHeaderOrigin : "";
String strCorsMethods = AppPropertiesService.getProperty( PROPERTY_CORS_METHODS_KEY, PROPERTY_CORS_METHODS_DEFAULT);
responseBuilder .header("Access-Control-Allow-Methods", strCorsMethods).header("Access-Control-Allow-Origin", strAccessControlAllowOrigin);

}
return responseBuilder
.entity(popupLocalized)
.build();
String popupLocalized = I18nService.localize( popup, request.getLocale( ) );

ResponseBuilder responseBuilder = Response.ok();
if ( AppPropertiesService.getPropertyBoolean( PROPERTY_CORS_ENABLED_KEY, PROPERTY_CORS_ENABLED_DEFAULT ) ) {

String strHeaderOrigin = request.getHeader( HEADER_ORIGIN );
String strAccessControlAllowOrigin = CorsUtils.isValidOrigin( strHeaderOrigin ) ? strHeaderOrigin : "";
String strCorsMethods = AppPropertiesService.getProperty( PROPERTY_CORS_METHODS_KEY, PROPERTY_CORS_METHODS_DEFAULT);
responseBuilder .header("Access-Control-Allow-Methods", strCorsMethods).header("Access-Control-Allow-Origin", strAccessControlAllowOrigin);

}
return responseBuilder
.entity(popupLocalized)
.build();
}

AppLogService.debug( "Leaflet popup rest API: icon was null" );
throw new WebApplicationException( 404 );
}

AppLogService.debug( "Leaflet popup rest API: icon was null" );
/**
* Get the popup provider from a provider instance
*
* @param popupContentProviderInstance the provider instance
* @param strProvider the provider
* @param strIdDocument the id document
* @return the provider
* @throws WebApplicationException if the provider cannot be resolved
*/
private IPopupContentProvider getPopupContentProvider( Instance<IPopupContentProvider> popupContentProviderInstance,
String strProvider, String strIdDocument )
{
if ( popupContentProviderInstance.isUnsatisfied( ) )
{
AppLogService.error(
"Leaflet popup rest API: No provider found for provider '{}' , document ID '{}'", strProvider, strIdDocument
);
throw new WebApplicationException( 404 );
}
catch ( NoSuchBeanDefinitionException e )

if ( popupContentProviderInstance.isAmbiguous( ) )
{
AppLogService.error( "Leaflet popup rest API: Missing strProvider " + strProvider + " , strDocId " +
strIdDocument + ", exception " + e );
AppLogService.error(
"Leaflet popup rest API: Multiple providers found for provider '{}' , document ID '{}'", strProvider, strIdDocument
);
throw new WebApplicationException( 404 );
}

return popupContentProviderInstance.get( );
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
*/
package fr.paris.lutece.plugins.leaflet.rest.service;

import javax.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletRequest;


/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,8 @@
package fr.paris.lutece.plugins.leaflet.service;


import fr.paris.lutece.util.http.AntPathMatcher;
import org.apache.commons.lang3.StringUtils;
import org.springframework.util.AntPathMatcher;
import org.springframework.util.PathMatcher;

import fr.paris.lutece.portal.service.util.AppPropertiesService;

Expand All @@ -49,7 +48,7 @@ public final class CorsUtils
{

/** The Constant PATH_MATCHER. */
private final static PathMatcher PATH_MATCHER = new AntPathMatcher( );
private static final AntPathMatcher PATH_MATCHER = new AntPathMatcher( );

/** The Constant PROPERTY_CORS_ORIGIN_KEY. */
private static final String PROPERTY_CORS_ORIGIN_KEY = "leaflet.cors.origin";
Expand Down
Loading