WADLApiReader.java

  1. /*
  2.  * GovWay - A customizable API Gateway
  3.  * https://govway.org
  4.  *
  5.  * Copyright (c) 2005-2025 Link.it srl (https://link.it).
  6.  *
  7.  * This program is free software: you can redistribute it and/or modify
  8.  * it under the terms of the GNU General Public License version 3, as published by
  9.  * the Free Software Foundation.
  10.  *
  11.  * This program is distributed in the hope that it will be useful,
  12.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14.  * GNU General Public License for more details.
  15.  *
  16.  * You should have received a copy of the GNU General Public License
  17.  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  18.  *
  19.  */


  20. package org.openspcoop2.utils.wadl;

  21. import java.io.File;
  22. import java.net.URI;
  23. import java.net.URL;
  24. import java.util.HashMap;
  25. import java.util.Iterator;
  26. import java.util.List;
  27. import java.util.Map;

  28. import javax.ws.rs.core.MultivaluedMap;

  29. import org.jvnet.ws.wadl.Param;
  30. import org.jvnet.ws.wadl.ast.ApplicationNode;
  31. import org.jvnet.ws.wadl.ast.FaultNode;
  32. import org.jvnet.ws.wadl.ast.MethodNode;
  33. import org.jvnet.ws.wadl.ast.PathSegment;
  34. import org.jvnet.ws.wadl.ast.RepresentationNode;
  35. import org.jvnet.ws.wadl.ast.ResourceNode;
  36. import org.openspcoop2.utils.rest.ApiReaderConfig;
  37. import org.openspcoop2.utils.rest.IApiReader;
  38. import org.openspcoop2.utils.rest.ProcessingException;
  39. import org.openspcoop2.utils.rest.api.Api;
  40. import org.openspcoop2.utils.rest.api.ApiOperation;
  41. import org.openspcoop2.utils.rest.api.ApiParameterSchema;
  42. import org.openspcoop2.utils.rest.api.ApiRequest;
  43. import org.openspcoop2.utils.rest.api.ApiBodyParameter;
  44. import org.openspcoop2.utils.rest.api.ApiRequestDynamicPathParameter;
  45. import org.openspcoop2.utils.rest.api.ApiHeaderParameter;
  46. import org.openspcoop2.utils.rest.api.ApiRequestQueryParameter;
  47. import org.openspcoop2.utils.rest.api.ApiResponse;
  48. import org.openspcoop2.utils.rest.api.ApiSchema;
  49. import org.openspcoop2.utils.rest.api.ApiSchemaType;
  50. import org.openspcoop2.utils.transport.http.HttpRequestMethod;
  51. import org.slf4j.Logger;
  52. import org.w3c.dom.Document;
  53. import org.w3c.dom.Element;


  54. /**
  55.  * WADLApiReader
  56.  *
  57.  * @author Andrea Poli (apoli@link.it)
  58.  * @author $Author$
  59.  * @version $Rev$, $Date$
  60.  *
  61.  */
  62. public class WADLApiReader implements IApiReader {

  63.     private ApplicationWrapper applicationWadlWrapper;
  64.     private ApiSchema[] schemas;
  65.    
  66.     private Map<String, byte[]> convert(ApiSchema ... schema) {
  67.         Map<String, byte[]> map = null;
  68.         if(schema!=null && schema.length>0) {
  69.             for (ApiSchema apiSchema : schema) {
  70.                 if(ApiSchemaType.XSD.equals(apiSchema.getType())) {
  71.                     if(map==null) {
  72.                         map = new HashMap<String, byte[]>();
  73.                     }
  74.                     map.put(apiSchema.getName(), apiSchema.getContent());
  75.                 }
  76.             }
  77.         }
  78.         return map;
  79.     }
  80.    
  81.    
  82.    
  83.     @Override
  84.     public void init(Logger log, String content, ApiReaderConfig config) throws ProcessingException {
  85.         this._init(log, content, config);
  86.     }
  87.     @Override
  88.     public void init(Logger log, String content, ApiReaderConfig config, ApiSchema ... schema) throws ProcessingException {
  89.         this._init(log, content, config, schema);
  90.     }
  91.     private void _init(Logger log, String content, ApiReaderConfig config, ApiSchema ... schema) throws ProcessingException {
  92.         try{
  93.             this.applicationWadlWrapper = WADLUtilities.getInstance(config.getXmlUtils()).readWADLFromBytes(log, content.getBytes(config.getCharset().getValue()),
  94.                     config.isVerbose(),config.isProcessInclude(),config.isProcessInlineSchema(),
  95.                     this.convert(schema));
  96.             this.schemas = schema;
  97.         }catch(Exception e){
  98.             throw new ProcessingException(e.getMessage(),e);
  99.         }
  100.     }
  101.    
  102.    
  103.    
  104.     @Override
  105.     public void init(Logger log, byte[] content, ApiReaderConfig config) throws ProcessingException {
  106.         this._init(log, content, config);
  107.     }
  108.     @Override
  109.     public void init(Logger log, byte[] content, ApiReaderConfig config, ApiSchema ... schema) throws ProcessingException {
  110.         this._init(log, content, config, schema);
  111.     }
  112.     private void _init(Logger log, byte[] content, ApiReaderConfig config, ApiSchema ... schema) throws ProcessingException {
  113.         try{
  114.             this.applicationWadlWrapper = WADLUtilities.getInstance(config.getXmlUtils()).readWADLFromBytes(log, content,
  115.                     config.isVerbose(),config.isProcessInclude(),config.isProcessInlineSchema(),
  116.                     this.convert(schema));
  117.             this.schemas = schema;
  118.         }catch(Exception e){
  119.             throw new ProcessingException(e.getMessage(),e);
  120.         }
  121.     }
  122.    
  123.    
  124.    
  125.    
  126.     @Override
  127.     public void init(Logger log, File file, ApiReaderConfig config) throws ProcessingException {
  128.         this._init(log, file, config);
  129.     }
  130.     @Override
  131.     public void init(Logger log, File file, ApiReaderConfig config, ApiSchema ... schema) throws ProcessingException {
  132.         this._init(log, file, config, schema);
  133.     }
  134.     private void _init(Logger log, File file, ApiReaderConfig config, ApiSchema ... schema) throws ProcessingException {
  135.         try{
  136.             this.applicationWadlWrapper = WADLUtilities.getInstance(config.getXmlUtils()).readWADLFromFile(log, file,
  137.                     config.isVerbose(),config.isProcessInclude(),config.isProcessInlineSchema(),
  138.                     this.convert(schema));
  139.             this.schemas = schema;
  140.         }catch(Exception e){
  141.             throw new ProcessingException(e.getMessage(),e);
  142.         }
  143.     }
  144.    
  145.    
  146.    
  147.    
  148.     @Override
  149.     public void init(Logger log, URI uri, ApiReaderConfig config) throws ProcessingException {
  150.         this._init(log, uri, config);
  151.     }
  152.     @Override
  153.     public void init(Logger log, URI uri, ApiReaderConfig config, ApiSchema ... schema) throws ProcessingException {
  154.         this._init(log, uri, config, schema);
  155.     }
  156.     private void _init(Logger log, URI uri, ApiReaderConfig config, ApiSchema ... schema) throws ProcessingException {
  157.         try{
  158.             this.applicationWadlWrapper = WADLUtilities.getInstance(config.getXmlUtils()).readWADLFromURI(log, uri,
  159.                     config.isVerbose(),config.isProcessInclude(),config.isProcessInlineSchema(),
  160.                     this.convert(schema));
  161.             this.schemas = schema;
  162.         }catch(Exception e){
  163.             throw new ProcessingException(e.getMessage(),e);
  164.         }
  165.     }




  166.     @Override
  167.     public void init(Logger log, Document doc, ApiReaderConfig config) throws ProcessingException {
  168.         this._init(log, doc, config);
  169.     }
  170.     @Override
  171.     public void init(Logger log, Document doc, ApiReaderConfig config, ApiSchema ... schema) throws ProcessingException {
  172.         this._init(log, doc, config, schema);
  173.     }
  174.     private void _init(Logger log, Document doc, ApiReaderConfig config, ApiSchema ... schema) throws ProcessingException {
  175.         try{
  176.             this.applicationWadlWrapper = WADLUtilities.getInstance(config.getXmlUtils()).readWADLFromDocument(log, doc,
  177.                     config.isVerbose(),config.isProcessInclude(),config.isProcessInlineSchema(),
  178.                     this.convert(schema));
  179.             this.schemas = schema;
  180.         }catch(Exception e){
  181.             throw new ProcessingException(e.getMessage(),e);
  182.         }
  183.     }

  184.    
  185.    
  186.    
  187.     @Override
  188.     public void init(Logger log, Element element, ApiReaderConfig config) throws ProcessingException {
  189.         this._init(log, element, config);
  190.     }
  191.     @Override
  192.     public void init(Logger log, Element element, ApiReaderConfig config, ApiSchema ... schema) throws ProcessingException {
  193.         this._init(log, element, config, schema);
  194.     }
  195.     private void _init(Logger log, Element element, ApiReaderConfig config, ApiSchema ... schema) throws ProcessingException {
  196.         try{
  197.             this.applicationWadlWrapper = WADLUtilities.getInstance(config.getXmlUtils()).readWADLFromDocument(log, element,
  198.                     config.isVerbose(),config.isProcessInclude(),config.isProcessInlineSchema(),
  199.                     this.convert(schema));
  200.             this.schemas = schema;
  201.         }catch(Exception e){
  202.             throw new ProcessingException(e.getMessage(),e);
  203.         }
  204.     }




  205.     @Override
  206.     public Api read() throws ProcessingException {
  207.        
  208.         Api api = new WADLApi(this.applicationWadlWrapper);
  209.        
  210.         if(this.schemas!=null && this.schemas.length>0) {
  211.             for (ApiSchema apiSchema : this.schemas) {
  212.                 api.addSchema(apiSchema);
  213.             }
  214.         }
  215.        
  216.         ApplicationNode an = this.applicationWadlWrapper.getApplicationNode();
  217.         List<ResourceNode> rs = an.getResources();
  218.         if(rs.size()<=0){
  219.             throw new ProcessingException("Non sono state trovate risorse registrate nel documento");
  220.         }
  221.         if(rs.size()>1){
  222.             throw new ProcessingException("Trovato più di un elemento 'resources' nella radice del documento");
  223.         }
  224.         try{
  225.             api.setBaseURL(new URL(rs.get(0).getUriTemplate()));
  226.         }catch(Exception e){
  227.             throw new ProcessingException("Trovata resources base url malformata: "+e.getMessage(),e);
  228.         }
  229.        
  230.         this.readOperations(rs, api);
  231.        
  232.         return api;
  233.     }
  234.     private void readOperations(List<ResourceNode> rs,Api api) throws ProcessingException{
  235.         try{    
  236.             if(rs!=null && rs.size()>0){
  237.                 for (ResourceNode resourceNode : rs) {
  238.                     List<MethodNode> method = resourceNode.getMethods();
  239.                     if(method!=null && method.size()>0){
  240.                         for (MethodNode methodNode : method) {
  241.                             ApiOperation operation = new ApiOperation(HttpRequestMethod.valueOf(methodNode.getName().toUpperCase()), resourceNode.getAllResourceUriTemplate());
  242.                            
  243.                             List<Param> lHeaders = methodNode.getHeaderParameters();
  244.                             if(lHeaders!=null && lHeaders.size()>0){
  245.                                 if(operation.getRequest()==null){
  246.                                     operation.setRequest(new ApiRequest());
  247.                                 }
  248.                                 for (Param param : lHeaders) {
  249.                                     ApiParameterSchema apiParameterSchema = new ApiParameterSchema();
  250.                                     apiParameterSchema.addType(param.getType().toString(), null);
  251.                                     ApiHeaderParameter header = new ApiHeaderParameter(param.getName(),apiParameterSchema);
  252.                                     header.setRequired(param.isRequired());
  253.                                     operation.getRequest().addHeaderParameter(header);
  254.                                 }
  255.                             }
  256.                            
  257.                             List<Param> lQuery = methodNode.getQueryParameters();
  258.                             if(lQuery!=null && lQuery.size()>0){
  259.                                 if(operation.getRequest()==null){
  260.                                     operation.setRequest(new ApiRequest());
  261.                                 }
  262.                                 for (Param param : lQuery) {
  263.                                     ApiParameterSchema apiParameterSchema = new ApiParameterSchema();
  264.                                     apiParameterSchema.addType(param.getType().toString(), null);
  265.                                     ApiRequestQueryParameter query = new ApiRequestQueryParameter(param.getName(),apiParameterSchema);
  266.                                     query.setRequired(param.isRequired());
  267.                                     operation.getRequest().addQueryParameter(query);
  268.                                 }
  269.                             }

  270.                             List<PathSegment> lSegment = resourceNode.getPathSegments();
  271.                             if(lSegment!=null && lSegment.size()>0){
  272.                                 for (PathSegment segment : lSegment) {
  273.                                     List<Param> lDynamicPath = segment.getTemplateParameters();
  274.                                     if(lDynamicPath!=null && lDynamicPath.size()>0){
  275.                                         for (Param param : lDynamicPath) {
  276.                                             if(operation.getRequest()==null){
  277.                                                 operation.setRequest(new ApiRequest());
  278.                                             }
  279.                                             ApiParameterSchema apiParameterSchema = new ApiParameterSchema();
  280.                                             apiParameterSchema.addType(param.getType().toString(), null);
  281.                                             ApiRequestDynamicPathParameter query = new ApiRequestDynamicPathParameter(param.getName(),apiParameterSchema);
  282.                                             //query.setRequired(param.isRequired());
  283.                                             query.setRequired(true);
  284.                                             operation.getRequest().addDynamicPathParameter(query);
  285.                                         }
  286.                                     }
  287.                                 }
  288.                             }
  289.                            
  290.                             List<RepresentationNode> lInput = methodNode.getSupportedInputs();
  291.                             if(lInput!=null && lInput.size()>0){
  292.                                 for (RepresentationNode representationNode : lInput) {
  293.                                     if(operation.getRequest()==null){
  294.                                         operation.setRequest(new ApiRequest());
  295.                                     }
  296.                                     ApiBodyParameter query = new ApiBodyParameter(null);
  297.                                     query.setMediaType(representationNode.getMediaType());
  298.                                     query.setElement(representationNode.getElement());
  299.                                     operation.getRequest().addBodyParameter(query);
  300.                                 }
  301.                             }
  302.                            
  303.                             MultivaluedMap<List<Long>, RepresentationNode> mapOutput = methodNode.getSupportedOutputs();
  304.                             if(mapOutput!=null && mapOutput.size()>0){
  305.                                 Iterator<List<Long>> itOutput = mapOutput.keySet().iterator();
  306.                                 while (itOutput.hasNext()) {
  307.                                     List<java.lang.Long> listLong = (List<java.lang.Long>) itOutput.next();
  308.                                     List<RepresentationNode> representationNode = mapOutput.get(listLong);
  309.                                    
  310.                                     for (int i = 0; i < listLong.size(); i++) {
  311.                                         int httpStatus = listLong.get(i).intValue();
  312.                                         RepresentationNode rNodeHttpStatus = representationNode.get(i);
  313.                                        
  314.                                         ApiResponse apiResponse = null;
  315.                                         for (ApiResponse responseExists : operation.getResponses()) {
  316.                                             if(responseExists.getHttpReturnCode() == httpStatus) {
  317.                                                 apiResponse = responseExists;
  318.                                                 break;
  319.                                             }
  320.                                         }
  321.                                        
  322.                                         if(apiResponse==null) {
  323.                                             apiResponse=new ApiResponse();
  324.                                             apiResponse.setHttpReturnCode(httpStatus);
  325.                                            
  326.                                             if(rNodeHttpStatus.getParam()!=null){
  327.                                                 for (Param param : rNodeHttpStatus.getParam()) {
  328.                                                     ApiParameterSchema apiParameterSchema = new ApiParameterSchema();
  329.                                                     apiParameterSchema.addType(param.getType().toString(), null);
  330.                                                     ApiHeaderParameter header = new ApiHeaderParameter(param.getName(),apiParameterSchema);
  331.                                                     header.setRequired(param.isRequired());
  332.                                                     apiResponse.addHeaderParameter(header);
  333.                                                 }
  334.                                             }
  335.                                            
  336.                                             operation.addResponse(apiResponse);
  337.                                         }
  338.                                        
  339.                                         if(rNodeHttpStatus.getMediaType()!=null) {
  340.                                             String name = null;
  341.                                             if(rNodeHttpStatus.getElement()!=null) {
  342.                                                 name = rNodeHttpStatus.getElement().getLocalPart();
  343.                                             }
  344.                                             ApiBodyParameter bodyParameter = new ApiBodyParameter(name);
  345.                                             bodyParameter.setMediaType(rNodeHttpStatus.getMediaType());
  346.                                             bodyParameter.setElement(rNodeHttpStatus.getElement());
  347.                                             apiResponse.addBodyParameter(bodyParameter);
  348.                                         }
  349.                                     }
  350.                                    
  351.                                 }
  352.                             }
  353.                            
  354.                             MultivaluedMap<List<Long>, FaultNode> mapFault = methodNode.getFaults();
  355.                             if(mapFault!=null && mapFault.size()>0){
  356.                                 Iterator<List<Long>> itFault = mapFault.keySet().iterator();
  357.                                 while (itFault.hasNext()) {
  358.                                     List<java.lang.Long> listLong = (List<java.lang.Long>) itFault.next();
  359.                                     List<FaultNode> representationNode = mapFault.get(listLong);
  360.                                    
  361.                                     for (int i = 0; i < listLong.size(); i++) {
  362.                                         int httpStatus = listLong.get(i).intValue();
  363.                                         FaultNode rNodeHttpStatus = representationNode.get(i);
  364.                                        
  365.                                         ApiResponse apiResponse = null;
  366.                                         for (ApiResponse responseExists : operation.getResponses()) {
  367.                                             if(responseExists.getHttpReturnCode() == httpStatus) {
  368.                                                 apiResponse = responseExists;
  369.                                                 break;
  370.                                             }
  371.                                         }
  372.                                        
  373.                                         if(apiResponse==null) {
  374.                                             apiResponse=new ApiResponse();
  375.                                             apiResponse.setHttpReturnCode(httpStatus);
  376.                                            
  377.                                             if(rNodeHttpStatus.getParam()!=null){
  378.                                                 for (Param param : rNodeHttpStatus.getParam()) {
  379.                                                     ApiParameterSchema apiParameterSchema = new ApiParameterSchema();
  380.                                                     apiParameterSchema.addType(param.getType().toString(), null);
  381.                                                     ApiHeaderParameter header = new ApiHeaderParameter(param.getName(),apiParameterSchema);
  382.                                                     header.setRequired(param.isRequired());
  383.                                                     apiResponse.addHeaderParameter(header);
  384.                                                 }
  385.                                             }
  386.                                            
  387.                                             operation.addResponse(apiResponse);
  388.                                         }
  389.                                        
  390.                                         if(rNodeHttpStatus.getMediaType()!=null) {
  391.                                             String name = null;
  392.                                             if(rNodeHttpStatus.getElement()!=null) {
  393.                                                 name = rNodeHttpStatus.getElement().getLocalPart();
  394.                                             }
  395.                                             ApiBodyParameter bodyParameter = new ApiBodyParameter(name);
  396.                                             bodyParameter.setMediaType(rNodeHttpStatus.getMediaType());
  397.                                             bodyParameter.setElement(rNodeHttpStatus.getElement());
  398.                                             apiResponse.addBodyParameter(bodyParameter);
  399.                                         }
  400.                                     }
  401.                                 }
  402.                             }
  403.                            
  404.                             api.addOperation(operation);
  405.                         }
  406.                     }
  407.                     this.readOperations(resourceNode.getChildResources(), api);
  408.                 }
  409.             }
  410.         }catch(Exception e){
  411.             throw new ProcessingException(e.getMessage(),e);
  412.         }
  413.     }

  414. }