diff --git a/src/gui/web/pom.xml b/src/gui/web/pom.xml
index 7915df72..d9d65655 100644
--- a/src/gui/web/pom.xml
+++ b/src/gui/web/pom.xml
@@ -276,8 +276,8 @@
3.1
utf8
-
- 1.5
+
+ 1.8
diff --git a/src/services/core/persistence/src/main/java/org/geoserver/geofence/core/dao/impl/AdminRuleDAOImpl.java b/src/services/core/persistence/src/main/java/org/geoserver/geofence/core/dao/impl/AdminRuleDAOImpl.java
index 4d2589b2..657bdaa4 100644
--- a/src/services/core/persistence/src/main/java/org/geoserver/geofence/core/dao/impl/AdminRuleDAOImpl.java
+++ b/src/services/core/persistence/src/main/java/org/geoserver/geofence/core/dao/impl/AdminRuleDAOImpl.java
@@ -20,6 +20,7 @@
import org.apache.log4j.LogManager;
import org.apache.log4j.Logger;
+import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
/**
@@ -66,6 +67,7 @@ public int shift(long priorityStart, long offset) {
}
@Override
+ @Transactional(propagation = Propagation.REQUIRED, value = "geofenceTransactionManager")
public long persist(AdminRule entity, InsertPosition position) {
return super.persist(AdminRule.class, entity, position);
diff --git a/src/services/core/persistence/src/main/java/org/geoserver/geofence/core/dao/impl/RuleDAOImpl.java b/src/services/core/persistence/src/main/java/org/geoserver/geofence/core/dao/impl/RuleDAOImpl.java
index a36aac97..f26ab7f0 100644
--- a/src/services/core/persistence/src/main/java/org/geoserver/geofence/core/dao/impl/RuleDAOImpl.java
+++ b/src/services/core/persistence/src/main/java/org/geoserver/geofence/core/dao/impl/RuleDAOImpl.java
@@ -21,6 +21,7 @@
import org.apache.log4j.Logger;
import org.geoserver.geofence.core.dao.DuplicateKeyException;
+import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
/**
diff --git a/src/services/core/services-api/pom.xml b/src/services/core/services-api/pom.xml
index 5f169682..108ced3b 100644
--- a/src/services/core/services-api/pom.xml
+++ b/src/services/core/services-api/pom.xml
@@ -25,6 +25,10 @@
+
+ commons-lang
+ commons-lang
+
org.geoserver.geofence
@@ -70,7 +74,10 @@
junit
test
-
+
+ org.javatuples
+ javatuples
+
diff --git a/src/services/core/services-api/src/main/java/org/geoserver/geofence/services/AdminRuleAdminService.java b/src/services/core/services-api/src/main/java/org/geoserver/geofence/services/AdminRuleAdminService.java
index 0b6e45af..2e391498 100644
--- a/src/services/core/services-api/src/main/java/org/geoserver/geofence/services/AdminRuleAdminService.java
+++ b/src/services/core/services-api/src/main/java/org/geoserver/geofence/services/AdminRuleAdminService.java
@@ -11,7 +11,10 @@
import org.geoserver.geofence.services.dto.ShortAdminRule;
import org.geoserver.geofence.services.exception.BadRequestServiceEx;
import org.geoserver.geofence.services.exception.NotFoundServiceEx;
+import org.javatuples.Pair;
+import org.javatuples.Tuple;
+import java.util.ArrayList;
import java.util.List;
@@ -28,6 +31,20 @@ public interface AdminRuleAdminService
long insert(AdminRule rule);
+ /**
+ * Inserts a list of admin rules
+ *
+ * @param rules list of pair of admin rules to be inserted along with the position.
+ */
+ default List insert(List> rules) {
+ List results=new ArrayList<>(rules.size());
+ for (Pair rule: rules) {
+ long id=insert(rule.getValue0(),rule.getValue1());
+ results.add(id);
+ }
+ return results;
+ }
+
long insert(AdminRule rule, InsertPosition position);
long update(AdminRule rule) throws NotFoundServiceEx;
@@ -128,7 +145,7 @@ public interface AdminRuleAdminService
* @throws BadRequestServiceEx if a wildcard type is used in filter
*/
ShortAdminRule getRule(RuleFilter filter) throws BadRequestServiceEx;
-
+
/**
* Return the Rules according to the filter.
* Rules will be enriched with all their joined data, so this method may be heavy to execute.
diff --git a/src/services/core/services-api/src/main/java/org/geoserver/geofence/services/RuleAdminService.java b/src/services/core/services-api/src/main/java/org/geoserver/geofence/services/RuleAdminService.java
index 97bd8825..a85ae77c 100644
--- a/src/services/core/services-api/src/main/java/org/geoserver/geofence/services/RuleAdminService.java
+++ b/src/services/core/services-api/src/main/java/org/geoserver/geofence/services/RuleAdminService.java
@@ -5,6 +5,9 @@
package org.geoserver.geofence.services;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Map;
import org.geoserver.geofence.core.model.LayerDetails;
import org.geoserver.geofence.core.model.Rule;
import org.geoserver.geofence.core.model.RuleLimits;
@@ -13,7 +16,8 @@
import org.geoserver.geofence.services.dto.ShortRule;
import org.geoserver.geofence.services.exception.BadRequestServiceEx;
import org.geoserver.geofence.services.exception.NotFoundServiceEx;
-
+import org.javatuples.Quartet;
+import org.javatuples.Triplet;
import java.util.List;
import java.util.Set;
@@ -33,6 +37,23 @@ public interface RuleAdminService
long insert(Rule rule, InsertPosition position);
+ /**
+ * @param rules to be inserted
+ * @return map of inserted rules along with their ids.
+ */
+ default List insert(List> rules) {
+ List ids = new ArrayList<>();
+ for (Quartet rule: rules) {
+ long id = insert(rule.getValue0(),rule.getValue3());
+ RuleLimits limits=rule.getValue1();
+ if (limits!=null) setLimits(id,limits);
+ LayerDetails details=rule.getValue2();
+ if (details!=null) setDetails(id,details);
+ ids.add(id);
+ }
+ return ids;
+ }
+
long update(Rule rule) throws NotFoundServiceEx;
/**
@@ -134,7 +155,7 @@ public interface RuleAdminService
* @throws BadRequestServiceEx if a wildcard type is used in filter
*/
ShortRule getRule(RuleFilter filter) throws BadRequestServiceEx;
-
+
/**
* Return the Rules according to the filter.
* Rules will be enriched with all their joined data, so this method may be heavy to execute.
diff --git a/src/services/core/services-impl/pom.xml b/src/services/core/services-impl/pom.xml
index c5244f83..bb656ce5 100644
--- a/src/services/core/services-impl/pom.xml
+++ b/src/services/core/services-impl/pom.xml
@@ -193,6 +193,11 @@
test
+
+ org.javatuples
+ javatuples
+
+
diff --git a/src/services/core/services-impl/src/main/java/org/geoserver/geofence/services/AdminRuleAdminServiceImpl.java b/src/services/core/services-impl/src/main/java/org/geoserver/geofence/services/AdminRuleAdminServiceImpl.java
index 10f81f78..d2fa40cd 100644
--- a/src/services/core/services-impl/src/main/java/org/geoserver/geofence/services/AdminRuleAdminServiceImpl.java
+++ b/src/services/core/services-impl/src/main/java/org/geoserver/geofence/services/AdminRuleAdminServiceImpl.java
@@ -26,6 +26,10 @@
import org.apache.log4j.LogManager;
import org.apache.log4j.Logger;
+import org.javatuples.Pair;
+import org.javatuples.Tuple;
+import org.springframework.transaction.annotation.Propagation;
+import org.springframework.transaction.annotation.Transactional;
/**
*
@@ -47,6 +51,13 @@ public long insert(AdminRule rule) {
return rule.getId();
}
+
+ @Override
+ @Transactional(propagation = Propagation.REQUIRED, value = "geofenceTransactionManager")
+ public List insert(List> rules) {
+ return AdminRuleAdminService.super.insert(rules);
+ }
+
@Override
public long insert(AdminRule rule, InsertPosition position) {
ruleDAO.persist(rule, position);
diff --git a/src/services/core/services-impl/src/main/java/org/geoserver/geofence/services/RuleAdminServiceImpl.java b/src/services/core/services-impl/src/main/java/org/geoserver/geofence/services/RuleAdminServiceImpl.java
index 7b5e98b0..d629902e 100644
--- a/src/services/core/services-impl/src/main/java/org/geoserver/geofence/services/RuleAdminServiceImpl.java
+++ b/src/services/core/services-impl/src/main/java/org/geoserver/geofence/services/RuleAdminServiceImpl.java
@@ -7,6 +7,10 @@
import com.googlecode.genericdao.search.Filter;
import com.googlecode.genericdao.search.Search;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.geoserver.geofence.core.dao.DuplicateKeyException;
import org.geoserver.geofence.core.dao.LayerDetailsDAO;
import org.geoserver.geofence.core.dao.RuleDAO;
import org.geoserver.geofence.core.dao.RuleLimitsDAO;
@@ -29,6 +33,10 @@
import org.geoserver.geofence.services.exception.BadRequestServiceEx;
import org.geoserver.geofence.services.exception.NotFoundServiceEx;
+import org.javatuples.Quartet;
+import org.javatuples.Triplet;
+import org.springframework.transaction.annotation.Propagation;
+import org.springframework.transaction.annotation.Transactional;
import static org.geoserver.geofence.services.util.FilterUtils.addCriteria;
import static org.geoserver.geofence.services.util.FilterUtils.addFixedCriteria;
@@ -64,6 +72,16 @@ public long insert(Rule rule) {
return rule.getId();
}
+ /**
+ * @param rules to be inserted
+ * @return map of inserted rules along with their ids.
+ */
+ @Override
+ @Transactional(propagation = Propagation.REQUIRED, value = "geofenceTransactionManager")
+ public List insert(List> rules) {
+ return RuleAdminService.super.insert(rules);
+ }
+
@Override
public long insert(Rule rule, InsertPosition position) {
sanitizeFields(rule);
diff --git a/src/services/modules/rest/api/pom.xml b/src/services/modules/rest/api/pom.xml
index ee2b9a29..4c23f86f 100644
--- a/src/services/modules/rest/api/pom.xml
+++ b/src/services/modules/rest/api/pom.xml
@@ -75,8 +75,8 @@
org.apache.maven.plugins
maven-compiler-plugin
-
- 1.6
+
+ 1.8
diff --git a/src/services/modules/rest/api/src/main/java/org/geoserver/geofence/services/rest/RESTAdminRuleService.java b/src/services/modules/rest/api/src/main/java/org/geoserver/geofence/services/rest/RESTAdminRuleService.java
index 13fcad54..71afca46 100644
--- a/src/services/modules/rest/api/src/main/java/org/geoserver/geofence/services/rest/RESTAdminRuleService.java
+++ b/src/services/modules/rest/api/src/main/java/org/geoserver/geofence/services/rest/RESTAdminRuleService.java
@@ -5,6 +5,7 @@
package org.geoserver.geofence.services.rest;
+import java.util.List;
import org.geoserver.geofence.services.rest.exception.BadRequestRestEx;
import org.geoserver.geofence.services.rest.exception.InternalErrorRestEx;
import org.geoserver.geofence.services.rest.exception.NotFoundRestEx;
@@ -23,6 +24,7 @@
import org.apache.cxf.jaxrs.ext.multipart.Multipart;
import org.geoserver.geofence.services.rest.model.RESTInputAdminRule;
+import org.geoserver.geofence.services.rest.model.RESTInputAdminRuleList;
import org.geoserver.geofence.services.rest.model.RESTOutputAdminRule;
import org.geoserver.geofence.services.rest.model.RESTOutputAdminRuleList;
@@ -40,6 +42,11 @@ public interface RESTAdminRuleService
@Produces(MediaType.APPLICATION_XML)
Response insert(@Multipart("rule") RESTInputAdminRule rule) throws BadRequestRestEx, NotFoundRestEx;
+ @POST
+ @Path("/many")
+ @Produces(MediaType.APPLICATION_XML)
+ Response insertMany(@Multipart("AdminRuleList") RESTInputAdminRuleList rules) throws BadRequestRestEx, NotFoundRestEx;
+
@GET
@Path("/id/{id}")
@Produces(MediaType.APPLICATION_XML)
diff --git a/src/services/modules/rest/api/src/main/java/org/geoserver/geofence/services/rest/RESTRuleService.java b/src/services/modules/rest/api/src/main/java/org/geoserver/geofence/services/rest/RESTRuleService.java
index 2b2a1b89..01fd4318 100644
--- a/src/services/modules/rest/api/src/main/java/org/geoserver/geofence/services/rest/RESTRuleService.java
+++ b/src/services/modules/rest/api/src/main/java/org/geoserver/geofence/services/rest/RESTRuleService.java
@@ -5,10 +5,12 @@
package org.geoserver.geofence.services.rest;
+import java.util.List;
import org.geoserver.geofence.services.rest.exception.BadRequestRestEx;
import org.geoserver.geofence.services.rest.exception.InternalErrorRestEx;
import org.geoserver.geofence.services.rest.exception.NotFoundRestEx;
import org.geoserver.geofence.services.rest.model.RESTInputRule;
+import org.geoserver.geofence.services.rest.model.RESTInputRuleList;
import org.geoserver.geofence.services.rest.model.RESTOutputRule;
import org.geoserver.geofence.services.rest.model.RESTOutputRuleList;
@@ -40,6 +42,16 @@ public interface RESTRuleService
@Produces(MediaType.TEXT_PLAIN)
Response insert(@Multipart("rule") RESTInputRule rule) throws BadRequestRestEx, NotFoundRestEx;
+ @POST
+ @Path("/many")
+ @Produces(MediaType.TEXT_PLAIN)
+ default Response insertMany(@Multipart("RuleList") RESTInputRuleList rules) throws BadRequestRestEx, NotFoundRestEx {
+ for (RESTInputRule r: rules){
+ insert(r);
+ }
+ return Response.status(Response.Status.CREATED).build();
+ }
+
@GET
@Path("/id/{id}")
@Produces(MediaType.APPLICATION_XML)
diff --git a/src/services/modules/rest/api/src/main/java/org/geoserver/geofence/services/rest/model/RESTInputAdminRuleList.java b/src/services/modules/rest/api/src/main/java/org/geoserver/geofence/services/rest/model/RESTInputAdminRuleList.java
new file mode 100644
index 00000000..5e651cfe
--- /dev/null
+++ b/src/services/modules/rest/api/src/main/java/org/geoserver/geofence/services/rest/model/RESTInputAdminRuleList.java
@@ -0,0 +1,37 @@
+/* (c) 2022 Open Source Geospatial Foundation - all rights reserved
+ * This code is licensed under the GPL 2.0 license, available at the root
+ * application directory.
+ */
+package org.geoserver.geofence.services.rest.model;
+
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlRootElement;
+import java.util.Iterator;
+import java.util.List;
+
+@XmlRootElement(name = "AdminRuleList")
+public class RESTInputAdminRuleList implements Iterable {
+
+ private List list;
+
+
+
+ @XmlElement(name = "adminrule")
+ public List getList() {
+ return list;
+ }
+
+ public void setList(List userList) {
+ this.list = userList;
+ }
+
+ @Override
+ public String toString() {
+ return getClass().getSimpleName() + "[" + list.size() + " users]";
+ }
+
+ @Override
+ public Iterator iterator() {
+ return list.iterator();
+ }
+}
diff --git a/src/services/modules/rest/api/src/main/java/org/geoserver/geofence/services/rest/model/RESTInputRule.java b/src/services/modules/rest/api/src/main/java/org/geoserver/geofence/services/rest/model/RESTInputRule.java
index f30c5319..fc068207 100644
--- a/src/services/modules/rest/api/src/main/java/org/geoserver/geofence/services/rest/model/RESTInputRule.java
+++ b/src/services/modules/rest/api/src/main/java/org/geoserver/geofence/services/rest/model/RESTInputRule.java
@@ -18,7 +18,7 @@
* @author Etj (etj at geo-solutions.it)
*/
@XmlRootElement(name = "rule")
-@XmlType(name="Rule", propOrder={"position","grant","username","rolename","instance","ipaddress","service","request","workspace","layer","constraints"})
+@XmlType(name="Rule", propOrder={"position","grant","username","rolename","instance","ipaddress","service","request","workspace","layer","limits","constraints"})
public class RESTInputRule extends AbstractRESTPayload {
private RESTRulePosition position;
@@ -38,6 +38,8 @@ public class RESTInputRule extends AbstractRESTPayload {
private GrantType grant;
+ private RESTRuleLimits limits;
+
private RESTLayerConstraints constraints;
public RESTInputRule() {
@@ -118,6 +120,13 @@ public void setWorkspace(String workspace) {
}
+ public RESTRuleLimits getLimits() {
+ return limits;
+ }
+
+ public void setLimits(RESTRuleLimits limits) {
+ this.limits = limits;
+ }
public RESTLayerConstraints getConstraints() {
return constraints;
diff --git a/src/services/modules/rest/api/src/main/java/org/geoserver/geofence/services/rest/model/RESTInputRuleList.java b/src/services/modules/rest/api/src/main/java/org/geoserver/geofence/services/rest/model/RESTInputRuleList.java
new file mode 100644
index 00000000..5b6178ac
--- /dev/null
+++ b/src/services/modules/rest/api/src/main/java/org/geoserver/geofence/services/rest/model/RESTInputRuleList.java
@@ -0,0 +1,43 @@
+/* (c) 2022 Open Source Geospatial Foundation - all rights reserved
+ * This code is licensed under the GPL 2.0 license, available at the root
+ * application directory.
+ */
+
+package org.geoserver.geofence.services.rest.model;
+
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlRootElement;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+/**
+ *
+ * @author ETj (etj at geo-solutions.it)
+ */
+@XmlRootElement(name = "RuleList")
+public class RESTInputRuleList implements Iterable{
+
+ private List list;
+
+
+
+ @XmlElement(name = "rule")
+ public List getList() {
+ return list;
+ }
+
+ public void setList(List userList) {
+ this.list = userList;
+ }
+
+ @Override
+ public String toString() {
+ return getClass().getSimpleName() + "[" + list.size() + " users]";
+ }
+
+ @Override
+ public Iterator iterator() {
+ return list.iterator();
+ }
+}
diff --git a/src/services/modules/rest/api/src/main/java/org/geoserver/geofence/services/rest/model/RESTOutputRule.java b/src/services/modules/rest/api/src/main/java/org/geoserver/geofence/services/rest/model/RESTOutputRule.java
index f4ef7b24..323b6272 100644
--- a/src/services/modules/rest/api/src/main/java/org/geoserver/geofence/services/rest/model/RESTOutputRule.java
+++ b/src/services/modules/rest/api/src/main/java/org/geoserver/geofence/services/rest/model/RESTOutputRule.java
@@ -20,7 +20,7 @@
* @author Etj (etj at geo-solutions.it)
*/
@XmlRootElement(name = "Rule")
-@XmlType(propOrder={"id", "priority","grant","username","rolename","instance","ipaddress","service","request","workspace","layer","constraints"})
+@XmlType(propOrder={"id", "priority","grant","username","rolename","instance","ipaddress","service","request","workspace","layer","limits","constraints"})
public class RESTOutputRule implements Serializable {
private Long id;
@@ -43,6 +43,8 @@ public class RESTOutputRule implements Serializable {
private RESTLayerConstraints constraints;
+ private RESTRuleLimits limits;
+
public RESTOutputRule() {
}
@@ -126,10 +128,18 @@ public RESTLayerConstraints getConstraints() {
return constraints;
}
+ public RESTRuleLimits getLimits() {
+ return limits;
+ }
+
public void setConstraints(RESTLayerConstraints constraints) {
this.constraints = constraints;
}
+ public void setLimits(RESTRuleLimits limits) {
+ this.limits = limits;
+ }
+
public Long getPriority() {
return priority;
}
diff --git a/src/services/modules/rest/api/src/main/java/org/geoserver/geofence/services/rest/model/RESTRuleLimits.java b/src/services/modules/rest/api/src/main/java/org/geoserver/geofence/services/rest/model/RESTRuleLimits.java
new file mode 100644
index 00000000..1c6756cf
--- /dev/null
+++ b/src/services/modules/rest/api/src/main/java/org/geoserver/geofence/services/rest/model/RESTRuleLimits.java
@@ -0,0 +1,53 @@
+/* (c) 2022 Open Source Geospatial Foundation - all rights reserved
+ * This code is licensed under the GPL 2.0 license, available at the root
+ * application directory.
+ */
+package org.geoserver.geofence.services.rest.model;
+
+import org.geoserver.geofence.core.model.enums.CatalogMode;
+import org.geoserver.geofence.core.model.enums.SpatialFilterType;
+
+import javax.xml.bind.annotation.XmlRootElement;
+import javax.xml.bind.annotation.XmlType;
+
+@XmlRootElement(name = "Limits")
+@XmlType(propOrder={"restrictedAreaWkt","spatialFilterType","catalogMode"})
+public class RESTRuleLimits {
+
+ private String restrictedAreaWkt;
+ private SpatialFilterType spatialFilterType;
+ private CatalogMode catalogMode;
+
+ public String getRestrictedAreaWkt() {
+ return restrictedAreaWkt;
+ }
+
+ public void setRestrictedAreaWkt(String restrictedAreaWkt) {
+ this.restrictedAreaWkt = restrictedAreaWkt;
+ }
+
+ public SpatialFilterType getSpatialFilterType() {
+ return spatialFilterType;
+ }
+
+ public void setSpatialFilterType(SpatialFilterType spatialFilterType) {
+ this.spatialFilterType = spatialFilterType;
+ }
+
+ public CatalogMode getCatalogMode() {
+ return catalogMode;
+ }
+
+ public void setCatalogMode(CatalogMode catalogMode) {
+ this.catalogMode = catalogMode;
+ }
+
+ @Override
+ public String toString() {
+ return "RESTRuleLimits{" +
+ "restrictedAreaWkt='" + restrictedAreaWkt + '\'' +
+ ", spatialFilterType=" + spatialFilterType +
+ ", catalogMode=" + catalogMode +
+ '}';
+ }
+}
diff --git a/src/services/modules/rest/impl/pom.xml b/src/services/modules/rest/impl/pom.xml
index 286ea511..74e4aa92 100644
--- a/src/services/modules/rest/impl/pom.xml
+++ b/src/services/modules/rest/impl/pom.xml
@@ -153,8 +153,8 @@
org.apache.maven.plugins
maven-compiler-plugin
-
- 1.6
+
+ 1.8
diff --git a/src/services/modules/rest/impl/src/main/java/org/geoserver/geofence/services/rest/impl/RESTAdminRuleServiceImpl.java b/src/services/modules/rest/impl/src/main/java/org/geoserver/geofence/services/rest/impl/RESTAdminRuleServiceImpl.java
index 79e5c50a..3b11280d 100644
--- a/src/services/modules/rest/impl/src/main/java/org/geoserver/geofence/services/rest/impl/RESTAdminRuleServiceImpl.java
+++ b/src/services/modules/rest/impl/src/main/java/org/geoserver/geofence/services/rest/impl/RESTAdminRuleServiceImpl.java
@@ -5,8 +5,13 @@
package org.geoserver.geofence.services.rest.impl;
+import java.util.ArrayList;
+import java.util.HashMap;
import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
import org.geoserver.geofence.core.model.AdminRule;
import org.geoserver.geofence.core.model.enums.InsertPosition;
@@ -20,6 +25,7 @@
import org.geoserver.geofence.services.rest.exception.GeoFenceRestEx;
import org.geoserver.geofence.services.rest.exception.InternalErrorRestEx;
import org.geoserver.geofence.services.rest.exception.NotFoundRestEx;
+import org.geoserver.geofence.services.rest.model.RESTInputAdminRuleList;
import org.geoserver.geofence.services.rest.model.util.IdName;
import org.geoserver.geofence.services.rest.model.RESTInputAdminRule;
import org.geoserver.geofence.services.rest.model.RESTOutputAdminRule;
@@ -33,6 +39,7 @@
import org.apache.log4j.LogManager;
import org.apache.log4j.Logger;
+import org.javatuples.Pair;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
@@ -61,7 +68,6 @@ public RESTOutputAdminRule get(Long id) throws BadRequestRestEx, NotFoundRestEx,
}
@Override
- @Transactional(propagation = Propagation.REQUIRED, value = "geofenceTransactionManager")
public Response insert(RESTInputAdminRule inputAdminRule) throws NotFoundRestEx, BadRequestRestEx, InternalErrorRestEx {
if (inputAdminRule.getPosition() == null || inputAdminRule.getPosition().getPosition() == null) {
@@ -74,14 +80,10 @@ public Response insert(RESTInputAdminRule inputAdminRule) throws NotFoundRestEx,
AdminRule rule = fromInput(inputAdminRule);
- InsertPosition position =
- inputAdminRule.getPosition().getPosition() == RulePosition.fixedPriority ? InsertPosition.FIXED
- : inputAdminRule.getPosition().getPosition() == RulePosition.offsetFromBottom ? InsertPosition.FROM_END
- : inputAdminRule.getPosition().getPosition() == RulePosition.offsetFromTop ? InsertPosition.FROM_START : null;
// ok: insert it
try {
- Long id = adminRuleAdminService.insert(rule, position);
+ Long id = adminRuleAdminService.insert(rule, insertPosition(inputAdminRule));
return Response.status(Status.CREATED).tag(id.toString()).entity(id).build();
} catch (BadRequestServiceEx ex) {
@@ -93,6 +95,40 @@ public Response insert(RESTInputAdminRule inputAdminRule) throws NotFoundRestEx,
}
}
+ @Override
+ public Response insertMany(RESTInputAdminRuleList inputAdminRules) throws NotFoundRestEx, BadRequestRestEx, InternalErrorRestEx {
+
+ List> rules=new ArrayList>();
+ for (RESTInputAdminRule inputAdminRule : inputAdminRules) {
+ if (inputAdminRule.getPosition() == null || inputAdminRule.getPosition().getPosition() == null) {
+ throw new BadRequestRestEx("Bad position: " + inputAdminRule.getPosition());
+ }
+
+ if (inputAdminRule.getGrant() == null) {
+ throw new BadRequestRestEx("Missing grant type");
+ }
+ rules.add(Pair.with(fromInput(inputAdminRule),insertPosition(inputAdminRule)));
+ }
+ try {
+ List ids=adminRuleAdminService.insert(rules);
+ String strIds=ids.stream().map(id->id.toString()).collect(Collectors.joining(","));
+ return Response.status(Status.CREATED).tag(strIds).entity(strIds).build();
+ } catch (BadRequestServiceEx ex) {
+ LOGGER.error(ex.getMessage());
+ throw new BadRequestRestEx(ex.getMessage());
+ } catch (Exception ex) {
+ LOGGER.error(ex.getMessage(), ex);
+ throw new InternalErrorRestEx(ex.getMessage());
+ }
+ }
+
+ private InsertPosition insertPosition(RESTInputAdminRule inputAdminRule){
+ return
+ inputAdminRule.getPosition().getPosition() == RulePosition.fixedPriority ? InsertPosition.FIXED
+ : inputAdminRule.getPosition().getPosition() == RulePosition.offsetFromBottom ? InsertPosition.FROM_END
+ : inputAdminRule.getPosition().getPosition() == RulePosition.offsetFromTop ? InsertPosition.FROM_START : null;
+ }
+
@Override
public void update(Long id, RESTInputAdminRule rule) throws BadRequestRestEx, NotFoundRestEx, InternalErrorRestEx {
diff --git a/src/services/modules/rest/impl/src/main/java/org/geoserver/geofence/services/rest/impl/RESTRuleServiceImpl.java b/src/services/modules/rest/impl/src/main/java/org/geoserver/geofence/services/rest/impl/RESTRuleServiceImpl.java
index ca5f237c..85321f79 100644
--- a/src/services/modules/rest/impl/src/main/java/org/geoserver/geofence/services/rest/impl/RESTRuleServiceImpl.java
+++ b/src/services/modules/rest/impl/src/main/java/org/geoserver/geofence/services/rest/impl/RESTRuleServiceImpl.java
@@ -5,8 +5,10 @@
package org.geoserver.geofence.services.rest.impl;
+import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
+import java.util.Map;
import java.util.Set;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status;
@@ -14,6 +16,11 @@
import org.apache.commons.lang.StringUtils;
+import org.geoserver.geofence.core.model.RuleLimits;
+import org.geoserver.geofence.services.rest.model.RESTInputRuleList;
+import org.geoserver.geofence.services.rest.model.RESTRuleLimits;
+import org.javatuples.Quartet;
+import org.javatuples.Triplet;
import org.locationtech.jts.geom.Geometry;
import org.locationtech.jts.geom.MultiPolygon;
import org.locationtech.jts.io.ParseException;
@@ -55,6 +62,7 @@
import java.util.Arrays;
import java.util.ArrayList;
import java.util.Comparator;
+import java.util.stream.Collectors;
/**
*
@@ -88,7 +96,6 @@ public RESTOutputRule get(Long id) throws BadRequestRestEx, NotFoundRestEx, Inte
}
@Override
- @Transactional(propagation = Propagation.REQUIRED, value = "geofenceTransactionManager")
public Response insert(RESTInputRule inputRule) throws NotFoundRestEx, BadRequestRestEx, InternalErrorRestEx {
if (inputRule.getPosition() == null || inputRule.getPosition().getPosition() == null) {
@@ -115,6 +122,11 @@ public Response insert(RESTInputRule inputRule) throws NotFoundRestEx, BadReques
ruleAdminService.setDetails(id, details);
}
+ RuleLimits limits=limitsFromInput(inputRule.getLimits());
+ if (limits!=null) {
+ ruleAdminService.setLimits(id,limits);
+ }
+
return Response.status(Status.CREATED).tag(id.toString()).entity(id).build();
} catch (BadRequestServiceEx ex) {
LOGGER.error(ex.getMessage());
@@ -125,6 +137,45 @@ public Response insert(RESTInputRule inputRule) throws NotFoundRestEx, BadReques
}
}
+
+ @Override
+ public Response insertMany(RESTInputRuleList inputRules) throws NotFoundRestEx, BadRequestRestEx, InternalErrorRestEx {
+
+ List> rules=
+ new ArrayList>();
+ for (RESTInputRule inputRule : inputRules) {
+ if (inputRule.getPosition() == null || inputRule.getPosition().getPosition() == null) {
+ throw new BadRequestRestEx("Bad position: " + inputRule.getPosition());
+ }
+
+ if (inputRule.getGrant() == null) {
+ throw new BadRequestRestEx("Missing grant type");
+ }
+ Rule rule = fromInput(inputRule);
+ InsertPosition insertPosition=insertPosition(inputRule);
+ RuleLimits limits=limitsFromInput(inputRule.getLimits());
+ rules.add(Quartet.with(rule, limits, detailsFromInput(inputRule),insertPosition));
+ }
+ try {
+ List ids = ruleAdminService.insert(rules);
+ String strIds=ids.stream().map(id->id.toString()).collect(Collectors.joining(","));
+ return Response.status(Status.CREATED).tag(strIds).entity(strIds).build();
+ } catch (BadRequestServiceEx ex) {
+ LOGGER.error(ex.getMessage());
+ throw new BadRequestRestEx(ex.getMessage());
+ } catch (Exception ex) {
+ LOGGER.error(ex.getMessage(), ex);
+ throw new InternalErrorRestEx(ex.getMessage());
+ }
+ }
+
+ private InsertPosition insertPosition(RESTInputRule inputRule){
+ return
+ inputRule.getPosition().getPosition() == RulePosition.fixedPriority ? InsertPosition.FIXED
+ : inputRule.getPosition().getPosition() == RulePosition.offsetFromBottom ? InsertPosition.FROM_END
+ : inputRule.getPosition().getPosition() == RulePosition.offsetFromTop ? InsertPosition.FROM_START : null;
+ }
+
@Override
public void update(Long id, RESTInputRule rule) throws BadRequestRestEx, NotFoundRestEx, InternalErrorRestEx {
@@ -579,6 +630,25 @@ protected RESTOutputRule toOutput(Rule rule) {
out.setConstraints(constraints);
}
+ if (rule.getRuleLimits()!=null){
+ RESTRuleLimits ruleLimits=new RESTRuleLimits();
+ RuleLimits limits=rule.getRuleLimits();
+ if (limits.getSpatialFilterType()!=null)
+ ruleLimits.setSpatialFilterType(limits.getSpatialFilterType());
+ if (limits.getCatalogMode()!=null)
+ ruleLimits.setCatalogMode(limits.getCatalogMode());
+ if (limits.getAllowedArea()!=null) {
+ MultiPolygon area = limits.getAllowedArea();
+ if (area != null) {
+ String areaWKT = "SRID=" + area.getSRID() + ";" + area.toText();
+ ruleLimits.setRestrictedAreaWkt(areaWKT);
+ }
+ if (limits.getSpatialFilterType()!=null)
+ ruleLimits.setSpatialFilterType(limits.getSpatialFilterType());
+ }
+ out.setLimits(ruleLimits);
+ }
+
return out;
}
@@ -608,6 +678,28 @@ protected Rule fromInput(RESTInputRule in) {
return rule;
}
+ protected RuleLimits limitsFromInput(RESTRuleLimits in){
+ RuleLimits limits=null;
+ if (in!=null && (in.getCatalogMode()!=null || in.getRestrictedAreaWkt()!=null)){
+ limits=new RuleLimits();
+ limits.setCatalogMode(in.getCatalogMode());
+ limits.setSpatialFilterType(in.getSpatialFilterType());
+ if (StringUtils.isNotBlank(in.getRestrictedAreaWkt())) {
+ if (in.getRestrictedAreaWkt() != null) {
+ Geometry g;
+ try {
+ g = toGeometryAllowedArea(in.getRestrictedAreaWkt());
+ } catch (ParseException ex) {
+ throw new BadRequestRestEx("Error parsing WKT:" + ex.getMessage());
+ }
+ limits.setAllowedArea((MultiPolygon) g);
+ }
+ }
+ }
+ return limits;
+ }
+
+
protected LayerDetails detailsFromInput(RESTInputRule in) {
RESTLayerConstraints constraints = in.getConstraints();
if (constraints != null) {
diff --git a/src/services/modules/rest/impl/src/test/java/org/geoserver/geofence/services/rest/impl/RESTAdminRuleServiceImplTest.java b/src/services/modules/rest/impl/src/test/java/org/geoserver/geofence/services/rest/impl/RESTAdminRuleServiceImplTest.java
new file mode 100644
index 00000000..5a88c6d8
--- /dev/null
+++ b/src/services/modules/rest/impl/src/test/java/org/geoserver/geofence/services/rest/impl/RESTAdminRuleServiceImplTest.java
@@ -0,0 +1,63 @@
+package org.geoserver.geofence.services.rest.impl;
+
+import org.geoserver.geofence.core.model.enums.AdminGrantType;
+import org.geoserver.geofence.core.model.enums.GrantType;
+import org.geoserver.geofence.services.rest.exception.BadRequestRestEx;
+import org.geoserver.geofence.services.rest.model.RESTInputAdminRule;
+import org.geoserver.geofence.services.rest.model.RESTInputAdminRuleList;
+import org.geoserver.geofence.services.rest.model.RESTInputGroup;
+import org.geoserver.geofence.services.rest.model.RESTInputRule;
+import org.geoserver.geofence.services.rest.model.RESTInputUser;
+import org.geoserver.geofence.services.rest.model.RESTOutputAdminRule;
+import org.geoserver.geofence.services.rest.model.RESTOutputRule;
+import org.geoserver.geofence.services.rest.model.RESTRulePosition;
+import org.geoserver.geofence.services.rest.model.util.IdName;
+import org.junit.Test;
+
+import javax.ws.rs.core.Response;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.stream.Collectors;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.fail;
+
+public class RESTAdminRuleServiceImplTest extends RESTBaseTest {
+
+ @Test
+ public void testInsert() {
+ List inputAdminRules=new ArrayList<>();
+ RESTInputAdminRule adminRule=new RESTInputAdminRule();
+ adminRule.setPosition(new RESTRulePosition(RESTRulePosition.RulePosition.offsetFromTop, 0));
+ adminRule.setGrant(AdminGrantType.ADMIN);
+ adminRule.setRolename("ROLE_TEST1");
+ adminRule.setWorkspace("wsAdmin00");
+ inputAdminRules.add(adminRule);
+ RESTInputAdminRule adminRule2=new RESTInputAdminRule();
+ adminRule2.setGrant(AdminGrantType.USER);
+ adminRule2.setPosition(new RESTRulePosition(RESTRulePosition.RulePosition.offsetFromTop, 1));
+ adminRule2.setRolename("ROLE_TEST2");
+ adminRule2.setWorkspace("wsAdmin01");
+ RESTInputAdminRuleList list=new RESTInputAdminRuleList();
+ list.setList(inputAdminRules);
+ Response res = restAdminRuleService.insertMany(list);
+ String ids = (String) res.getEntity();
+ assertNotNull(ids);
+ List longList= Arrays.asList(ids.split(",")).stream().map(s->Long.valueOf(s)).collect(Collectors.toList());
+ for(Long id: longList) {
+ RESTOutputAdminRule out = restAdminRuleService.get(id);
+ assertNotNull(out);
+ String ws=out.getWorkspace();
+ if (ws.equals("wsAdmin00")){
+ assertEquals("ROLE_TEST1",out.getRolename());
+ assertEquals(AdminGrantType.ADMIN,out.getGrant());
+ } else {
+ assertEquals("ROLE_TEST2",out.getRolename());
+ assertEquals(AdminGrantType.USER,out.getGrant());
+ }
+ }
+ }
+}
diff --git a/src/services/modules/rest/impl/src/test/java/org/geoserver/geofence/services/rest/impl/RESTBaseTest.java b/src/services/modules/rest/impl/src/test/java/org/geoserver/geofence/services/rest/impl/RESTBaseTest.java
index 53bb3590..cec2584b 100644
--- a/src/services/modules/rest/impl/src/test/java/org/geoserver/geofence/services/rest/impl/RESTBaseTest.java
+++ b/src/services/modules/rest/impl/src/test/java/org/geoserver/geofence/services/rest/impl/RESTBaseTest.java
@@ -7,6 +7,7 @@
import org.geoserver.geofence.services.RuleAdminService;
import org.geoserver.geofence.services.dto.ShortGroup;
+import org.geoserver.geofence.services.rest.RESTAdminRuleService;
import org.geoserver.geofence.services.rest.RESTRuleService;
import org.geoserver.geofence.services.rest.RESTUserGroupService;
import org.geoserver.geofence.services.rest.RESTUserService;
@@ -39,6 +40,7 @@ public abstract class RESTBaseTest {
protected static RESTUserService restUserService;
protected static RESTUserGroupService restUserGroupService;
protected static RESTRuleService restRuleService;
+ protected static RESTAdminRuleService restAdminRuleService;
public RESTBaseTest() {
@@ -59,6 +61,7 @@ public RESTBaseTest() {
restUserService = (RESTUserService)ctx.getBean("restUserService");
restUserGroupService = (RESTUserGroupService)ctx.getBean("restUserGroupService");
restRuleService = (RESTRuleService)ctx.getBean("restRuleService");
+ restAdminRuleService = (RESTAdminRuleService) ctx.getBean("restAdminRuleService");
}
assertNotNull(restUserService);
diff --git a/src/services/modules/rest/impl/src/test/java/org/geoserver/geofence/services/rest/impl/RESTRuleServiceImplTest.java b/src/services/modules/rest/impl/src/test/java/org/geoserver/geofence/services/rest/impl/RESTRuleServiceImplTest.java
index a470b3f8..ce802b8d 100644
--- a/src/services/modules/rest/impl/src/test/java/org/geoserver/geofence/services/rest/impl/RESTRuleServiceImplTest.java
+++ b/src/services/modules/rest/impl/src/test/java/org/geoserver/geofence/services/rest/impl/RESTRuleServiceImplTest.java
@@ -5,8 +5,14 @@
package org.geoserver.geofence.services.rest.impl;
+import java.util.List;
+
import org.geoserver.geofence.core.model.Rule;
+import org.geoserver.geofence.core.model.enums.CatalogMode;
+import org.geoserver.geofence.core.model.enums.LayerType;
+import org.geoserver.geofence.core.model.enums.SpatialFilterType;
import org.geoserver.geofence.services.RuleAdminService;
+import org.geoserver.geofence.services.rest.model.RESTInputRuleList;
import org.geoserver.geofence.services.rest.model.RESTInputUser;
import org.geoserver.geofence.services.rest.model.RESTInputRule;
import org.geoserver.geofence.services.rest.model.RESTOutputRule;
@@ -16,10 +22,12 @@
import org.geoserver.geofence.core.model.enums.AccessType;
import org.geoserver.geofence.core.model.enums.GrantType;
import org.geoserver.geofence.services.rest.exception.BadRequestRestEx;
+import org.geoserver.geofence.services.rest.model.RESTRuleLimits;
import org.geoserver.geofence.services.rest.model.util.IdName;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
+import java.util.stream.Collectors;
import javax.ws.rs.core.Response;
import org.apache.log4j.LogManager;
import org.apache.log4j.Logger;
@@ -332,5 +340,154 @@ public void testAllowedAreaSRID() {
}
+ @Test
+ public void testInsertAll() {
+ RESTInputGroup group = new RESTInputGroup();
+ group.setName("g1");
+ restUserGroupService.insert(group);
+
+ RESTInputUser user = new RESTInputUser();
+ user.setName("user0");
+ user.setEnabled(Boolean.TRUE);
+ user.setGroups(new ArrayList());
+ user.getGroups().add(new IdName("g1"));
+ restUserService.insert(user);
+
+ RESTInputRule rule0 = new RESTInputRule();
+ rule0.setUsername("user0");
+ rule0.setPosition(new RESTRulePosition(RESTRulePosition.RulePosition.offsetFromTop, 0));
+ rule0.setGrant(GrantType.ALLOW);
+ RESTInputRule rule1 = new RESTInputRule();
+ rule1.setUsername("user1");
+ rule1.setPosition(new RESTRulePosition(RESTRulePosition.RulePosition.offsetFromTop, 0));
+ rule1.setGrant(GrantType.ALLOW);
+ List rules = new ArrayList();
+ rules.add(rule0);
+ rules.add(rule1);
+ RESTInputRuleList list= new RESTInputRuleList();
+ list.setList(rules);
+ String ids = (String) restRuleService.insertMany(list).getEntity();
+ assertNotNull(ids);
+ List longList=Arrays.asList(ids.split(",")).stream().map(s->Long.valueOf(s)).collect(Collectors.toList());
+ for(Long id: longList) {
+ RESTOutputRule out = restRuleService.get(id);
+ assertNotNull(out);
+ }
+ }
+
+ @Test
+ public void testLimits() {
+
+ RESTInputRule rule = new RESTInputRule();
+ rule.setPosition(new RESTRulePosition(RESTRulePosition.RulePosition.fixedPriority, 42));
+ rule.setGrant(GrantType.ALLOW);
+ rule.setWorkspace("wLimits0");
+ rule.setLayer("lLimits0");
+ restRuleService.insert(rule);
+ rule = new RESTInputRule();
+ rule.setPosition(new RESTRulePosition(RESTRulePosition.RulePosition.offsetFromTop, 0));
+ rule.setGrant(GrantType.LIMIT);
+ rule.setWorkspace("wLimits0");
+ rule.setLayer("lLimits0");
+
+ RESTRuleLimits limits = new RESTRuleLimits();
+ String allowedArea = "MULTIPOLYGON (((4146.5 1301.4, 4147.5 1301.1, 4147.8 1301.4, 4146.5 1301.4)))";
+ limits.setRestrictedAreaWkt(allowedArea);
+ limits.setCatalogMode(CatalogMode.HIDE);
+ limits.setSpatialFilterType(SpatialFilterType.CLIP);
+ rule.setLimits(limits);
+
+ Long rid = (Long) restRuleService.insert(rule).getEntity();
+ assertNotNull(rid);
+ RESTOutputRule out = restRuleService.get(rid);
+ assertNotNull(out);
+ limits = out.getLimits();
+ assertEquals(CatalogMode.HIDE, limits.getCatalogMode());
+ assertEquals(SpatialFilterType.CLIP, limits.getSpatialFilterType());
+ assertEquals("SRID=4326;" + allowedArea, limits.getRestrictedAreaWkt());
+ }
+
+ @Test
+ public void testInsertAllWithLimits() {
+
+ RESTInputRule rule0 = new RESTInputRule();
+ rule0.setWorkspace("wsLimits01");
+ rule0.setPosition(new RESTRulePosition(RESTRulePosition.RulePosition.offsetFromTop, 30));
+ rule0.setGrant(GrantType.ALLOW);
+ restRuleService.insert(rule0);
+
+ RESTInputRule rule1 = new RESTInputRule();
+ rule1.setWorkspace("wsLimits01");
+ rule1.setUsername("userLimits01");
+ rule1.setPosition(new RESTRulePosition(RESTRulePosition.RulePosition.offsetFromTop, 30));
+ rule1.setGrant(GrantType.LIMIT);
+ RESTRuleLimits limits=new RESTRuleLimits();
+ limits.setCatalogMode(CatalogMode.HIDE);
+ rule1.setLimits(limits);
+ RESTInputRule rule2 = new RESTInputRule();
+ rule2.setWorkspace("wsLimits01");
+ rule2.setUsername("userLimits02");
+ rule2.setPosition(new RESTRulePosition(RESTRulePosition.RulePosition.offsetFromTop, 0));
+ rule2.setGrant(GrantType.LIMIT);
+ limits=new RESTRuleLimits();
+ limits.setCatalogMode(CatalogMode.HIDE);
+ rule2.setLimits(limits);
+ List rules = new ArrayList();
+ rules.add(rule1);
+ rules.add(rule2);
+ RESTInputRuleList list= new RESTInputRuleList();
+ list.setList(rules);
+ String ids = (String) restRuleService.insertMany(list).getEntity();
+ assertNotNull(ids);
+ List longList=Arrays.asList(ids.split(",")).stream().map(s->Long.valueOf(s)).collect(Collectors.toList());
+ for(Long id: longList) {
+ RESTOutputRule out = restRuleService.get(id);
+ assertNotNull(out);
+ assertNotNull(out.getLimits());
+ assertEquals(CatalogMode.HIDE, out.getLimits().getCatalogMode());
+ }
+ }
+
+
+ @Test
+ public void testInsertAllWithConstraints() {
+
+ RESTInputRule rule1 = new RESTInputRule();
+ rule1.setWorkspace("wsConstraints00");
+ rule1.setUsername("userConstraints00");
+ rule1.setLayer("layerConstraints00");
+ rule1.setPosition(new RESTRulePosition(RESTRulePosition.RulePosition.offsetFromTop, 1));
+ rule1.setGrant(GrantType.ALLOW);
+ RESTLayerConstraints constraints = new RESTLayerConstraints();
+ constraints.setType(LayerType.VECTOR);
+ constraints.setAllowedStyles(new HashSet<>(Arrays.asList("s1","s2")));
+ rule1.setConstraints(constraints);
+ RESTInputRule rule2 = new RESTInputRule();
+ rule2.setWorkspace("wsConstraints01");
+ rule2.setUsername("userConstraints01");
+ rule2.setLayer("layerConstraints01");
+
+ rule2.setPosition(new RESTRulePosition(RESTRulePosition.RulePosition.offsetFromTop, 0));
+ rule2.setGrant(GrantType.ALLOW);
+ constraints = new RESTLayerConstraints();
+ constraints.setType(LayerType.VECTOR);
+ constraints.setAllowedStyles(new HashSet<>(Arrays.asList("s1","s2")));
+ rule2.setConstraints(constraints);
+ List rules = new ArrayList();
+ rules.add(rule1);
+ rules.add(rule2);
+ RESTInputRuleList list= new RESTInputRuleList();
+ list.setList(rules);
+ String ids = (String) restRuleService.insertMany(list).getEntity();
+ assertNotNull(ids);
+ List longList=Arrays.asList(ids.split(",")).stream().map(s->Long.valueOf(s)).collect(Collectors.toList());
+ for(Long id: longList) {
+ RESTOutputRule out = restRuleService.get(id);
+ assertNotNull(out);
+ assertNotNull(out.getConstraints());
+ assertEquals(2,out.getConstraints().getAllowedStyles().size());
+ }
+ }
+
}
diff --git a/src/services/pom.xml b/src/services/pom.xml
index adb1c861..0dc3877b 100644
--- a/src/services/pom.xml
+++ b/src/services/pom.xml
@@ -797,6 +797,12 @@
gt-epsg-wkt
${gt-version}
+
+
+ org.javatuples
+ javatuples
+ 1.2
+