| APISpec.java |
/*
* $Id: APISpec.java,v 1.31 2013/01/29 10:49:58 agoubard Exp $
*
* See the COPYRIGHT file for redistribution and use restrictions.
*/
package org.xins.common.spec;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.net.URL;
import java.util.LinkedHashMap;
import java.util.Map;
import org.w3c.dom.Element;
import org.xins.common.MandatoryArgumentChecker;
import org.xins.common.xml.ElementList;
import org.xins.common.xml.ElementFormatter;
import org.xml.sax.SAXException;
/**
* Specification of an API.
* This class gets the specification of the API as defined in the api.xml file.
*
* @version $Revision: 1.31 $ $Date: 2013/01/29 10:49:58 $
* @author <a href="mailto:anthony.goubard@japplis.com">Anthony Goubard</a>
*
* @since XINS 1.3.0
*/
public final class APISpec {
/**
* Name of the API, cannot be <code>null</code>.
*/
private String _apiName;
/**
* Owner of the API, can be <code>null</code>.
*/
private String _owner;
/**
* Description of the API, cannot be <code>null</code>.
*/
private String _description;
/**
* The functions of the API, cannot be <code>null</code>.
*/
private Map<String, FunctionSpec> _functions = new LinkedHashMap<String, FunctionSpec>();
/**
* Creates a new instance of <code>APISpec</code>.
*
* @param reference
* the reference class used to get the type of the parameters, cannot be <code>null</code>.
*
* @param baseURL
* the base URL path where are located the specifications, cannot be <code>null</code>.
*
* @throws IllegalArgumentException
* if <code>reference == null || baseURL == null</code>.
*
* @throws InvalidSpecificationException
* if the result code file cannot be found or is incorrect.
*/
public APISpec(Class reference, String baseURL)
throws IllegalArgumentException, InvalidSpecificationException {
MandatoryArgumentChecker.check("reference", reference, "baseURL", baseURL);
try {
Reader reader = getReader(baseURL, "api.xml");
parseApi(reader, reference, baseURL);
} catch (IOException ioe) {
throw new InvalidSpecificationException("Cannot read API specification files.", ioe);
}
}
/**
* Gets the content of the file without the DTD declaration.
*
* @param baseURL
* the base URL used to located the specifications, cannot be <code>null</code>.
*
* @param fileName
* the name of the file that contains the specifications, cannot be <code>null</code>.
*
* @return
* the content of the file, never <code>null</code>.
*
* @throws InvalidSpecificationException
* if the specified file cannot be found.
*
* @throws IOException
* if the specification cannot be read.
*/
static Reader getReader(String baseURL, String fileName)
throws InvalidSpecificationException, IOException {
URL fileURL = new URL(baseURL + fileName);
InputStream in = fileURL.openStream();
if (in == null) {
throw new InvalidSpecificationException("File \"" + baseURL + fileName +"\" not found in the specifications.");
}
BufferedReader reader = new BufferedReader(new InputStreamReader(in));
return reader;
}
/**
* Gets the name of the API.
*
* @return
* the name of the API, never <code>null</code>.
*/
public String getName() {
return _apiName;
}
/**
* Gets the owner of the API.
*
* @return
* the owner of the API or <code>null</code> if no owner is defined.
*/
public String getOwner() {
return _owner;
}
/**
* Gets the description of the API. The description will be the text
* specified in the <i>description</i> element of the API specification file.
*
* @return
* the description of the API, never <code>null</code>.
*/
public String getDescription() {
return _description;
}
/**
* Gets the function specifications defined in the API.
* The key of the returned {@link Map} is the name of the function and the
* value is the {@link FunctionSpec} object. The values in the {@link Map}
* are never <code>null</code>.
*
* @return
* the function specifications, never <code>null</code>.
*/
public Map<String, FunctionSpec> getFunctions() {
return _functions;
}
/**
* Gets the specification of the given function.
*
* @param functionName
* The name of the function, can not be <code>null</code>
*
* @return
* The function specification, never <code>null</code>.
*
* @throws IllegalArgumentException
* if <code>functionName == null</code>.
*
* @throws EntityNotFoundException
* If the API does not define any function for the given name.
*/
public FunctionSpec getFunction(String functionName)
throws IllegalArgumentException, EntityNotFoundException {
MandatoryArgumentChecker.check("functionName", functionName);
FunctionSpec function = _functions.get(functionName);
if (function == null) {
throw new EntityNotFoundException("Function \"" + functionName + "\" not found.");
}
return function;
}
/**
* Parses the API specification file.
*
* @param reader
* the reader that contains the content of the API specification file, cannot be <code>null</code>.
*
* @param reference
* the reference class used to get the type of the parameters, cannot be <code>null</code>.
*
* @param baseURL
* the base URL path where are located the specifications, cannot be <code>null</code>.
*
* @throws IllegalArgumentException
* if <code>reader == null || reference == null || baseURL == null</code>.
*
* @throws IOException
* if one of the specification files cannot be read correctly.
*
* @throws InvalidSpecificationException
* if the specification is incorrect.
*/
private void parseApi(Reader reader, Class reference, String baseURL)
throws IllegalArgumentException, IOException, InvalidSpecificationException {
MandatoryArgumentChecker.check("reader", reader, "reference", reference, "baseURL", baseURL);
Element api;
try {
api = ElementFormatter.parse(reader);
} catch (SAXException pe) {
throw new InvalidSpecificationException("[API] Cannot parse.", pe);
}
// Get the result from the parsed API specification.
_apiName = api.getAttribute("name");
if (_apiName.equals("")) {
throw new InvalidSpecificationException("[API] No name defined.");
}
_owner = api.getAttribute("owner");
ElementList descriptionElementList = new ElementList(api, "description");
if (descriptionElementList.isEmpty()) {
throw new InvalidSpecificationException("[API] No description specified.");
}
Element descriptionElement = descriptionElementList.get(0);
_description = descriptionElement.getTextContent();
if (_description == null) {
_description = "";
}
// Get the specification of the functions.
for (Element nextFunction : new ElementList(api, "function")) {
String functionName = nextFunction.getAttribute("name");
FunctionSpec function = new FunctionSpec(functionName, reference, baseURL);
_functions.put(functionName, function);
}
}
}