diff --git a/src/main/java/br/com/elementalsource/mock/generic/api/v1/controller/GenericApiController.java b/src/main/java/br/com/elementalsource/mock/generic/api/v1/controller/GenericApiController.java index e7bc76a..bcaeac0 100755 --- a/src/main/java/br/com/elementalsource/mock/generic/api/v1/controller/GenericApiController.java +++ b/src/main/java/br/com/elementalsource/mock/generic/api/v1/controller/GenericApiController.java @@ -1,11 +1,15 @@ package br.com.elementalsource.mock.generic.api.v1.controller; +import static org.apache.commons.lang3.StringUtils.isNotBlank; + import br.com.elementalsource.mock.generic.service.GenericApiService; import br.com.elementalsource.mock.infra.component.JsonFormatter; import br.com.elementalsource.mock.infra.component.RequestFormatter; import br.com.elementalsource.mock.generic.api.v1.mapper.RequestMapper; import com.google.gson.Gson; import com.google.gson.JsonParseException; + +import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -47,7 +51,9 @@ private void logRequest(final HttpServletRequest request, final Optional private void logJson(final String jsonString) { try { - LOGGER.info(jsonFormatter.format(jsonString)); + if(isNotBlank(jsonString)){ + LOGGER.info(jsonFormatter.format(jsonString)); + } } catch (JsonParseException e) { LOGGER.warn("cannot print json: " + jsonString); } diff --git a/src/main/java/br/com/elementalsource/mock/generic/repository/impl/EndpointFileFilterRequest.java b/src/main/java/br/com/elementalsource/mock/generic/repository/impl/EndpointFileFilterRequest.java index dc3d867..3b8cbc7 100755 --- a/src/main/java/br/com/elementalsource/mock/generic/repository/impl/EndpointFileFilterRequest.java +++ b/src/main/java/br/com/elementalsource/mock/generic/repository/impl/EndpointFileFilterRequest.java @@ -2,12 +2,17 @@ import br.com.elementalsource.mock.generic.model.Endpoint; import br.com.elementalsource.mock.generic.model.Request; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @Component class EndpointFileFilterRequest implements EndpointFileFilter { + private static final Logger LOGGER = LoggerFactory.getLogger(EndpointFileFilterRequest.class); + private final EndpointFileFilterQuery endpointFileFilterQuery; private final EndpointFileFilterBody endpointMockFileFilterBody; @@ -19,8 +24,10 @@ public EndpointFileFilterRequest(EndpointFileFilterQuery endpointFileFilterQuery @Override public Boolean apply(Endpoint endpoint, Request request) { - return endpointFileFilterQuery.apply(endpoint, request.getQuery()) && - endpointMockFileFilterBody.apply(endpoint, request.getBody()); + final Boolean queryFilter = endpointFileFilterQuery.apply(endpoint, request.getQuery()); + final Boolean bodyFilter = endpointMockFileFilterBody.apply(endpoint, request.getBody()); + + return queryFilter && bodyFilter; } -} +} \ No newline at end of file diff --git a/src/main/java/br/com/elementalsource/mock/generic/repository/impl/ExistingFile.java b/src/main/java/br/com/elementalsource/mock/generic/repository/impl/ExistingFile.java new file mode 100644 index 0000000..e94ae31 --- /dev/null +++ b/src/main/java/br/com/elementalsource/mock/generic/repository/impl/ExistingFile.java @@ -0,0 +1,71 @@ +package br.com.elementalsource.mock.generic.repository.impl; + +import java.util.HashMap; +import java.util.Map; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import com.google.common.base.MoreObjects; + +public class ExistingFile implements Comparable { + + private final Pattern regex; + private final String originalPath; + + ExistingFile(String path) { + originalPath = path; + regex = Pattern.compile(path.replaceAll("#\\{\\{\\w*\\}\\}", "(.*)")); + } + + public PathParamExtractor extract(String rawPath) { + return new PathParamExtractor(rawPath); + } + + @Override + public String toString() { + return MoreObjects.toStringHelper(this) + .add("regex", regex) + .add("originalPath", originalPath) + .toString(); + } + + @Override + public int compareTo(final ExistingFile o) { + return this.originalPath.compareTo(o.originalPath) * -1; + } + + public class PathParamExtractor { + + private boolean matches; + private Map parameters = new HashMap<>(); + + public PathParamExtractor(String rawPath ) { + Matcher rawPathMatcher = regex.matcher(rawPath); + Matcher originalPathMatcher = regex.matcher(originalPath); + + matches = rawPathMatcher.matches() && originalPathMatcher.matches(); + + if(matches){ + for (int i = 1; i <= rawPathMatcher.groupCount(); i++){ + parameters.put(originalPathMatcher.group(i).replaceAll("\\W", ""),rawPathMatcher.group(i)); + } + + } + } + + public boolean matches() { + return matches; + } + + public Map getParameters() { + return parameters; + } + + public String getOriginalPath(){ + return originalPath; + } + } + + + +} diff --git a/src/main/java/br/com/elementalsource/mock/generic/repository/impl/ExistingFiles.java b/src/main/java/br/com/elementalsource/mock/generic/repository/impl/ExistingFiles.java new file mode 100644 index 0000000..44ab4cc --- /dev/null +++ b/src/main/java/br/com/elementalsource/mock/generic/repository/impl/ExistingFiles.java @@ -0,0 +1,43 @@ +package br.com.elementalsource.mock.generic.repository.impl; + +import static java.util.stream.Collectors.toList; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.List; + +import javax.annotation.PostConstruct; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.stereotype.Component; +import org.springframework.web.context.annotation.ApplicationScope; + +import br.com.elementalsource.mock.infra.property.FileProperty; + +@Component +@ApplicationScope +public class ExistingFiles { + @Autowired @Qualifier("FilePropertyModel") + private FileProperty fileProperty; + private List existingFiles; + + @PostConstruct + public void setup() throws IOException { + String fileBase = fileProperty.getFileBase(); + existingFiles = Files.walk(Paths.get(fileBase)) + .filter(Files::isRegularFile) + .map(Path::getParent) + .map(Path::toString) + .map(ExistingFile::new) + .sorted() + .distinct() + .collect(toList()); + } + + public List getExistingFiles(){ + return existingFiles; + } +} diff --git a/src/main/java/br/com/elementalsource/mock/infra/component/file/BaseFileNameBuilderBase.java b/src/main/java/br/com/elementalsource/mock/infra/component/file/BaseFileNameBuilderBase.java index 308a285..c77c014 100755 --- a/src/main/java/br/com/elementalsource/mock/infra/component/file/BaseFileNameBuilderBase.java +++ b/src/main/java/br/com/elementalsource/mock/infra/component/file/BaseFileNameBuilderBase.java @@ -1,12 +1,13 @@ package br.com.elementalsource.mock.infra.component.file; -import br.com.elementalsource.mock.infra.property.FileProperty; import org.springframework.web.bind.annotation.RequestMethod; +import br.com.elementalsource.mock.infra.property.FileProperty; + public class BaseFileNameBuilderBase implements BaseFileNameBuilder { private final FileProperty fileProperty; - + public BaseFileNameBuilderBase(FileProperty fileProperty) { this.fileProperty = fileProperty; } diff --git a/src/main/java/br/com/elementalsource/mock/infra/component/file/BaseFileNameBuilderModel.java b/src/main/java/br/com/elementalsource/mock/infra/component/file/BaseFileNameBuilderModel.java index 708c84b..4e4112d 100755 --- a/src/main/java/br/com/elementalsource/mock/infra/component/file/BaseFileNameBuilderModel.java +++ b/src/main/java/br/com/elementalsource/mock/infra/component/file/BaseFileNameBuilderModel.java @@ -1,25 +1,51 @@ package br.com.elementalsource.mock.infra.component.file; +import br.com.elementalsource.mock.generic.repository.impl.ExistingFile; +import br.com.elementalsource.mock.generic.repository.impl.ExistingFile.PathParamExtractor; +import br.com.elementalsource.mock.generic.repository.impl.ExistingFiles; import br.com.elementalsource.mock.infra.property.FileProperty; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.stereotype.Component; +import org.springframework.web.bind.annotation.RequestMethod; import java.io.File; +import java.util.List; + +import javax.servlet.http.HttpServletRequest; @Component("BaseFileNameBuilderModel") public class BaseFileNameBuilderModel extends BaseFileNameBuilderBase implements BaseFileNameBuilder { private static final Logger LOGGER = LoggerFactory.getLogger(BaseFileNameBuilderModel.class); + private ExistingFiles existingFiles; + private HttpServletRequest request; @Autowired - public BaseFileNameBuilderModel(@Qualifier("FilePropertyModel") FileProperty fileProperty) { + public BaseFileNameBuilderModel(@Qualifier("FilePropertyModel") FileProperty fileProperty, ExistingFiles existingFiles, HttpServletRequest request) { super(fileProperty); + this.existingFiles = existingFiles; + this.request = request; final String fileBase = fileProperty.getFileBase(); final File file = new File(fileBase); LOGGER.info("Base path to files fileBase={}, exists?{}, path={}", fileBase, file.exists(), file.getAbsoluteFile()); } + @Override + public String buildPath(RequestMethod requestMethod, String pathUri) { + List files = existingFiles.getExistingFiles(); + String rawPath = super.buildPath(requestMethod, pathUri); + + return files.stream() + .map(ef -> ef.extract(rawPath)) + .filter(PathParamExtractor::matches) + .peek(pe -> { + pe.getParameters().forEach(request::setAttribute); + }) + .map(pe -> pe.getOriginalPath()) + .findFirst() + .orElse(rawPath); + } } diff --git a/src/main/java/br/com/elementalsource/mock/infra/component/impl/JsonFormatterPretty.java b/src/main/java/br/com/elementalsource/mock/infra/component/impl/JsonFormatterPretty.java index d939a54..ae2616d 100755 --- a/src/main/java/br/com/elementalsource/mock/infra/component/impl/JsonFormatterPretty.java +++ b/src/main/java/br/com/elementalsource/mock/infra/component/impl/JsonFormatterPretty.java @@ -14,7 +14,6 @@ public class JsonFormatterPretty implements JsonFormatter { public String format(final String jsonString) { final JsonParser parser = new JsonParser(); final Gson gson = new GsonBuilder().setPrettyPrinting().create(); - final JsonElement el = parser.parse(jsonString); return gson.toJson(el).concat("\n"); } diff --git a/src/main/java/br/com/elementalsource/mock/infra/component/impl/ParameterJsonValueCompilerImpl.java b/src/main/java/br/com/elementalsource/mock/infra/component/impl/ParameterJsonValueCompilerImpl.java index 5bbadd1..f0a1893 100755 --- a/src/main/java/br/com/elementalsource/mock/infra/component/impl/ParameterJsonValueCompilerImpl.java +++ b/src/main/java/br/com/elementalsource/mock/infra/component/impl/ParameterJsonValueCompilerImpl.java @@ -2,6 +2,7 @@ import java.time.LocalDate; import java.time.format.DateTimeFormatter; +import java.util.Optional; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -30,7 +31,7 @@ public String compile(String json) { final StringBuffer sb = new StringBuffer(); while (m.find()) { String paramName = m.group(1); - String paramValue = request.getParameter(paramName); + String paramValue = getValue(paramName); if(paramValue != null){ m.appendReplacement(sb, paramValue); @@ -40,4 +41,8 @@ public String compile(String json) { return sb.toString(); } + private String getValue(String paramName) { + return Optional.ofNullable(request.getParameter(paramName)).orElse((String) request.getAttribute(paramName)); + } + } diff --git a/src/test/java/br/com/elementalsource/mock/generic/repository/impl/ExistingFileTest.java b/src/test/java/br/com/elementalsource/mock/generic/repository/impl/ExistingFileTest.java new file mode 100644 index 0000000..4a8682c --- /dev/null +++ b/src/test/java/br/com/elementalsource/mock/generic/repository/impl/ExistingFileTest.java @@ -0,0 +1,52 @@ +package br.com.elementalsource.mock.generic.repository.impl; + +import static org.junit.Assert.*; + +import org.junit.Test; + +public class ExistingFileTest { + + @Test + public void shouldMatchesSamePath(){ + String path = "/some/path"; + ExistingFile existingFile = new ExistingFile(path); + + ExistingFile.PathParamExtractor paramExtractor = existingFile.extract(path); + + assertTrue(paramExtractor.matches()); + assertEquals(0, paramExtractor.getParameters().size()); + + } + + @Test + public void shouldMatchesAPathWithAVariable(){ + String filePath = "/some/#{{variable}}/path"; + String urlPath = "/some/value/path"; + + ExistingFile existingFile = new ExistingFile(filePath); + + ExistingFile.PathParamExtractor paramExtractor = existingFile.extract(urlPath); + + assertTrue(paramExtractor.matches()); + assertEquals(1, paramExtractor.getParameters().size()); + assertEquals("value", paramExtractor.getParameters().get("variable")); + + } + + @Test + public void shouldMatchesAPathWithMultipleVariables(){ + String filePath = "/some/#{{variable1}}/path/#{{variable2}}"; + String urlPath = "/some/value/path/another"; + + ExistingFile existingFile = new ExistingFile(filePath); + + ExistingFile.PathParamExtractor paramExtractor = existingFile.extract(urlPath); + + assertTrue(paramExtractor.matches()); + assertEquals(2, paramExtractor.getParameters().size()); + assertEquals("value", paramExtractor.getParameters().get("variable1")); + assertEquals("another", paramExtractor.getParameters().get("variable2")); + + } + +} \ No newline at end of file