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
8 changes: 8 additions & 0 deletions src/main/java/org/gbif/ipt/action/portal/ResourceAction.java
Original file line number Diff line number Diff line change
Expand Up @@ -267,6 +267,14 @@ public String rss() {
return SUCCESS;
}

public String apiResources() {
resources = resourceManager.list(PublicationStatus.PUBLIC);
return SUCCESS;
}

public String apiResource() {
return detail();
}
/**
* Finish loading all details shown on resource homepage.
*
Expand Down
12 changes: 12 additions & 0 deletions src/main/java/org/gbif/ipt/config/AppConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -259,6 +259,18 @@ public URI getResourceUri(@NotNull String shortname) {
return UriBuilder.fromPath(getBaseUrl()).path(Constants.REQ_PATH_RESOURCE)
.queryParam(Constants.REQ_PARAM_RESOURCE, shortname).build();
}
/**
* @return URI to resource default homepage (no version number) used in DOI registration
*/
@NotNull
public URI getResourceApiUrl(@NotNull String shortname) {
Preconditions.checkNotNull(getBaseUrl());

return UriBuilder.fromPath(getBaseUrl())
.path(Constants.REQ_PATH_API)
.path("resource")
.queryParam(Constants.REQ_PARAM_RESOURCE, shortname).build();
}

/**
* @return String URI used as resource EML GUID, similar to resource homepage URI but with id param versus r param
Expand Down
1 change: 1 addition & 0 deletions src/main/java/org/gbif/ipt/config/Constants.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ public final class Constants {
public static final String SESSION_FILE_NAME = "fileName";
public static final String SESSION_FILE_CONTENT_TYPE = "contentType";
public static final String REQ_PATH_RESOURCE = "resource";
public static final String REQ_PATH_API = "api";
public static final String REQ_PATH_EML = "eml.do";
public static final String REQ_PATH_DWCA = "archive.do";
public static final String REQ_PATH_LOGO = "logo.do";
Expand Down
135 changes: 119 additions & 16 deletions src/main/java/org/gbif/ipt/model/Resource.java
Original file line number Diff line number Diff line change
@@ -1,33 +1,27 @@
package org.gbif.ipt.model;

import com.google.gson.ExclusionStrategy;
import com.google.gson.FieldAttributes;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.annotations.Expose;
import org.gbif.api.model.common.DOI;
import org.gbif.dwc.terms.Term;
import org.gbif.dwc.terms.TermFactory;
import org.gbif.dwc.terms.*;
import org.gbif.dwca.io.ArchiveField;
import org.gbif.ipt.config.Constants;
import org.gbif.ipt.model.voc.IdentifierStatus;
import org.gbif.ipt.model.voc.PublicationMode;
import org.gbif.ipt.model.voc.PublicationStatus;
import org.gbif.ipt.service.AlreadyExistingException;
import org.gbif.ipt.utils.ResourceUtils;
import org.gbif.metadata.eml.Agent;
import org.gbif.metadata.eml.Citation;
import org.gbif.metadata.eml.Eml;
import org.gbif.metadata.eml.MaintenanceUpdateFrequency;
import org.gbif.metadata.eml.*;

import java.io.File;
import java.io.Serializable;
import java.math.BigDecimal;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collections;
import java.util.Date;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import java.util.UUID;
import java.util.*;
import javax.annotation.Nullable;
import javax.validation.constraints.NotNull;

Expand All @@ -41,6 +35,7 @@
import com.google.common.collect.Sets;
import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.Logger;
import org.gbif.metadata.eml.Collection;

import static com.google.common.base.Objects.equal;

Expand Down Expand Up @@ -1258,4 +1253,112 @@ public synchronized void updateCitationIdentifierForDOI() {
public boolean hasOccurrenceMapping() {
return !getMappings(Constants.DWC_ROWTYPE_OCCURRENCE).isEmpty();
}

/**
* Return JSON representation of object
* @return string
*/
public String toJSONSimple() {
//return (new GsonBuilder().create()).toJson(this);
// Using a allow first approach to avoid recursive classes
Class[] classes = new Class[]{
String.class
,Date.class
,BigDecimal.class
,Resource.class
,Collection.class
};
final Set<Class> allowedClasses = new HashSet<Class>(Arrays.asList(classes));
return (new GsonBuilder().addSerializationExclusionStrategy(new ExclusionStrategy() {
@Override
public boolean shouldSkipField(FieldAttributes fieldAttributes) {
return fieldAttributes.getName().equals("resource");
}

@Override
public boolean shouldSkipClass(Class<?> aClass) {
return !allowedClasses.contains(aClass);
}
}).create()).toJson(this);
}

