Java tutorial
/* * Copyright 2002-2016 the original author or authors. * * Licensed under the Apache 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://www.apache.org/licenses/LICENSE-2.0 * * 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 com.phoenixnap.oss.ramlapisync.verification.checkers; import java.io.IOException; import java.util.LinkedHashSet; import java.util.Map; import java.util.Map.Entry; import java.util.Set; import org.jsonschema2pojo.DefaultGenerationConfig; import org.jsonschema2pojo.GenerationConfig; import org.jsonschema2pojo.Jackson2Annotator; import org.jsonschema2pojo.SchemaGenerator; import org.jsonschema2pojo.SchemaMapper; import org.jsonschema2pojo.SchemaStore; import org.jsonschema2pojo.rules.RuleFactory; import org.raml.model.Action; import org.raml.model.ActionType; import org.raml.model.MimeType; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.util.StringUtils; import com.phoenixnap.oss.ramlapisync.naming.Pair; import com.phoenixnap.oss.ramlapisync.verification.Issue; import com.phoenixnap.oss.ramlapisync.verification.IssueLocation; import com.phoenixnap.oss.ramlapisync.verification.IssueSeverity; import com.phoenixnap.oss.ramlapisync.verification.IssueType; import com.phoenixnap.oss.ramlapisync.verification.RamlActionVisitorCheck; import com.sun.codemodel.JCodeModel; import com.sun.codemodel.JFieldVar; /** * A checker that will check the response body declared in an API and the supplied implementation * * @author Kurt Paris * @since 0.1.1 * */ public class ActionResponseBodySchemaChecker implements RamlActionVisitorCheck { public static String RESPONSE_BODY_DIFFERENTSIZE = "Response Body in target has a different number of fields to reference"; public static String RESPONSE_BODY_FIELDMISSING = "Response Body field type is missing"; public static String RESPONSE_BODY_MISSING = "Response Body required but not found in target"; public static String RESPONSE_BODY_FIELDDIFFERENT = "Response Body field type is different"; /** * Class Logger */ protected static final Logger logger = LoggerFactory.getLogger(ActionResponseBodySchemaChecker.class); @Override public Pair<Set<Issue>, Set<Issue>> check(ActionType name, Action reference, Action target, IssueLocation location, IssueSeverity maxSeverity) { logger.debug("Checking action " + name); Set<Issue> errors = new LinkedHashSet<>(); Set<Issue> warnings = new LinkedHashSet<>(); Issue issue; //Only apply this checker in the contract if (location.equals(IssueLocation.CONTRACT)) { return new Pair<>(warnings, errors); } //Now the response if (reference.getResponses() != null && !reference.getResponses().isEmpty() && reference.getResponses().containsKey("200") && reference.getResponses().get("200").getBody() != null) { //successful response Map<String, MimeType> response = reference.getResponses().get("200").getBody(); for (Entry<String, MimeType> responseBodyMime : response.entrySet()) { MimeType value = responseBodyMime.getValue(); if (StringUtils.hasText(value.getSchema())) { logger.debug("Found body for mime type " + responseBodyMime.getKey()); String targetSchema = null; try { //lets assume the implementation contains exactly what we're looking for targetSchema = target.getResponses().get("200").getBody().get(responseBodyMime.getKey()) .getSchema(); } catch (NullPointerException npe) { try { // lets try the first response we get targetSchema = target.getResponses().get("200").getBody().values().iterator().next() .getSchema(); } catch (Exception ex) { issue = new Issue(maxSeverity, location, IssueType.MISSING, RESPONSE_BODY_MISSING, reference.getResource(), reference); RamlCheckerResourceVisitorCoordinator.addIssue(errors, warnings, issue, RESPONSE_BODY_MISSING + " " + responseBodyMime.getKey()); break; } } //just a sanity check in case someone removes the break if (targetSchema != null) { JCodeModel referenceCodeModel = new JCodeModel(); JCodeModel targetCodeModel = new JCodeModel(); GenerationConfig config = new DefaultGenerationConfig() { @Override public boolean isGenerateBuilders() { // set config // option by // overriding // method return false; } }; try { SchemaMapper mapper = new SchemaMapper( new RuleFactory(config, new Jackson2Annotator(), new SchemaStore()), new SchemaGenerator()); mapper.generate(referenceCodeModel, "Reference", "com.response", value.getSchema()); mapper.generate(targetCodeModel, "Target", "com.response", targetSchema); Map<String, JFieldVar> referenceResponseFields = referenceCodeModel ._getClass("com.response.Reference").fields(); Map<String, JFieldVar> targetResponseClassFields = targetCodeModel ._getClass("com.response.Target").fields(); for (Entry<String, JFieldVar> referenceField : referenceResponseFields.entrySet()) { String fieldKey = referenceField.getKey(); JFieldVar targetField = targetResponseClassFields.get(fieldKey); if (targetField == null) { issue = new Issue(maxSeverity, location, IssueType.MISSING, RESPONSE_BODY_FIELDMISSING, reference.getResource(), reference, fieldKey); RamlCheckerResourceVisitorCoordinator.addIssue(errors, warnings, issue, RESPONSE_BODY_FIELDMISSING + " " + fieldKey); } else if (!referenceField.getValue().type().fullName() .equals(targetField.type().fullName())) { issue = new Issue(IssueSeverity.WARNING, location, IssueType.DIFFERENT, RESPONSE_BODY_FIELDDIFFERENT, reference.getResource(), reference, fieldKey); RamlCheckerResourceVisitorCoordinator.addIssue(errors, warnings, issue, RESPONSE_BODY_FIELDDIFFERENT + " " + fieldKey); } } if (referenceResponseFields.size() != targetResponseClassFields.size()) { for (Entry<String, JFieldVar> targetField : targetResponseClassFields.entrySet()) { String fieldKey = targetField.getKey(); JFieldVar referenceField = referenceResponseFields.get(fieldKey); if (referenceField == null) { issue = new Issue(maxSeverity, IssueLocation.CONTRACT, IssueType.MISSING, RESPONSE_BODY_FIELDMISSING, reference.getResource(), reference, fieldKey); RamlCheckerResourceVisitorCoordinator.addIssue(errors, warnings, issue, RESPONSE_BODY_FIELDMISSING + " " + fieldKey); } else if (!targetField.getValue().type().fullName() .equals(referenceField.type().fullName())) { issue = new Issue(IssueSeverity.WARNING, IssueLocation.CONTRACT, IssueType.DIFFERENT, RESPONSE_BODY_FIELDDIFFERENT, reference.getResource(), reference, fieldKey); RamlCheckerResourceVisitorCoordinator.addIssue(errors, warnings, issue, RESPONSE_BODY_FIELDDIFFERENT + " " + fieldKey); } } } } catch (IOException ex) { logger.error("Error during Schema to POJO generation"); } } } } } return new Pair<>(warnings, errors); } }