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); } } }