/**
* Return JSON representation of object
* @return string
*/
public String toJSON() {
//return (new GsonBuilder().create()).toJson(this);
// Using a allow first approach to avoid recursive classes
Class[] classes = new Class[]{
String.class
,Date.class
,BigDecimal.class
,Resource.class
,Eml.class
,KeywordSet.class
,Agent.class
,UserId.class
,UUID.class
,User.class
,BibliographicCitationSet.class
,Citation.class
,Collection.class
,Project.class
,PhysicalData.class
,MaintenanceUpdateFrequency.class
,PublicationMode.class
,PublicationStatus.class
,TemporalCoverage.class
,TaxonomicCoverage.class
,GeospatialCoverage.class
,TaxonKeyword.class
,Organisation.class
,IdentifierStatus.class
,User.class
,List.class
,Set.class
,Source.class
,SourceBase.class
,SqlSource.class
,FileSource.class
,TextFileSource.class
,ExcelFileSource.class
,File.class
,Source.class
,ExtensionMapping.class
,VersionHistory.class
,PropertyMapping.class
,Map.class
,ArchiveField.class
,Integer.class
,Boolean.class
,Term.class
,VocabularyTerm.class
,AcTerm.class
,EolReferenceTerm.class
,IucnTerm.class
,GbifInternalTerm.class
,GbifTerm.class
,XmpTerm.class
,XmpRightsTerm.class
,UnknownTerm.class
,DcTerm.class
,DwcTerm.class
,DcElement.class
,UnknownTerm.class
,ArchiveField.DataType.class
};
final Set<Class> allowedClasses = new HashSet<Class>(Arrays.asList(classes));
return (new GsonBuilder().addSerializationExclusionStrategy(new ExclusionStrategy() {
@Override
public boolean shouldSkipField(FieldAttributes fieldAttributes) {
return fieldAttributes.getName().equals("resource");
}

@Override
public boolean shouldSkipClass(Class<?> aClass) {
return !allowedClasses.contains(aClass);
}
}).create()).toJson(this);
}
}
40 changes: 40 additions & 0 deletions src/main/resources/struts-api.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
"http://struts.apache.org/dtds/struts-2.0.dtd">

<!--
Actions related to the data browse/search area of the IPT
These will be accessible by everyone for resources that have been published, but
some of the resources will only be accessible to the owning user or the administrator
-->
<struts>
<!-- The entry to the public section -->
<package name="api" extends="ipt-default" namespace="/api">
<default-interceptor-ref name="portalStack"/>
<default-action-ref name="resources"/>
<global-results>
<result name="404">
<param name="location">/WEB-INF/pages/api/404.ftl</param>
</result>
<result name="410">
<param name="location">/WEB-INF/pages/api/410.ftl</param>
</result>
</global-results>

<action name="resources"
class="org.gbif.ipt.action.portal.ResourceAction" method="apiResources">
<result name="success" type="freemarker">
<param name="location">/WEB-INF/pages/api/resources.ftl</param>
<param name="contentType">application/json</param>
</result>
</action>

<action name="resource"
class="org.gbif.ipt.action.portal.ResourceAction" method="apiResource">
<result name="success" type="freemarker">
<param name="location">/WEB-INF/pages/api/resource.ftl</param>
<param name="contentType">application/json</param>
</result>
</action>
</package>
</struts>
3 changes: 2 additions & 1 deletion src/main/resources/struts.xml
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@
<result name="setupIncomplete" type="redirect">/setup.do</result>
<result name="login" type="redirect">${baseURL}/login.do</result>
<result name="home" type="redirect">${baseURL}/home.do</result>

<result name="api" type="redirect">${baseURL}/api/resources</result>
</global-results>

<global-exception-mappings>
Expand Down Expand Up @@ -188,4 +188,5 @@
<include file="struts-portal.xml"/>
<include file="struts-manage.xml"/>
<include file="struts-admin.xml"/>
<include file="struts-api.xml"/>
</struts>
6 changes: 6 additions & 0 deletions src/main/webapp/WEB-INF/pages/api/404.ftl
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{"ipt":{
"name":"${ipt.name!}",
"link":"${baseURL!}",
"root":"${baseURL!}/${REQ_PATH_API!"api"}"
}
,"error":"not found"}
6 changes: 6 additions & 0 deletions src/main/webapp/WEB-INF/pages/api/410.ftl
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{"ipt":{
"name":"${ipt.name!}",
"link":"${baseURL!}",
"root":"${baseURL!}/${REQ_PATH_API!"api"}"
}
,"error":"not authorized"}
13 changes: 13 additions & 0 deletions src/main/webapp/WEB-INF/pages/api/resource.ftl
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{"ipt":{
"name":"${ipt.name!}",
"link":"${baseURL!}",
"root":"${baseURL!}/${REQ_PATH_API!"api"}/resources"
},
"resource": {"data":${resource.toJSON()}
,"links":{
"self":"${cfg.getResourceApiUrl(resource.shortname)}"
,"dwca":"${cfg.getResourceArchiveUrl(resource.shortname)}"
,"eml":"${cfg.getResourceEmlUrl(resource.shortname)}"
,"resource":"${cfg.getResourceUrl(resource.shortname)}"
}}
}
17 changes: 17 additions & 0 deletions src/main/webapp/WEB-INF/pages/api/resources.ftl
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{"ipt":{
"name":"${ipt.name!}",
"link":"${baseURL!}",
"root":"${baseURL!}/${REQ_PATH_API!"api"}/resources"
},
"resources": [
<#list resources as resource>
{"data":${resource.toJSONSimple()}
,"links":{
"self":"${cfg.getResourceApiUrl(resource.shortname)}"
,"dwca":"${cfg.getResourceArchiveUrl(resource.shortname)}"
,"eml":"${cfg.getResourceEmlUrl(resource.shortname)}"
,"resource":"${cfg.getResourceUrl(resource.shortname)}"
}}<#sep>,</#sep>
</#list>
]
}