/**
* Licensed to The Apereo Foundation under one or more contributor license
* agreements. See the NOTICE file distributed with this work for additional
* information regarding copyright ownership.
*
*
* The Apereo Foundation licenses this file to you under the Educational
* Community 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://opensource.org/licenses/ecl2.txt
*
* 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.opencastproject.runtimeinfo.rest;
import org.opencastproject.util.doc.DocData;
import org.apache.commons.lang3.StringEscapeUtils;
import java.util.ArrayList;
import java.util.List;
import java.util.Vector;
@Deprecated
public class RestEndpoint {
public enum Type {
WRITE, READ
};
public enum Method {
GET, POST, PUT, DELETE, ANY
};
private String name; // unique key
private String method;
private String path;
private String description;
private Param bodyParam;
private List<Param> pathParams;
private List<Param> requiredParams;
private List<Param> optionalParams;
private List<Format> formats;
private List<Status> statuses;
private List<String> notes;
private RestTestForm form;
private boolean autoPathFormat = false;
private String pathFormat = ""; // this is used when the automatic path format is enabled (e.g. )
private String pathFormatHtml = ""; // this is used when the automatic path format is enabled (e.g. )
/**
* Create a new basic endpoint, you should use the add methods to fill in the rest of the information about the
* endpoint data
*
* @param name
* the endpoint name (this should be unique for this set of endpoints)
* @param method
* the HTTP method used for this endpoint
* @param path
* the path for this endpoint (e.g. /search OR /add/{id})
* @param description
* [optional]
*/
public RestEndpoint(String name, Method method, String path, String description) {
if (!DocData.isValidName(name)) {
throw new IllegalArgumentException("name must not be null and must be alphanumeric");
}
if (method == null) {
throw new IllegalArgumentException("method must not be null");
}
if (!DocRestData.isValidPath(path)) {
throw new IllegalArgumentException("path must not be null and must look something like /a/b/{c}");
}
this.name = name;
this.method = method.name().toUpperCase();
this.path = path;
this.description = description;
}
@Override
public String toString() {
return "ENDP:" + name + ":" + method + " " + path + " :body=" + bodyParam + " :req=" + requiredParams + " :opt="
+ optionalParams + " :formats=" + formats + " :status=" + statuses + " :notes=" + notes + " :form=" + form;
}
/**
* This is a special parameter which indicates that this value is to be sent as the body of the request, in general
* the type of this parameter should only be FILE or TEXT but nothing stops you from using the other types<br>
* This is always a required parameter as you should never design an endpoint that takes a file sometimes but not
* always
*
* @param isBinary
* if true then this should use an uploader to send, otherwise the data can be placed in a text area
* @param defaultValue
* the default value (only viable for text)
* @param description
* the optional description
* @return the new param object in case you want to set attributes
* @throws IllegalArgumentException
* if the params are null
*/
public Param addBodyParam(boolean isBinary, String defaultValue, String description) {
Param.Type type = isBinary ? Param.Type.FILE : Param.Type.TEXT;
Param param = new Param("BODY", type, defaultValue, description);
param.setRequired(true);
param.setAttribute("rows", "8");
this.bodyParam = param;
return param;
}
/**
* Adds a path parameter for this endpoint, this would be a parameter which is passed as part of the path (e.g.
* /my/path/{param}) and thus must use a name which is safe to place in a URL and does not contain a slash (/)
*
* @param param
* the path param to add
* @throws IllegalArgumentException
* if the params are null
*/
public void addPathParam(Param param) {
if (param == null) {
throw new IllegalArgumentException("param must not be null");
}
if (Param.Type.FILE.name().equals(param.getType()) || Param.Type.TEXT.name().equals(param.getType())) {
throw new IllegalStateException("Cannot add path param of type FILE or TEXT");
}
param.setRequired(true);
param.setPath(true);
if (this.pathParams == null) {
this.pathParams = new Vector<Param>(3);
}
this.pathParams.add(param);
}
/**
* Adds a required form parameter for this endpoint, this would be a parameter which is passed encoded as part of the
* request body (commonly referred to as a post or form parameter) <br>
* WARNING: This should generally be reserved for endpoints which are used for processing, it is better to use path
* params unless the required parameter is not part of an identifier for the resource
*
* @param param
* the required param to add
* @throws IllegalArgumentException
* if the params are null
*/
public void addRequiredParam(Param param) {
if (param == null) {
throw new IllegalArgumentException("param must not be null");
}
if (isGetMethod()) {
throw new IllegalStateException("Cannot add required params for GET endpoints");
}
param.setRequired(true);
param.setPath(false);
if (this.requiredParams == null) {
this.requiredParams = new Vector<Param>(3);
}
this.requiredParams.add(param);
}
/**
* Adds an optional parameter for this endpoint, this would be a parameter which is passed in the query string (for
* GET) or encoded as part of the body otherwise (often referred to as a post or form parameter)
*
* @param param
* the optional param to add
* @throws IllegalArgumentException
* if the params are null
*/
public void addOptionalParam(Param param) {
if (param == null) {
throw new IllegalArgumentException("param must not be null");
}
param.setRequired(false);
param.setPath(false);
if (this.optionalParams == null) {
this.optionalParams = new Vector<Param>(3);
}
this.optionalParams.add(param);
}
/**
* Adds a format for the return data for this endpoint
*
* @param format
* a format object
* @throws IllegalArgumentException
* if the params are null
*/
public void addFormat(Format format) {
if (format == null) {
throw new IllegalArgumentException("format must not be null");
}
if (this.formats == null) {
this.formats = new Vector<Format>(2);
}
this.formats.add(format);
}
/**
* Adds a response status for this endpoint
*
* @param status
* a response status object
* @throws IllegalArgumentException
* if the params are null
*/
public void addStatus(Status status) {
if (status == null) {
throw new IllegalArgumentException("status must not be null");
}
if (this.statuses == null) {
this.statuses = new Vector<Status>(3);
}
this.statuses.add(status);
}
/**
* Adds a note for this endpoint
*
* @param note
* a note object
* @throws IllegalArgumentException
* if the params are null
*/
public void addNote(String note) {
if (DocData.isBlank(note)) {
throw new IllegalArgumentException("note must not be null");
}
if (this.notes == null) {
this.notes = new Vector<String>(3);
}
this.notes.add(note);
}
/**
* Sets the test form for this endpoint, if this is null then no test form is rendered for this endpoint
*
* @param form
* the test form object (null to clear the form)
* @throws IllegalArgumentException
* if the params are null
*/
public void setTestForm(RestTestForm form) {
this.form = form;
}
/**
* @param pathFormat
* the pathFormat to set
*/
public void setPathFormat(String pathFormat) {
this.pathFormat = pathFormat;
}
/**
* @param pathFormatHtml
* the pathFormatHtml to set
*/
public void setPathFormatHtml(String pathFormatHtml) {
this.pathFormatHtml = pathFormatHtml;
}
/**
* Setting this to true will cause the path to be filled in with format extensions which will work with the {FORMAT}
* convention (which is automatically filled in with the selected or default format key - e.g. json) <br>
* This will generate a path like /your/path.{FORMAT} and will show the following on screen GET /your/path.{xml|json}
* if you have 2 formats in this endpoint
*
* @param autoPathFormat
* true to enable, false to disable
*/
public void setAutoPathFormat(boolean autoPathFormat) {
this.autoPathFormat = autoPathFormat;
}
/**
* @return true if this endpoint method is GET, otherwise false
*/
public boolean isGetMethod() {
boolean match = false;
if (Method.GET.name().equals(this.method)) {
match = true;
}
return match;
}
/**
* @return the calculated query string for a GET endpoint (e.g. ?blah=1), will be urlencoded for html display
*/
public String getQueryString() {
String qs = "";
if (isGetMethod()) {
if (this.optionalParams != null && !this.optionalParams.isEmpty()) {
StringBuilder sb = new StringBuilder();
sb.append("?");
for (Param p : this.optionalParams) {
if (sb.length() > 2) {
sb.append("&");
}
sb.append(p.getName());
sb.append("=");
if (p.getDefaultValue() != null) {
sb.append(p.getDefaultValue());
} else {
sb.append("{");
sb.append(p.getName());
sb.append("}");
}
}
/*
* try { qs = URLEncoder.encode(sb.toString(),"UTF-8"); } catch (UnsupportedEncodingException e) { qs =
* sb.toString(); }
*/
qs = StringEscapeUtils.escapeHtml4(sb.toString());
}
}
return qs;
}
// GETTERS
public String getName() {
return name;
}
public String getMethod() {
return method;
}
public String getPath() {
return path;
}
public String getDescription() {
return description;
}
public Param getBodyParam() {
return bodyParam;
}
public List<Param> getPathParams() {
if (this.pathParams == null) {
this.pathParams = new ArrayList<Param>(0);
}
return this.pathParams;
}
public List<Param> getRequiredParams() {
if (this.requiredParams == null) {
this.requiredParams = new ArrayList<Param>(0);
}
return this.requiredParams;
}
public List<Param> getOptionalParams() {
if (this.optionalParams == null) {
this.optionalParams = new ArrayList<Param>(0);
}
return this.optionalParams;
}
public List<Format> getFormats() {
if (this.formats == null) {
this.formats = new ArrayList<Format>(0);
}
return this.formats;
}
public List<Status> getStatuses() {
if (this.statuses == null) {
this.statuses = new ArrayList<Status>(0);
}
return this.statuses;
}
public List<String> getNotes() {
if (this.notes == null) {
this.notes = new ArrayList<String>(0);
}
return this.notes;
}
public RestTestForm getForm() {
return form;
}
public String getPathFormat() {
return pathFormat;
}
public String getPathFormatHtml() {
return pathFormatHtml;
}
public boolean isAutoPathFormat() {
return autoPathFormat;
}
}