Profiles interface
This commit is contained in:
parent
aa5717b78a
commit
8b5f25cb75
|
@ -93,6 +93,13 @@
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
|
||||||
|
<!-- POSTGRES DRIVERS -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>net.postgis</groupId>
|
||||||
|
<artifactId>postgis-jdbc</artifactId>
|
||||||
|
<version>2.5.0</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
<!-- SDI -->
|
<!-- SDI -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.gcube.spatial.data</groupId>
|
<groupId>org.gcube.spatial.data</groupId>
|
||||||
|
@ -100,12 +107,6 @@
|
||||||
<version>[2.4.6,3.0.0)</version>
|
<version>[2.4.6,3.0.0)</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<!-- POSTGRES DRIVERS -->
|
|
||||||
<dependency>
|
|
||||||
<groupId>net.postgis</groupId>
|
|
||||||
<artifactId>postgis-jdbc</artifactId>
|
|
||||||
<version>2.5.0</version>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<!-- GS communication -->
|
<!-- GS communication -->
|
||||||
<!-- <dependency>-->
|
<!-- <dependency>-->
|
||||||
|
@ -216,6 +217,12 @@
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.gcube.application.cms</groupId>
|
||||||
|
<artifactId>sdi-plugins</artifactId>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>junit</groupId>
|
<groupId>junit</groupId>
|
||||||
<artifactId>junit</artifactId>
|
<artifactId>junit</artifactId>
|
||||||
|
|
|
@ -0,0 +1,22 @@
|
||||||
|
package org.gcube.application.geoportal.service.engine.mongo;
|
||||||
|
|
||||||
|
import org.bson.Document;
|
||||||
|
import org.gcube.application.cms.caches.Engine;
|
||||||
|
import org.gcube.application.geoportal.common.model.document.ProfiledDocument;
|
||||||
|
import org.gcube.application.geoportal.common.model.profile.Profile;
|
||||||
|
import org.gcube.application.geoportal.common.model.rest.QueryRequest;
|
||||||
|
|
||||||
|
import java.util.Iterator;
|
||||||
|
|
||||||
|
public interface ProfileManager {
|
||||||
|
|
||||||
|
public Profile create(Document toCreate);
|
||||||
|
|
||||||
|
public Iterable<Profile> query(QueryRequest request);
|
||||||
|
|
||||||
|
public void deleteById(String id,boolean force);
|
||||||
|
|
||||||
|
public Profile update(String ID, Document toSet);
|
||||||
|
|
||||||
|
public Profile getById(String id);
|
||||||
|
}
|
|
@ -312,7 +312,11 @@ public class ProfiledMongoManager extends MongoManager implements MongoManagerI<
|
||||||
if(matchingPaths.isEmpty()) throw new WebApplicationException("PArent path not found at "+request.getParentPath(),Response.Status.BAD_REQUEST);
|
if(matchingPaths.isEmpty()) throw new WebApplicationException("PArent path not found at "+request.getParentPath(),Response.Status.BAD_REQUEST);
|
||||||
|
|
||||||
String parentMatchingPath = matchingPaths.get(0);
|
String parentMatchingPath = matchingPaths.get(0);
|
||||||
Document parent = Serialization.asDocument(docWrapper.getByPath(parentMatchingPath).get(0));
|
List<Object> foundElementsByMatchingPaths = docWrapper.getByPath(parentMatchingPath);
|
||||||
|
if(foundElementsByMatchingPaths == null || foundElementsByMatchingPaths.isEmpty())
|
||||||
|
throw new WebApplicationException("No element found at "+ parentMatchingPath,Response.Status.BAD_REQUEST);
|
||||||
|
|
||||||
|
Document parent = Serialization.asDocument(foundElementsByMatchingPaths.get(0));
|
||||||
|
|
||||||
|
|
||||||
// PREPARE REGISTERED FS
|
// PREPARE REGISTERED FS
|
||||||
|
|
|
@ -25,8 +25,8 @@ public class PostgisDBManager implements PostgisDBManagerI {
|
||||||
|
|
||||||
// TODO GENERIC
|
// TODO GENERIC
|
||||||
DatabaseConnection defaultConfiguration=
|
DatabaseConnection defaultConfiguration=
|
||||||
((ISUtils)ImplementationProvider.get().getEngineByClass(ISInterface.class))
|
ImplementationProvider.get().getEngineByClass(ISInterface.class)
|
||||||
.queryForDB("postgis", "Concessioni");
|
.queryForDatabase("Database","postgis", "GNA_DB","Concessioni");
|
||||||
|
|
||||||
log.debug("Found configuration : "+defaultConfiguration);
|
log.debug("Found configuration : "+defaultConfiguration);
|
||||||
config=defaultConfiguration;
|
config=defaultConfiguration;
|
||||||
|
|
|
@ -6,6 +6,7 @@ import lombok.extern.slf4j.Slf4j;
|
||||||
import org.gcube.application.cms.caches.AbstractScopedMap;
|
import org.gcube.application.cms.caches.AbstractScopedMap;
|
||||||
import org.gcube.application.cms.plugins.*;
|
import org.gcube.application.cms.plugins.*;
|
||||||
import org.gcube.application.cms.plugins.faults.InitializationException;
|
import org.gcube.application.cms.plugins.faults.InitializationException;
|
||||||
|
import org.gcube.application.cms.plugins.faults.PluginExecutionException;
|
||||||
import org.gcube.application.cms.plugins.faults.ShutDownException;
|
import org.gcube.application.cms.plugins.faults.ShutDownException;
|
||||||
import org.gcube.application.cms.plugins.reports.InitializationReport;
|
import org.gcube.application.cms.plugins.reports.InitializationReport;
|
||||||
import org.gcube.application.geoportal.common.model.profile.Profile;
|
import org.gcube.application.geoportal.common.model.profile.Profile;
|
||||||
|
@ -115,18 +116,26 @@ public class PluginManager extends AbstractScopedMap<PluginManager.PluginMap> im
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final void logReport(Plugin p, InitializationReport report){
|
private static final void logReport(Plugin p, InitializationReport report){
|
||||||
switch(report.getStatus()){
|
if(report==null)
|
||||||
|
log.warn("WARNING : Initialization Report by {} IS null ",p.getDescriptor().getId());
|
||||||
|
else
|
||||||
|
try {
|
||||||
|
report.validate();
|
||||||
|
switch (report.getStatus()) {
|
||||||
case ERROR: {
|
case ERROR: {
|
||||||
log.error("Plugin [{}] STATUS : {}, INFO {} ",p.getDescriptor().getId(),report.getStatus(),report.getMessages());
|
log.error("Plugin [{}] STATUS : {}, INFO {} ", p.getDescriptor().getId(), report.getStatus(), report.getMessages());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case WARNING: {
|
case WARNING: {
|
||||||
log.warn("Plugin [{}] STATUS : {}, INFO {} ",p.getDescriptor().getId(),report.getStatus(),report.getMessages());
|
log.warn("Plugin [{}] STATUS : {}, INFO {} ", p.getDescriptor().getId(), report.getStatus(), report.getMessages());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default :{
|
default: {
|
||||||
log.info("Plugin [{}] STATUS : {}, INFO {} ",p.getDescriptor().getId(),report.getStatus(),report.getMessages());
|
log.info("Plugin [{}] STATUS : {}, INFO {} ", p.getDescriptor().getId(), report.getStatus(), report.getMessages());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}catch (PluginExecutionException e) {
|
||||||
|
log.warn("Invalid report provided by {} ",p.getDescriptor().getId(),e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,94 @@
|
||||||
|
package org.gcube.application.geoportal.service.rest;
|
||||||
|
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.bson.Document;
|
||||||
|
import org.gcube.application.cms.serialization.Serialization;
|
||||||
|
import org.gcube.application.geoportal.common.model.document.ProfiledDocument;
|
||||||
|
import org.gcube.application.geoportal.common.model.profile.Profile;
|
||||||
|
import org.gcube.application.geoportal.common.rest.InterfaceConstants;
|
||||||
|
import org.gcube.application.geoportal.service.engine.mongo.ProfileManager;
|
||||||
|
|
||||||
|
import javax.ws.rs.*;
|
||||||
|
import javax.ws.rs.core.MediaType;
|
||||||
|
|
||||||
|
@Path(InterfaceConstants.Methods.PROFILES)
|
||||||
|
@Slf4j
|
||||||
|
public class UseCaseDescriptors {
|
||||||
|
|
||||||
|
private ProfileManager profileEngine;
|
||||||
|
|
||||||
|
|
||||||
|
@POST
|
||||||
|
@Consumes(MediaType.APPLICATION_JSON)
|
||||||
|
@Produces(MediaType.APPLICATION_JSON)
|
||||||
|
public Profile createNew(Document toCreate) {
|
||||||
|
return new GuardedMethod<Profile>() {
|
||||||
|
@Override
|
||||||
|
protected Profile run() throws Exception, WebApplicationException {
|
||||||
|
log.info("Creating new Profile ({})",toCreate);
|
||||||
|
Profile toReturn= profileEngine.create(toCreate);
|
||||||
|
log.info("Created new Profile (ID {})",toReturn.getId());
|
||||||
|
return toReturn;
|
||||||
|
}
|
||||||
|
}.execute().getResult();
|
||||||
|
}
|
||||||
|
|
||||||
|
@PUT
|
||||||
|
@Path("{"+InterfaceConstants.Parameters.PROFILE_ID+"}")
|
||||||
|
@Consumes(MediaType.APPLICATION_JSON)
|
||||||
|
@Produces(MediaType.APPLICATION_JSON)
|
||||||
|
public Profile update(@PathParam(InterfaceConstants.Parameters.PROFILE_ID) String profileId, Document d) {
|
||||||
|
return new GuardedMethod<Profile>() {
|
||||||
|
@Override
|
||||||
|
protected Profile run() throws Exception, WebApplicationException {
|
||||||
|
log.warn("Updating Profile ({})",profileId);
|
||||||
|
return profileEngine.update(profileId,d);
|
||||||
|
}
|
||||||
|
}.execute().getResult();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@DELETE
|
||||||
|
@Produces(MediaType.APPLICATION_JSON)
|
||||||
|
@Path("{"+InterfaceConstants.Parameters.PROFILE_ID+"}")
|
||||||
|
public Boolean delete(@PathParam(InterfaceConstants.Parameters.PROFILE_ID) String id,
|
||||||
|
@DefaultValue("false")
|
||||||
|
@QueryParam(InterfaceConstants.Parameters.FORCE) Boolean force) {
|
||||||
|
return new GuardedMethod<Boolean>() {
|
||||||
|
@Override
|
||||||
|
protected Boolean run() throws Exception, WebApplicationException {
|
||||||
|
log.warn("Deleting Profile (ID {}). Force is {}",id,force);
|
||||||
|
profileEngine.deleteById(id,force);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}.execute().getResult();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// BY ID
|
||||||
|
@GET
|
||||||
|
@Produces(MediaType.APPLICATION_JSON)
|
||||||
|
@Path("{"+InterfaceConstants.Parameters.PROFILE_ID+"}")
|
||||||
|
public Profile getById(@PathParam(InterfaceConstants.Parameters.PROFILE_ID) String id) {
|
||||||
|
return new GuardedMethod<Profile>() {
|
||||||
|
@Override
|
||||||
|
protected Profile run() throws Exception, WebApplicationException {
|
||||||
|
return profileEngine.getById(id);
|
||||||
|
}
|
||||||
|
}.execute().getResult();
|
||||||
|
}
|
||||||
|
|
||||||
|
@POST
|
||||||
|
@Consumes(MediaType.APPLICATION_JSON)
|
||||||
|
@Produces(MediaType.APPLICATION_JSON)
|
||||||
|
@Path("/"+InterfaceConstants.Methods.QUERY_PATH)
|
||||||
|
public Iterable<?> query(String queryString){
|
||||||
|
return new GuardedMethod<Iterable<?>>() {
|
||||||
|
@Override
|
||||||
|
protected Iterable<?> run() throws Exception, WebApplicationException {
|
||||||
|
return profileEngine.query(Serialization.parseQuery(queryString));
|
||||||
|
}
|
||||||
|
}.execute().getResult();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -92,79 +92,79 @@ public class DummyProfiledDocumentTest extends AbstractProfiledDocumentsTests{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
// @Test
|
||||||
public void testSDI() throws Exception {
|
// public void testSDI() throws Exception {
|
||||||
// Create new
|
// // Create new
|
||||||
ProfiledDocument doc = createNew(new Document("posizionamentoScavo",new Document("title","Mio pos")));
|
// ProfiledDocument doc = createNew(new Document("posizionamentoScavo",new Document("title","Mio pos")));
|
||||||
|
//
|
||||||
// register filesets
|
// // register filesets
|
||||||
doc = upload(
|
// doc = upload(
|
||||||
new StorageUtils(),
|
// new StorageUtils(),
|
||||||
doc.getId(),
|
// doc.getId(),
|
||||||
"posizionamentoScavo","fileset",
|
// "posizionamentoScavo","fileset",
|
||||||
"posizionamentoScavo."+Field.CHILDREN+"[?(@.fileset)]",
|
// "posizionamentoScavo."+Field.CHILDREN+"[?(@.fileset)]",
|
||||||
null,
|
// null,
|
||||||
RegisterFileSetRequest.ClashOptions.REPLACE_EXISTING,
|
// RegisterFileSetRequest.ClashOptions.REPLACE_EXISTING,
|
||||||
"pos.shp","pos.shx");
|
// "pos.shp","pos.shx");
|
||||||
|
//
|
||||||
System.out.println("Registered posizionamento, result is "+ Serialization.write(doc));
|
// System.out.println("Registered posizionamento, result is "+ Serialization.write(doc));
|
||||||
|
//
|
||||||
// invoke step SUBMIT-FOR-REVIEW
|
// // invoke step SUBMIT-FOR-REVIEW
|
||||||
StepExecutionRequest req=new StepExecutionRequest();
|
// StepExecutionRequest req=new StepExecutionRequest();
|
||||||
req.setStepID("SUBMIT-FOR-REVIEW");
|
// req.setStepID("SUBMIT-FOR-REVIEW");
|
||||||
doc=step(doc.getId(),req);
|
// doc=step(doc.getId(),req);
|
||||||
System.out.println(doc);
|
// System.out.println(doc);
|
||||||
if(doc.getLifecycleInformation().getErrorMessages()!=null) {
|
// if(doc.getLifecycleInformation().getErrorMessages()!=null) {
|
||||||
System.out.println("ERROR MESSAGES");
|
// System.out.println("ERROR MESSAGES");
|
||||||
doc.getLifecycleInformation().getErrorMessages().forEach(s -> System.out.println(s));
|
// doc.getLifecycleInformation().getErrorMessages().forEach(s -> System.out.println(s));
|
||||||
}
|
// }
|
||||||
if(doc.getLifecycleInformation().getWarningMessages()!=null) {
|
// if(doc.getLifecycleInformation().getWarningMessages()!=null) {
|
||||||
System.out.println("WARNING MESSAGES");
|
// System.out.println("WARNING MESSAGES");
|
||||||
doc.getLifecycleInformation().getWarningMessages().forEach(s -> System.out.println(s));
|
// doc.getLifecycleInformation().getWarningMessages().forEach(s -> System.out.println(s));
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
assertTrue(doc.getLifecycleInformation().getLastOperationStatus().equals(LifecycleInformation.Status.OK));
|
// assertTrue(doc.getLifecycleInformation().getLastOperationStatus().equals(LifecycleInformation.Status.OK));
|
||||||
|
//
|
||||||
JSONPathWrapper wrapper = new JSONPathWrapper(doc.getTheDocument().toJson());
|
// JSONPathWrapper wrapper = new JSONPathWrapper(doc.getTheDocument().toJson());
|
||||||
RegisteredFileSet fs = Serialization.convert(wrapper.getByPath("$..fileset").get(0),RegisteredFileSet.class);
|
// RegisteredFileSet fs = Serialization.convert(wrapper.getByPath("$..fileset").get(0),RegisteredFileSet.class);
|
||||||
assertTrue(fs!=null);
|
// assertTrue(fs!=null);
|
||||||
assertTrue(fs.getPayloads().size()==2);
|
// assertTrue(fs.getPayloads().size()==2);
|
||||||
assertTrue(fs.getMaterializations().size()>0);
|
// assertTrue(fs.getMaterializations().size()>0);
|
||||||
|
//
|
||||||
|
//
|
||||||
for(Object matObj : wrapper.getByPath("$..[?(@."+ Materialization.TYPE +" == '"+GCubeSDILayer.GCUBE_SDY_LAYER_TYPE+"' )]")){
|
// for(Object matObj : wrapper.getByPath("$..[?(@."+ Materialization.TYPE +" == '"+GCubeSDILayer.GCUBE_SDY_LAYER_TYPE+"' )]")){
|
||||||
GCubeSDILayer layer = Serialization.convert(matObj, GCubeSDILayer.class);
|
// GCubeSDILayer layer = Serialization.convert(matObj, GCubeSDILayer.class);
|
||||||
System.out.println("Checking Layer : "+layer);
|
// System.out.println("Checking Layer : "+layer);
|
||||||
assertTrue(layer.getType().equals(GCubeSDILayer.GCUBE_SDY_LAYER_TYPE));
|
// assertTrue(layer.getType().equals(GCubeSDILayer.GCUBE_SDY_LAYER_TYPE));
|
||||||
assertTrue(layer.getOGCLinks().size()>0);
|
// assertTrue(layer.getOGCLinks().size()>0);
|
||||||
assertTrue(layer.getPlatformInfo().size()>0);
|
// assertTrue(layer.getPlatformInfo().size()>0);
|
||||||
assertTrue(layer.getBBox()!=null);
|
// assertTrue(layer.getBBox()!=null);
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
// Checking platform info GeoServer
|
// // Checking platform info GeoServer
|
||||||
for(Object platformObj : wrapper.getByPath("$..[?(@."+ Materialization.TYPE +" == 'GeoServer' )]")){
|
// for(Object platformObj : wrapper.getByPath("$..[?(@."+ Materialization.TYPE +" == 'GeoServer' )]")){
|
||||||
Document platform=Serialization.asDocument(platformObj);
|
// Document platform=Serialization.asDocument(platformObj);
|
||||||
assertTrue(platform.containsKey("layerName"));
|
// assertTrue(platform.containsKey("layerName"));
|
||||||
assertTrue(platform.containsKey("workspace"));
|
// assertTrue(platform.containsKey("workspace"));
|
||||||
assertTrue(platform.containsKey("storeName"));
|
// assertTrue(platform.containsKey("storeName"));
|
||||||
assertTrue(platform.containsKey("persistencePath"));
|
// assertTrue(platform.containsKey("persistencePath"));
|
||||||
assertTrue(platform.get("files",List.class).size()==2);
|
// assertTrue(platform.get("files",List.class).size()==2);
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
|
//
|
||||||
req.setStepID("APPROVE DRAFT");
|
// req.setStepID("APPROVE DRAFT");
|
||||||
doc=step(doc.getId(),req);
|
// doc=step(doc.getId(),req);
|
||||||
if(doc.getLifecycleInformation().getErrorMessages()!=null) {
|
// if(doc.getLifecycleInformation().getErrorMessages()!=null) {
|
||||||
System.out.println("ERROR MESSAGES");
|
// System.out.println("ERROR MESSAGES");
|
||||||
doc.getLifecycleInformation().getErrorMessages().forEach(s -> System.out.println(s));
|
// doc.getLifecycleInformation().getErrorMessages().forEach(s -> System.out.println(s));
|
||||||
}
|
// }
|
||||||
if(doc.getLifecycleInformation().getWarningMessages()!=null) {
|
// if(doc.getLifecycleInformation().getWarningMessages()!=null) {
|
||||||
System.out.println("WARNING MESSAGES");
|
// System.out.println("WARNING MESSAGES");
|
||||||
doc.getLifecycleInformation().getWarningMessages().forEach(s -> System.out.println(s));
|
// doc.getLifecycleInformation().getWarningMessages().forEach(s -> System.out.println(s));
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
assertTrue(doc.getLifecycleInformation().getLastOperationStatus().equals(LifecycleInformation.Status.OK));
|
// assertTrue(doc.getLifecycleInformation().getLastOperationStatus().equals(LifecycleInformation.Status.OK));
|
||||||
|
//
|
||||||
}
|
// }
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@ import org.bson.Document;
|
||||||
import org.gcube.application.cms.serialization.Serialization;
|
import org.gcube.application.cms.serialization.Serialization;
|
||||||
import org.gcube.application.geoportal.common.model.document.ProfiledDocument;
|
import org.gcube.application.geoportal.common.model.document.ProfiledDocument;
|
||||||
import org.gcube.application.geoportal.common.model.document.lifecycle.LifecycleInformation;
|
import org.gcube.application.geoportal.common.model.document.lifecycle.LifecycleInformation;
|
||||||
|
import org.gcube.application.geoportal.common.model.profile.Field;
|
||||||
import org.gcube.application.geoportal.common.model.rest.RegisterFileSetRequest;
|
import org.gcube.application.geoportal.common.model.rest.RegisterFileSetRequest;
|
||||||
import org.gcube.application.geoportal.common.model.rest.StepExecutionRequest;
|
import org.gcube.application.geoportal.common.model.rest.StepExecutionRequest;
|
||||||
import org.gcube.application.geoportal.common.rest.InterfaceConstants;
|
import org.gcube.application.geoportal.common.rest.InterfaceConstants;
|
||||||
|
@ -27,15 +28,21 @@ public class ProfiledConcessioniTests extends AbstractProfiledDocumentsTests{
|
||||||
@Test
|
@Test
|
||||||
public void testSDI() throws Exception {
|
public void testSDI() throws Exception {
|
||||||
// Create new
|
// Create new
|
||||||
ProfiledDocument doc = createNew(new Document());
|
Document theDoc=Document.parse("{\n" +
|
||||||
|
"\"posizionamentoScavo\" :{\n" +
|
||||||
|
"\t\"titolo\" : \"mio titolo\"}}");
|
||||||
|
|
||||||
|
ProfiledDocument doc = createNew(theDoc);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// register filesets
|
// register filesets
|
||||||
doc = upload(
|
doc = upload(
|
||||||
new StorageUtils(),
|
new StorageUtils(),
|
||||||
doc.getId(),
|
doc.getId(),
|
||||||
"posizionamentoScavo","fileset",
|
"posizionamentoScavo","fileset",
|
||||||
"posizionamentoScavo.children[?(@.fileset)]",
|
"posizionamentoScavo."+ Field.CHILDREN+"[?(@.fileset)]",
|
||||||
Document.parse("{\"titolo\" : \"mio titolo\",\"some\" : \"something\" }"),
|
null,
|
||||||
RegisterFileSetRequest.ClashOptions.MERGE_EXISTING,
|
RegisterFileSetRequest.ClashOptions.MERGE_EXISTING,
|
||||||
"pos.shp");
|
"pos.shp");
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue