491 lines
14 KiB
Java
491 lines
14 KiB
Java
/*
|
|
* Copyright 2015 Trento Rise.
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
package org.gcube.datacatalogue.ckanutillibrary.shared.jackan.model;
|
|
|
|
import java.io.File;
|
|
import java.sql.Timestamp;
|
|
import java.util.HashMap;
|
|
import java.util.Map;
|
|
|
|
import javax.annotation.Nullable;
|
|
|
|
import org.gcube.com.fasterxml.jackson.annotation.JsonAnyGetter;
|
|
import org.gcube.com.fasterxml.jackson.annotation.JsonAnySetter;
|
|
import org.gcube.com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
|
import org.gcube.datacatalogue.ckanutillibrary.shared.jackan.model.exceptions.JackanException;
|
|
import org.slf4j.Logger;
|
|
|
|
|
|
|
|
/**
|
|
*
|
|
* A Ckan Resource describes with metadata a physical file, which may reside
|
|
* outside ckan. Resources are part of {@link CkanDataset}. In DCAT terminology,
|
|
* a Ckan Resource is a DCAT Distribution.
|
|
*
|
|
* {@link CkanResourceBase} holds fields that can be sent when
|
|
* <a href="http://docs.ckan.org/en/latest/api/index.html?#ckan.logic.action.create.resource_create" target="_blank">creating
|
|
* a resource,</a>, while {@link CkanResource} holds more fields that can be
|
|
* returned with searches.
|
|
*
|
|
* This class initializes nothing to fully preserve all we get from ckan. In
|
|
* practice, all fields of retrieved resources can be null except maybe
|
|
* {@code url}.
|
|
*
|
|
* @author David Leoni
|
|
* @since 0.4.1
|
|
*/
|
|
@JsonIgnoreProperties({"upload"})
|
|
public class CkanResourceBase {
|
|
|
|
private static final Logger LOG = org.slf4j.LoggerFactory.getLogger(CkanResourceBase.class.getName());
|
|
|
|
private String cacheLastUpdated;
|
|
private String cacheUrl;
|
|
private Timestamp created;
|
|
private String description;
|
|
private String format;
|
|
private String hash;
|
|
private String id;
|
|
private String lastModified;
|
|
private String mimetype;
|
|
private String mimetypeInner;
|
|
private String name;
|
|
private String resourceType;
|
|
private String revisionId;
|
|
private String size;
|
|
private String url;
|
|
private File upload;
|
|
|
|
private Timestamp webstoreLastUpdated;
|
|
|
|
private String webstoreUrl;
|
|
|
|
/**
|
|
* The dataset this resource belongs to. Not present when getting resources
|
|
* but needed when uploading them.
|
|
*/
|
|
private String packageId;
|
|
|
|
/**
|
|
* See {@link #getOthers()}
|
|
*/
|
|
private Map<String, Object> others;
|
|
|
|
/**
|
|
* The dataset this resource belongs to. Latest ckan give it back, but older ones
|
|
* may return {@code null}. Required when creating resources.
|
|
*/
|
|
@Nullable
|
|
public String getPackageId() {
|
|
return packageId;
|
|
}
|
|
|
|
/**
|
|
* The dataset this resource belongs to. Latest ckan give it back, but older ones
|
|
* may return {@code null}. Required when creating resources.
|
|
*
|
|
* @param packageId the dataset this resource belongs to.
|
|
*/
|
|
public void setPackageId(@Nullable String packageId) {
|
|
this.packageId = packageId;
|
|
}
|
|
|
|
public CkanResourceBase() {
|
|
}
|
|
|
|
/**
|
|
* Constructor with the minimal list of required items to successfully
|
|
* create a resource on the server.
|
|
*
|
|
* @param url the Url to the pyhsical file i.e.
|
|
* http://dati.trentino.it/storage/f/2013-05-09T140831/TRENTO_Laghi_monitorati_UTM.csv
|
|
* (could also be a file outside ckan server)
|
|
* @param packageId id of the dataset that contains the resource
|
|
*/
|
|
public CkanResourceBase(String url,
|
|
String packageId) {
|
|
this();
|
|
this.url = url;
|
|
this.packageId = packageId;
|
|
}
|
|
|
|
/**
|
|
* CKAN instances might have
|
|
* <a href="http://docs.ckan.org/en/latest/extensions/adding-custom-fields.html">
|
|
* custom data schemas</a> that force presence of custom properties among
|
|
* 'regular' ones. In this case, they go to 'others' field. Notice that
|
|
* differently from dataset a resource down't have 'extras' field.
|
|
*
|
|
* @see #putOthers(java.lang.String, java.lang.Object)
|
|
*/
|
|
@JsonAnyGetter
|
|
@Nullable
|
|
public Map<String, Object> getOthers() {
|
|
return others;
|
|
}
|
|
|
|
/**
|
|
* @param others
|
|
* @see #getOthers()
|
|
* @see #putOthers(java.lang.String, java.lang.Object)
|
|
*/
|
|
public void setOthers(@Nullable Map<String, Object> others) {
|
|
this.others = others;
|
|
}
|
|
|
|
/**
|
|
* See {@link #getOthers()}
|
|
*
|
|
* @see #setOthers(java.util.Map)
|
|
*/
|
|
@JsonAnySetter
|
|
public void putOthers(String name, Object value) {
|
|
if (others == null) {
|
|
others = new HashMap();
|
|
}
|
|
others.put(name, value);
|
|
}
|
|
|
|
/**
|
|
* Should be a Timestamp
|
|
*/
|
|
public String getCacheLastUpdated() {
|
|
return cacheLastUpdated;
|
|
}
|
|
|
|
/**
|
|
* Should be a Timestamp
|
|
*/
|
|
public void setCacheLastUpdated(@Nullable String cacheLastUpdated) {
|
|
this.cacheLastUpdated = cacheLastUpdated;
|
|
}
|
|
|
|
/**
|
|
* God only knows what this is
|
|
*/
|
|
@Nullable
|
|
public String getCacheUrl() {
|
|
return cacheUrl;
|
|
}
|
|
|
|
/**
|
|
* God only knows what this is
|
|
*/
|
|
public void setCacheUrl(String cacheUrl) {
|
|
this.cacheUrl = cacheUrl;
|
|
}
|
|
|
|
/**
|
|
* In JSON is something like this: i.e. "2013-05-09T14:08:32.666477" . Ckan
|
|
* always refers to UTC timezone
|
|
*/
|
|
public Timestamp getCreated() {
|
|
return created;
|
|
}
|
|
|
|
/**
|
|
* Ckan always refers to UTC timezone
|
|
*/
|
|
public void setCreated(Timestamp created) {
|
|
this.created = created;
|
|
}
|
|
|
|
public String getDescription() {
|
|
return description;
|
|
}
|
|
|
|
public void setDescription(String description) {
|
|
this.description = description;
|
|
}
|
|
|
|
/**
|
|
* In Ckan 1.8 was lowercase, 2.2a seems capitalcase.
|
|
*/
|
|
public String getFormat() {
|
|
return format;
|
|
}
|
|
|
|
/**
|
|
* In Ckan 1.8 was lowercase, 2.2a seems capitalcase.
|
|
*/
|
|
public void setFormat(String format) {
|
|
this.format = format;
|
|
}
|
|
|
|
/**
|
|
* Sometimes for dati.trentino.it can be the empty string
|
|
*/
|
|
public String getHash() {
|
|
return hash;
|
|
}
|
|
|
|
/**
|
|
* Sometimes for dati.trentino.it can be the empty string
|
|
*/
|
|
public void setHash(String hash) {
|
|
this.hash = hash;
|
|
}
|
|
|
|
/**
|
|
* Returns the alphanumerical id, i.e.
|
|
* "c4577b8f-5603-4098-917e-da03e8ddf461"
|
|
*/
|
|
public String getId() {
|
|
return id;
|
|
}
|
|
|
|
/**
|
|
* @param id alphanumerical id, i.e. "c4577b8f-5603-4098-917e-da03e8ddf461"
|
|
*/
|
|
public void setId(String id) {
|
|
this.id = id;
|
|
}
|
|
|
|
/**
|
|
* Jackan note: this field should represent the timestamp of the last update
|
|
* of the resource *data*, not metadata. I think it's set by extensions and
|
|
* harvesters. Notice Ckan always refers to UTC timezone in
|
|
* {@link eu.trentorise.opendata.jackan.CkanClient#CKAN_TIMESTAMP_PATTERN} format, so this field probably
|
|
* should follow the same format.
|
|
*/
|
|
public String getLastModified() {
|
|
return lastModified;
|
|
}
|
|
|
|
/**
|
|
* Jackan note: this field should represent the timestamp of the last update
|
|
* of the resource *data*, not metadata. I think it's set by extensions and
|
|
* harvesters. Notice Ckan always refers to UTC timezone in
|
|
* {@link eu.trentorise.opendata.jackan.CkanClient#CKAN_TIMESTAMP_PATTERN} format, so this field probably
|
|
* should follow the same format.
|
|
*/
|
|
public void setLastModified(String lastModified) {
|
|
this.lastModified = lastModified;
|
|
}
|
|
|
|
/**
|
|
* i.e. text/csv
|
|
*/
|
|
public String getMimetype() {
|
|
return mimetype;
|
|
}
|
|
|
|
/**
|
|
* i.e. text/csv
|
|
*/
|
|
public void setMimetype(String mimetype) {
|
|
this.mimetype = mimetype;
|
|
}
|
|
|
|
/**
|
|
* Unknown meaning, as usual. Can be the empty string or null
|
|
*/
|
|
public String getMimetypeInner() {
|
|
return mimetypeInner;
|
|
}
|
|
|
|
/**
|
|
* Unknown meaning, as usual. Can be the empty string or null
|
|
*/
|
|
public void setMimetypeInner(@Nullable String mimetypeInner) {
|
|
this.mimetypeInner = mimetypeInner;
|
|
}
|
|
|
|
/**
|
|
*
|
|
* Human readable name, i.e. "Apple Production 2013 in CSV format". Not to
|
|
* be confused with {@link CkanDataset#name} which instead is lowercased and
|
|
* intended to be part of the url.
|
|
*
|
|
*
|
|
* Notice we found name null in data.gov.uk datasets... i.e.
|
|
* <a href="http://data.gov.uk/api/3/action/resource_show?id=77d2dba8-d0d9-49ef-9fd2-37a4a8bc5a17" target="_blank">
|
|
* unclaimed-estates-list </a>, taken
|
|
* <a href="http://data.gov.uk/api/3/action/package_search?rows=20&start=0" target="_blank">from
|
|
* this dataset search</a> (They use description field instead)
|
|
*/
|
|
@Nullable
|
|
public String getName() {
|
|
return name;
|
|
}
|
|
|
|
/**
|
|
* Human readable name, i.e. "Apple Production 2013 in CSV format". Not to
|
|
* be confused with {@link CkanDataset#name} which instead is lowercased and
|
|
* intended to be part of the url. For Nullable explanation see
|
|
* {@link #getName()}
|
|
*/
|
|
public void setName(@Nullable String name) {
|
|
this.name = name;
|
|
}
|
|
|
|
/**
|
|
* So far, found: "api", "file", "file.upload"
|
|
*/
|
|
public String getResourceType() {
|
|
return resourceType;
|
|
}
|
|
|
|
/**
|
|
* So far, found: "api", "file", "file.upload"
|
|
*/
|
|
public void setResourceType(String resourceType) {
|
|
this.resourceType = resourceType;
|
|
}
|
|
|
|
/**
|
|
* alphanumerical id, i.e. 0c949f17-d123-4379-8536-cfcf25b3b0e9
|
|
*/
|
|
public String getRevisionId() {
|
|
return revisionId;
|
|
}
|
|
|
|
/**
|
|
* alphanumerical id, i.e. 0c949f17-d123-4379-8536-cfcf25b3b0e9
|
|
*/
|
|
public void setRevisionId(String revisionId) {
|
|
this.revisionId = revisionId;
|
|
}
|
|
|
|
/**
|
|
* File size in bytes, if calculated by ckan for files in storage, like i.e.
|
|
* "242344". Otherwise it can be anything a human can insert.
|
|
*/
|
|
public String getSize() {
|
|
return size;
|
|
}
|
|
|
|
/**
|
|
* File size in bytes, if calculated by ckan for files in storage, like i.e.
|
|
* "242344". Otherwise it can be anything a human can insert.
|
|
*/
|
|
public void setSize(@Nullable String size) {
|
|
this.size = size;
|
|
}
|
|
|
|
/**
|
|
* The Url to the pyhsical file i.e.
|
|
* http://dati.trentino.it/storage/f/2013-05-09T140831/TRENTO_Laghi_monitorati_UTM.csv
|
|
* (could also be a file outside ckan server)
|
|
*/
|
|
public String getUrl() {
|
|
return url;
|
|
}
|
|
|
|
/**
|
|
* The Url to the pyhsical file i.e.
|
|
* http://dati.trentino.it/storage/f/2013-05-09T140831/TRENTO_Laghi_monitorati_UTM.csv
|
|
* (could also be a file outside ckan server)
|
|
*/
|
|
public void setUrl(String url) {
|
|
this.url = url;
|
|
}
|
|
|
|
/**
|
|
* The file to be added to the resource. See {@link #setUpload(File, boolean)} for further info.
|
|
*
|
|
* @since 0.4.3
|
|
*/
|
|
public File getUpload() {
|
|
return upload;
|
|
}
|
|
|
|
/**
|
|
* Sets the file to upload.
|
|
*
|
|
* @param upload the File to upload.
|
|
* @deprecated Put here only to have a bean-style setter,
|
|
* if possible prefer calling {@link #setUpload(File, boolean)}
|
|
*
|
|
* @since 0.4.3
|
|
*/
|
|
public void setUpload(@Nullable File upload){
|
|
this.setUpload(upload, false);
|
|
}
|
|
|
|
/**
|
|
* A file to be added to the resource.
|
|
*
|
|
* @param upload
|
|
* the file to upload. Its {@link #getSize() size} is automatically set. If passed file is {@code null},
|
|
* reset upload and size fields.
|
|
* @param guessMimeTypeAndFormat
|
|
* whether automatic guessing of {@link #getMimetype() mime type} and {@link #getFormat() format} is done.
|
|
*
|
|
* @throws JackanException
|
|
* if asked for automatic guessing of mime type and format but those could not be guessed.
|
|
*
|
|
* @since 0.4.3
|
|
*/
|
|
public void setUpload(@Nullable File upload, boolean guessMimeTypeAndFormat) {
|
|
LOG.error("Set UPLOAD IS NOT IMPLEMENTED!");
|
|
// if (upload == null) {
|
|
// this.upload = null;
|
|
// this.size = null;
|
|
// } else {
|
|
// this.upload = upload;
|
|
// this.size = String.valueOf(upload.length());
|
|
// if (guessMimeTypeAndFormat) {
|
|
// try (InputStream is = new FileInputStream(upload);
|
|
// BufferedInputStream bis = new BufferedInputStream(is);) {
|
|
// AutoDetectParser parser = new AutoDetectParser();
|
|
// Metadata md = new Metadata();
|
|
// md.add(Metadata.RESOURCE_NAME_KEY, upload.getName());
|
|
// MediaType mediaType = parser.getDetector().detect(bis, md);
|
|
// this.mimetype = mediaType.getBaseType().toString();
|
|
// this.format = mediaType.getSubtype().toUpperCase();
|
|
// } catch (FileNotFoundException e) {
|
|
// LOG.log(Level.WARNING, "Unable to load file {0}", upload.getName());
|
|
// throw new JackanException("Unable to load file " + upload.getName(), e);
|
|
// } catch (IOException e) {
|
|
// LOG.log(Level.WARNING, "Unable to detect mime type and format for file " + upload.getName(), e);
|
|
// throw new JackanException("Unable to detect mime type and format for file " + upload.getName(), e);
|
|
// }
|
|
// }
|
|
// }
|
|
|
|
}
|
|
|
|
/**
|
|
* Ckan always refers to UTC timezone
|
|
*/
|
|
public Timestamp getWebstoreLastUpdated() {
|
|
return webstoreLastUpdated;
|
|
}
|
|
|
|
/**
|
|
* Ckan always refers to UTC timezone
|
|
*/
|
|
public void setWebstoreLastUpdated(Timestamp webstoreLastUpdated) {
|
|
this.webstoreLastUpdated = webstoreLastUpdated;
|
|
}
|
|
|
|
/**
|
|
* Found "active" as value. Maybe it is a CkanState?
|
|
*/
|
|
public String getWebstoreUrl() {
|
|
return webstoreUrl;
|
|
}
|
|
|
|
/**
|
|
* @param webstoreUrl Found "active" as value. Maybe it is a CkanState?
|
|
*/
|
|
public void setWebstoreUrl(String webstoreUrl) {
|
|
this.webstoreUrl = webstoreUrl;
|
|
}
|
|
}
|