/**
* Copyright 2005-2014 Restlet
*
* The contents of this file are subject to the terms of one of the following
* open source licenses: Apache 2.0 or or EPL 1.0 (the "Licenses"). You can
* select the license that you prefer but you may not use this file except in
* compliance with one of these Licenses.
*
* You can obtain a copy of the Apache 2.0 license at
* http://www.opensource.org/licenses/apache-2.0
*
* You can obtain a copy of the EPL 1.0 license at
* http://www.opensource.org/licenses/eclipse-1.0
*
* See the Licenses for the specific language governing permissions and
* limitations under the Licenses.
*
* Alternatively, you can obtain a royalty free commercial license with less
* limitations, transferable or non-transferable, directly at
* http://restlet.com/products/restlet-framework
*
* Restlet is a registered trademark of Restlet S.A.S.
*/
package org.restlet.ext.apispark.internal.utils;
import org.restlet.data.ChallengeScheme;
import org.restlet.data.MediaType;
import org.restlet.ext.apispark.internal.introspection.IntrospectionHelper;
import org.restlet.ext.apispark.internal.model.Definition;
import org.restlet.ext.apispark.internal.model.Operation;
import org.restlet.ext.apispark.internal.model.Representation;
import org.restlet.ext.apispark.internal.model.Resource;
import org.restlet.ext.apispark.internal.model.Response;
import org.restlet.ext.apispark.internal.model.Section;
import org.restlet.resource.ClientResource;
import org.restlet.resource.ResourceException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.ServiceLoader;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* Tools library.
*
* @author Thierry Boileau
*/
public class IntrospectionUtils {
public static List<String> STRATEGIES = Arrays.asList("update", "replace");
/**
* Discover introspection helpers.
*
* @return the discovered introspection helpers.
*/
public static List<IntrospectionHelper> getIntrospectionHelpers() {
List<IntrospectionHelper> introspectionHelpers = new ArrayList<>();
ServiceLoader<IntrospectionHelper> ihLoader = ServiceLoader
.load(IntrospectionHelper.class);
for (IntrospectionHelper helper : ihLoader) {
introspectionHelpers.add(helper);
}
return introspectionHelpers;
}
/**
* Indicates if the given value is either null or empty.
*
* @param value
* The value.
* @return True if the value is either null or empty.
*/
public static boolean isEmpty(String value) {
return value == null || value.isEmpty();
}
public static void sendDefinition(Definition definition,
String ulogin, String upwd, String serviceUrl,
String cellType, String cellId, String cellVersion,
boolean createNewCell, boolean createNewVersion,
boolean updateCell, String updateStrategy,
Logger logger) {
String url = serviceUrl + "api/";
sortDefinition(definition);
ClientResource cr = new ClientResource(url);
try {
cr.setChallengeResponse(ChallengeScheme.HTTP_BASIC, ulogin, upwd);
cr.addQueryParameter("type", "rwadef");
if (createNewCell) {
cr.addQueryParameter("cellType", cellType);
cr.addSegment("apis").addSegment("");
logger.info("Create a new cell of type " + cellType);
cr.post(definition, MediaType.APPLICATION_JSON);
} else if (createNewVersion) {
cr.addSegment("apis").addSegment(cellId)
.addSegment("versions").addSegment("");
logger.info("Create a new version of the cell "
+ cellId);
cr.post(definition, MediaType.APPLICATION_JSON);
} else if (updateCell) {
cr.addSegment("apis").addSegment(cellId)
.addSegment("versions").addSegment(cellVersion);
logger.info("Update version " + cellVersion + " of cell "
+ cellId + " with strategy " + updateStrategy);
cr.addQueryParameter("strategy", updateStrategy);
cr.put(definition, MediaType.APPLICATION_JSON);
} else {
throw new RuntimeException("No action error");
}
logger.fine("Call success to "+ cr.getRequest());
if (!cr.getResponse().getStatus().isSuccess()) {
throw new RuntimeException("Request failed with following status: " + cr.getResponse().getStatus());
}
// This is not printed by a logger which may be muted.
if (cr.getResponseEntity() != null
&& cr.getResponseEntity().isAvailable()) {
try {
cr.getResponseEntity().write(System.out);
System.out.println();
} catch (IOException e) {
// [PENDING] analysis
logger.log(Level.WARNING, "Request successfully achieved by the server, but it's response cannot be printed", e);
}
}
if (cr.getLocationRef() != null) {
System.out
.println("Your Web API documentation is accessible at this URL: "
+ cr.getLocationRef());
}
} catch (ResourceException e) {
logger.fine("Error during call to "+ cr.getRequest());
if (e.getStatus().isConnectorError()) {
throw new RuntimeException("APISpark communication error. Please check the root cause below.", e);
} else if (e.getStatus().isClientError()) {
if (e.getStatus().getCode() == 403) {
throw new RuntimeException("APISpark Authentication fails. Check that you provide valid credentials.", e);
} else if (e.getStatus().getCode() == 404) {
throw new RuntimeException("Resource not found. Check that you provide valid cell id and cell version.", e);
} else {
throw new RuntimeException("APISpark returns client error. Please check the root cause below.", e);
}
} else {
throw new RuntimeException("APISpark server encounters some issues, please try later", e);
}
}
}
/**
* Sorts the sections, representations and resources alphabetically in the
* given RWADef definition
*
* @param definition
* The RWADef definition
*/
public static void sortDefinition(Definition definition) {
Collections.sort(definition.getContract().getSections(),
new Comparator<Section>() {
@Override
public int compare(Section o1, Section o2) {
return o1.getName().compareTo(o2.getName());
}
});
Collections.sort(definition.getContract().getRepresentations(),
new Comparator<Representation>() {
@Override
public int compare(Representation o1, Representation o2) {
return o1.getName().compareTo(o2.getName());
}
});
Collections.sort(definition.getContract().getResources(),
new Comparator<Resource>() {
@Override
public int compare(Resource o1, Resource o2) {
return o1.getResourcePath().compareTo(
o2.getResourcePath());
}
});
}
public static void updateRepresentationsSectionsFromResources(
Definition definition) {
Map<Resource, Collection<String>> resourcesLinks = new HashMap<Resource, Collection<String>>();
Map<Representation, Collection<String>> representationsSections = new HashMap<Representation, Collection<String>>();
for (Resource resource : definition.getContract().getResources()) {
Collection<String> representations = new HashSet<String>();
for (Operation operation : resource.getOperations()) {
if (operation.getInputPayLoad() != null
&& operation.getInputPayLoad().getType() != null) {
representations.add(operation.getInputPayLoad().getType());
}
for (Response response : operation.getResponses()) {
if (response.getOutputPayLoad() != null
&& response.getOutputPayLoad().getType() != null) {
representations.add(response.getOutputPayLoad()
.getType());
}
}
}
resourcesLinks.put(resource, representations);
}
for (Entry<Resource, Collection<String>> entry : resourcesLinks
.entrySet()) {
for (String representationIdentifier : entry.getValue()) {
Representation representation = definition.getContract()
.getRepresentation(representationIdentifier);
// primitives types are not present in representations list
if (representation != null) {
if (representationsSections.get(representation) != null) {
representationsSections.get(representation).addAll(
entry.getKey().getSections());
} else {
Collection<String> representationSections = new HashSet<String>();
representationSections.addAll(representation
.getSections());
representationSections.addAll(entry.getKey()
.getSections());
representationsSections.put(representation,
representationSections);
}
}
}
}
for (Entry<Representation, Collection<String>> entry : representationsSections
.entrySet()) {
entry.getKey().setSections(new ArrayList<String>(entry.getValue()));
}
}
}