Skip to content

Commit

Permalink
initial commit of Search API
Browse files Browse the repository at this point in the history
SearchWrapper classes, derrserialization of search hit subtypes
  • Loading branch information
Richard Adams committed Oct 10, 2016
1 parent 74608dd commit f7e4190
Show file tree
Hide file tree
Showing 16 changed files with 448 additions and 0 deletions.
63 changes: 63 additions & 0 deletions src/main/java/com/researchspace/dataverse/api/v1/SearchConfig.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
package com.researchspace.dataverse.api.v1;

import java.util.EnumSet;

import org.apache.commons.lang.Validate;
import org.springframework.web.util.UriComponentsBuilder;

import lombok.Builder;
import lombok.Data;
import lombok.Value;

@Builder(toBuilder = true)
@Value
public class SearchConfig {
/**
* Builder for configuring search
* @author rspace
*
*/
public static class SearchConfigBuilder {
/**
* Sets results per page. Maximum is 1000
*
* @param perPage
* if &gt 1000, will set to 1000
* @return
* @throws IllegalArgumentException
* if <code>perPage</code> &lt= 0
*/
SearchConfigBuilder perPage(int perPage) {
Validate.isTrue(perPage > 0, "Cannot have negative results per page");
if (perPage > MAX_RESULTS_PER_PAGE) {
perPage = MAX_RESULTS_PER_PAGE;
}
this.perPage = perPage;
return this;
}

/**
* Sets results per page. Maximum is 1000
*
* @param perPage
* if &gt 1000, will set to 1000
* @return
* @throws IllegalArgumentException
* if <code>perPage</code> &lt= 0
*/
SearchConfigBuilder start(int start) {
Validate.isTrue(start > 0, "Cannot have negative starting point");
this.start = start;
return this;
}

}
private static final int MAX_RESULTS_PER_PAGE = 1000;
private EnumSet<SearchType> type;
private String q, subtree, filterQuery;
private SortBy sortBy;
private SortOrder sortOrder;
private int perPage, start;
private boolean showRelevance, showFacets;

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package com.researchspace.dataverse.api.v1;

import com.researchspace.dataverse.api.v1.SearchConfig.SearchConfigBuilder;

/**
* <pre>
Copyright 2016 ResearchSpace
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.
</pre>
Top-level entry point into the Dataverse Level1 Search API
* @author rspace
*
*/
public interface SearchOperations {

SearchConfigBuilder builder();

void search(SearchConfig cfg);

}
12 changes: 12 additions & 0 deletions src/main/java/com/researchspace/dataverse/api/v1/SearchType.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package com.researchspace.dataverse.api.v1;
/**
* A value for the 'type' parameter of a search
* @author rspace
*
*/
public enum SearchType {

dataverse,
dataset,
file;
}
9 changes: 9 additions & 0 deletions src/main/java/com/researchspace/dataverse/api/v1/SortBy.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package com.researchspace.dataverse.api.v1;
/**
* Sorting category
* @author rspace
*
*/
public enum SortBy {
name, date
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package com.researchspace.dataverse.api.v1;

public enum SortOrder {

asc, desc;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package com.researchspace.dataverse.entities;

import com.fasterxml.jackson.annotation.JsonProperty;

import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;

@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class DatasetSearchHit extends SearchHit {

private @JsonProperty("global_id") String globalId;
private @JsonProperty("published_at") String publishedAt;
private String description, citation, citationHtml;

public String getType (){
return "file";
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package com.researchspace.dataverse.entities;

import com.fasterxml.jackson.annotation.JsonProperty;

import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;

@Data
@EqualsAndHashCode(callSuper=true)
@ToString(callSuper=true)
public class DataverseSearchHit extends SearchHit {
String identifier;
@JsonProperty("published_at")
String publishedAt;

public String getType (){
return "dataverse";
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package com.researchspace.dataverse.entities;

import com.fasterxml.jackson.annotation.JsonProperty;

import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;


@EqualsAndHashCode(callSuper=true)
@ToString(callSuper=true)
@Data
public class FileSearchHit extends SearchHit {

private @JsonProperty("file_id") String fileId;
private @JsonProperty("dataset_citation") String datasetCitation;
private @JsonProperty("file_content_type") String fileContentType;
private String description, md5;
private @JsonProperty("size_in_bytes") int size;
@JsonProperty("published_at")
private String publishedAt;

public String getType (){
return "file";
}

}
28 changes: 28 additions & 0 deletions src/main/java/com/researchspace/dataverse/entities/SearchHit.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package com.researchspace.dataverse.entities;

import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonSubTypes;
import com.fasterxml.jackson.annotation.JsonSubTypes.Type;
import com.fasterxml.jackson.annotation.JsonTypeInfo;

import lombok.Data;


@JsonTypeInfo(
use = JsonTypeInfo.Id.NAME,
include = JsonTypeInfo.As.PROPERTY,
property = "type"
)
@JsonSubTypes({
@Type(value = DataverseSearchHit.class, name = "dataverse"),
@Type(value = DatasetSearchHit.class, name = "dataset"),
@Type(value = FileSearchHit.class, name = "file"),
})
@Data
public abstract class SearchHit {
private String name, type, url;

@JsonProperty(value="image_url")
private String imageUrl;

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.researchspace.dataverse.entities;

import java.util.ArrayList;

public class SearchHitList extends ArrayList<SearchHit>{

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package com.researchspace.dataverse.entities;

import java.util.List;

import com.fasterxml.jackson.annotation.JsonProperty;

import lombok.Data;

@Data
public class SearchResults {

String q;
@JsonProperty(value="total_count")
private int totalCount;
@JsonProperty(value="count_in_response")
private int countInResponse;
int start;

List<Object> spellingAlternatives;
List<SearchHit> items;

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
package com.researchspace.dataverse.http;

import java.util.Arrays;

import org.apache.commons.lang.StringUtils;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.client.RestClientException;
import org.springframework.web.client.RestTemplate;

import com.researchspace.dataverse.api.v1.DataverseConfig;
import com.researchspace.dataverse.entities.DataverseResponse;
import com.researchspace.springrest.ext.LoggingResponseErrorHandler;
import com.researchspace.springrest.ext.RestUtil;

import lombok.extern.slf4j.Slf4j;
@Slf4j
public abstract class AbstractOpsImplV1 {

String apiKey = "";
String serverURL = "";
String serverAPIURL = serverURL +"/api";
String serverAPIv1URL = serverAPIURL +"/v1";

final String apiHeader = "X-Dataverse-key";
public void setApiKey(String apiKey) {
this.apiKey = apiKey;
}

public void setServerURL(String serverURL) {
this.serverURL = serverURL;
this.serverAPIURL = serverURL + "/api";
this.serverAPIv1URL = this.serverAPIURL +"/v1";
}

public void configure(DataverseConfig config) {
setApiKey(config.getApiKey());
setServerURL(config.getServerURL().toString());
}

<T> void handleError(ResponseEntity<DataverseResponse<T>> resp) {
log.debug("{}", resp.getBody());
if (RestUtil.isError(resp.getStatusCode())) {
String msg = String.format("Error code returned %d with message [%s]", resp.getStatusCodeValue(),
resp.getBody().getMessage());
log.error(msg);
throw new RestClientException(msg);
}

}

RestTemplate createTemplate() {
RestTemplate template = new RestTemplate();
template.setErrorHandler(new LoggingResponseErrorHandler());
return template;
}

String createV1Url(String ... pathComponents) {
String url = serverAPIv1URL + "/" + StringUtils.join(pathComponents, "/") ;
log.info("URL is {}", url);
return url;
}

String createAdminUrl(String ... pathComponents) {
String url = serverAPIURL + "/" + StringUtils.join(pathComponents, "/") ;
log.info("URL is {}", url);
return url;
}

HttpHeaders addAPIKeyToHeader() {
HttpHeaders headers = new HttpHeaders();
headers.setAccept(Arrays.asList(MediaType.APPLICATION_JSON));
headers.add(apiHeader, apiKey);
return headers;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package com.researchspace.dataverse.http;

import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.util.UriComponentsBuilder;

import com.researchspace.dataverse.api.v1.SearchConfig;
import com.researchspace.dataverse.api.v1.SearchConfig.SearchConfigBuilder;
import com.researchspace.dataverse.api.v1.SearchOperations;
import com.researchspace.dataverse.entities.DataverseResponse;
import com.researchspace.dataverse.entities.DataverseSearchHit;
import com.researchspace.dataverse.entities.SearchHit;
import com.researchspace.dataverse.entities.SearchResults;

import lombok.extern.slf4j.Slf4j;
import org.springframework.core.ParameterizedTypeReference;
@Slf4j
public class SearchOperationsImplV1 extends AbstractOpsImplV1 implements SearchOperations {

@Override
public SearchConfigBuilder builder() {
return SearchConfig.builder();
}

@Override
public void search(SearchConfig cfg) {
String url = createV1Url("search");
url = UriComponentsBuilder.fromUriString(url)
.queryParam("q", cfg.getQ())
.build(true)
.toUriString();
RestTemplate template = createTemplate();
HttpHeaders headers = addAPIKeyToHeader();
HttpEntity<String> entity = new HttpEntity<String>("", headers);
ParameterizedTypeReference<DataverseResponse<SearchResults>> type = new ParameterizedTypeReference<DataverseResponse<SearchResults>>() {
};

ResponseEntity<DataverseResponse< SearchResults>> resp = template.exchange(url, HttpMethod.GET, entity, type);

log.info(resp.getBody().getData().toString());



}



}
Loading

0 comments on commit f7e4190

Please sign in to comment.