2022-03-23 18:38:07 +01:00
|
|
|
package org.gcube.application.geoportal.service.engine.providers.ucd;
|
|
|
|
|
|
|
|
import lombok.*;
|
|
|
|
import lombok.extern.slf4j.Slf4j;
|
|
|
|
import org.gcube.application.cms.caches.AbstractScopedMap;
|
2022-04-27 19:36:10 +02:00
|
|
|
import org.gcube.application.cms.caches.ObjectManager;
|
2022-03-23 18:38:07 +01:00
|
|
|
import org.gcube.application.cms.implementations.ISInterface;
|
|
|
|
import org.gcube.application.cms.implementations.ImplementationProvider;
|
|
|
|
import org.gcube.application.cms.serialization.Serialization;
|
2022-04-27 19:36:10 +02:00
|
|
|
import org.gcube.application.geoportal.common.model.document.filesets.RegisteredFile;
|
2022-03-23 18:38:07 +01:00
|
|
|
import org.gcube.application.geoportal.common.model.rest.ConfigurationException;
|
|
|
|
import org.gcube.application.geoportal.common.model.useCaseDescriptor.UseCaseDescriptor;
|
2022-04-27 19:36:10 +02:00
|
|
|
import org.gcube.application.geoportal.service.engine.WorkspaceManager;
|
2022-03-23 18:38:07 +01:00
|
|
|
import org.gcube.common.resources.gcore.GenericResource;
|
2022-04-27 19:36:10 +02:00
|
|
|
import org.gcube.common.storagehub.client.dsl.FolderContainer;
|
2022-03-23 18:38:07 +01:00
|
|
|
|
|
|
|
import javax.xml.bind.JAXBContext;
|
|
|
|
import javax.xml.bind.JAXBException;
|
|
|
|
import javax.xml.bind.Marshaller;
|
|
|
|
import javax.xml.bind.Unmarshaller;
|
|
|
|
import javax.xml.bind.annotation.*;
|
2022-04-27 19:36:10 +02:00
|
|
|
import java.io.ByteArrayInputStream;
|
2022-03-23 18:38:07 +01:00
|
|
|
import java.io.StringReader;
|
|
|
|
import java.io.StringWriter;
|
|
|
|
import java.net.URL;
|
2022-04-27 19:36:10 +02:00
|
|
|
import java.nio.charset.StandardCharsets;
|
|
|
|
import java.text.SimpleDateFormat;
|
2022-03-23 18:38:07 +01:00
|
|
|
import java.time.Duration;
|
2022-04-27 19:36:10 +02:00
|
|
|
import java.time.LocalDateTime;
|
2022-03-23 18:38:07 +01:00
|
|
|
import java.time.temporal.ChronoUnit;
|
2022-04-27 19:36:10 +02:00
|
|
|
import java.util.ArrayList;
|
2022-03-23 18:38:07 +01:00
|
|
|
import java.util.List;
|
|
|
|
import java.util.Scanner;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Retrieves available UCDs from a single Generic Resource
|
|
|
|
* - secondary Type : "CMS"
|
|
|
|
* - name : "UCDs"
|
|
|
|
*
|
|
|
|
* containing e.g.
|
|
|
|
* <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
|
|
|
* <UCDs>
|
|
|
|
* <record label="Human readable name" ucdUrl="some url" defaultForRegex="[opt] regex"/>
|
|
|
|
* <record label="Another readable name" ucdUrl="some other url" defaultForRegex="[opt] regex"/>
|
|
|
|
* </UCDs>
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
@Slf4j
|
2022-04-27 19:36:10 +02:00
|
|
|
public class SingleISResourceUCDProvider extends AbstractScopedMap<ProfileMap> implements ObjectManager<UseCaseDescriptor> {
|
|
|
|
|
|
|
|
private static final String GR_SECONDARY_TYPE="CMS";
|
|
|
|
private static final String GR_NAME="UCDs";
|
2022-03-23 18:38:07 +01:00
|
|
|
|
|
|
|
|
|
|
|
public SingleISResourceUCDProvider() {
|
|
|
|
super("Single IS Resource UCD Provider");
|
|
|
|
setTTL(Duration.of(2, ChronoUnit.MINUTES));
|
|
|
|
}
|
|
|
|
|
2022-04-27 19:36:10 +02:00
|
|
|
@Override
|
|
|
|
public UseCaseDescriptor insert(UseCaseDescriptor object) throws ConfigurationException{
|
|
|
|
try{
|
|
|
|
log.info("Registering UCID {}",object.getId());
|
|
|
|
log.debug("Full UCD {} ",object);
|
|
|
|
// Register entity in WS
|
|
|
|
WorkspaceManager manager =new WorkspaceManager();
|
|
|
|
WorkspaceManager.FolderOptions fo=new WorkspaceManager.FolderOptions();
|
|
|
|
fo.setFolderName("UCDs");
|
|
|
|
fo.setParent(manager.getAppBase());
|
|
|
|
fo.setFolderDescription("UCDs registered from server");
|
|
|
|
FolderContainer folder = manager.createFolder(fo);
|
|
|
|
|
|
|
|
String jsonString = Serialization.write(object);
|
|
|
|
WorkspaceManager.FileOptions fileOptions=new WorkspaceManager.FileOptions(new ByteArrayInputStream(jsonString.getBytes(StandardCharsets.UTF_8)));
|
|
|
|
fileOptions.setFileName(object.getId());
|
|
|
|
fileOptions.setFileDescription(object.getName()+", ID : "+object.getId());
|
|
|
|
fileOptions.setParent(folder);
|
|
|
|
RegisteredFile f = manager.registerFile(fileOptions);
|
|
|
|
log.info("Registered File {}",f);
|
|
|
|
|
|
|
|
// Create / Update GR
|
|
|
|
|
|
|
|
|
|
|
|
ISInterface is = ImplementationProvider.get().getProvidedObjectByClass(ISInterface.class);
|
|
|
|
List<GenericResource> l = is.getGenericResource(GR_SECONDARY_TYPE,GR_NAME);
|
|
|
|
log.debug("Found {} resources ",l.size());
|
|
|
|
GenericResource toupdate = null;
|
|
|
|
ISBean bean = new ISBean();
|
|
|
|
// If GR present, then use it
|
|
|
|
try{
|
|
|
|
toupdate = l.get(0);
|
|
|
|
log.debug("GR IS {}",toupdate);
|
|
|
|
bean = read(toupdate.profile().bodyAsString());
|
|
|
|
}catch (Throwable t){
|
|
|
|
log.warn("Unable to read from selected GR, creating it..",t);
|
|
|
|
toupdate = new GenericResource();
|
|
|
|
toupdate.newProfile().name(GR_NAME).type(GR_SECONDARY_TYPE).
|
|
|
|
description("Generated by service at "+ LocalDateTime.now());
|
|
|
|
}
|
|
|
|
|
|
|
|
if(bean.getRecords()==null) bean.setRecords(new ArrayList<>());
|
|
|
|
ISBean.Record record = new ISBean.Record();
|
|
|
|
record.setUcdUrl(f.getLink());
|
|
|
|
record.setLabel(object.getName());
|
|
|
|
bean.getRecords().add(record);
|
|
|
|
log.debug("Inserting record {} ",record);
|
|
|
|
String xml = write(bean).replaceFirst("<\\?.*\\?>","");
|
|
|
|
//remove processing instructions
|
|
|
|
toupdate.profile().newBody(xml);
|
|
|
|
log.info("Creating / Updating GR {} ",toupdate);
|
|
|
|
is.createUpdateGR(toupdate);
|
|
|
|
|
|
|
|
}catch(ConfigurationException e){
|
|
|
|
throw e;
|
|
|
|
} catch (Throwable e) {
|
|
|
|
throw new ConfigurationException(e);
|
|
|
|
}
|
|
|
|
return object;
|
|
|
|
}
|
|
|
|
|
2022-03-23 18:38:07 +01:00
|
|
|
@XmlAccessorType(XmlAccessType.FIELD)
|
|
|
|
@XmlRootElement(name = "UCDs")
|
|
|
|
@Data
|
|
|
|
@EqualsAndHashCode
|
|
|
|
public static class ISBean {
|
|
|
|
|
|
|
|
@NoArgsConstructor
|
|
|
|
@ToString
|
|
|
|
@Getter
|
|
|
|
@Setter
|
|
|
|
@AllArgsConstructor
|
|
|
|
@XmlAccessorType(XmlAccessType.FIELD)
|
|
|
|
@EqualsAndHashCode
|
|
|
|
public static class Record {
|
|
|
|
@XmlAttribute
|
|
|
|
private String label;
|
|
|
|
@XmlAttribute
|
|
|
|
private String ucdUrl;
|
|
|
|
@XmlAttribute
|
|
|
|
private String defaultForRegex;
|
|
|
|
}
|
|
|
|
|
|
|
|
@XmlElement(name = "record")
|
|
|
|
private List<Record> records;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void init() {
|
|
|
|
super.init();
|
|
|
|
try{
|
|
|
|
directInit();
|
|
|
|
}catch(Throwable t){
|
|
|
|
throw new RuntimeException("Unable to initialize. Can't read Use case descriptors ",t);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void directInit() throws JAXBException {
|
|
|
|
jaxbContext = JAXBContext.newInstance(ISBean.class);
|
|
|
|
marshaller = jaxbContext.createMarshaller();
|
|
|
|
unmarshaller = jaxbContext.createUnmarshaller();
|
|
|
|
}
|
2022-04-27 19:36:10 +02:00
|
|
|
private static JAXBContext jaxbContext=null;
|
|
|
|
private static Marshaller marshaller=null;
|
|
|
|
private static Unmarshaller unmarshaller = null;
|
2022-03-23 18:38:07 +01:00
|
|
|
|
|
|
|
|
|
|
|
static ISBean read(String xml) throws JAXBException {
|
|
|
|
log.trace("Loading from xml {}",xml);
|
2022-04-27 19:36:10 +02:00
|
|
|
if(xml == null || xml.isEmpty()) return new ISBean();
|
2022-03-23 18:38:07 +01:00
|
|
|
return (ISBean) unmarshaller.unmarshal(new StringReader(xml));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2022-04-27 19:36:10 +02:00
|
|
|
|
|
|
|
|
2022-03-23 18:38:07 +01:00
|
|
|
static String write(ISBean obj) throws JAXBException {
|
|
|
|
log.trace("Writing {} to xml",obj);
|
|
|
|
StringWriter writer = new StringWriter();
|
|
|
|
marshaller.marshal(obj,writer);
|
|
|
|
writer.flush();
|
|
|
|
return writer.toString();
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
protected ProfileMap retrieveObject(String key) throws ConfigurationException {
|
|
|
|
try {
|
|
|
|
log.info("Loading UCDs for context {} ",key);
|
2022-04-27 19:36:10 +02:00
|
|
|
ISInterface is = ImplementationProvider.get().getProvidedObjectByClass(ISInterface.class);
|
|
|
|
List<GenericResource> l = is.getGenericResource(GR_SECONDARY_TYPE,GR_NAME);
|
2022-03-23 18:38:07 +01:00
|
|
|
log.debug("Found {} resources ",l.size());
|
|
|
|
|
|
|
|
ProfileMap toReturn = new ProfileMap();
|
|
|
|
l.forEach(g->{
|
|
|
|
try {
|
|
|
|
log.debug("Reading from ID {} ", g.id());
|
|
|
|
ISBean bean = read(g.profile().bodyAsString());
|
|
|
|
log.debug("Found {} records ", bean.getRecords().size());
|
|
|
|
int before = toReturn.size();
|
|
|
|
bean.getRecords().forEach(record -> {
|
|
|
|
try {
|
|
|
|
log.debug("Loading UCD From {} ", record);
|
|
|
|
String json = new Scanner(
|
2022-03-23 18:48:49 +01:00
|
|
|
new URL(record.getUcdUrl()).openStream(),
|
|
|
|
"UTF-8").useDelimiter("\\A").next();
|
|
|
|
log.trace("JSON IS {} ",json);
|
2022-03-23 18:38:07 +01:00
|
|
|
UseCaseDescriptor ucd = Serialization.read(json, UseCaseDescriptor.class);
|
2022-04-27 19:36:10 +02:00
|
|
|
if(toReturn.containsKey(ucd.getId()))
|
|
|
|
log.warn("DUPLICATE UCID found {} in resource {} ",ucd.getId(),g.id());
|
2022-03-23 18:38:07 +01:00
|
|
|
toReturn.put(ucd.getId(), ucd);
|
|
|
|
}catch (Throwable t){
|
|
|
|
log.warn("Unable to read record {} from GR ID {} ",record,g.id(),t);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
log.debug("Loaded {} from {} ",toReturn.size()-before,g.id());
|
|
|
|
}catch (Throwable t){
|
|
|
|
log.warn("Unable to read from GR {} ",g.id(),t);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
return toReturn;
|
|
|
|
}catch(Throwable t){
|
|
|
|
throw new ConfigurationException("Unable to load UCDs for "+key,t);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|