Compare commits
68 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 57a08c3246 | |||
| 5a331d9815 | |||
| e9221e2393 | |||
| 7318708bd2 | |||
| 66b20f8256 | |||
| b6e6277074 | |||
| fb128070dc | |||
| d0c19e19df | |||
| c41c3f5abc | |||
| 9b18a9f42d | |||
| a8d93fc2a5 | |||
| 6058169818 | |||
| d336f5d18e | |||
| 45fab20cc4 | |||
| b733e1e344 | |||
| 97042faaa3 | |||
| 8815f657e0 | |||
| ecafb17f05 | |||
| f9b426bb30 | |||
| 02c10b8354 | |||
| 5b69fd1de0 | |||
| 2aaf993f7a | |||
| d5e33381a2 | |||
| d231a7476b | |||
| 369256baf2 | |||
| e697a783ae | |||
| 1930cde695 | |||
| bcbfd34feb | |||
| 2d97e39dbe | |||
| c89623c3a8 | |||
| dc3df79fc1 | |||
| 34038a2ce9 | |||
| d8504ee8f8 | |||
| 6a1c6aac46 | |||
| 7fd6fd3788 | |||
| 41d3b90fd8 | |||
| c55942c24a | |||
| 21f5911b1c | |||
| 71bbe668f6 | |||
| 4a04ac3b70 | |||
| b26840ffba | |||
| 1199e06bef | |||
| 1b7f6e6f70 | |||
| fe6585d509 | |||
| 093c8756b1 | |||
| 2b8a9c3008 | |||
| 1f10a1d5b5 | |||
| 8a852b7a83 | |||
| 38c1215889 | |||
| 1fc1ab76ec | |||
| 2f0541fe3d | |||
| 5c39b7cfe0 | |||
| db055ef58b | |||
| 420bfaccd9 | |||
| 3d41447581 | |||
| a773022f0d | |||
| afcd52815f | |||
| b72157377d | |||
| 0946982ab6 | |||
| 8098aeacd9 | |||
| de94eca0ac | |||
| a7edf934f7 | |||
| 7c0d79612a | |||
| 02f1977ff0 | |||
| 1816302ba1 | |||
| 00f3606da6 | |||
| f77a6f15c2 | |||
| 0e9a87bfe7 |
@@ -9,11 +9,11 @@ import Parser
|
||||
|
||||
app = Flask(__name__)
|
||||
CORS(app)
|
||||
cors = CORS(app, resource={
|
||||
r"/*":{
|
||||
"origins":"*"
|
||||
}
|
||||
})
|
||||
# cors = CORS(app, resource={
|
||||
# r"/*":{
|
||||
# "origins":"*"
|
||||
# }
|
||||
# })
|
||||
|
||||
def process_xml(request: request, type: str) -> str:
|
||||
"""Function to process
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
lxml
|
||||
flask
|
||||
flask_cors
|
||||
lxml==4.9.2
|
||||
flask==2.3.2
|
||||
flask_cors==3.0.10
|
||||
@@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-parent</artifactId>
|
||||
<version>2.3.1.RELEASE</version>
|
||||
<version>2.7.11</version>
|
||||
<relativePath/> <!-- lookup parent from repository -->
|
||||
</parent>
|
||||
|
||||
@@ -18,9 +18,10 @@
|
||||
<jedis.version>3.3.0</jedis.version>
|
||||
<logback-redis-appender.version>1.1.6</logback-redis-appender.version>
|
||||
<assertj.version>3.16.1</assertj.version>
|
||||
<mapstruct.version>1.3.1.Final</mapstruct.version>
|
||||
<mapstruct.version>1.5.5.Final</mapstruct.version>
|
||||
<docker.image.prefix>Release11</docker.image.prefix>
|
||||
<docker.image.name>${project.artifactId}</docker.image.name>
|
||||
<lombok.version>1.18.26</lombok.version>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
@@ -57,21 +58,6 @@
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-data-redis</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.cwbase</groupId>
|
||||
<artifactId>logback-redis-appender</artifactId>
|
||||
<version>${logback-redis-appender.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>redis.clients</groupId>
|
||||
<artifactId>jedis</artifactId>
|
||||
<version>${jedis.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.codehaus.jettison</groupId>
|
||||
<artifactId>jettison</artifactId>
|
||||
<version>1.4.1</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
@@ -101,6 +87,11 @@
|
||||
<artifactId>lombok</artifactId>
|
||||
<version>${lombok.version}</version>
|
||||
</path>
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok-mapstruct-binding</artifactId>
|
||||
<version>0.2.0</version>
|
||||
</dependency>
|
||||
</annotationProcessorPaths>
|
||||
<compilerArgs>
|
||||
<compilerArg>-Amapstruct.defaultComponentModel=spring</compilerArg>
|
||||
|
||||
@@ -1,68 +0,0 @@
|
||||
package com.r11.tools.config;
|
||||
|
||||
import java.util.Objects;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.PropertySource;
|
||||
import org.springframework.core.env.Environment;
|
||||
import org.springframework.data.redis.connection.RedisStandaloneConfiguration;
|
||||
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
|
||||
import org.springframework.data.redis.core.RedisTemplate;
|
||||
import org.springframework.data.redis.repository.configuration.EnableRedisRepositories;
|
||||
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
|
||||
import redis.clients.jedis.JedisPool;
|
||||
|
||||
/**
|
||||
* Class containing configuration for Redis db client
|
||||
* @author Rafał Żukowicz
|
||||
*/
|
||||
@Configuration
|
||||
@EnableRedisRepositories
|
||||
@PropertySource("classpath:data-access.properties")
|
||||
public class RedisConfig {
|
||||
|
||||
@Autowired
|
||||
private Environment environment;
|
||||
|
||||
/**
|
||||
* Bean of JedisPool - the Redis client. It stores requests in "the pool" and then fires them at Redis.
|
||||
* It's considered super lightweight and fast client variant
|
||||
* @return lightweight client of the Redis - the JedisPool
|
||||
*/
|
||||
@Bean
|
||||
JedisPool jedisPool(){
|
||||
final JedisPool pool = new JedisPool(environment.getProperty("redis.host"),
|
||||
Integer.parseInt(environment.getProperty("redis.port")));
|
||||
return pool;
|
||||
}
|
||||
|
||||
/**
|
||||
* Bean of a factory for connenction object.
|
||||
* It's initialized with Redis db url property and is fed to other methods.
|
||||
* @return the factory for RedisTemplates
|
||||
*/
|
||||
@Bean
|
||||
JedisConnectionFactory jedisConnectionFactory() {
|
||||
RedisStandaloneConfiguration redisStandaloneConfiguration =
|
||||
new RedisStandaloneConfiguration(Objects.requireNonNull(environment.getProperty("redis.host")),
|
||||
Integer.parseInt(Objects.requireNonNull(environment.getProperty("redis.port"))));
|
||||
return new JedisConnectionFactory(redisStandaloneConfiguration);
|
||||
}
|
||||
|
||||
/**
|
||||
* RedisTemplate is the tool to store and retrieve given type (object) of hash from the database.
|
||||
* It's like you could store your Java object by just naming it inside database. You might thing about it
|
||||
* as of DAO.
|
||||
* @return RedisTemplate the redis dao.
|
||||
*/
|
||||
@Bean
|
||||
public RedisTemplate<String, Object> redisTemplate() {
|
||||
RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
|
||||
redisTemplate.setConnectionFactory(jedisConnectionFactory());
|
||||
redisTemplate.setExposeConnection(true);
|
||||
redisTemplate.setDefaultSerializer(new GenericJackson2JsonRedisSerializer());
|
||||
return redisTemplate;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
package com.r11.tools.configuration;
|
||||
|
||||
import com.r11.tools.repository.MockedResponseRepository;
|
||||
import com.r11.tools.repository.RequestHistoryRepository;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.scheduling.annotation.Async;
|
||||
import org.springframework.scheduling.annotation.EnableAsync;
|
||||
import org.springframework.scheduling.annotation.EnableScheduling;
|
||||
import org.springframework.scheduling.annotation.Scheduled;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* Based on configuration deletes all outdated messages and history records from database.
|
||||
*
|
||||
* @author Mikołaj Widła
|
||||
*/
|
||||
|
||||
@EnableScheduling
|
||||
@EnableAsync
|
||||
@Configuration
|
||||
public class RetentionConfiguration {
|
||||
|
||||
private final MockedResponseRepository responseRepository;
|
||||
private final RequestHistoryRepository historyRepository;
|
||||
private final RetentionConfigurationProperties retentionProperties;
|
||||
private final Logger log = LogManager.getRootLogger();
|
||||
|
||||
|
||||
public RetentionConfiguration(MockedResponseRepository responseRepository,
|
||||
RequestHistoryRepository historyRepository,
|
||||
RetentionConfigurationProperties retentionProperties){
|
||||
this.historyRepository = historyRepository;
|
||||
this.responseRepository = responseRepository;
|
||||
this.retentionProperties = retentionProperties;
|
||||
}
|
||||
@Scheduled(fixedDelayString = "#{${retention.retention-cooldown} * 60000 }")
|
||||
@Async
|
||||
public void deleteMessagesAndHistoryRecords(){
|
||||
log.info("OUTDATED MESSAGES AND HISTORY RECORDS DELETED!");
|
||||
responseRepository
|
||||
.findAll()
|
||||
.iterator()
|
||||
.forEachRemaining( mockedMessage -> {
|
||||
if (mockedMessage.getCreatedAt().plusMinutes(retentionProperties.getMinutesToDeleteMessage()).isBefore(LocalDateTime.now())){
|
||||
responseRepository.delete(mockedMessage);
|
||||
}
|
||||
} );
|
||||
|
||||
historyRepository
|
||||
.findAll()
|
||||
.iterator()
|
||||
.forEachRemaining(
|
||||
historyRecord -> {
|
||||
if (historyRecord.getDateTimeStamp().plusMinutes(retentionProperties.getMinutesToDeleteHistoryRecord()).isBefore(LocalDateTime.now())){
|
||||
historyRepository.delete(historyRecord);
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
package com.r11.tools.configuration;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
import javax.validation.constraints.Positive;
|
||||
|
||||
/**
|
||||
* Store all properties needed to change a retention in {@link RetentionConfiguration}
|
||||
*
|
||||
* @author Mikołaj Widła
|
||||
*/
|
||||
|
||||
@Configuration
|
||||
@ConfigurationProperties(prefix = "retention")
|
||||
@Getter
|
||||
@Setter
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class RetentionConfigurationProperties {
|
||||
@Positive
|
||||
private Integer minutesToDeleteMessage;
|
||||
@Positive
|
||||
private Integer minutesToDeleteHistoryRecord;
|
||||
@Positive
|
||||
private Integer retentionCooldown;
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
package com.r11.tools.configuration;
|
||||
|
||||
import com.r11.tools.interceptor.IncomingMockRequestInterceptor;
|
||||
import lombok.AllArgsConstructor;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
|
||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
||||
|
||||
/**
|
||||
* Configuration for {@link IncomingMockRequestInterceptor}
|
||||
*
|
||||
* @author Mikołaj Widła
|
||||
*/
|
||||
|
||||
@Configuration
|
||||
@AllArgsConstructor
|
||||
public class WebConfig implements WebMvcConfigurer{
|
||||
|
||||
private final IncomingMockRequestInterceptor requestInterceptor;
|
||||
|
||||
|
||||
@Override
|
||||
public void addInterceptors(InterceptorRegistry registry) {
|
||||
registry.addInterceptor( requestInterceptor )
|
||||
.addPathPatterns("/api/mock/r/**");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,56 +0,0 @@
|
||||
package com.r11.tools.controller;
|
||||
|
||||
import com.r11.tools.model.EventRequestDto;
|
||||
import com.r11.tools.service.EtrackService;
|
||||
import lombok.AllArgsConstructor;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* It's the REST api for {@link com.r11.tools.model.Event}
|
||||
* @author Gabriel Modzelewski
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping(path = "/api/event")
|
||||
@AllArgsConstructor
|
||||
public class EventController {
|
||||
private final EtrackService service;
|
||||
|
||||
/**
|
||||
* Returns the list of Events in given time bracket.
|
||||
* The list of objects is received via {@link EventRequestDto}, which contains time brackets,
|
||||
* as well as the key - uuid.
|
||||
* @param event EventRequestDto object that contains data needed to query the database
|
||||
* @return list of {@link com.r11.tools.model.Event}
|
||||
*/
|
||||
@PostMapping
|
||||
public ResponseEntity filterHistory(@RequestBody EventRequestDto event){
|
||||
return new ResponseEntity(service.getEventsByDateTimeAndBusinessKeys(event), HttpStatus.OK);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the list of Events of last 24h from given date.
|
||||
* @param uuid unique id of message list
|
||||
* @param messageId unique id of message in message list
|
||||
* @return list of {@link com.r11.tools.model.Event}
|
||||
*/
|
||||
@GetMapping(path = "/{uuid}/{messageId}")
|
||||
public ResponseEntity getLastDay(@PathVariable UUID uuid,
|
||||
@PathVariable Integer messageId){
|
||||
LocalDateTime requestTime = LocalDateTime.now();
|
||||
LocalDateTime dayBeforeRequest = requestTime.minusDays(1L);
|
||||
EventRequestDto eventRequestDto = EventRequestDto.builder()
|
||||
.clientUUID(uuid)
|
||||
.mockedResponseId(messageId)
|
||||
.localDateTimeFrom(dayBeforeRequest)
|
||||
.localDateTimeTo(requestTime)
|
||||
.build();
|
||||
return new ResponseEntity(service.getEventsByDateTimeAndBusinessKeys(eventRequestDto), HttpStatus.OK);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
package com.r11.tools.controller;
|
||||
|
||||
import lombok.SneakyThrows;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
|
||||
/**
|
||||
* Class responsible for returning homepage html
|
||||
* @author Gabriel Modzelewski
|
||||
*/
|
||||
@Controller
|
||||
@RequestMapping("/")
|
||||
public class MainController {
|
||||
/**
|
||||
* Default path to get the homepage
|
||||
* @return the view of homepage
|
||||
*/
|
||||
@SneakyThrows
|
||||
@GetMapping
|
||||
public ModelAndView showHome(){
|
||||
ModelAndView mov = new ModelAndView();
|
||||
mov.setViewName("html/mock");
|
||||
return mov;
|
||||
}
|
||||
}
|
||||
@@ -3,13 +3,14 @@ package com.r11.tools.controller;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.r11.tools.model.MockedMessageDto;
|
||||
import com.r11.tools.service.KlausService;
|
||||
import com.r11.tools.utilis.BusinessKey;
|
||||
import com.r11.tools.utilis.TrackingClient;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.SneakyThrows;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.springframework.http.*;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
@@ -18,17 +19,19 @@ import java.util.*;
|
||||
/**
|
||||
* Returns the homepage and provides the api for javascript async requests.
|
||||
* @author Gabriel Modzelewski
|
||||
* @author Mikołaj Widła
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping(path = "/api/mock")
|
||||
@AllArgsConstructor
|
||||
@CrossOrigin(origins = "*")
|
||||
public class MockController {
|
||||
private final KlausService klausService;
|
||||
private final Logger log = LogManager.getRootLogger();
|
||||
|
||||
@ExceptionHandler(Exception.class)
|
||||
public void errorHandler(Exception ex){
|
||||
log.error(ex.getStackTrace());
|
||||
log.error(Arrays.toString(ex.getStackTrace()));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -48,106 +51,35 @@ public class MockController {
|
||||
* Returns the full list of messages. It's used by javascript on the client side to initialize homepage
|
||||
* with data from the database.
|
||||
* @param uuidValue the key-uuid of given set of messages
|
||||
* @return responds with 200 OK and list of {@link MockedMessageDto}
|
||||
* @return responds with 200 OK and {@link MockedMessageDto}
|
||||
*/
|
||||
@GetMapping({"/", "/{uuidValue}"})
|
||||
public List<MockedMessageDto> getListOfMessages(@PathVariable(required = false) String uuidValue){
|
||||
public MockedMessageDto getMessage(@PathVariable(required = false) String uuidValue){
|
||||
UUID clientUUID;
|
||||
MockedMessageDto message ;
|
||||
if(uuidValue == null || uuidValue.equals("")) clientUUID = UUID.randomUUID();
|
||||
else clientUUID = UUID.fromString(uuidValue);
|
||||
List<MockedMessageDto> messages = klausService.getAllMockedResponses(clientUUID);
|
||||
if(messages.size() == 0) {
|
||||
klausService.setMockedResponse(buildDefaultMessage(clientUUID));
|
||||
messages = klausService.getAllMockedResponses(clientUUID);
|
||||
}
|
||||
Collections.sort(messages);
|
||||
return messages;
|
||||
}
|
||||
message = klausService
|
||||
.getMockedMessageByClientUUID(clientUUID)
|
||||
.orElse( buildDefaultMessage(clientUUID) );
|
||||
|
||||
/**
|
||||
* If provided UUID does not exist in database returns ResponseEntity with new generated UUID(if previous UUID is not provided),
|
||||
* or old UUID(if previous UUID is provided). If provided UUID exists function returns provided UUID.
|
||||
* @param givenUUIDValue the UUID client wants to check exsitance in database
|
||||
* @param previousUUIDValue the previous UUID used by client(optional variable)
|
||||
* @return ResponseEntity with UUID
|
||||
*/
|
||||
@RequestMapping(
|
||||
method = RequestMethod.GET ,
|
||||
path = {"/check/{givenUUIDValue}/{previousUUIDValue}",
|
||||
"/check/{givenUUIDValue}"})
|
||||
public ResponseEntity<String> checkUUID(
|
||||
@PathVariable String givenUUIDValue
|
||||
,@PathVariable(required = false) String previousUUIDValue ){
|
||||
try{
|
||||
UUID.fromString(givenUUIDValue);
|
||||
} catch (IllegalArgumentException ex){
|
||||
log.error("Wrong UUID value!");
|
||||
if (previousUUIDValue == null || previousUUIDValue.equals("")){
|
||||
UUID newUUID = UUID.randomUUID();
|
||||
log.info("New UUID generated.");
|
||||
return ResponseEntity.ok(newUUID.toString());
|
||||
}
|
||||
log.info("Previous UUID value restored.");
|
||||
return ResponseEntity.ok(previousUUIDValue);
|
||||
}
|
||||
return ResponseEntity.ok(givenUUIDValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Accepts empty post request and creates new message in given set. The new message has default set of data,
|
||||
* which is constructed in {@link #buildDefaultMessage(UUID, int)} method.
|
||||
* @param uuidValue the key-uuid of given set of messages
|
||||
* @return confirmation response with 200 OK
|
||||
*/
|
||||
@PostMapping("/{uuidValue}")
|
||||
public ResponseEntity<String> addNewMessage(@PathVariable String uuidValue){
|
||||
UUID clientUUID = UUID.fromString(uuidValue);
|
||||
List<MockedMessageDto> messages = klausService.getAllMockedResponses(clientUUID);
|
||||
MockedMessageDto nextMessage = buildDefaultMessage(clientUUID, findNextId(messages));
|
||||
return klausService.setMockedResponse(nextMessage);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes message of given id via client request
|
||||
* @param uuidValue the key-uuid of given set of messages
|
||||
* @param idValue unique id of given message
|
||||
* @return after deletion the confirmation is send with status 200 OK
|
||||
*/
|
||||
@DeleteMapping("/{uuidValue}/{idValue}")
|
||||
public ResponseEntity<String> removeMessage(@PathVariable String uuidValue,
|
||||
@PathVariable String idValue){
|
||||
UUID clientUUID = UUID.fromString(uuidValue);
|
||||
int id = Integer.parseInt(idValue);
|
||||
return klausService.deleteMockedResponse(clientUUID, id);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Recalls {@link #buildDefaultMessage(UUID)} for message construction and sets id of message
|
||||
* @param uuid the key-uuid of given set of messages
|
||||
* @param id unique id of given message
|
||||
* @return message with default dataset and set id
|
||||
*/
|
||||
private static MockedMessageDto buildDefaultMessage(UUID uuid, int id){
|
||||
MockedMessageDto message = buildDefaultMessage(uuid);
|
||||
message.setMockedResponseId(id);
|
||||
return message;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Constructs message with default set of data
|
||||
* @param uuid the key-uuid of given set of messages
|
||||
* @return message with default dataset
|
||||
*/
|
||||
private static MockedMessageDto buildDefaultMessage(UUID uuid){
|
||||
private MockedMessageDto buildDefaultMessage(UUID uuid){
|
||||
Map<String, String> headers = new HashMap<>();
|
||||
headers.put("Keep-Alive", "timeout=60");
|
||||
headers.put("Connection", "keep-alive");
|
||||
headers.put("Date", LocalDateTime.now().toString());
|
||||
return MockedMessageDto.builder()
|
||||
MockedMessageDto mockedMessageDto = MockedMessageDto.builder()
|
||||
.clientUUID(uuid)
|
||||
.mockedResponseId(1)
|
||||
.mediaType(MediaType.APPLICATION_XML_VALUE)
|
||||
.contentType(MediaType.APPLICATION_XML_VALUE)
|
||||
.messageBody("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
|
||||
"<note>\n" +
|
||||
" <to>Tove</to>\n" +
|
||||
@@ -158,46 +90,24 @@ public class MockController {
|
||||
.httpHeaders(headers)
|
||||
.httpStatus(200)
|
||||
.build();
|
||||
klausService.setMockedResponse(mockedMessageDto);
|
||||
return mockedMessageDto;
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds the highest id in the list and returns it incremented by 1
|
||||
* @param messages list of messages
|
||||
* @return highest id incremented by 1
|
||||
*/
|
||||
public static int findNextId(List<MockedMessageDto> messages) {
|
||||
int highestId = 0;
|
||||
for (MockedMessageDto m : messages)
|
||||
highestId = highestId > m.getMockedResponseId() ? highestId : m.getMockedResponseId();
|
||||
return ++highestId;
|
||||
}
|
||||
|
||||
/**
|
||||
* It's one of the most important features - the bread and butter of the Mocked Service. It's link that allows
|
||||
* to receive mocked response from the server and use it to mock!
|
||||
* @param requestEntity Logs the data of request
|
||||
* @param clientUUID the key-uuid of given set of messages
|
||||
* @param mockedResponseId unique id of given message
|
||||
* @return
|
||||
*/
|
||||
@GetMapping(value = "/r/{clientUUID}/{mockedResponseId}")
|
||||
public ResponseEntity getMockedResponse(RequestEntity<String> requestEntity,
|
||||
@PathVariable UUID clientUUID,
|
||||
@PathVariable int mockedResponseId) {
|
||||
TrackingClient.setBusinessKeys(Map.of(BusinessKey.INTERFACE_NAME, "getMockedResponse - request",
|
||||
BusinessKey.CLIENT_UUID, String.valueOf(clientUUID),
|
||||
BusinessKey.MESSAGE_ID, String.valueOf(mockedResponseId)));
|
||||
// log.info(requestEntity.toString().replaceAll("\"", "\\\\\"").substring(1).replaceAll("\n",""));
|
||||
TrackingClient.setBusinessKeys(Map.of(BusinessKey.INTERFACE_NAME, "getMockedResponse - response",
|
||||
BusinessKey.CLIENT_UUID, String.valueOf(clientUUID),
|
||||
BusinessKey.MESSAGE_ID, String.valueOf(mockedResponseId)));
|
||||
MockedMessageDto mockedMessageDto = klausService.getMockedResponse(clientUUID, mockedResponseId);
|
||||
@RequestMapping(value = "/r/{clientUUID}")
|
||||
public ResponseEntity getMockedResponse(
|
||||
@PathVariable UUID clientUUID) {
|
||||
MockedMessageDto mockedMessageDto = klausService.getMockedResponse(clientUUID);
|
||||
HttpHeaders httpHeaders = new HttpHeaders();
|
||||
if (mockedMessageDto.getHttpHeaders() != null) mockedMessageDto.getHttpHeaders().forEach(httpHeaders::set);
|
||||
httpHeaders.add("Content-Type", mockedMessageDto.getMediaType());
|
||||
httpHeaders.add("Content-Type", mockedMessageDto.getContentType());
|
||||
return new ResponseEntity<>(mockedMessageDto.getMessageBody(), httpHeaders,
|
||||
Objects.requireNonNull(HttpStatus.valueOf(mockedMessageDto.getHttpStatus())));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.validation.BindException;
|
||||
import org.springframework.web.bind.annotation.ControllerAdvice;
|
||||
import org.springframework.web.bind.annotation.CrossOrigin;
|
||||
import org.springframework.web.bind.annotation.ExceptionHandler;
|
||||
|
||||
|
||||
@@ -15,6 +16,7 @@ import org.springframework.web.bind.annotation.ExceptionHandler;
|
||||
* @author Rafał Żukowicz
|
||||
*/
|
||||
@ControllerAdvice
|
||||
@CrossOrigin(origins = "*")
|
||||
public class MvcExceptionHandler {
|
||||
|
||||
/**
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
package com.r11.tools.controller;
|
||||
|
||||
import com.r11.tools.mappers.RequestHistoryMapper;
|
||||
import com.r11.tools.model.RequestHistory;
|
||||
import com.r11.tools.model.RequestHistoryDTO;
|
||||
import com.r11.tools.service.RequestHistoryService;
|
||||
import lombok.AllArgsConstructor;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* It's the REST api for {@link RequestHistory}
|
||||
* @author Gabriel Modzelewski
|
||||
* @author Mikołaj Widła
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping(path = "/api/event")
|
||||
@AllArgsConstructor
|
||||
@CrossOrigin(origins = "*")
|
||||
public class RequestHistoryController {
|
||||
private final RequestHistoryService service;
|
||||
private final RequestHistoryMapper mapper;
|
||||
|
||||
/**
|
||||
* Returns the list of Events.
|
||||
* @param uuid unique id of message list
|
||||
* @return list of {@link RequestHistory}
|
||||
*/
|
||||
@GetMapping(path = "/{uuid}")
|
||||
public ResponseEntity<List<RequestHistoryDTO>> getLastDay(@PathVariable String uuid){
|
||||
List<RequestHistoryDTO> requestHistory = service.getHistoryRecordsByUUID(
|
||||
uuid
|
||||
).stream()
|
||||
.map(mapper::requestHistoryToRequestHistoryDTO)
|
||||
.collect(Collectors.toList());
|
||||
return ResponseEntity.ok(requestHistory);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,78 @@
|
||||
package com.r11.tools.interceptor;
|
||||
|
||||
import com.r11.tools.model.RequestHistoryDTO;
|
||||
import com.r11.tools.service.RequestHistoryService;
|
||||
import lombok.AllArgsConstructor;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.util.StreamUtils;
|
||||
import org.springframework.web.servlet.HandlerInterceptor;
|
||||
import org.springframework.web.servlet.HandlerMapping;
|
||||
import org.springframework.web.util.ContentCachingRequestWrapper;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.Charset;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.StreamSupport;
|
||||
|
||||
/**
|
||||
* Interceptor that gets needed data from HttpRequest, and saves it to history
|
||||
* @author Mikołaj Widła
|
||||
*/
|
||||
|
||||
@Component
|
||||
@AllArgsConstructor
|
||||
public class IncomingMockRequestInterceptor implements HandlerInterceptor {
|
||||
|
||||
private final RequestHistoryService historyService;
|
||||
|
||||
@Override
|
||||
public boolean preHandle(HttpServletRequest httpRequest, HttpServletResponse response, Object handler){
|
||||
Map<String,String> headers = getHeadersFromHttpRequest(httpRequest);
|
||||
Map<String,String> pathVariable = getPathVariablesFromHttpRequest(httpRequest);
|
||||
String requestBody = getRequestBodyFromHttpRequest(httpRequest);
|
||||
|
||||
RequestHistoryDTO historyDTO = RequestHistoryDTO.builder()
|
||||
.httpMethod(HttpMethod.valueOf(httpRequest.getMethod()))
|
||||
.headers( headers )
|
||||
.clientUUID(UUID.fromString(pathVariable.get("clientUUID")))
|
||||
.dateTimeStamp(LocalDateTime.now())
|
||||
.requestBody(requestBody)
|
||||
.build();
|
||||
historyService.saveRequest(historyDTO);
|
||||
return true;
|
||||
}
|
||||
|
||||
private Map<String,String> getHeadersFromHttpRequest( HttpServletRequest httpRequest ){
|
||||
Set<String> headersName = StreamSupport.stream(
|
||||
Spliterators.spliteratorUnknownSize(
|
||||
httpRequest.getHeaderNames().asIterator(),
|
||||
Spliterator.ORDERED
|
||||
), false
|
||||
).collect(Collectors.toSet());
|
||||
|
||||
return headersName.stream()
|
||||
.collect(Collectors.toMap(
|
||||
value -> value,
|
||||
httpRequest::getHeader
|
||||
));
|
||||
}
|
||||
|
||||
private Map<String,String> getPathVariablesFromHttpRequest( HttpServletRequest httpRequest ){
|
||||
return (Map<String, String>) httpRequest.getAttribute(HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE);
|
||||
}
|
||||
|
||||
private String getRequestBodyFromHttpRequest( HttpServletRequest httpRequest ){
|
||||
HttpServletRequest wrappedRequest = new ContentCachingRequestWrapper(httpRequest);
|
||||
try {
|
||||
return StreamUtils.copyToString(wrappedRequest.getInputStream(), Charset.defaultCharset());
|
||||
} catch (IOException e) {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -4,14 +4,23 @@ import com.r11.tools.model.MockedMessage;
|
||||
import com.r11.tools.model.MockedMessageDto;
|
||||
import org.mapstruct.*;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* Creates key value for redis entry
|
||||
* @author Rafał Źukowicz
|
||||
*/
|
||||
@Mapper
|
||||
public interface MockedMessageMapper {
|
||||
@Mapping( target = "compositePrimaryKey", expression = "java(mockedMessageDto.getClientUUID() + \"_\"" +
|
||||
" + mockedMessageDto.getMockedResponseId())")
|
||||
@Mapping( target = "createdAt" , expression = "java(java.time.LocalDateTime.now())")
|
||||
MockedMessage mockedMessageDtoToMockedMessage(MockedMessageDto mockedMessageDto);
|
||||
MockedMessageDto mockedMessageToMockedMessageDto(MockedMessage mockedMessage);
|
||||
|
||||
default Optional<MockedMessageDto> optionalMockedMessageToOptionalMockedMessageDTO(Optional<MockedMessage> optionalMockedMessage){
|
||||
return optionalMockedMessage.map(this::mockedMessageToMockedMessageDto);
|
||||
}
|
||||
|
||||
default Optional<MockedMessage> optionalMockedMessageDTOToOptionalMockedMessage(Optional<MockedMessageDto> optionalMockedMessageDto){
|
||||
return optionalMockedMessageDto.map(this::mockedMessageDtoToMockedMessage);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
package com.r11.tools.mappers;
|
||||
|
||||
import com.r11.tools.model.RequestHistory;
|
||||
import com.r11.tools.model.RequestHistoryDTO;
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.Mapping;
|
||||
|
||||
/**
|
||||
* Map between DTO and Entity
|
||||
*
|
||||
* @author Mikołaj Widła
|
||||
*
|
||||
*/
|
||||
|
||||
@Mapper
|
||||
public interface RequestHistoryMapper {
|
||||
|
||||
@Mapping(target = "clientUUID", expression = "java(requestHistoryDTO.getClientUUID().toString())")
|
||||
RequestHistory requestHistoryDTOToRequestHistory(RequestHistoryDTO requestHistoryDTO);
|
||||
@Mapping(target = "clientUUID", expression = "java(java.util.UUID.fromString(requestHistory.getClientUUID()))")
|
||||
RequestHistoryDTO requestHistoryToRequestHistoryDTO(RequestHistory requestHistory);
|
||||
|
||||
}
|
||||
@@ -1,36 +0,0 @@
|
||||
package com.r11.tools.model;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import lombok.*;
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
import org.springframework.lang.Nullable;
|
||||
|
||||
/**
|
||||
* Pojo class for Event entity
|
||||
* @author Rafał Żukowicz
|
||||
*/
|
||||
@Data
|
||||
@Builder
|
||||
@ToString
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class Event implements Comparable<Event>{
|
||||
|
||||
@DateTimeFormat(pattern = "yyyy-MM-ddTHH:mm:ss")
|
||||
private LocalDateTime dateTimeStamp;
|
||||
@Nullable
|
||||
private String interfaceName;
|
||||
@Nullable
|
||||
private String clientUUID;
|
||||
@Nullable
|
||||
private Integer messageId;
|
||||
private String thread;
|
||||
private String level;
|
||||
@Nullable
|
||||
private String message;
|
||||
|
||||
@Override
|
||||
public int compareTo(Event o) {
|
||||
return this.getDateTimeStamp().compareTo(o.getDateTimeStamp()) * -1;
|
||||
}
|
||||
}
|
||||
@@ -1,10 +1,6 @@
|
||||
package com.r11.tools.model;
|
||||
|
||||
import com.r11.tools.model.constraints.HttpCode;
|
||||
import java.io.Serializable;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import javax.validation.constraints.Positive;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
@@ -13,6 +9,11 @@ import org.springframework.data.annotation.Id;
|
||||
import org.springframework.data.redis.core.RedisHash;
|
||||
import org.springframework.data.redis.core.index.Indexed;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* MockedMessage redis entity pojo
|
||||
* @author Rafał Żukowicz
|
||||
@@ -23,18 +24,14 @@ import org.springframework.data.redis.core.index.Indexed;
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class MockedMessage implements Serializable {
|
||||
@Id
|
||||
private String compositePrimaryKey;
|
||||
@Indexed
|
||||
@Id
|
||||
private UUID clientUUID;
|
||||
@Positive
|
||||
private Integer mockedResponseId;
|
||||
private String mediaType;
|
||||
private String contentType;
|
||||
private String messageBody;
|
||||
private Map<String, String> httpHeaders;
|
||||
@HttpCode
|
||||
private Integer httpStatus;
|
||||
private LocalDateTime createdAt;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
package com.r11.tools.model;
|
||||
|
||||
import com.r11.tools.model.constraints.HttpCode;
|
||||
import lombok.*;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import javax.validation.constraints.Positive;
|
||||
import lombok.*;
|
||||
|
||||
/**
|
||||
* Alternative version of {@link MockedMessage} used in http body
|
||||
@@ -18,19 +17,12 @@ import lombok.*;
|
||||
@ToString
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class MockedMessageDto implements Serializable, Comparable<MockedMessageDto> {
|
||||
public class MockedMessageDto implements Serializable{
|
||||
private UUID clientUUID;
|
||||
@NotNull
|
||||
@Positive
|
||||
private Integer mockedResponseId;
|
||||
private String mediaType;
|
||||
private String contentType;
|
||||
private String messageBody;
|
||||
private Map<String, String> httpHeaders;
|
||||
@HttpCode
|
||||
private Integer httpStatus;
|
||||
|
||||
@Override
|
||||
public int compareTo(MockedMessageDto message) {
|
||||
return this.mockedResponseId > message.getMockedResponseId() ? 1 : -1;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
package com.r11.tools.model;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import org.springframework.data.annotation.Id;
|
||||
import org.springframework.data.redis.core.RedisHash;
|
||||
import org.springframework.data.redis.core.index.Indexed;
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
import org.springframework.http.HttpMethod;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Pojo class for Event entity
|
||||
* @author Rafał Żukowicz
|
||||
* @author Mikołaj Widła
|
||||
*/
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@RedisHash("mockHistory")
|
||||
public class RequestHistory implements Comparable<RequestHistory>, Serializable {
|
||||
@Id
|
||||
private String id;
|
||||
@DateTimeFormat(pattern = "yyyy-MM-ddTHH:mm:ss")
|
||||
private LocalDateTime dateTimeStamp;
|
||||
@Indexed
|
||||
private String clientUUID;
|
||||
private Map<String,String> headers;
|
||||
private HttpMethod httpMethod;
|
||||
private String requestBody;
|
||||
|
||||
@Override
|
||||
public int compareTo(RequestHistory o) {
|
||||
return this.getDateTimeStamp().compareTo(o.getDateTimeStamp()) * -1;
|
||||
}
|
||||
}
|
||||
@@ -1,28 +1,32 @@
|
||||
package com.r11.tools.model;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.UUID;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
import org.springframework.http.HttpMethod;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* Pojo for history query request. Contains information necessary to obtain {@link Event} list
|
||||
* Pojo for history query request. Contains information necessary to obtain {@link RequestHistory} list
|
||||
* @author Rafał Żukowicz
|
||||
* @author Mikołaj Widła
|
||||
*/
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class EventRequestDto {
|
||||
public class RequestHistoryDTO {
|
||||
|
||||
private UUID clientUUID;
|
||||
@DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME)
|
||||
private LocalDateTime localDateTimeFrom;
|
||||
@DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME)
|
||||
private LocalDateTime localDateTimeTo;
|
||||
private Integer mockedResponseId;
|
||||
private LocalDateTime dateTimeStamp;
|
||||
private Map<String,String> headers;
|
||||
private HttpMethod httpMethod;
|
||||
private String requestBody;
|
||||
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
package com.r11.tools.repository;
|
||||
|
||||
import com.r11.tools.model.Event;
|
||||
import com.r11.tools.utilis.BusinessKey;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import org.springframework.stereotype.Repository;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
/**
|
||||
* Event entity dao interface
|
||||
* @author Rafał Żukowicz
|
||||
*/
|
||||
@Repository
|
||||
@Transactional
|
||||
public interface EventRepository {
|
||||
List<Event> findEvents(LocalDateTime localDateTimeFrom, LocalDateTime localDateTimeTo,
|
||||
Map<BusinessKey, String> businessKeys);
|
||||
}
|
||||
@@ -1,99 +0,0 @@
|
||||
package com.r11.tools.repository;
|
||||
|
||||
import static com.r11.tools.utilis.RedisAppender.LOG_PREFIX;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.r11.tools.model.Event;
|
||||
import com.r11.tools.utilis.BusinessKey;
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.LocalTime;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
import lombok.AllArgsConstructor;
|
||||
import org.springframework.stereotype.Repository;
|
||||
import redis.clients.jedis.Jedis;
|
||||
import redis.clients.jedis.JedisPool;
|
||||
|
||||
/**
|
||||
* Builds Event list based on logs created via {@link com.r11.tools.utilis.TrackingClient} and {@link com.r11.tools.utilis.RedisAppender}
|
||||
* @author Rafał Żukowicz
|
||||
*/
|
||||
@Repository
|
||||
@AllArgsConstructor
|
||||
public class EventRepositoryImpl implements EventRepository {
|
||||
private final JedisPool jedisPool;
|
||||
private final ObjectMapper objectMapper;
|
||||
|
||||
/**
|
||||
* Creates list of {@link Event} based on {@link com.r11.tools.model.EventRequestDto} data via searching logs
|
||||
* @param localDateTimeFrom date from which logs are retrieved
|
||||
* @param localDateTimeTo date to which logs are retrieved
|
||||
* @param businessKeys set keys for redis values
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public List<Event> findEvents(LocalDateTime localDateTimeFrom, LocalDateTime localDateTimeTo,
|
||||
Map<BusinessKey, String> businessKeys) {
|
||||
List<String> eventStrings = findEventsBetweenDates(localDateTimeFrom.toLocalDate(), localDateTimeTo.toLocalDate());
|
||||
if (businessKeys.size() > 0) {
|
||||
eventStrings = businessKeysFilter(eventStrings, businessKeys);
|
||||
}
|
||||
List<Event> events = parseEvents(eventStrings);
|
||||
if (localDateTimeFrom.toLocalTime() != LocalTime.MIN) {
|
||||
events = events.stream().filter(event -> event.getDateTimeStamp().compareTo(localDateTimeFrom) >= 0)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
return events.stream().filter(event -> event.getDateTimeStamp().compareTo(localDateTimeTo) <= 0)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns logs between given dates
|
||||
* @param localDateFrom date from which logs are retrieved
|
||||
* @param localDateTo date to which logs are retrieved
|
||||
* @return
|
||||
*/
|
||||
private List<String> findEventsBetweenDates(LocalDate localDateFrom, LocalDate localDateTo) {
|
||||
try (Jedis jedis = jedisPool.getResource()) {
|
||||
return localDateFrom.datesUntil(localDateTo.plusDays(1)).map(day -> LOG_PREFIX + day.toString())
|
||||
.map(key -> jedis.lrange(key, 0, -1)).flatMap(Collection::stream).collect(Collectors.toList());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Filters keys so only the ones queried are retirned
|
||||
* @param events list of logs
|
||||
* @param businessKeys set keys for redis values
|
||||
* @return filtered list of logs
|
||||
*/
|
||||
private List<String> businessKeysFilter(List<String> events, Map<BusinessKey, String> businessKeys) {
|
||||
for (Map.Entry<BusinessKey, String> entry : businessKeys.entrySet()) {
|
||||
String stringPattern = entry.getKey().getReasonPhrase()+ "\"" + ":" + "\"" + entry.getValue() + "\"";
|
||||
events = events.stream().filter(s -> s.contains(stringPattern)).collect(Collectors.toList());
|
||||
}
|
||||
return events;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses list of logs into list of {@link Event}
|
||||
* @param eventStrings list of logs
|
||||
* @return list of {@link Event}
|
||||
*/
|
||||
private List<Event> parseEvents(List<String> eventStrings) {
|
||||
List<Event> events = new ArrayList<>();
|
||||
for (String eventString : eventStrings) {
|
||||
eventString = eventString.replaceAll("\\R", "");
|
||||
try {
|
||||
events.add(objectMapper.readValue(eventString, Event.class));
|
||||
} catch (JsonProcessingException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
return events;
|
||||
}
|
||||
}
|
||||
@@ -14,11 +14,11 @@ import org.springframework.transaction.annotation.Transactional;
|
||||
*/
|
||||
@Repository
|
||||
@Transactional
|
||||
public interface MockedResponseRepository extends CrudRepository<MockedMessage, String> {
|
||||
public interface MockedResponseRepository extends CrudRepository<MockedMessage, UUID> {
|
||||
/**
|
||||
* Finds all messages by their uuid
|
||||
* @param clientUUID the key-uuid of given set of messages
|
||||
* @return Optional of list of {@link com.r11.tools.model.MockedMessage}
|
||||
*/
|
||||
Optional<List<MockedMessage>> findAllByClientUUID(UUID clientUUID);
|
||||
Optional<MockedMessage> findAllByClientUUID(UUID clientUUID);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
package com.r11.tools.repository;
|
||||
|
||||
import com.r11.tools.model.RequestHistory;
|
||||
import org.springframework.data.repository.CrudRepository;
|
||||
import org.springframework.stereotype.Repository;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* History Record entity dao interface
|
||||
* @author Rafał Żukowicz
|
||||
*/
|
||||
@Repository
|
||||
@Transactional
|
||||
public interface RequestHistoryRepository extends CrudRepository<RequestHistory,String> {
|
||||
List<RequestHistory> findAllByClientUUID(String clientUUID);
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
package com.r11.tools.service;
|
||||
|
||||
import com.r11.tools.model.Event;
|
||||
import com.r11.tools.model.EventRequestDto;
|
||||
import java.util.List;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/**
|
||||
* Spring service interface for {@link com.r11.tools.controller.EventController}
|
||||
* @author Rafał Żukowicz
|
||||
*/
|
||||
@Service
|
||||
public interface EtrackService {
|
||||
/**
|
||||
* Searches for {@link Event} objects between date brackets
|
||||
* @param eventsDto object containing required data for request
|
||||
* @return list of {@link Event}
|
||||
*/
|
||||
List<Event> getEventsByDateTimeAndBusinessKeys(EventRequestDto eventsDto);
|
||||
}
|
||||
@@ -1,44 +0,0 @@
|
||||
package com.r11.tools.service;
|
||||
|
||||
import com.r11.tools.model.Event;
|
||||
import com.r11.tools.model.EventRequestDto;
|
||||
import com.r11.tools.repository.EventRepository;
|
||||
import com.r11.tools.utilis.BusinessKey;
|
||||
import lombok.AllArgsConstructor;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Spring Service for {@link com.r11.tools.controller.EventController}. Contains logic required for quering
|
||||
* the database for {@link Event} objects
|
||||
* @author Rafał Żukowicz
|
||||
*/
|
||||
@Service
|
||||
@AllArgsConstructor
|
||||
public class EtrackServiceImpl implements EtrackService {
|
||||
|
||||
private final EventRepository eventRepository;
|
||||
|
||||
/**
|
||||
* Adds {@link BusinessKey} to {@link EventRequestDto}
|
||||
* in order to create query via{@link com.r11.tools.repository.EventRepositoryImpl}
|
||||
* @param eventsDto object containing required data for request
|
||||
* @return list of {@link Event}
|
||||
*/
|
||||
@Override
|
||||
public List<Event> getEventsByDateTimeAndBusinessKeys(EventRequestDto eventsDto) {
|
||||
Map<BusinessKey, String> businessKeys = new HashMap<>();
|
||||
businessKeys.put(BusinessKey.CLIENT_UUID, eventsDto.getClientUUID().toString());
|
||||
if (eventsDto.getMockedResponseId() != null){
|
||||
businessKeys.put(BusinessKey.MESSAGE_ID, String.valueOf(eventsDto.getMockedResponseId()));
|
||||
}
|
||||
List<Event> events = eventRepository.findEvents(eventsDto.getLocalDateTimeFrom(), eventsDto.getLocalDateTimeTo(),
|
||||
businessKeys);
|
||||
Collections.sort(events);
|
||||
return events;
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,8 @@
|
||||
package com.r11.tools.service;
|
||||
|
||||
import com.r11.tools.model.MockedMessageDto;
|
||||
import java.util.List;
|
||||
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.stereotype.Service;
|
||||
@@ -12,8 +13,7 @@ import org.springframework.stereotype.Service;
|
||||
*/
|
||||
@Service
|
||||
public interface KlausService {
|
||||
ResponseEntity<String> deleteMockedResponse(UUID clientUUID, int mockedResponseId);
|
||||
List<MockedMessageDto> getAllMockedResponses(UUID clientUUID);
|
||||
MockedMessageDto getMockedResponse(UUID clientUUID, int mockedResponseId);
|
||||
Optional<MockedMessageDto> getMockedMessageByClientUUID(UUID clientUUID);
|
||||
MockedMessageDto getMockedResponse(UUID clientUUID);
|
||||
ResponseEntity<String> setMockedResponse(MockedMessageDto mockedMessageDto);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package com.r11.tools.service;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.r11.tools.mappers.MockedMessageMapper;
|
||||
import com.r11.tools.model.MockedMessage;
|
||||
import com.r11.tools.model.MockedMessageDto;
|
||||
@@ -13,16 +12,16 @@ import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.stereotype.Service;
|
||||
import java.util.List;
|
||||
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Service for {@link com.r11.tools.controller.MockController} and {@link com.r11.tools.controller.MockController}
|
||||
* Allows for performing CRUD operations on {@link MockedMessageDto}
|
||||
* @author Rafał Żukowicz
|
||||
* @author Gabriel Modzelewski
|
||||
* @author Mikołaj Widła
|
||||
*/
|
||||
@Service
|
||||
@AllArgsConstructor
|
||||
@@ -30,22 +29,7 @@ public class KlausServiceImpl implements KlausService {
|
||||
private final MockedMessageMapper mockedMessageMapper;
|
||||
private final Logger log = LogManager.getRootLogger();
|
||||
private final MockedResponseRepository mockedResponseRepository;
|
||||
private final ObjectMapper objectMapper;
|
||||
|
||||
/**
|
||||
* Removes message of given id in given key-uuid set
|
||||
* @param clientUUID the key-uuid of given set of messages
|
||||
* @param mockedResponseId unique id of given message
|
||||
* @return confirmation and status 200 OK
|
||||
*/
|
||||
@Override
|
||||
public ResponseEntity<String> deleteMockedResponse(UUID clientUUID, int mockedResponseId) {
|
||||
String key = clientUUID.toString() + "_" + mockedResponseId;
|
||||
mockedResponseRepository.deleteById(key);
|
||||
log.info("Message: "+mockedResponseId+" has been removed.");
|
||||
return new ResponseEntity<>("MockedResponse has been removed successfully",
|
||||
new HttpHeaders(), HttpStatus.ACCEPTED);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all messages of given key-uuid
|
||||
@@ -53,28 +37,23 @@ public class KlausServiceImpl implements KlausService {
|
||||
* @return List of {@link MockedMessageDto}
|
||||
*/
|
||||
@Override
|
||||
public List<MockedMessageDto> getAllMockedResponses(UUID clientUUID){
|
||||
Optional<List<MockedMessage>> listOptional = mockedResponseRepository.findAllByClientUUID(clientUUID);
|
||||
log.info("Messages for UUID: "+clientUUID+" has been fetched from DB.");
|
||||
return listOptional.map(mockedMessages -> mockedMessages.stream()
|
||||
.map(mockedMessageMapper::mockedMessageToMockedMessageDto)
|
||||
.collect(Collectors.toList())).orElse(List.of());
|
||||
public Optional<MockedMessageDto> getMockedMessageByClientUUID(UUID clientUUID){
|
||||
Optional<MockedMessage> mockedMessageOptional = mockedResponseRepository.findAllByClientUUID(clientUUID);
|
||||
log.info("Message for UUID: "+clientUUID+" has been fetched from DB.");
|
||||
return mockedMessageMapper.optionalMockedMessageToOptionalMockedMessageDTO(mockedMessageOptional);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@link MockedMessageDto} of given id and key-uuid. If message doesn't then empty message is returned
|
||||
* @param clientUUID the key-uuid of given set of messages
|
||||
* @param mockedResponseId unique id of given message
|
||||
* @return {@link MockedMessageDto} object
|
||||
*/
|
||||
@SneakyThrows
|
||||
@Override
|
||||
public MockedMessageDto getMockedResponse(UUID clientUUID, int mockedResponseId){
|
||||
String key = clientUUID.toString() + "_" + mockedResponseId;
|
||||
Optional<MockedMessage> optionalMockedMessage = mockedResponseRepository.findById(key);
|
||||
public MockedMessageDto getMockedResponse(UUID clientUUID){
|
||||
Optional<MockedMessage> optionalMockedMessage = mockedResponseRepository.findById(clientUUID);
|
||||
MockedMessageDto mockedMessageDto = MockedMessageDto.builder()
|
||||
.clientUUID(clientUUID)
|
||||
.mockedResponseId(mockedResponseId)
|
||||
.build();
|
||||
if (optionalMockedMessage.isPresent()) {
|
||||
mockedMessageDto = mockedMessageMapper.mockedMessageToMockedMessageDto(optionalMockedMessage.get());
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
package com.r11.tools.service;
|
||||
|
||||
import com.r11.tools.controller.RequestHistoryController;
|
||||
import com.r11.tools.model.RequestHistory;
|
||||
import com.r11.tools.model.RequestHistoryDTO;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Spring service interface for {@link RequestHistoryController}
|
||||
* @author Rafał Żukowicz
|
||||
*/
|
||||
@Service
|
||||
public interface RequestHistoryService {
|
||||
/**
|
||||
* Searches for {@link RequestHistory} objects between date brackets
|
||||
* @param uuid user uuid
|
||||
* @return list of {@link RequestHistory}
|
||||
*/
|
||||
List<RequestHistory> getHistoryRecordsByUUID(String uuid);
|
||||
void saveRequest(RequestHistoryDTO requestDTO);
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
package com.r11.tools.service;
|
||||
|
||||
import com.r11.tools.controller.RequestHistoryController;
|
||||
import com.r11.tools.mappers.RequestHistoryMapper;
|
||||
import com.r11.tools.model.RequestHistory;
|
||||
import com.r11.tools.model.RequestHistoryDTO;
|
||||
import com.r11.tools.repository.RequestHistoryRepository;
|
||||
import lombok.AllArgsConstructor;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Spring Service for {@link RequestHistoryController}. Contains logic required for quering
|
||||
* the database for {@link RequestHistory} objects
|
||||
* @author Rafał Żukowicz
|
||||
* @author Mikołaj Widła
|
||||
*/
|
||||
@Service
|
||||
@AllArgsConstructor
|
||||
public class RequestHistoryServiceImpl implements RequestHistoryService {
|
||||
|
||||
private final RequestHistoryRepository repository;
|
||||
private final RequestHistoryMapper requestMapper;
|
||||
|
||||
@Override
|
||||
public List<RequestHistory> getHistoryRecordsByUUID(String uuid) {
|
||||
List<RequestHistory> history = repository.findAllByClientUUID(uuid);
|
||||
Collections.sort(history);
|
||||
return history;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void saveRequest(RequestHistoryDTO requestDTO) {
|
||||
repository.save(requestMapper.requestHistoryDTOToRequestHistory(requestDTO));
|
||||
}
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
package com.r11.tools.utilis;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
|
||||
/**
|
||||
* Enum of keys for redis database.
|
||||
* @author Rafał Żukowicz
|
||||
*/
|
||||
@AllArgsConstructor
|
||||
public enum BusinessKey {
|
||||
INTERFACE_NAME("interfaceName"),
|
||||
CLIENT_UUID("clientUUID"),
|
||||
MESSAGE_ID("messageId");
|
||||
|
||||
private final String phrase;
|
||||
|
||||
/**
|
||||
* Returns string value of given enum variant
|
||||
* @return string value of enum
|
||||
*/
|
||||
public String getReasonPhrase() {
|
||||
return this.phrase;
|
||||
}
|
||||
}
|
||||
@@ -1,235 +0,0 @@
|
||||
package com.r11.tools.utilis;
|
||||
|
||||
import ch.qos.logback.classic.spi.ILoggingEvent;
|
||||
import ch.qos.logback.core.Layout;
|
||||
import ch.qos.logback.core.UnsynchronizedAppenderBase;
|
||||
import com.cwbase.logback.AdditionalField;
|
||||
import com.cwbase.logback.JSONEventLayout;
|
||||
import java.time.LocalDate;
|
||||
import java.util.Arrays;
|
||||
import java.util.Iterator;
|
||||
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
|
||||
import redis.clients.jedis.Jedis;
|
||||
import redis.clients.jedis.JedisPool;
|
||||
import redis.clients.jedis.Protocol;
|
||||
|
||||
/**
|
||||
* Class is used to insert logs directly to Redis. {@link com.release11.klaus.repository.EventRepositoryImpl} is using those logs.
|
||||
* @author Rafał Żukowicz
|
||||
* @author Gabriel Modzelewski
|
||||
*/
|
||||
public class RedisAppender extends UnsynchronizedAppenderBase<ILoggingEvent> {
|
||||
|
||||
JedisPool pool;
|
||||
JSONEventLayout jsonlayout;
|
||||
Layout<ILoggingEvent> layout;
|
||||
String host = "localhost";
|
||||
int port = Protocol.DEFAULT_PORT;
|
||||
String key = null;
|
||||
int timeout = Protocol.DEFAULT_TIMEOUT;
|
||||
String password = null;
|
||||
int database = Protocol.DEFAULT_DATABASE;
|
||||
|
||||
public static final String LOG_PREFIX = "logstash_";
|
||||
|
||||
|
||||
public RedisAppender() {
|
||||
jsonlayout = new JSONEventLayout();
|
||||
}
|
||||
|
||||
/**
|
||||
* Appends JedisPool by another log
|
||||
* @param event object containing log info
|
||||
*/
|
||||
@Override
|
||||
protected void append(ILoggingEvent event) {
|
||||
Jedis client = pool.getResource();
|
||||
try {
|
||||
String json = layout == null ? jsonlayout.doLayout(event) : layout.doLayout(event);
|
||||
key = LOG_PREFIX + LocalDate.now();
|
||||
client.rpush(key, json);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
if (client != null) {
|
||||
client.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public String getSource() {
|
||||
return jsonlayout.getSource();
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public void setSource(String source) {
|
||||
jsonlayout.setSource(source);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public String getSourceHost() {
|
||||
return jsonlayout.getSourceHost();
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public void setSourceHost(String sourceHost) {
|
||||
jsonlayout.setSourceHost(sourceHost);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public String getSourcePath() {
|
||||
return jsonlayout.getSourcePath();
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public void setSourcePath(String sourcePath) {
|
||||
jsonlayout.setSourcePath(sourcePath);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public String getTags() {
|
||||
if (jsonlayout.getTags() != null) {
|
||||
Iterator<String> i = jsonlayout.getTags().iterator();
|
||||
StringBuilder sb = new StringBuilder();
|
||||
while (i.hasNext()) {
|
||||
sb.append(i.next());
|
||||
if (i.hasNext()) {
|
||||
sb.append(',');
|
||||
}
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public void setTags(String tags) {
|
||||
if (tags != null) {
|
||||
String[] atags = tags.split(",");
|
||||
jsonlayout.setTags(Arrays.asList(atags));
|
||||
}
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public String getType() {
|
||||
return jsonlayout.getType();
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public void setType(String type) {
|
||||
jsonlayout.setType(type);
|
||||
}
|
||||
|
||||
public String getHost() {
|
||||
return host;
|
||||
}
|
||||
|
||||
public void setHost(String host) {
|
||||
this.host = host;
|
||||
}
|
||||
|
||||
public int getPort() {
|
||||
return port;
|
||||
}
|
||||
|
||||
public void setPort(int port) {
|
||||
this.port = port;
|
||||
}
|
||||
|
||||
public String getKey() {
|
||||
return key;
|
||||
}
|
||||
|
||||
public void setKey(String key) {
|
||||
this.key = key;
|
||||
}
|
||||
|
||||
public int getTimeout() {
|
||||
return timeout;
|
||||
}
|
||||
|
||||
public void setTimeout(int timeout) {
|
||||
this.timeout = timeout;
|
||||
}
|
||||
|
||||
public String getPassword() {
|
||||
return password;
|
||||
}
|
||||
|
||||
public void setPassword(String password) {
|
||||
this.password = password;
|
||||
}
|
||||
|
||||
public int getDatabase() {
|
||||
return database;
|
||||
}
|
||||
|
||||
public void setDatabase(int database) {
|
||||
this.database = database;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public void setMdc(boolean flag) {
|
||||
jsonlayout.setProperties(flag);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public boolean getMdc() {
|
||||
return jsonlayout.getProperties();
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public void setLocation(boolean flag) {
|
||||
jsonlayout.setLocationInfo(flag);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public boolean getLocation() {
|
||||
return jsonlayout.getLocationInfo();
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public void setCallerStackIndex(int index) {
|
||||
jsonlayout.setCallerStackIdx(index);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public int getCallerStackIndex() {
|
||||
return jsonlayout.getCallerStackIdx();
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public void addAdditionalField(AdditionalField p) {
|
||||
jsonlayout.addAdditionalField(p);
|
||||
}
|
||||
|
||||
public Layout<ILoggingEvent> getLayout() {
|
||||
return layout;
|
||||
}
|
||||
|
||||
public void setLayout(Layout<ILoggingEvent> layout) {
|
||||
this.layout = layout;
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts new instance of JedisPool
|
||||
*/
|
||||
@Override
|
||||
public void start() {
|
||||
super.start();
|
||||
GenericObjectPoolConfig config = new GenericObjectPoolConfig();
|
||||
config.setTestOnBorrow(true);
|
||||
pool = new JedisPool(config, host, port, timeout, password, database);
|
||||
}
|
||||
|
||||
/**
|
||||
* Stops and destroys JedisPool object
|
||||
*/
|
||||
@Override
|
||||
public void stop() {
|
||||
super.stop();
|
||||
pool.destroy();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
package com.r11.tools.utilis;
|
||||
|
||||
import java.util.Map;
|
||||
import org.slf4j.MDC;
|
||||
|
||||
/**
|
||||
* This static class has one purpose and one purpose only. It logs data about incomming requests.
|
||||
* The data from logs is received via {@link com.release11.klaus.repository.EventRepositoryImpl}
|
||||
* @author Rafał Żukowski
|
||||
*/
|
||||
public final class TrackingClient {
|
||||
|
||||
/**
|
||||
* Logs data inside the given map
|
||||
* @param businessKeysMap map containing all the information about incomming request
|
||||
*/
|
||||
public static void setBusinessKeys(Map<BusinessKey, String> businessKeysMap){
|
||||
for (Map.Entry<BusinessKey, String> entry : businessKeysMap.entrySet()) {
|
||||
MDC.put(entry.getKey().getReasonPhrase(), entry.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -5,3 +5,12 @@ spring.mvc.view.suffix=.html
|
||||
logging.level.root=INFO
|
||||
logging.level.org.springframework.web=INFO
|
||||
logging.level.com.release11=INFO
|
||||
|
||||
#database:
|
||||
spring.redis.host=redis
|
||||
spring.redis.port=6379
|
||||
|
||||
#retention
|
||||
retention.minutes-to-delete-message=120
|
||||
retention.minutes-to-delete-history-record=1440
|
||||
retention.retention-cooldown=1440
|
||||
|
||||
@@ -1,2 +0,0 @@
|
||||
redis.host = redis
|
||||
redis.port = 6379
|
||||
@@ -2,25 +2,8 @@
|
||||
<configuration>
|
||||
<include resource="org/springframework/boot/logging/logback/base.xml"/>
|
||||
<property name="HOME_LOG" value="/log/mockServices.log"/>
|
||||
<!--https://github.com/kmtong/logback-redis-appender-->
|
||||
<appender name="LOGSTASH" class="com.r11.tools.utilis.RedisAppender">
|
||||
<host>redis</host>
|
||||
<port>6379</port>
|
||||
<key>logstash</key>
|
||||
<layout class="ch.qos.logback.classic.PatternLayout">
|
||||
<!--https://logging.apache.org/log4j/1.2/apidocs/org/apache/log4j/PatternLayout.html-->
|
||||
<Pattern>
|
||||
{"dateTimeStamp" : "%d{yyyy-MM-dd}T%d{HH:mm:ss}", "eventId":"%X{eventId}", "interfaceName":"%X{interfaceName}", "clientUUID":"%X{clientUUID}", "messageId":"%X{messageId}", "thread":"%t","level":"%-5level", "message":"%msg"}%n
|
||||
</Pattern>
|
||||
</layout>
|
||||
</appender>
|
||||
<appender name="ASYNC" class="ch.qos.logback.classic.AsyncAppender">
|
||||
<appender-ref ref="LOGSTASH" />
|
||||
</appender>
|
||||
|
||||
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
|
||||
<file>${HOME_LOG}</file>
|
||||
|
||||
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
|
||||
<fileNamePattern>logs/mockServices.%d{yyyy-MM-dd}.%i.log</fileNamePattern>
|
||||
<maxFileSize>10MB</maxFileSize>
|
||||
@@ -34,7 +17,6 @@
|
||||
</appender>
|
||||
|
||||
<root level="DEBUG">
|
||||
<appender-ref ref="ASYNC" />
|
||||
<appender-ref ref="CONSOLE" />
|
||||
<appender-ref ref="FILE" />
|
||||
</root>
|
||||
|
||||
@@ -1,541 +0,0 @@
|
||||
var clientUUID = '';
|
||||
var advancedDisplayed = false;
|
||||
var json = {};
|
||||
var jsonIndex = 0;
|
||||
var lastId = 1;
|
||||
var htable_row = 0;
|
||||
var host = getDomain();
|
||||
var dataModified = false;
|
||||
const addMessageName = 'addMessage';
|
||||
const loadMessageName = 'changeMessage';
|
||||
const removeMessageName = 'removeMessage';
|
||||
|
||||
const C_UUID = 'mock-uuid';
|
||||
const C_ID = 'last-displayed-id';
|
||||
const C_ADV = 'advanced-mode';
|
||||
|
||||
const color_red = "#ff8f8f";
|
||||
const color_grey = "#6b6b6b";
|
||||
|
||||
const setModified = function(){
|
||||
setDataModified();
|
||||
}
|
||||
const setOrigin = function(){
|
||||
setDataOrigin();
|
||||
}
|
||||
|
||||
const getUpdate = function(){
|
||||
updateData();
|
||||
}
|
||||
const dataRefresh = function(){
|
||||
getData();
|
||||
}
|
||||
$('#btn-newtile').click(function(){callAddMessage()});
|
||||
// $('#btn-addRow').click(function(){addRow()});
|
||||
// $('#btn-save').click(getUpdate);
|
||||
|
||||
function getData(){
|
||||
$.getJSON(host + '/api/mock/'+clientUUID, function(data) {
|
||||
json = data;
|
||||
checkUuid();
|
||||
|
||||
|
||||
refreshData();
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
function checkUuid(){
|
||||
if(clientUUID == null || clientUUID == undefined || clientUUID == ''){
|
||||
clientUUID = json[0].clientUUID;
|
||||
setCookie();
|
||||
}
|
||||
}
|
||||
|
||||
function getDomain(){
|
||||
var url = window.location.href;
|
||||
var arr = url.split("/");
|
||||
var result = arr[0] + "//" + arr[2];
|
||||
return result;
|
||||
}
|
||||
|
||||
function httpStatusInvalid(){
|
||||
value = $('#httpStatus').val();
|
||||
return value == '';
|
||||
}
|
||||
|
||||
function setDataModified(){
|
||||
if(httpStatusInvalid()){
|
||||
$('#btn-save').removeClass('active');
|
||||
$('#btn-save').off();
|
||||
document.getElementById("httpStatus").style.backgroundColor = color_red;
|
||||
return;
|
||||
}
|
||||
dataModified = true;
|
||||
$('#btn-save').addClass('active');
|
||||
$('#btn-save').click(getUpdate);
|
||||
document.getElementById("httpStatus").style.backgroundColor = null;
|
||||
}
|
||||
|
||||
//Adding change listener to fields
|
||||
$('.data-field').change(setModified);
|
||||
|
||||
function setDataOrigin(){
|
||||
dataModified = false;
|
||||
$('#btn-save').removeClass('active');
|
||||
$('#btn-save').off();
|
||||
}
|
||||
|
||||
const idToDisplay = function(){
|
||||
let defaultId = json[0].mockedResponseId;
|
||||
if(lastId == undefined || lastId == null) return defaultId;
|
||||
for(let i=0; i<json.length; i++){
|
||||
if(json[i].mockedResponseId == lastId){
|
||||
return lastId;
|
||||
}
|
||||
}
|
||||
if(jsonIndex <= json.length && jsonIndex > 0){
|
||||
jsonIndex -= 1;
|
||||
return json[jsonIndex].mockedResponseId;
|
||||
}
|
||||
return defaultId;
|
||||
}
|
||||
|
||||
function refreshData(){
|
||||
$("#uuid-input").val(clientUUID);
|
||||
fillMessageList();
|
||||
|
||||
let id = idToDisplay();
|
||||
|
||||
loadMessage(id);
|
||||
|
||||
}
|
||||
|
||||
function setCookie(){
|
||||
document.cookie = C_UUID + '=' +clientUUID;
|
||||
document.cookie = C_ID + '=' + lastId;
|
||||
document.cookie = C_ADV + '=' + advancedVisibility;
|
||||
}
|
||||
|
||||
function loadCookies(){
|
||||
clientUUID = getCookie(C_UUID);
|
||||
lastId = getCookie(C_ID);
|
||||
advancedDisplayed = getCookie(C_ADV) == 'true';
|
||||
}
|
||||
|
||||
function getCookie(cname) {
|
||||
var name = cname + '=';
|
||||
var decodedCookie = decodeURIComponent(document.cookie);
|
||||
var ca = decodedCookie.split(';');
|
||||
for(var i = 0; i <ca.length; i++) {
|
||||
var c = ca[i];
|
||||
while (c.charAt(0) == ' ') {
|
||||
c = c.substring(1);
|
||||
}
|
||||
if (c.indexOf(name) == 0) {
|
||||
return c.substring(name.length, c.length);
|
||||
}
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
||||
function callMethodByName(methodObject){
|
||||
let name = methodObject.name;
|
||||
let id = methodObject.id;
|
||||
switch(name){
|
||||
case addMessageName:
|
||||
addMessage();
|
||||
break;
|
||||
case loadMessageName:
|
||||
loadMessage(id);
|
||||
break;
|
||||
case removeMessageName:
|
||||
removeMessage(id);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function updateData(){
|
||||
var updatedJson = generateJson();
|
||||
const dataSaved = function () {
|
||||
setDataOrigin();
|
||||
refreshData();
|
||||
savedModalDisplay();
|
||||
}
|
||||
$.ajax({
|
||||
url: host + '/api/mock',
|
||||
type: 'PUT',
|
||||
data: JSON.stringify(updatedJson, null, 2),
|
||||
contentType: "application/json",
|
||||
}).done(dataSaved);
|
||||
}
|
||||
|
||||
function callAddMessage(){
|
||||
if(dataModified){
|
||||
setMethodToCall(addMessageName, null);
|
||||
dataLossModalDisplay();
|
||||
}
|
||||
else {
|
||||
addMessage();
|
||||
}
|
||||
}
|
||||
|
||||
function addMessage(){
|
||||
$.ajax({
|
||||
url: host + '/api/mock/'+clientUUID,
|
||||
type: 'POST',
|
||||
}).done(dataRefresh);
|
||||
}
|
||||
|
||||
function callRemoveMessage(id){
|
||||
if(dataModified){
|
||||
setMethodToCall(removeMessageName, id);
|
||||
dataLossModalDisplay();
|
||||
}
|
||||
else {
|
||||
removeMessage(id);
|
||||
}
|
||||
}
|
||||
|
||||
function removeMessage(id){
|
||||
var jsonObject = findJsonById(id);
|
||||
$.ajax({
|
||||
url: host + '/api/mock/'+clientUUID + '/' + id,
|
||||
type: 'DELETE',
|
||||
}).done(dataRefresh);
|
||||
}
|
||||
|
||||
|
||||
function clearMock(){
|
||||
fillStaticFields('','','','');
|
||||
htable_row = 0;
|
||||
$('#httpStatusValues').html('');
|
||||
}
|
||||
|
||||
function initializeMock(index){
|
||||
clearMock();
|
||||
fillStaticFields(json[index].clientUUID
|
||||
, json[index].mockedResponseId
|
||||
, json[index].mediaType
|
||||
, json[index].messageBody
|
||||
, json[index].httpStatus);
|
||||
fillHeaderTable(json[index].httpHeaders);
|
||||
}
|
||||
|
||||
function fillStaticFields(uuid, id, mediaType, body, httpStatus){
|
||||
let link = createLink(uuid,id);
|
||||
let linkHtml = '<a class="hyperlink" target="_blank" href="'+link+'">'+link+'</a>';
|
||||
$('#messageLink').html(linkHtml);
|
||||
$('#httpStatus').val(httpStatus);
|
||||
$('#uuid-input').val(uuid);
|
||||
$('#typeSelector').val(mediaType);
|
||||
$('#bodyEditor').val(body);
|
||||
$('#mockedMessageId').html(id);
|
||||
|
||||
}
|
||||
|
||||
function changeEditionOfUUID(element){
|
||||
|
||||
var inputFieldId= "#uuid-input"
|
||||
var inputFieldDiv = "#uuid-edit-field"
|
||||
if(element.checked){
|
||||
$(inputFieldId).removeAttr('disabled');
|
||||
$(inputFieldDiv).removeClass('disabled');
|
||||
} else{
|
||||
$(inputFieldId).attr('disabled', true);
|
||||
$(inputFieldDiv).addClass('disabled');
|
||||
}
|
||||
}
|
||||
|
||||
function copyUUIDToClipboard(){
|
||||
navigator.clipboard.writeText( document.getElementById('uuid-input').value );
|
||||
}
|
||||
|
||||
|
||||
async function fetchUUIDCheck(givenUUID , strategy){
|
||||
var newUUID = "UUID" ;
|
||||
url = host + "/api/mock/check/";
|
||||
|
||||
switch(strategy){
|
||||
case "new":{
|
||||
await fetch(url + givenUUID+ "/", { method : "GET" })
|
||||
.then ( response => response.text() )
|
||||
.then ( data => {
|
||||
newUUID = data;
|
||||
|
||||
} )
|
||||
break;
|
||||
}
|
||||
case "restore":{
|
||||
await fetch(url + givenUUID + "/" + clientUUID + "/" , { method: "GET" })
|
||||
.then (response => response.text() )
|
||||
.then (data => {
|
||||
newUUID = data;
|
||||
|
||||
} )
|
||||
break;
|
||||
}
|
||||
}
|
||||
return newUUID ;
|
||||
}
|
||||
|
||||
function checkUUIDChars(uuid) {
|
||||
uuid.replace(/ /g,'')
|
||||
const regex = new RegExp("^[A-z0-9-]+$");
|
||||
|
||||
if(regex.test(uuid) && uuid != ""){
|
||||
return uuid ;
|
||||
}
|
||||
return "invalid";
|
||||
}
|
||||
|
||||
function changeUUID(element){
|
||||
|
||||
const uuidStrategy = $('input[name="uuid-validation-type"]:checked').val();
|
||||
const givenUUID = checkUUIDChars(element.value);
|
||||
|
||||
if( givenUUID == clientUUID ){
|
||||
$("#uuid-input").attr("disabled", true);
|
||||
uuidChangeModalDisplay("noChg");
|
||||
return;
|
||||
}
|
||||
|
||||
var newUUID = fetchUUIDCheck(givenUUID , uuidStrategy);
|
||||
var changeMessage = uuidStrategy;
|
||||
newUUID
|
||||
.then( data => {
|
||||
if (givenUUID == data) {
|
||||
changeMessage = "success";
|
||||
}
|
||||
clientUUID = data;
|
||||
$("#editable").attr("checked", false);
|
||||
|
||||
uuidChangeModalDisplay(changeMessage);
|
||||
document.cookie = C_UUID + '=' + data ;
|
||||
} )
|
||||
loadCookies();
|
||||
refreshData();
|
||||
}
|
||||
|
||||
|
||||
function createLink(uuid, id){
|
||||
var link = host + '/api/mock/r/'+uuid+'/'+id;
|
||||
return link;
|
||||
}
|
||||
|
||||
function fillHeaderTable(headers){
|
||||
var innerHTML = buildHeaderMapHtml(headers);
|
||||
refreshHeaderTable(innerHTML);
|
||||
}
|
||||
|
||||
function refreshHeaderTable(html){
|
||||
$('#headerMapTable').html(html);
|
||||
$('.table-map').change(function(){setDataModified()});
|
||||
$('.btn-hashmap').click(function(){
|
||||
$(this).closest('tr').remove();
|
||||
setDataModified();
|
||||
})
|
||||
}
|
||||
|
||||
function buildHeaderMapHtml(headers){
|
||||
var innerHTML = '';
|
||||
for(var key in headers){
|
||||
innerHTML += buildRowHtml(key, headers[key]);
|
||||
}
|
||||
return innerHTML;
|
||||
}
|
||||
|
||||
function addRow(key, value){
|
||||
var headerMap = $('#headerMapTable');
|
||||
var headersMapHtml = headerMap.html();
|
||||
headersMapHtml += buildRowHtml(key, value);
|
||||
refreshHeaderTable(headersMapHtml);
|
||||
}
|
||||
|
||||
const newRowInput = function(){
|
||||
const hName = $('#headerKeyInput');
|
||||
const hValue = $('#headerValueInput');
|
||||
if(checkIfInputValid(hName.val()) && checkIfInputValid(hValue.val())){
|
||||
addRow(hName.val(), hValue.val());
|
||||
hName.val(null);
|
||||
hValue.val(null);
|
||||
setDataModified();
|
||||
}
|
||||
}
|
||||
|
||||
$('#btn-newRow').click(newRowInput);
|
||||
|
||||
function checkIfInputValid(input){
|
||||
return !(input == '' || input == null || input == undefined);
|
||||
}
|
||||
|
||||
function checkIfHeaderEssential(key){
|
||||
|
||||
if( key == "Connection" || key == "Keep-Alive" || key == "Date" ){
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
function buildRowHtml(key, value){
|
||||
|
||||
if(checkIfHeaderEssential(key)){
|
||||
return '' +
|
||||
'<tr>' +
|
||||
'<td><input class="key data-field" value="' + key + '" readonly></td>' +
|
||||
'<td><input class="data-field" value="' + value + '"></td>' +
|
||||
'</tr>';
|
||||
}
|
||||
return '' +
|
||||
'<tr>' +
|
||||
'<td><input class="key data-field" value="' + key + '"></td>' +
|
||||
'<td><input class="data-field" value="' + value + '"></td>' +
|
||||
'<td><button class="modification-button btn-hashmap"><i class="icon-cancel"></i></button></td>' +
|
||||
'</tr>';
|
||||
}
|
||||
|
||||
|
||||
function fillMessageList(){
|
||||
$("#listItems").html('');
|
||||
var innerHTML = '';
|
||||
for(let i=0; i<json.length; i++){
|
||||
innerHTML += generateMessageTileHtml(json[i].mockedResponseId, json[i].httpStatus, json[i].mediaType);
|
||||
}
|
||||
$("#listItems").append(innerHTML);
|
||||
$('.tile').click(function(e) {
|
||||
var element = $(this);
|
||||
var button = element.find('.btn-tile').children().get(0);
|
||||
|
||||
if(!(button == e.target)){
|
||||
|
||||
callLoadMessage(parseInt($(this).attr('tileid')));
|
||||
}
|
||||
});
|
||||
$('.btn-tile').click(function(){
|
||||
//
|
||||
callRemoveMessage($(this).closest('.tile').attr('tileId'));
|
||||
})
|
||||
}
|
||||
|
||||
function findJsonById(id){
|
||||
return json[findJsonIndexById(id)];
|
||||
}
|
||||
|
||||
function findJsonIndexById(id){
|
||||
for(let i=0; i<json.length; i++)
|
||||
if(id == json[i].mockedResponseId) return i;
|
||||
}
|
||||
|
||||
function callLoadMessage(id){
|
||||
if(dataModified) {
|
||||
setMethodToCall(loadMessageName, id);
|
||||
dataLossModalDisplay();
|
||||
}
|
||||
else {
|
||||
loadMessage(id);
|
||||
}
|
||||
}
|
||||
|
||||
function loadMessage(id){
|
||||
if(id == null || id == undefined){
|
||||
|
||||
return;
|
||||
}
|
||||
lastId = id;
|
||||
setCookie();
|
||||
setDataOrigin();
|
||||
for(let i=0; i<json.length; i++){
|
||||
|
||||
if(id == json[i].mockedResponseId){
|
||||
jsonIndex = i;
|
||||
|
||||
initializeMock(jsonIndex);
|
||||
|
||||
selectMessage(id);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
function selectMessage(id){
|
||||
const tiles = $('.tile');
|
||||
|
||||
tiles.removeClass("active");
|
||||
|
||||
$('.tile[tileid="'+id+'"]').addClass("active");
|
||||
|
||||
initializeHistory();
|
||||
refreshHeaderTable(innerHTML);
|
||||
}
|
||||
|
||||
|
||||
|
||||
function generateMessageTileHtml(id, httpStatus, mediaType){
|
||||
var innerHTML = '' +
|
||||
'<div tileid="' + id + '" class="tile">' +
|
||||
'<div class="content">' +
|
||||
'<div class="display-space-between">' +
|
||||
'<div class="centered-vertically">' +
|
||||
'<p>Id: ' + id + '</p>' +
|
||||
'<p>Status: ' + httpStatus + '</p>' +
|
||||
'</div>' +
|
||||
'<div>' +
|
||||
'<button class="modification-button btn-tile"><i class="icon-cancel"></i></button>' +
|
||||
'</div>' +
|
||||
'</div>' +
|
||||
'</div>' +
|
||||
'</div>';
|
||||
return innerHTML;
|
||||
}
|
||||
|
||||
|
||||
|
||||
const onbuild = function(){
|
||||
loadCookies();
|
||||
getData();
|
||||
if(advancedDisplayed) {
|
||||
changeAdvancedVisibility();
|
||||
}
|
||||
}
|
||||
|
||||
$(document).ready(onbuild);
|
||||
|
||||
function sleep(ms) {
|
||||
return new Promise(resolve => setTimeout(resolve, ms));
|
||||
}
|
||||
|
||||
|
||||
|
||||
function generateJson(){
|
||||
var newJson =
|
||||
{
|
||||
clientUUID: json[jsonIndex].clientUUID,
|
||||
mockedResponseId: json[jsonIndex].mockedResponseId,
|
||||
mediaType: $('#typeSelector').val(),
|
||||
messageBody: $('#bodyEditor').val(),
|
||||
httpStatus: $('#httpStatus').val(),
|
||||
httpHeaders: {},
|
||||
};
|
||||
newJson['httpHeaders'] = convertTableToJson();
|
||||
|
||||
json[jsonIndex] = newJson;
|
||||
return newJson;
|
||||
}
|
||||
|
||||
|
||||
function convertTableToJson(){
|
||||
const rows = $('#headerMapTable').children();
|
||||
|
||||
var obj = {};
|
||||
var key;
|
||||
for(let i=0; i<rows.length; i++){
|
||||
key = rows.eq(i).children().eq(0).children().eq(0).val();
|
||||
obj[key] = rows.eq(i).children().eq(1).children().eq(0).val();
|
||||
}
|
||||
return obj;
|
||||
}
|
||||
@@ -1,58 +0,0 @@
|
||||
var historyJson = {};
|
||||
const maxIterations = 200;
|
||||
|
||||
function filterHistory(){
|
||||
var dateFrom = new Date($('#historyFrom').val() + 'T' + $('#historyTimeFrom').val());
|
||||
|
||||
var dateTo = new Date($('#historyTo').val() + 'T' + $('#historyTimeTo').val());
|
||||
|
||||
loadHistory(dateFrom, dateTo);
|
||||
}
|
||||
|
||||
const startSearch = function(){
|
||||
filterHistory();
|
||||
}
|
||||
$('#btn-searchHistory').click(startSearch);
|
||||
|
||||
function loadHistory(dateFrom, dateTo){
|
||||
|
||||
var eventRequest = {
|
||||
clientUUID : json[jsonIndex].clientUUID,
|
||||
localDateTimeFrom : dateFrom,
|
||||
localDateTimeTo : dateTo,
|
||||
mockedResponseId : json[jsonIndex].mockedResponseId
|
||||
};
|
||||
$.ajax({
|
||||
url: host + '/api/event',
|
||||
type: 'POST',
|
||||
data: JSON.stringify(eventRequest, null, 2),
|
||||
contentType: "application/json"
|
||||
}).done(function(data){
|
||||
historyJson = data;
|
||||
displayHistory();
|
||||
});
|
||||
}
|
||||
|
||||
function getLast24hHistoryData(){
|
||||
$.getJSON(host + '/api/event/' + clientUUID + '/' + lastId, function(data){
|
||||
historyJson = data;
|
||||
displayHistory();
|
||||
});
|
||||
}
|
||||
|
||||
function historyToHtml(){
|
||||
var innerHTML = '';
|
||||
var iterations = historyJson.length <= maxIterations ? historyJson.length : maxIterations;
|
||||
for(let i=0; i<iterations; i++){
|
||||
let style = i%2==0 ? ' class="even"' : '';
|
||||
innerHTML += '<tr' + style + '>' +
|
||||
'<td>' + historyJson[i].dateTimeStamp + '</td>' +
|
||||
'<td>' + historyJson[i].interfaceName + '</td>' +
|
||||
'</tr>';
|
||||
}
|
||||
return innerHTML;
|
||||
}
|
||||
|
||||
function displayHistory(){
|
||||
$('#historyTable tbody').html(historyToHtml());
|
||||
}
|
||||
@@ -1,141 +0,0 @@
|
||||
var advancedVisibility = false;
|
||||
var selectMenu = $("#selectMenuContent");
|
||||
var advancedTab = $("#advanced");
|
||||
var basicID = $("#basicItemData")
|
||||
var advancedID = $("#advancedItemData");
|
||||
var advancedUUIDOptions = $("#uuid-validation-strategy");
|
||||
var focusedField = false;
|
||||
function changeAdvancedVisibility(){
|
||||
if(advancedVisibility){
|
||||
selectMenu.removeClass('active');
|
||||
advancedTab.removeClass('active');
|
||||
advancedID.removeClass('active');
|
||||
advancedUUIDOptions.removeClass('active');
|
||||
basicID.addClass('active');
|
||||
advancedVisibility = false;
|
||||
}
|
||||
else {
|
||||
selectMenu.addClass('active');
|
||||
advancedTab.addClass('active');
|
||||
advancedID.addClass('active');
|
||||
advancedUUIDOptions.addClass('active');
|
||||
basicID.removeClass('active');
|
||||
advancedVisibility = true;
|
||||
}
|
||||
setCookie();
|
||||
}
|
||||
|
||||
const historyFilter = $('#history-filter');
|
||||
const historyFilterSwitch = function(){
|
||||
historyFilter.toggleClass('active');
|
||||
}
|
||||
|
||||
$("#optional").click(changeAdvancedVisibility);
|
||||
$('#historyTab').click(showHistory);
|
||||
$('#btn-history-filter').click(historyFilterSwitch);
|
||||
|
||||
|
||||
|
||||
const tabitem = $('.tabitem');
|
||||
function showHistory(){
|
||||
$('#headersTab').click(showHeaders);
|
||||
tabitem.removeClass('active');
|
||||
$('.tabcontent').removeClass('active');
|
||||
$('#history').addClass('active');
|
||||
$('#historyTab').addClass('active');
|
||||
$('#historyTab').off('click');
|
||||
initializeHistory();
|
||||
}
|
||||
|
||||
function initializeHistory(){
|
||||
historyFilter.removeClass('active');
|
||||
getLast24hHistoryData();
|
||||
}
|
||||
|
||||
|
||||
|
||||
function showHeaders(){
|
||||
$('#historyTab').click(showHistory);
|
||||
tabitem.removeClass('active');
|
||||
$('.tabcontent').removeClass('active');
|
||||
$('#headers').addClass('active');
|
||||
$('#headersTab').addClass('active');
|
||||
$('#headersTab').off('click');
|
||||
}
|
||||
|
||||
function focusInTip(element){
|
||||
showTip(element);
|
||||
focusedField = true;
|
||||
}
|
||||
|
||||
function focusOutTip(element){
|
||||
focusedField = false;
|
||||
hidTip(element);
|
||||
}
|
||||
|
||||
function hidTip(element){
|
||||
if(focusedField) return;
|
||||
$('#'+element).removeClass('active');
|
||||
}
|
||||
|
||||
function showTip(element){
|
||||
if(focusedField) return;
|
||||
$('.tip').removeClass('active');
|
||||
$('#'+element).addClass('active');
|
||||
}
|
||||
|
||||
$('#messageLink').mouseover(function(){showTip('messageLinkTip')});
|
||||
$('#messageLink').mouseleave(function(){hidTip('messageLinkTip')});
|
||||
|
||||
$('#httpStatus').mouseover(function(){showTip('httpStatusTip')});
|
||||
$('#httpStatus').focusin(function(){focusInTip('httpStatusTip')});
|
||||
$('#httpStatus').mouseleave(function(){hidTip('httpStatusTip')});
|
||||
$('#httpStatus').focusout(function(){focusOutTip('httpStatusTip')});
|
||||
|
||||
$('#typeSelector').mouseover(function(){showTip('typeSelectorTip')});
|
||||
$('#typeSelector').focusin(function(){focusInTip('typeSelectorTip')});
|
||||
$('#typeSelector').mouseleave(function(){hidTip('typeSelectorTip')});
|
||||
$('#typeSelector').focusout(function(){focusOutTip('typeSelectorTip')});
|
||||
|
||||
$('#bodyEditor').mouseover(function(){showTip('bodyEditorTip')});
|
||||
$('#bodyEditor').focusin(function(){focusInTip('bodyEditorTip')});
|
||||
$('#bodyEditor').mouseleave(function(){hidTip('bodyEditorTip')});
|
||||
$('#bodyEditor').focusout(function(){focusOutTip('bodyEditorTip')});
|
||||
|
||||
$('#headersTab').mouseover(function(){showTip('headersTabTip')});
|
||||
$('#headersTab').mouseleave(function(){hidTip('headersTabTip')});
|
||||
|
||||
$('#historyTab').mouseover(function(){showTip('historyTabTip')});
|
||||
$('#historyTab').mouseleave(function(){hidTip('historyTabTip')});
|
||||
|
||||
$('#headerKeyInput').mouseover(function(){showTip('newHeaderTip')});
|
||||
$('#headerKeyInput').focusin(function(){focusInTip('newHeaderTip')});
|
||||
$('#headerKeyInput').mouseleave(function(){hidTip('newHeaderTip')});
|
||||
$('#headerKeyInput').focusout(function(){focusOutTip('newHeaderTip')});
|
||||
|
||||
$('#headerValueInput').mouseover(function(){showTip('newHeaderTip')});
|
||||
$('#headerValueInput').focusin(function(){focusInTip('newHeaderTip')});
|
||||
$('#headerValueInput').mouseleave(function(){hidTip('newHeaderTip')});
|
||||
$('#headerValueInput').focusout(function(){focusOutTip('newHeaderTip')});
|
||||
|
||||
$('#btnSave').mouseover(function(){showTip('btnSaveTip');});
|
||||
$('#btnSave').focusin(function(){focusInTip('btnSaveTip')});
|
||||
$('#btnSave').mouseleave(function(){hidTip('btnSaveTip')});
|
||||
$('#btnSave').focusout(function(){focusOutTip('btnSaveTip')});
|
||||
|
||||
$('#new-tile').mouseover(function(){showTip('btn-newTileTip');});
|
||||
$('#new-tile').mouseleave(function(){hidTip('btn-newTileTip')});
|
||||
$('#new-tile').focusout(function(){focusOutTip('btn-newTileTip')});
|
||||
|
||||
$('#listItems').mouseover(function(){showTip('messagesTip');});
|
||||
$('#listItems').mouseleave(function(){hidTip('messagesTip')});
|
||||
|
||||
|
||||
$('#uuid-edit-field').mouseover(function(){ showTip('UUIDFieldTip') });
|
||||
$('#uuid-edit-field').mouseleave(function(){ hidTip('UUIDFieldTip') });
|
||||
|
||||
$('#uuid-validation-strategy').mouseover(function(){ showTip('UUIDValidationStrategyTip') });
|
||||
$('#uuid-validation-strategy').mouseleave(function(){ hidTip('UUIDValidationStrategyTip') });
|
||||
|
||||
$('#editableBlock').mouseover( function(){ showTip('UUIDEditionTip') } );
|
||||
$('#editableBlock').mouseleave(function(){ hidTip('UUIDEditionTip') });
|
||||
@@ -8,6 +8,9 @@ import com.r11.tools.controller.XPathController;
|
||||
import com.r11.tools.controller.XsdController;
|
||||
import com.r11.tools.controller.XsltController;
|
||||
import com.r11.tools.controller.internal.RestControllerRegistry;
|
||||
import com.r11.tools.xml.Saxon;
|
||||
import com.r11.tools.xml.Xalan;
|
||||
import com.r11.tools.xml.XmlEngine;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import spark.Spark;
|
||||
@@ -35,12 +38,15 @@ public class SparkApplication {
|
||||
Gson jsongson = new GsonBuilder()
|
||||
.disableHtmlEscaping()
|
||||
.create();
|
||||
XmlEngine saxon = new Saxon();
|
||||
XmlEngine xalan = new Xalan();
|
||||
|
||||
|
||||
RestControllerRegistry registry = new RestControllerRegistry();
|
||||
registry.registerController(new ProcessorInfoController(logger));
|
||||
registry.registerController(new XsdController(gson, logger));
|
||||
registry.registerController(new XPathController(gson, logger));
|
||||
registry.registerController(new XsltController(gson, logger));
|
||||
registry.registerController(new ProcessorInfoController(logger, saxon, xalan));
|
||||
registry.registerController(new XsdController(gson, logger, xalan));
|
||||
registry.registerController(new XPathController(gson, logger, saxon, xalan));
|
||||
registry.registerController(new XsltController(gson, logger, saxon, xalan));
|
||||
registry.registerController(new JsonController(gson, jsongson, logger));
|
||||
|
||||
registry.register();
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
package com.r11.tools.controller;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.*;
|
||||
//import com.google.gson.GsonBuilder;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.r11.tools.controller.internal.GlobalControllerManifest;
|
||||
import com.r11.tools.controller.internal.HandlerType;
|
||||
import com.r11.tools.controller.internal.RestController;
|
||||
@@ -11,6 +10,9 @@ import spark.Request;
|
||||
import spark.Response;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@GlobalControllerManifest(path = "/json")
|
||||
public class JsonController implements RestController {
|
||||
|
||||
@@ -32,9 +34,7 @@ public class JsonController implements RestController {
|
||||
JsonObject responseJson = new JsonObject();
|
||||
|
||||
try {
|
||||
JsonObject requestJson = this.gson.fromJson(request.body(), JsonObject.class);
|
||||
|
||||
response.status(200);
|
||||
Object requestJson = this.gson.fromJson(request.body(), Object.class);
|
||||
|
||||
responseJson.addProperty("data", this.prettyGson.toJson(requestJson));
|
||||
responseJson.addProperty("time", System.currentTimeMillis() - startProcess);
|
||||
@@ -61,7 +61,7 @@ public class JsonController implements RestController {
|
||||
JsonObject responseJson = new JsonObject();
|
||||
|
||||
try {
|
||||
JsonObject requestJson = this.prettyGson.fromJson(request.body(), JsonObject.class);
|
||||
Object requestJson = this.prettyGson.fromJson(request.body(), Object.class);
|
||||
|
||||
response.status(200);
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@ import com.r11.tools.controller.internal.HandlerType;
|
||||
import com.r11.tools.controller.internal.RestController;
|
||||
import com.r11.tools.controller.internal.ScopedControllerManifest;
|
||||
import com.r11.tools.xml.Saxon;
|
||||
import com.r11.tools.xml.XmlEngine;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import spark.Request;
|
||||
import spark.Response;
|
||||
@@ -13,9 +14,13 @@ import spark.Response;
|
||||
public class ProcessorInfoController implements RestController {
|
||||
|
||||
private final Logger logger;
|
||||
private final XmlEngine saxon;
|
||||
private final XmlEngine xalan;
|
||||
|
||||
public ProcessorInfoController(Logger logger) {
|
||||
public ProcessorInfoController(Logger logger, XmlEngine saxon, XmlEngine xalan) {
|
||||
this.logger = logger;
|
||||
this.saxon = saxon;
|
||||
this.xalan = xalan;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -24,8 +29,8 @@ public class ProcessorInfoController implements RestController {
|
||||
@ScopedControllerManifest(method = HandlerType.GET, path = "/procinfo")
|
||||
public void processorInfo(Request request, Response response) {
|
||||
try {
|
||||
response.header("processor", "Saxon " + Saxon.getVersion() + " over s9api");
|
||||
response.body(Saxon.getVersion());
|
||||
response.header("processor", "Saxon " + saxon.getVersion() + " over s9api");
|
||||
response.body(saxon.getVersion());
|
||||
} catch (Exception ex) {
|
||||
this.logger.error("Error on retrieving engine version. " + ex);
|
||||
response.body(ex.getMessage());
|
||||
|
||||
@@ -3,8 +3,7 @@ package com.r11.tools.controller;
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.r11.tools.controller.internal.*;
|
||||
import com.r11.tools.xml.Saxon;
|
||||
import com.r11.tools.xml.Xalan;
|
||||
import com.r11.tools.xml.XmlEngine;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import spark.Request;
|
||||
import spark.Response;
|
||||
@@ -15,9 +14,14 @@ public class XPathController implements RestController {
|
||||
private final Gson gson;
|
||||
private final Logger logger;
|
||||
|
||||
public XPathController(Gson gson, Logger logger) {
|
||||
private final XmlEngine saxon;
|
||||
private final XmlEngine xalan;
|
||||
|
||||
public XPathController(Gson gson, Logger logger, XmlEngine saxon, XmlEngine xalan) {
|
||||
this.gson = gson;
|
||||
this.logger = logger;
|
||||
this.saxon = saxon;
|
||||
this.xalan = xalan;
|
||||
}
|
||||
|
||||
@ScopedControllerManifest(method = HandlerType.POST, path = "/xpath")
|
||||
@@ -44,10 +48,6 @@ public class XPathController implements RestController {
|
||||
String processor = requestJson.get("processor").getAsString();
|
||||
String version = requestJson.get("version").getAsString();
|
||||
|
||||
String tmp = "";
|
||||
long timeStart;
|
||||
long duration;
|
||||
|
||||
if (processor == null) {
|
||||
response.body("saxon, xalan");
|
||||
return;
|
||||
@@ -56,65 +56,77 @@ public class XPathController implements RestController {
|
||||
JsonObject responseJson = new JsonObject();
|
||||
switch (processor) {
|
||||
case "saxon":
|
||||
response.header("processor", "Saxon " + Saxon.getVersion() + " " + version + " over s9api");
|
||||
timeStart = System.currentTimeMillis();
|
||||
|
||||
try {
|
||||
tmp = Saxon.processXPath(data, query, version).getData().trim();
|
||||
|
||||
response.status(200);
|
||||
|
||||
responseJson.addProperty("result", tmp);
|
||||
responseJson.addProperty("status", "OK");
|
||||
} catch (Exception ex) {
|
||||
this.logger.error("Error on processing XPath using Saxon. " + ex);
|
||||
|
||||
response.status(400);
|
||||
|
||||
responseJson.addProperty("result", ex.getMessage());
|
||||
responseJson.addProperty("status", "ERR");
|
||||
}
|
||||
|
||||
duration = System.currentTimeMillis() - timeStart;
|
||||
this.logger.info("Request (XPath, Saxon) processed in " + duration + " ms.");
|
||||
|
||||
responseJson.addProperty("processor", "Saxon " + Saxon.getVersion() + " " + version + " over s9api");
|
||||
responseJson.addProperty("time", duration);
|
||||
|
||||
response.body(this.gson.toJson(responseJson));
|
||||
return;
|
||||
|
||||
processWithSaxon(response, data, query, version, responseJson);
|
||||
break;
|
||||
case "xalan":
|
||||
response.header("processor", Xalan.getVersion());
|
||||
timeStart = System.currentTimeMillis();
|
||||
|
||||
try {
|
||||
XPathQueryResult xPathQueryResult = Xalan.processXPath(data, query);
|
||||
|
||||
response.status(200);
|
||||
|
||||
responseJson.addProperty("result", xPathQueryResult.getData().trim());
|
||||
responseJson.addProperty("status", "OK");
|
||||
responseJson.addProperty("type", xPathQueryResult.getType());
|
||||
} catch (Exception ex) {
|
||||
this.logger.error("Error on processing XPath using Xalan. " + ex);
|
||||
|
||||
response.status(400);
|
||||
|
||||
responseJson.addProperty("result", ex.getMessage());
|
||||
responseJson.addProperty("status", "ERR");
|
||||
}
|
||||
|
||||
duration = System.currentTimeMillis() - timeStart;
|
||||
this.logger.info("Request (XPath, Xalan) processed in " + duration + " ms.");
|
||||
|
||||
responseJson.addProperty("processor", Xalan.getVersion());
|
||||
responseJson.addProperty("time", duration);
|
||||
|
||||
response.body(this.gson.toJson(responseJson));
|
||||
return;
|
||||
processWithXalan(response, data, query, responseJson);
|
||||
break;
|
||||
default:
|
||||
response.body("saxon, xalan");
|
||||
}
|
||||
}
|
||||
|
||||
private void processWithXalan(Response response, String data, String query, JsonObject responseJson) {
|
||||
long timeStart;
|
||||
long duration;
|
||||
response.header("processor", xalan.getVersion());
|
||||
timeStart = System.currentTimeMillis();
|
||||
|
||||
try {
|
||||
XPathQueryResult xPathQueryResult = xalan.processXPath(data, query, "");
|
||||
|
||||
response.status(200);
|
||||
|
||||
responseJson.addProperty("result", xPathQueryResult.getData().trim());
|
||||
responseJson.addProperty("status", "OK");
|
||||
responseJson.addProperty("type", xPathQueryResult.getType());
|
||||
} catch (Exception ex) {
|
||||
this.logger.error("Error on processing XPath using Xalan. " + ex);
|
||||
|
||||
response.status(400);
|
||||
|
||||
responseJson.addProperty("result", ex.getMessage());
|
||||
responseJson.addProperty("status", "ERR");
|
||||
}
|
||||
|
||||
duration = System.currentTimeMillis() - timeStart;
|
||||
this.logger.info("Request (XPath, Xalan) processed in " + duration + " ms.");
|
||||
|
||||
responseJson.addProperty("processor", xalan.getVersion());
|
||||
responseJson.addProperty("time", duration);
|
||||
|
||||
response.body(this.gson.toJson(responseJson));
|
||||
}
|
||||
|
||||
private void processWithSaxon(Response response, String data, String query, String version, JsonObject responseJson) {
|
||||
long timeStart;
|
||||
String tmp;
|
||||
long duration;
|
||||
response.header("processor", "Saxon " + saxon.getVersion() + " " + version + " over s9api");
|
||||
timeStart = System.currentTimeMillis();
|
||||
|
||||
try {
|
||||
tmp = saxon.processXPath(data, query, version).getData().trim();
|
||||
|
||||
response.status(200);
|
||||
|
||||
responseJson.addProperty("result", tmp);
|
||||
responseJson.addProperty("status", "OK");
|
||||
} catch (Exception ex) {
|
||||
this.logger.error("Error on processing XPath using Saxon. " + ex);
|
||||
|
||||
response.status(400);
|
||||
|
||||
responseJson.addProperty("result", ex.getMessage());
|
||||
responseJson.addProperty("status", "ERR");
|
||||
}
|
||||
|
||||
duration = System.currentTimeMillis() - timeStart;
|
||||
this.logger.info("Request (XPath, Saxon) processed in " + duration + " ms.");
|
||||
|
||||
responseJson.addProperty("processor", "Saxon " + saxon.getVersion() + " " + version + " over s9api");
|
||||
responseJson.addProperty("time", duration);
|
||||
|
||||
response.body(this.gson.toJson(responseJson));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ import com.r11.tools.controller.internal.HandlerType;
|
||||
import com.r11.tools.controller.internal.RestController;
|
||||
import com.r11.tools.controller.internal.ScopedControllerManifest;
|
||||
import com.r11.tools.xml.Xalan;
|
||||
import com.r11.tools.xml.XmlEngine;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import spark.Request;
|
||||
import spark.Response;
|
||||
@@ -17,9 +18,12 @@ public class XsdController implements RestController {
|
||||
private final Gson gson;
|
||||
private final Logger logger;
|
||||
|
||||
public XsdController(Gson gson, Logger logger) {
|
||||
private final XmlEngine xalan;
|
||||
|
||||
public XsdController(Gson gson, Logger logger, XmlEngine xalan) {
|
||||
this.gson = gson;
|
||||
this.logger = logger;
|
||||
this.xalan = xalan;
|
||||
}
|
||||
|
||||
@ScopedControllerManifest(method = HandlerType.POST, path = "/xsd")
|
||||
@@ -44,14 +48,14 @@ public class XsdController implements RestController {
|
||||
String data = requestJson.get("data").getAsString();
|
||||
String xsd = requestJson.get("process").getAsString();
|
||||
|
||||
response.header("processor", Xalan.getVersion());
|
||||
response.header("processor", xalan.getVersion());
|
||||
|
||||
long timeStart = System.currentTimeMillis();
|
||||
String tmp;
|
||||
|
||||
JsonObject responseJson = new JsonObject();
|
||||
try {
|
||||
tmp = Xalan.validate(data, xsd).trim();
|
||||
tmp = xalan.validate(data, xsd).trim();
|
||||
|
||||
response.status(200);
|
||||
|
||||
@@ -69,7 +73,7 @@ public class XsdController implements RestController {
|
||||
long duration = System.currentTimeMillis() - timeStart;
|
||||
this.logger.info("Request (XSD, Xalan) processed in " + duration + " ms.");
|
||||
|
||||
responseJson.addProperty("processor", Xalan.getVersion());
|
||||
responseJson.addProperty("processor", xalan.getVersion());
|
||||
responseJson.addProperty("time", duration);
|
||||
|
||||
response.body(this.gson.toJson(responseJson));
|
||||
|
||||
@@ -8,6 +8,7 @@ import com.r11.tools.controller.internal.RestController;
|
||||
import com.r11.tools.controller.internal.ScopedControllerManifest;
|
||||
import com.r11.tools.xml.Saxon;
|
||||
import com.r11.tools.xml.Xalan;
|
||||
import com.r11.tools.xml.XmlEngine;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import spark.Request;
|
||||
import spark.Response;
|
||||
@@ -18,9 +19,14 @@ public class XsltController implements RestController {
|
||||
private final Gson gson;
|
||||
private final Logger logger;
|
||||
|
||||
public XsltController(Gson gson, Logger logger) {
|
||||
private final XmlEngine saxon;
|
||||
private final XmlEngine xalan;
|
||||
|
||||
public XsltController(Gson gson, Logger logger, XmlEngine saxon, XmlEngine xalan) {
|
||||
this.gson = gson;
|
||||
this.logger = logger;
|
||||
this.saxon = saxon;
|
||||
this.xalan = xalan;
|
||||
}
|
||||
|
||||
@ScopedControllerManifest(method = HandlerType.POST, path = "/xslt")
|
||||
@@ -51,69 +57,78 @@ public class XsltController implements RestController {
|
||||
response.body("saxon, xalan");
|
||||
return;
|
||||
}
|
||||
|
||||
String tmp;
|
||||
long timeStart;
|
||||
long duration;
|
||||
|
||||
JsonObject responseJson = new JsonObject();
|
||||
switch (processor) {
|
||||
case "saxon":
|
||||
timeStart = System.currentTimeMillis();
|
||||
try {
|
||||
tmp = Saxon.processXSLT(data, query);
|
||||
|
||||
response.status(200);
|
||||
|
||||
responseJson.addProperty("result", tmp);
|
||||
responseJson.addProperty("status", "OK");
|
||||
} catch (Exception ex) {
|
||||
this.logger.error("Error on processing XSLT using Saxon. " + ex);
|
||||
|
||||
response.status(400);
|
||||
|
||||
responseJson.addProperty("result", ex.getMessage());
|
||||
responseJson.addProperty("status", "ERR");
|
||||
}
|
||||
|
||||
duration = System.currentTimeMillis() - timeStart;
|
||||
this.logger.info("Request (XSLT, Saxon) processed in " + duration + " ms.");
|
||||
|
||||
responseJson.addProperty("processor", "Saxon " + Saxon.getVersion() + " " + version);
|
||||
responseJson.addProperty("time", duration);
|
||||
|
||||
response.body(this.gson.toJson(responseJson));
|
||||
processWithSaxon(response, data, query, version, responseJson);
|
||||
return;
|
||||
|
||||
case "xalan":
|
||||
timeStart = System.currentTimeMillis();
|
||||
try {
|
||||
tmp = Xalan.processXSLT(data, query);
|
||||
|
||||
response.status(200);
|
||||
|
||||
responseJson.addProperty("result", tmp);
|
||||
responseJson.addProperty("status", "OK");
|
||||
} catch (Exception ex) {
|
||||
this.logger.error("Error on processing XSLT using Xalan. " + ex);
|
||||
|
||||
response.status(400);
|
||||
|
||||
responseJson.addProperty("result", ex.getMessage());
|
||||
responseJson.addProperty("status", "ERR");
|
||||
}
|
||||
|
||||
duration = System.currentTimeMillis() - timeStart;
|
||||
this.logger.info("Request (XSLT, Xalan) processed in " + duration + " ms.");
|
||||
|
||||
responseJson.addProperty("processor", Xalan.getVersion());
|
||||
responseJson.addProperty("time", duration);
|
||||
|
||||
response.body(this.gson.toJson(responseJson));
|
||||
processWithXalan(response, data, query, responseJson);
|
||||
return;
|
||||
|
||||
default:
|
||||
response.body("saxon, xalan");
|
||||
}
|
||||
}
|
||||
|
||||
private void processWithXalan(Response response, String data, String query, JsonObject responseJson) {
|
||||
long duration;
|
||||
long timeStart;
|
||||
String tmp;
|
||||
timeStart = System.currentTimeMillis();
|
||||
try {
|
||||
tmp = xalan.processXSLT(data, query);
|
||||
|
||||
response.status(200);
|
||||
|
||||
responseJson.addProperty("result", tmp);
|
||||
responseJson.addProperty("status", "OK");
|
||||
} catch (Exception ex) {
|
||||
this.logger.error("Error on processing XSLT using Xalan. " + ex);
|
||||
|
||||
response.status(400);
|
||||
|
||||
responseJson.addProperty("result", ex.getMessage());
|
||||
responseJson.addProperty("status", "ERR");
|
||||
}
|
||||
|
||||
duration = System.currentTimeMillis() - timeStart;
|
||||
this.logger.info("Request (XSLT, Xalan) processed in " + duration + " ms.");
|
||||
|
||||
responseJson.addProperty("processor", xalan.getVersion());
|
||||
responseJson.addProperty("time", duration);
|
||||
|
||||
response.body(this.gson.toJson(responseJson));
|
||||
}
|
||||
|
||||
private void processWithSaxon(Response response, String data, String query, String version, JsonObject responseJson) {
|
||||
long duration;
|
||||
String tmp;
|
||||
long timeStart;
|
||||
timeStart = System.currentTimeMillis();
|
||||
try {
|
||||
tmp = saxon.processXSLT(data, query);
|
||||
|
||||
response.status(200);
|
||||
|
||||
responseJson.addProperty("result", tmp);
|
||||
responseJson.addProperty("status", "OK");
|
||||
} catch (Exception ex) {
|
||||
this.logger.error("Error on processing XSLT using Saxon. " + ex);
|
||||
|
||||
response.status(400);
|
||||
|
||||
responseJson.addProperty("result", ex.getMessage());
|
||||
responseJson.addProperty("status", "ERR");
|
||||
}
|
||||
|
||||
duration = System.currentTimeMillis() - timeStart;
|
||||
this.logger.info("Request (XSLT, Saxon) processed in " + duration + " ms.");
|
||||
|
||||
responseJson.addProperty("processor", "Saxon " + saxon.getVersion() + " " + version);
|
||||
responseJson.addProperty("time", duration);
|
||||
|
||||
response.body(this.gson.toJson(responseJson));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ import java.io.StringWriter;
|
||||
* Handler for Saxon engine
|
||||
* @author Wojciech Czop
|
||||
*/
|
||||
public class Saxon {
|
||||
public class Saxon implements XmlEngine{
|
||||
|
||||
/**
|
||||
* Transforms string containing xml document via xslt
|
||||
@@ -20,7 +20,7 @@ public class Saxon {
|
||||
* @return transformed xml
|
||||
* @throws SaxonApiException thrown on stylesheet or transformation errors
|
||||
*/
|
||||
public static String processXSLT(String data, String transform) throws SaxonApiException {
|
||||
public String processXSLT(String data, String transform) throws SaxonApiException {
|
||||
Processor processor = new Processor(false);
|
||||
XsltCompiler compiler = processor.newXsltCompiler();
|
||||
XsltExecutable stylesheet = compiler.compile(new StreamSource(new StringReader(transform)));
|
||||
@@ -34,6 +34,11 @@ public class Saxon {
|
||||
return sw.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String validate(String data, String xsd) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
/**
|
||||
* Process xpath and return either node or wrapped atomic value
|
||||
* @param data xml to be querried
|
||||
@@ -42,7 +47,7 @@ public class Saxon {
|
||||
* @return string xml representation of the node
|
||||
* @throws Exception thrown on node building errors or invalid xpath
|
||||
*/
|
||||
public static XPathQueryResult processXPath(String data, String query, String version) throws Exception {
|
||||
public XPathQueryResult processXPath(String data, String query, String version) throws Exception {
|
||||
Processor p = new Processor(false);
|
||||
XPathCompiler compiler = p.newXPathCompiler();
|
||||
DocumentBuilder builder = p.newDocumentBuilder();
|
||||
@@ -70,7 +75,7 @@ public class Saxon {
|
||||
* Returns version of the processor
|
||||
* @return version of the processor
|
||||
*/
|
||||
public static String getVersion() {
|
||||
public String getVersion() {
|
||||
return new Processor(false).getSaxonProductVersion();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,7 +24,7 @@ import java.io.*;
|
||||
* Handler for Xalan engine
|
||||
* @author Wojciech Czop
|
||||
*/
|
||||
public class Xalan {
|
||||
public class Xalan implements XmlEngine{
|
||||
|
||||
/**
|
||||
* Transforms string containing xml document via xslt
|
||||
@@ -33,7 +33,7 @@ public class Xalan {
|
||||
* @return transformed xml
|
||||
* @throws Exception thrown on stylesheet or transformation errors
|
||||
*/
|
||||
public static String processXSLT(String data, String transform) throws Exception{
|
||||
public String processXSLT(String data, String transform) throws Exception {
|
||||
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
|
||||
DocumentBuilder builder = factory.newDocumentBuilder();
|
||||
Document document = builder.parse(new InputSource(new StringReader(data)));
|
||||
@@ -51,7 +51,7 @@ public class Xalan {
|
||||
return sw.toString();
|
||||
}
|
||||
|
||||
private static boolean isTextNode(Node n) {
|
||||
private boolean isTextNode(Node n) {
|
||||
if (n == null)
|
||||
return false;
|
||||
short nodeType = n.getNodeType();
|
||||
@@ -65,7 +65,7 @@ public class Xalan {
|
||||
* @return xml processed using given xpath
|
||||
* @throws Exception thrown on node building errors or invalid xpath
|
||||
*/
|
||||
public static XPathQueryResult processXPath(String data, String transform) throws Exception {
|
||||
public XPathQueryResult processXPath(String data, String transform, String version) throws Exception {
|
||||
|
||||
// Set up a DOM tree to query.
|
||||
InputSource in = new InputSource(new StringReader(data));
|
||||
@@ -103,7 +103,7 @@ public class Xalan {
|
||||
return new XPathQueryResult(resultString.toString(), "node");
|
||||
} catch (TransformerException e) {
|
||||
String returnData = XPathAPI.eval(doc, transform).toString();
|
||||
return new XPathQueryResult(data, "string");
|
||||
return new XPathQueryResult(returnData, "string");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -112,7 +112,7 @@ public class Xalan {
|
||||
* Returns version of the processor
|
||||
* @return version of the processor
|
||||
*/
|
||||
public static String getVersion(){
|
||||
public String getVersion(){
|
||||
return org.apache.xalan.Version.getVersion();
|
||||
}
|
||||
|
||||
@@ -123,7 +123,7 @@ public class Xalan {
|
||||
* @return statement of validity
|
||||
* @throws Exception thrown on invalid xsd schema or xml
|
||||
*/
|
||||
public static String validate(String data, String xsd) throws Exception{
|
||||
public String validate(String data, String xsd) throws Exception {
|
||||
Source dataSource = new StreamSource(new StringReader(data));
|
||||
Source xsdSource = new StreamSource(new StringReader(xsd));
|
||||
SchemaFactory schemaFactory = SchemaFactory
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
package com.r11.tools.xml;
|
||||
|
||||
import com.r11.tools.controller.internal.XPathQueryResult;
|
||||
|
||||
public interface XmlEngine {
|
||||
XPathQueryResult processXPath(String data, String query, String version) throws Exception;
|
||||
String processXSLT(String data, String transform) throws Exception;
|
||||
String validate(String data, String xsd) throws Exception;
|
||||
|
||||
public String getVersion();
|
||||
|
||||
}
|
||||
@@ -1,5 +1,8 @@
|
||||
FROM nginx:stable-alpine
|
||||
|
||||
RUN apk add --no-cache tzdata
|
||||
ENV TZ Europe/Warsaw
|
||||
|
||||
COPY ./tools/ /usr/share/nginx/html/tools/
|
||||
COPY ./lawful/ /usr/share/nginx/html/lawful/
|
||||
COPY ./assets/ /usr/share/nginx/html/assets/
|
||||
|
||||
@@ -41,7 +41,7 @@ div#header {
|
||||
grid-column: 1;
|
||||
}
|
||||
|
||||
iframe#frame {
|
||||
iframe#iframe {
|
||||
flex-grow: 1;
|
||||
background-color: #FFFFFF;
|
||||
}
|
||||
|
||||
@@ -6,6 +6,8 @@
|
||||
@import url('r11tooltip.css');
|
||||
@import url('r11modal.css');
|
||||
@import url('r11flexbox.css');
|
||||
@import url('r11popup.css');
|
||||
@import url('../../highlight.css');
|
||||
|
||||
@font-face {
|
||||
font-family: 'Material Icons';
|
||||
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
@@ -69,4 +69,27 @@
|
||||
.content p {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.refresh-button{
|
||||
float: right;
|
||||
border: none;
|
||||
background-color: unset;
|
||||
font-size: xx-large;
|
||||
}
|
||||
|
||||
.refresh-button:hover{
|
||||
animation-name: rotation;
|
||||
animation-duration: 0.8s;
|
||||
animation-iteration-count: infinite;
|
||||
animation-timing-function: linear;
|
||||
}
|
||||
|
||||
@keyframes rotation{
|
||||
from{
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
to {
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
83
Frontend/assets/css/tools/mock/r11popup.css
Normal file
83
Frontend/assets/css/tools/mock/r11popup.css
Normal file
@@ -0,0 +1,83 @@
|
||||
.popup-flex:not(.hiddable-container){
|
||||
animation: blur 0.5s ease-in-out ;
|
||||
animation-fill-mode: forwards;
|
||||
}
|
||||
.popup-flex{
|
||||
display: flex;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
z-index: 50;
|
||||
flex-direction: column;
|
||||
gap: 2%;
|
||||
position: fixed;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.popup-body{
|
||||
min-width: 33%;
|
||||
max-width: 60%;
|
||||
max-height: 70%;
|
||||
background-color: white;
|
||||
box-shadow: 10px 10px 5px lightblue;
|
||||
min-height: 45%;
|
||||
border-radius: 1em;
|
||||
text-align: center;
|
||||
padding: 10px 15px 15px 15px;
|
||||
color: black;
|
||||
border: 1px #2A93B0 solid;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
position: fixed;
|
||||
}
|
||||
|
||||
.popup-button-close-container{
|
||||
text-align: right;
|
||||
margin-right: 2%;
|
||||
margin-top: 1%;
|
||||
font-size: xx-large;
|
||||
font-weight: bold;
|
||||
position: sticky;
|
||||
top:0
|
||||
}
|
||||
|
||||
.hiddable-popup-option{
|
||||
flex-grow: 1;
|
||||
overflow: auto;
|
||||
padding: 1.5%;
|
||||
}
|
||||
|
||||
.popup-button-close{
|
||||
background: padding-box;
|
||||
border: 0;
|
||||
}
|
||||
|
||||
.popup-button-close:hover{
|
||||
color: #2A93B0;
|
||||
}
|
||||
|
||||
.hiddable-container{
|
||||
display:none;
|
||||
}
|
||||
|
||||
.hidden-popup-type{
|
||||
display: none;
|
||||
}
|
||||
|
||||
#history-request-body{
|
||||
text-align: justify;
|
||||
}
|
||||
|
||||
@keyframes blur {
|
||||
0% {
|
||||
backdrop-filter: blur(0px);
|
||||
}
|
||||
|
||||
50% {
|
||||
backdrop-filter: blur(5px);
|
||||
}
|
||||
|
||||
100% {
|
||||
backdrop-filter: blur(10px);
|
||||
}
|
||||
}
|
||||
@@ -68,4 +68,29 @@
|
||||
background-color: #3bc4f1;
|
||||
text-align: left;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.table-default td{
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
#header-table tr td {
|
||||
border: 1px black solid;
|
||||
padding: 1.5%;
|
||||
|
||||
}
|
||||
|
||||
#header-table{
|
||||
border-collapse: collapse;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.history-header-name{
|
||||
min-width: 10vw;
|
||||
}
|
||||
|
||||
#historyTable, td{
|
||||
padding: 1%;
|
||||
overflow-x: scroll;
|
||||
}
|
||||
@@ -21,6 +21,7 @@ input {
|
||||
border: 2px solid rgba(93, 99, 96, 0.705);
|
||||
border-radius: 5px;
|
||||
padding: 8px;
|
||||
display: block;
|
||||
|
||||
}
|
||||
|
||||
@@ -62,10 +63,6 @@ body {
|
||||
width: 90%;
|
||||
}
|
||||
|
||||
.tool.extended .tool-context {
|
||||
width: 75%;
|
||||
}
|
||||
|
||||
.tool.extended .tool-extention {
|
||||
width: 20%;
|
||||
padding-top: 2%;
|
||||
@@ -1,6 +0,0 @@
|
||||
$(document).ready( function() {
|
||||
document.getElementById("rest-mock").href =
|
||||
window.location.protocol + "//" + window.location.hostname + ":8097";
|
||||
|
||||
});
|
||||
|
||||
@@ -1,6 +1,41 @@
|
||||
const tools = new Map();
|
||||
|
||||
/**
|
||||
* Get address of Mock Services
|
||||
*
|
||||
* @function
|
||||
* @name getMockHost
|
||||
* @kind function
|
||||
* @returns {string}
|
||||
*/
|
||||
function getMockHost() {
|
||||
return window.location.protocol + "//" + window.location.hostname + ":8097";
|
||||
}
|
||||
|
||||
/**
|
||||
* Function called after page is loaded
|
||||
*
|
||||
* @function
|
||||
* @name init
|
||||
* @kind function
|
||||
* @returns {void}
|
||||
*/
|
||||
function init() {
|
||||
changeActiveTools('xmlTool', 'XML');
|
||||
|
||||
tools.set("xpath", "tools/xpath.html");
|
||||
tools.set("xsd", "tools/xsd.html");
|
||||
tools.set("xslt", "tools/xslt.html");
|
||||
tools.set("xmlform", "tools/xmlFormatter.html");
|
||||
tools.set("jsonform", "tools/jsonFormatter.html");
|
||||
tools.set("mock", "tools/mock.html");
|
||||
|
||||
changeActiveTools('XML');
|
||||
var toolUrl = window.location.search.substring(1);
|
||||
if (tools.has(toolUrl))
|
||||
changeTool(toolUrl, false);
|
||||
else
|
||||
loadLastPage();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -12,26 +47,77 @@ function init() {
|
||||
* @param {any} activeClass class of elements that have to be shown
|
||||
* @param {any} activeCategoryButton class of category button that has to be active
|
||||
*/
|
||||
function changeActiveTools(activeClass, activeCategoryButton) {
|
||||
let tools = document.getElementById("toolList").children
|
||||
function changeActiveTools(activeCategoryButton) {
|
||||
let toolList = document.getElementById("toolList").children;
|
||||
let categoryToClass = new Map([["XML", "xmlTool"],
|
||||
["JSON", "jsonTool"],
|
||||
["REST", "restTool"]]);
|
||||
|
||||
for (i = 0; i < tools.length; i++) {
|
||||
if (tools[i].classList.contains(activeClass)) {
|
||||
tools[i].style.display = "block";
|
||||
}
|
||||
else {
|
||||
tools[i].style.display = "none";
|
||||
}
|
||||
let activeClass = categoryToClass.get(activeCategoryButton.toUpperCase());
|
||||
if(activeClass == null) return;
|
||||
|
||||
for (i = 0; i < toolList.length; i++) {
|
||||
if (toolList[i].classList.contains(activeClass))
|
||||
toolList[i].style.display = "block";
|
||||
else
|
||||
toolList[i].style.display = "none";
|
||||
}
|
||||
|
||||
let categories = document.getElementById("menu").children
|
||||
let categoryList = document.getElementById("menu").children;
|
||||
|
||||
for (i = 0; i < categories.length; i++) {
|
||||
if (categories[i].innerText == activeCategoryButton) {
|
||||
categories[i].classList.add("active")
|
||||
}
|
||||
else {
|
||||
categories[i].classList.remove("active")
|
||||
}
|
||||
for (i = 0; i < categoryList.length; i++) {
|
||||
if (categoryList[i].innerText == activeCategoryButton)
|
||||
categoryList[i].classList.add("active");
|
||||
else
|
||||
categoryList[i].classList.remove("active");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This function changes active tool.
|
||||
* Optional updateURL can be set to false to stop changing URL.
|
||||
* This helps avoiding endless reload loop when loading page.
|
||||
*
|
||||
* @function
|
||||
* @name changeTool
|
||||
* @kind function
|
||||
* @param {any} tool
|
||||
* @param {boolean} updateURL?
|
||||
* @returns {void}
|
||||
*/
|
||||
function changeTool(tool, updateURL = true) {
|
||||
if (! tools.has(tool)) return;
|
||||
const url = tools.get(tool);
|
||||
if (updateURL) document.location.search = tool;
|
||||
|
||||
|
||||
switch (tool) { // XML category is default.
|
||||
case "jsonform":
|
||||
changeActiveTools('JSON');
|
||||
break;
|
||||
case "mock":
|
||||
changeActiveTools('REST');
|
||||
break;
|
||||
}
|
||||
|
||||
localStorage.setItem("lastPage", tool);
|
||||
document.getElementById("iframe").src = url;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Function that loads last used tool and sets active category accordingly
|
||||
*
|
||||
* @function
|
||||
* @name loadLastPage
|
||||
* @kind function
|
||||
* @returns {void}
|
||||
*/
|
||||
function loadLastPage() {
|
||||
var lastPage = localStorage.getItem("lastPage");
|
||||
if (lastPage == null) {
|
||||
lastPage = "xpath";
|
||||
}
|
||||
changeTool(lastPage);
|
||||
}
|
||||
@@ -1,72 +0,0 @@
|
||||
function formatAndValidateJson(errorElement) {
|
||||
const input = document.querySelector('#jsonBlock');
|
||||
const processInfo = document.getElementById(errorElement);
|
||||
|
||||
const address = window.location.protocol + "//" + window.location.hostname + ":" + 8081 + "/json/formatting"
|
||||
|
||||
fetch(address, {
|
||||
method: 'POST',
|
||||
body: input.textContent
|
||||
})
|
||||
.then(async (response) => {
|
||||
const promise = response.json();
|
||||
if (!response.ok) {
|
||||
throw Error(await promise);
|
||||
}
|
||||
|
||||
return promise;
|
||||
})
|
||||
.then((data) => {
|
||||
input.innerText = data.data;
|
||||
processInfo.innerText = "";
|
||||
hljs.highlightElement(input);
|
||||
|
||||
processInfo.innerHTML = "<b style='color: green'>Computed in </b> <span style='color: green'>" + data.time + "ms</span>";
|
||||
})
|
||||
.catch((error) => {
|
||||
processInfo.innerHTML = "<b style='color: red'>" + error.data + "</b>";
|
||||
console.error('Error:', error);
|
||||
});
|
||||
}
|
||||
|
||||
function minimizeJson(errorElement) {
|
||||
const input = document.querySelector('#jsonBlock');
|
||||
const processInfo = document.getElementById(errorElement);
|
||||
|
||||
const address = window.location.protocol + "//" + window.location.hostname + ":" + 8081 + "/json/minimize"
|
||||
|
||||
fetch(address, {
|
||||
method: 'POST',
|
||||
body: input.textContent
|
||||
})
|
||||
.then(async (response) => {
|
||||
const promise = response.json();
|
||||
if (!response.ok) {
|
||||
throw Error(await promise);
|
||||
}
|
||||
|
||||
return promise;
|
||||
})
|
||||
.then((data) => {
|
||||
input.innerText = data.data;
|
||||
processInfo.innerText = "";
|
||||
hljs.highlightElement(input);
|
||||
|
||||
processInfo.innerHTML = "<b style='color: green'>Computed in </b> <span style='color: green'>" + data.time + "ms</span>";
|
||||
})
|
||||
.catch((error) => {
|
||||
processInfo.innerHTML = "<b style='color: red'>" + error.data + "</b>";
|
||||
console.error('Error:', error);
|
||||
});
|
||||
}
|
||||
|
||||
function clearJsonData() {
|
||||
const input = document.querySelector('#jsonBlock');
|
||||
input.textContent = "";
|
||||
}
|
||||
|
||||
function insertDefaultJson() {
|
||||
const input = document.querySelector('#jsonBlock');
|
||||
input.textContent = "{\"enter\": \"your\", \"json\": \"here\"}";
|
||||
hljs.highlightElement(input);
|
||||
}
|
||||
250
Frontend/assets/scripts/tools/jsonFormatter.js
Normal file
250
Frontend/assets/scripts/tools/jsonFormatter.js
Normal file
@@ -0,0 +1,250 @@
|
||||
|
||||
|
||||
const mergeHTMLPlugin = (function () {
|
||||
'use strict';
|
||||
|
||||
var originalStream;
|
||||
|
||||
/**
|
||||
* @param {string} value
|
||||
* @returns {string}
|
||||
*/
|
||||
function escapeHTML(value) {
|
||||
return value
|
||||
.replace(/&/g, '&')
|
||||
.replace(/</g, '<')
|
||||
.replace(/>/g, '>')
|
||||
.replace(/"/g, '"')
|
||||
.replace(/'/g, ''');
|
||||
}
|
||||
|
||||
|
||||
/* plugin itself */
|
||||
|
||||
/** @type {HLJSPlugin} */
|
||||
const mergeHTMLPlugin = {
|
||||
// preserve the original HTML token stream
|
||||
"before:highlightElement": ({ el }) => {
|
||||
originalStream = nodeStream(el);
|
||||
},
|
||||
// merge it afterwards with the highlighted token stream
|
||||
"after:highlightElement": ({ el, result, text }) => {
|
||||
if (!originalStream.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
const resultNode = document.createElement('div');
|
||||
resultNode.innerHTML = result.value;
|
||||
result.value = mergeStreams(originalStream, nodeStream(resultNode), text);
|
||||
el.innerHTML = result.value;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {Node} node
|
||||
*/
|
||||
function tag(node) {
|
||||
return node.nodeName.toLowerCase();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Node} node
|
||||
*/
|
||||
function nodeStream(node) {
|
||||
/** @type Event[] */
|
||||
const result = [];
|
||||
(function _nodeStream(node, offset) {
|
||||
for (let child = node.firstChild; child; child = child.nextSibling) {
|
||||
if (child.nodeType === 3) {
|
||||
offset += child.nodeValue.length;
|
||||
} else if (child.nodeType === 1) {
|
||||
result.push({
|
||||
event: 'start',
|
||||
offset: offset,
|
||||
node: child
|
||||
});
|
||||
offset = _nodeStream(child, offset);
|
||||
|
||||
if (!tag(child).match(/br|hr|img|input/)) {
|
||||
result.push({
|
||||
event: 'stop',
|
||||
offset: offset,
|
||||
node: child
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
return offset;
|
||||
})(node, 0);
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {any} original - the original stream
|
||||
* @param {any} highlighted - stream of the highlighted source
|
||||
* @param {string} value - the original source itself
|
||||
*/
|
||||
function mergeStreams(original, highlighted, value) {
|
||||
let processed = 0;
|
||||
let result = '';
|
||||
const nodeStack = [];
|
||||
|
||||
function selectStream() {
|
||||
if (!original.length || !highlighted.length) {
|
||||
return original.length ? original : highlighted;
|
||||
}
|
||||
if (original[0].offset !== highlighted[0].offset) {
|
||||
return (original[0].offset < highlighted[0].offset) ? original : highlighted;
|
||||
}
|
||||
|
||||
return highlighted[0].event === 'start' ? original : highlighted;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Node} node
|
||||
*/
|
||||
function open(node) {
|
||||
/** @param {Attr} attr */
|
||||
function attributeString(attr) {
|
||||
return ' ' + attr.nodeName + '="' + escapeHTML(attr.value) + '"';
|
||||
}
|
||||
|
||||
// @ts-ignore
|
||||
result += '<' + tag(node) + [].map.call(node.attributes, attributeString).join('')
|
||||
+ '>';
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Node} node
|
||||
*/
|
||||
function close(node) {
|
||||
result += '</' + tag(node) + '>';
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Event} event
|
||||
*/
|
||||
function render(event) {
|
||||
(event.event === 'start' ? open : close)(event.node);
|
||||
}
|
||||
|
||||
while (original.length || highlighted.length) {
|
||||
let stream = selectStream();
|
||||
result += escapeHTML(value.substring(processed, stream[0].offset));
|
||||
processed = stream[0].offset;
|
||||
if (stream === original) {
|
||||
/*
|
||||
On any opening or closing tag of the original markup we first close
|
||||
the entire highlighted node stack, then render the original tag along
|
||||
with all the following original tags at the same offset and then
|
||||
reopen all the tags on the highlighted stack.
|
||||
*/
|
||||
nodeStack.reverse().forEach(close);
|
||||
do {
|
||||
render(stream.splice(0, 1)[0]);
|
||||
stream = selectStream();
|
||||
} while (stream === original && stream.length && stream[0].offset === processed);
|
||||
nodeStack.reverse().forEach(open);
|
||||
} else {
|
||||
if (stream[0].event === 'start') {
|
||||
nodeStack.push(stream[0].node);
|
||||
} else {
|
||||
nodeStack.pop();
|
||||
}
|
||||
render(stream.splice(0, 1)[0]);
|
||||
}
|
||||
}
|
||||
return result + escapeHTML(value.substr(processed));
|
||||
}
|
||||
|
||||
return mergeHTMLPlugin;
|
||||
|
||||
}());
|
||||
|
||||
function formatAndValidateJson(errorElement) {
|
||||
const input = document.querySelector('#jsonBlock');
|
||||
const processInfo = document.getElementById(errorElement);
|
||||
|
||||
const address = window.location.protocol + "//" + window.location.hostname + ":" + 8081 + "/json/formatting"
|
||||
|
||||
fetch(address, {
|
||||
method: 'POST',
|
||||
body: input.textContent
|
||||
})
|
||||
.then(async (response) => {
|
||||
const promise = response.json();
|
||||
if (!response.ok) {
|
||||
throw Error(await promise);
|
||||
}
|
||||
|
||||
return promise;
|
||||
})
|
||||
.then((data) => {
|
||||
input.innerText = data.data;
|
||||
processInfo.innerText = "";
|
||||
hljs.highlightElement(input);
|
||||
|
||||
processInfo.innerHTML = "<b style='color: green'>Computed in </b> <span style='color: green'>" + data.time + "ms</span>";
|
||||
})
|
||||
.catch((error) => {
|
||||
processInfo.innerHTML = "<b style='color: red'>" + error.data + "</b>";
|
||||
console.error('Error:', error);
|
||||
});
|
||||
}
|
||||
|
||||
function minimizeJson(errorElement) {
|
||||
const input = document.querySelector('#jsonBlock');
|
||||
const processInfo = document.getElementById(errorElement);
|
||||
|
||||
const address = window.location.protocol + "//" + window.location.hostname + ":" + 8081 + "/json/minimize"
|
||||
|
||||
fetch(address, {
|
||||
method: 'POST',
|
||||
body: input.textContent
|
||||
})
|
||||
.then(async (response) => {
|
||||
const promise = response.json();
|
||||
if (!response.ok) {
|
||||
throw Error(await promise);
|
||||
}
|
||||
|
||||
return promise;
|
||||
})
|
||||
.then((data) => {
|
||||
input.innerText = data.data;
|
||||
processInfo.innerText = "";
|
||||
hljs.highlightElement(input);
|
||||
|
||||
processInfo.innerHTML = "<b style='color: green'>Computed in </b> <span style='color: green'>" + data.time + "ms</span>";
|
||||
})
|
||||
.catch((error) => {
|
||||
processInfo.innerHTML = "<b style='color: red'>" + error.data + "</b>";
|
||||
console.error('Error:', error);
|
||||
});
|
||||
}
|
||||
|
||||
function clearJsonData() {
|
||||
const input = document.querySelector('#jsonBlock');
|
||||
input.textContent = "";
|
||||
}
|
||||
|
||||
function insertDefaultJson() {
|
||||
const input = document.querySelector('#jsonBlock');
|
||||
input.textContent = "{\"enter\": \"your\", \"json\": \"here\"}";
|
||||
hljs.highlightElement(input);
|
||||
}
|
||||
|
||||
/**
|
||||
* This function is executed after the page is loaded.
|
||||
*
|
||||
* @function
|
||||
* @name init
|
||||
* @kind function
|
||||
*/
|
||||
function init() {
|
||||
// Make sure that only plain text is pasted
|
||||
configurePastingInElement("jsonBlock");
|
||||
|
||||
hljs.addPlugin(mergeHTMLPlugin);
|
||||
}
|
||||
|
||||
254
Frontend/assets/scripts/tools/mock/datatransfer.js
Normal file
254
Frontend/assets/scripts/tools/mock/datatransfer.js
Normal file
@@ -0,0 +1,254 @@
|
||||
var clientUUID = '';
|
||||
var advancedDisplayed = false;
|
||||
var json = {};
|
||||
var jsonIndex = 0;
|
||||
var host = window.location.protocol + "//" + window.location.hostname + "/mock";
|
||||
|
||||
const C_UUID = 'mock-uuid';
|
||||
const C_ADV = 'advanced-mode';
|
||||
|
||||
const color_red = "#ff8f8f";
|
||||
const color_grey = "#6b6b6b";
|
||||
|
||||
const setModified = function(){
|
||||
setDataModified();
|
||||
}
|
||||
|
||||
const getUpdate = function(){
|
||||
updateData();
|
||||
}
|
||||
const dataRefresh = function(){
|
||||
getData();
|
||||
}
|
||||
|
||||
/*
|
||||
Listeners segment
|
||||
*/
|
||||
|
||||
$(document).on('change', '.data-field', setModified);
|
||||
|
||||
$('#btn-save').click(
|
||||
() => {
|
||||
disableSaveButton();
|
||||
}
|
||||
);
|
||||
|
||||
$('#btn-newRow').click(
|
||||
()=> {
|
||||
newRowInput();
|
||||
setDataModified();
|
||||
}
|
||||
);
|
||||
|
||||
/*
|
||||
Functions segment
|
||||
*/
|
||||
|
||||
function disableSaveButton(){
|
||||
$('#btn-save').removeClass('active');
|
||||
$('#btn-save').off();
|
||||
}
|
||||
|
||||
function createLink(uuid){
|
||||
var link = host + '/api/mock/r/'+uuid;
|
||||
return link;
|
||||
}
|
||||
|
||||
|
||||
function onLoad(){
|
||||
loadCookies();
|
||||
getData();
|
||||
}
|
||||
|
||||
function getData(){
|
||||
$.getJSON(host + '/api/mock/'+clientUUID, function(data) {
|
||||
json = data;
|
||||
loadFetchedMessage();
|
||||
initializeUUID();
|
||||
});
|
||||
}
|
||||
|
||||
function loadCookies(){
|
||||
clientUUID = getCookie(C_UUID);
|
||||
advancedDisplayed = getCookie(C_ADV) == 'true';
|
||||
}
|
||||
|
||||
function setCookie(){
|
||||
document.cookie = C_UUID + '=' +clientUUID;
|
||||
document.cookie = C_ADV + '=' + advancedVisibility;
|
||||
}
|
||||
|
||||
function initializeUUID(){
|
||||
if(clientUUID == null || clientUUID == undefined || clientUUID == ''){
|
||||
clientUUID = json.clientUUID;
|
||||
setCookie();
|
||||
}
|
||||
}
|
||||
|
||||
function httpStatusInvalid(){
|
||||
value = $('#httpStatus').val();
|
||||
return value == '';
|
||||
}
|
||||
|
||||
function setDataModified(){
|
||||
if(httpStatusInvalid()){
|
||||
$('#btn-save').removeClass('active');
|
||||
$('#btn-save').off();
|
||||
document.getElementById("httpStatus").style.backgroundColor = color_red;
|
||||
return;
|
||||
}
|
||||
$('#btn-save').addClass('active');
|
||||
$('#btn-save').click(getUpdate);
|
||||
document.getElementById("httpStatus").style.backgroundColor = null;
|
||||
}
|
||||
|
||||
function getCookie(cname) {
|
||||
var name = cname + '=';
|
||||
var decodedCookie = decodeURIComponent(document.cookie);
|
||||
var ca = decodedCookie.split(';');
|
||||
for(var i = 0; i <ca.length; i++) {
|
||||
var c = ca[i];
|
||||
while (c.charAt(0) == ' ') {
|
||||
c = c.substring(1);
|
||||
}
|
||||
if (c.indexOf(name) == 0) {
|
||||
return c.substring(name.length, c.length);
|
||||
}
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
||||
function updateData(){
|
||||
var updatedJson = createRequestBody();
|
||||
const dataSaved = function () {
|
||||
loadFetchedMessage();
|
||||
savedModalDisplay();
|
||||
}
|
||||
$.ajax({
|
||||
url: host + '/api/mock',
|
||||
type: 'PUT',
|
||||
data: JSON.stringify(updatedJson, null, 2),
|
||||
contentType: "application/json",
|
||||
}).done(dataSaved);
|
||||
disableSaveButton();
|
||||
}
|
||||
|
||||
function loadFetchedMessage(){
|
||||
fillStaticFields(
|
||||
json.clientUUID,
|
||||
json.contentType,
|
||||
json.messageBody,
|
||||
json.httpStatus);
|
||||
fillHeaderTable(json.httpHeaders);
|
||||
getHistoryData();
|
||||
refreshHeaderTable(document.innerHTML);
|
||||
}
|
||||
|
||||
function fillStaticFields(uuid, contentType, body, httpStatus){
|
||||
let link = createLink(uuid);
|
||||
let linkHtml = '<a class="hyperlink" target="_blank" href="'+link+'">'+link+'</a>';
|
||||
$('#messageLink').html(linkHtml);
|
||||
$('#httpStatus').val(httpStatus);
|
||||
$('#typeSelector').val(contentType);
|
||||
$('#bodyEditor').val(body);
|
||||
}
|
||||
|
||||
function fillHeaderTable(headers){
|
||||
var innerHTML = buildHeaderMapHtml(headers);
|
||||
refreshHeaderTable(innerHTML);
|
||||
}
|
||||
|
||||
function refreshHeaderTable(html){
|
||||
$('#headerMapTable').html(html);
|
||||
$('.btn-hashmap').click(function(){
|
||||
setDataModified();
|
||||
$(this).closest('tr').remove();
|
||||
})
|
||||
}
|
||||
|
||||
function buildHeaderMapHtml(headers){
|
||||
var innerHTML = '';
|
||||
for(var key in headers){
|
||||
innerHTML += buildRowHtml(key, headers[key]);
|
||||
}
|
||||
return innerHTML;
|
||||
}
|
||||
|
||||
function addRow(key, value){
|
||||
var headerMap = $('#headerMapTable');
|
||||
var headersMapHtml = headerMap.html();
|
||||
headersMapHtml += buildRowHtml(key, value);
|
||||
refreshHeaderTable(headersMapHtml);
|
||||
}
|
||||
|
||||
function newRowInput(){
|
||||
const hName = $('#headerKeyInput');
|
||||
const hValue = $('#headerValueInput');
|
||||
if(checkIfInputValid(hName.val()) && checkIfInputValid(hValue.val())){
|
||||
addRow(hName.val(), hValue.val());
|
||||
hName.val(null);
|
||||
hValue.val(null);
|
||||
}
|
||||
}
|
||||
|
||||
function checkIfInputValid(input){
|
||||
return !(input == '' || input == null || input == undefined);
|
||||
}
|
||||
|
||||
function checkIfHeaderEssential(key){
|
||||
|
||||
if( key == "Connection" || key == "Keep-Alive" || key == "Date" ){
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
function buildRowHtml(key, value){
|
||||
|
||||
if(checkIfHeaderEssential(key)){
|
||||
return '' +
|
||||
'<tr>' +
|
||||
'<td><input class="key data-field" value="' + key + '" readonly></td>' +
|
||||
'<td><input class="data-field" value="' + value + '"></td>' +
|
||||
'</tr>';
|
||||
}
|
||||
return '' +
|
||||
'<tr>' +
|
||||
'<td><input class="key data-field" value="' + key + '"></td>' +
|
||||
'<td><input class="data-field" value="' + value + '"></td>' +
|
||||
'<td><button class="modification-button btn-hashmap"><i class="icon-cancel"></i></button></td>' +
|
||||
'</tr>';
|
||||
}
|
||||
|
||||
function sleep(ms) {
|
||||
return new Promise(resolve => setTimeout(resolve, ms));
|
||||
}
|
||||
|
||||
function createRequestBody(){
|
||||
var newJson =
|
||||
{
|
||||
clientUUID: json.clientUUID,
|
||||
contentType: $('#typeSelector').val(),
|
||||
messageBody: $('#bodyEditor').val(),
|
||||
httpStatus: $('#httpStatus').val(),
|
||||
httpHeaders: {},
|
||||
};
|
||||
newJson['httpHeaders'] = convertTableToJson();
|
||||
|
||||
json = newJson;
|
||||
return newJson;
|
||||
}
|
||||
|
||||
|
||||
function convertTableToJson(){
|
||||
const rows = $('#headerMapTable').children();
|
||||
|
||||
var obj = {};
|
||||
var key;
|
||||
for(let i=0; i<rows.length; i++){
|
||||
key = rows.eq(i).children().eq(0).children().eq(0).val();
|
||||
obj[key] = rows.eq(i).children().eq(1).children().eq(0).val();
|
||||
}
|
||||
return obj;
|
||||
}
|
||||
49
Frontend/assets/scripts/tools/mock/historyloader.js
Normal file
49
Frontend/assets/scripts/tools/mock/historyloader.js
Normal file
@@ -0,0 +1,49 @@
|
||||
var historyJson = {};
|
||||
const maxIterations = 200;
|
||||
|
||||
function getHistoryData(){
|
||||
$.getJSON(host + '/api/event/' + clientUUID, function(data){
|
||||
historyJson = data;
|
||||
displayHistory();
|
||||
});
|
||||
}
|
||||
|
||||
function historyToHtml(){
|
||||
var innerHTML = '';
|
||||
var iterations = historyJson.length <= maxIterations ? historyJson.length : maxIterations;
|
||||
for(let i=0; i<iterations; i++){
|
||||
let style = i%2==0 ? ' class="even"' : '';
|
||||
innerHTML += '<tr' + style + '>' +
|
||||
'<td>' + parseTimeStamp(historyJson[i].dateTimeStamp) + '</td>' +
|
||||
'<td>' + historyJson[i].httpMethod + '</td>' +
|
||||
'<td>' + parseRequestBody(historyJson[i].requestBody, i) + '</td>' +
|
||||
'<td> <button id="'+i+'" class="showHeaderButton" onClick="showHeadersHistory(this);"> Show headers </button> </td>' +
|
||||
'</tr>';
|
||||
}
|
||||
return innerHTML;
|
||||
}
|
||||
|
||||
function parseRequestBody(requestBody,i){
|
||||
return requestBody.length == 0 ?
|
||||
"No request body" :
|
||||
'<button id="'+i+'" class="showRequestBodyButton" onClick="showRequestBody(this);"> Show request body </button>'
|
||||
}
|
||||
|
||||
function parseTimeStamp(timeStamp){
|
||||
return timeStamp.substring(0,19).replace('T',' ');
|
||||
}
|
||||
|
||||
function parseHeaders(pos){
|
||||
parsedJson = new Map();
|
||||
headers = historyJson[pos].headers
|
||||
Object.keys( headers ).forEach(
|
||||
(jsonKey) => {
|
||||
parsedJson.set( jsonKey , headers[jsonKey] );
|
||||
}
|
||||
)
|
||||
return parsedJson;
|
||||
}
|
||||
|
||||
function displayHistory(){
|
||||
$('#historyTable tbody').html(historyToHtml());
|
||||
}
|
||||
@@ -7,7 +7,6 @@ var methodToCall = {
|
||||
const overlay = $('#overlay');
|
||||
const savedModal = $('#modal-confirm');
|
||||
const dataLossModal = $('#modal-query');
|
||||
const uuidChangeModal = $('#modal-uuidChanged')
|
||||
const dataLossModalYes = dataLossModal.children().eq(2).children().eq(0);
|
||||
const dataLossModalNo = dataLossModal.children().eq(2).children().eq(1);
|
||||
const allModals = $('.modal');
|
||||
@@ -24,36 +23,10 @@ const dataLossModalDisplay = function(){
|
||||
showModal(dataLossModal);
|
||||
}
|
||||
|
||||
const uuidChangeModalDisplay = function(addidionalMessage){
|
||||
|
||||
switch(addidionalMessage){
|
||||
case "success":{
|
||||
|
||||
$(".uuid-modal-body").removeClass("active");
|
||||
$("#changeUUIDSuccess").addClass("active");
|
||||
break;
|
||||
}
|
||||
case "new":{
|
||||
|
||||
$(".uuid-modal-body").removeClass("active");
|
||||
$("#newUUID").addClass("active");
|
||||
break;
|
||||
}
|
||||
case "restore":{
|
||||
|
||||
$(".uuid-modal-body").removeClass("active");
|
||||
$("#restoredUUID").addClass("active");
|
||||
break;
|
||||
}
|
||||
case "noChg":{
|
||||
|
||||
$(".uuid-modal-body").removeClass("active");
|
||||
$("#noChgUUID").addClass("active");
|
||||
break;
|
||||
}
|
||||
}
|
||||
showModal(uuidChangeModal);
|
||||
}
|
||||
btnModalClose.click(closeModals);
|
||||
overlay.click(closeModals);
|
||||
dataLossModalNo.click(closeModals);
|
||||
dataLossModalYes.click(dropChangesAndClose);
|
||||
|
||||
function setMethodToCall(name, id){
|
||||
methodToCall.name = name;
|
||||
@@ -74,16 +47,7 @@ function showModal(jmodal){
|
||||
|
||||
function hideModal(jmodal){
|
||||
if(!modalDisplayed) return;
|
||||
if ($(uuidChangeModal).hasClass('active')) window.location.reload();
|
||||
overlay.removeClass('active');
|
||||
jmodal.removeClass('active');
|
||||
modalDisplayed = false;
|
||||
}
|
||||
|
||||
btnModalClose.click(closeModals);
|
||||
|
||||
overlay.click(closeModals);
|
||||
|
||||
dataLossModalNo.click(closeModals);
|
||||
dataLossModalYes.click(dropChangesAndClose);
|
||||
|
||||
34
Frontend/assets/scripts/tools/mock/popup.js
Normal file
34
Frontend/assets/scripts/tools/mock/popup.js
Normal file
@@ -0,0 +1,34 @@
|
||||
|
||||
function switchPopups (neededPopupOption) {
|
||||
$('.hiddable-popup-option').addClass('hidden-popup-type');
|
||||
$('#'+neededPopupOption).removeClass('hidden-popup-type');
|
||||
}
|
||||
|
||||
function showPopup(){
|
||||
$('.popup-flex').removeClass('hiddable-container');
|
||||
}
|
||||
|
||||
function hidePopup(){
|
||||
$('.popup-flex').addClass('hiddable-container');
|
||||
$('.hiddable-popup-option').addClass('hidden-popup-type');
|
||||
}
|
||||
|
||||
/*
|
||||
* Event listener that's close the popup when user clicks out of a popup.
|
||||
*/
|
||||
|
||||
window.addEventListener(
|
||||
'click' ,
|
||||
(clickedElement) => {
|
||||
if(!document.getElementById('popup-body').contains(clickedElement.target) && clickedElement.target.className == 'popup-flex' ) {
|
||||
hidePopup();
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
$('.popup-button-close').click(
|
||||
() => {
|
||||
hidePopup();
|
||||
$('.hiddable-popup-option').addClass('hidden-popup-type')
|
||||
}
|
||||
);
|
||||
165
Frontend/assets/scripts/tools/mock/uianimation.js
Normal file
165
Frontend/assets/scripts/tools/mock/uianimation.js
Normal file
@@ -0,0 +1,165 @@
|
||||
var advancedVisibility = false;
|
||||
var focusedField = false;
|
||||
/*
|
||||
Listeners
|
||||
*/
|
||||
$("#optional").click(changeAdvancedVisibility);
|
||||
|
||||
$('#historyTab').click(showHistory);
|
||||
|
||||
$('.tooltipped').on("mouseenter" , (event) => {showTip(event.currentTarget.id+'Tip')})
|
||||
.on( "mouseleave", (event) => {hideTip(event.currentTarget.id+'Tip')});
|
||||
|
||||
/*
|
||||
Functions
|
||||
*/
|
||||
|
||||
function changeAdvancedVisibility(){
|
||||
if(advancedVisibility){
|
||||
$("#advanced").removeClass('active');
|
||||
advancedVisibility = false;
|
||||
}
|
||||
else {
|
||||
$('#advanced').addClass('active');
|
||||
advancedVisibility = true;
|
||||
}
|
||||
setCookie();
|
||||
}
|
||||
|
||||
const tabitem = $('.tabitem');
|
||||
function showHistory(){
|
||||
$('#headersTab').click(showHeaders);
|
||||
tabitem.removeClass('active');
|
||||
$('.tabcontent').removeClass('active');
|
||||
$('#history').addClass('active');
|
||||
$('#historyTab').addClass('active');
|
||||
$('#historyTab').off('click');
|
||||
getHistoryData();
|
||||
}
|
||||
|
||||
function showHeaders(){
|
||||
$('#historyTab').click(showHistory);
|
||||
tabitem.removeClass('active');
|
||||
$('.tabcontent').removeClass('active');
|
||||
$('#headers').addClass('active');
|
||||
$('#headersTab').addClass('active');
|
||||
$('#headersTab').off('click');
|
||||
}
|
||||
|
||||
function showHeadersHistory(record){
|
||||
historyTable = '';
|
||||
headers = parseHeaders(record.id)
|
||||
headers.forEach(
|
||||
(value,key) => {
|
||||
historyTable +=
|
||||
'<tr>' +
|
||||
'<td class="history-header-name">'+ key + '</td>' +
|
||||
'<td class="history-header-value">'+ value + '</td>' +
|
||||
'</tr>'
|
||||
}
|
||||
);
|
||||
document.getElementById('header-history-table-body').innerHTML = historyTable;
|
||||
switchPopups('history-headers-table');
|
||||
showPopup();
|
||||
}
|
||||
|
||||
async function formatJSON(json) {
|
||||
const backend = "java";
|
||||
const address = window.location.protocol + "//" + window.location.hostname + "/" + backend + "/json/formatting";
|
||||
|
||||
var init = {
|
||||
body: json,
|
||||
method: "POST"
|
||||
};
|
||||
var request = new Request(address, init);
|
||||
|
||||
var result = await fetch(request).then(response => {
|
||||
return response.text().then(function (text) {
|
||||
var json = JSON.parse(text);
|
||||
json.status = response.status;
|
||||
return json;
|
||||
});
|
||||
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
async function formatXML(xml) {
|
||||
const backend = "libxml";
|
||||
const address = window.location.protocol + "//" + window.location.hostname + "/" + backend + "/prettify";
|
||||
var data = {
|
||||
data: xml,
|
||||
process: "",
|
||||
processor: "libxml",
|
||||
version: "1.0"
|
||||
}
|
||||
|
||||
var init = {
|
||||
body: JSON.stringify(data),
|
||||
method: "POST"
|
||||
};
|
||||
var request = new Request(address, init);
|
||||
|
||||
var result = await fetch(request).then(response => {
|
||||
return response.text().then(function (text) {
|
||||
return JSON.parse(text);
|
||||
});
|
||||
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
function showRequestBody(element){
|
||||
var historyRequestBody = historyJson[element.id].requestBody;
|
||||
const popupContent = document.getElementById('code-highlight-content')
|
||||
|
||||
document.getElementById('code-highlight-content').innerText = "Loading...";
|
||||
switch(historyJson[element.id].headers["content-type"]){
|
||||
case "application/json":{
|
||||
formatJSON(historyRequestBody).then(function(result) {
|
||||
|
||||
if (result.status == "200") {
|
||||
popupContent.innerText = result.data;
|
||||
highlightSyntax('code-highlight-content');
|
||||
}
|
||||
else {
|
||||
popupContent.innerText = historyRequestBody;
|
||||
}
|
||||
});
|
||||
break;
|
||||
}
|
||||
case "application/xml": {
|
||||
formatXML(historyRequestBody).then(function(result) {
|
||||
if (result.status == "OK") {
|
||||
popupContent.innerText = result.result;
|
||||
highlightSyntax('code-highlight-content');
|
||||
}
|
||||
else {
|
||||
popupContent.innerText = historyRequestBody;
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
break;
|
||||
}
|
||||
default:{
|
||||
popupContent.innerText = historyRequestBody;
|
||||
highlightSyntax('code-highlight-content');
|
||||
}
|
||||
}
|
||||
switchPopups('history-request-body');
|
||||
showPopup();
|
||||
}
|
||||
|
||||
function refreshHistoryRecords(){
|
||||
getHistoryData();
|
||||
}
|
||||
|
||||
function hideTip(element){
|
||||
$('#'+element).removeClass('active');
|
||||
}
|
||||
|
||||
function showTip(element){
|
||||
$('.tip').removeClass('active');
|
||||
$('#'+element).addClass('active');
|
||||
}
|
||||
@@ -65,28 +65,6 @@ function clearDataField() {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* The `escapeHTML` function is used to escape special characters in an HTML element's innerHTML property.
|
||||
* This is done to prevent these characters from being interpreted as HTML tags or attributes,
|
||||
* which could potentially cause security vulnerabilities or unintended behavior.
|
||||
*
|
||||
* @function
|
||||
* @name escapeHTML
|
||||
* @kind function
|
||||
* @param {any} element
|
||||
* @returns {void}
|
||||
*/
|
||||
function escapeHTML(elementID) {
|
||||
document.getElementById(elementID).innerHTML = document.getElementById(elementID).innerHTML
|
||||
.replace(/&/g, "&")
|
||||
.replace(/</g, "<")
|
||||
.replace(/>/g, ">")
|
||||
.replace(/"/g, """)
|
||||
.replace(/'/g, "'");
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* It fills the XML area with a sample XML.
|
||||
*
|
||||
@@ -98,7 +76,7 @@ function escapeHTML(elementID) {
|
||||
*/
|
||||
function fillDefaultXML(element) {
|
||||
if (element.classList.contains("active")) {
|
||||
const serverAddress = window.location.protocol + "//" + window.location.hostname + ":8086";
|
||||
const serverAddress = window.location.protocol + "//" + window.location.hostname;
|
||||
clearDefaultContent(document.getElementById("xmlArea"), "Insert XML here");
|
||||
fetch(serverAddress + "/assets/samples/sampleXml.xml")
|
||||
.then(response => response.text())
|
||||
@@ -111,8 +89,18 @@ function fillDefaultXML(element) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* It fills the XSD area with a sample XSD and XML area with matching XML.
|
||||
*
|
||||
* @function
|
||||
* @name fillDefaultXSD
|
||||
* @kind function
|
||||
* @param {any} element
|
||||
* @returns {void}
|
||||
*/
|
||||
function fillDefaultXSD(){
|
||||
const serverAddress = window.location.protocol + "//" + window.location.hostname + ":8086";
|
||||
const serverAddress = window.location.protocol + "//" + window.location.hostname;
|
||||
fetch(serverAddress + "/assets/samples/sampleXSD.xsd")
|
||||
.then( response => response.text() )
|
||||
.then( (XSDSchema) => {
|
||||
@@ -138,7 +126,7 @@ function fillDefaultXSD(){
|
||||
* @returns {void}
|
||||
*/
|
||||
function fillDefaultXSLT() {
|
||||
const serverAddress = window.location.protocol + "//" + window.location.hostname + ":8086";
|
||||
const serverAddress = window.location.protocol + "//" + window.location.hostname;
|
||||
fetch(serverAddress + "/assets/samples/XSLTTemplate.xslt")
|
||||
.then( response => response.text() )
|
||||
.then( (XSTLTemplate) => {
|
||||
@@ -289,9 +277,9 @@ function performRequest(endpoint, checkXML, checkTransform) {
|
||||
var xmlData = document.getElementById(sourceId).innerText.trim();
|
||||
var transformData = document.getElementById(transformId).innerText.trim();
|
||||
|
||||
var port = 8081;
|
||||
var backend = "java";
|
||||
if (getProcessor() == "libxml") {
|
||||
port = 8082;
|
||||
backend = "libxml";
|
||||
}
|
||||
|
||||
var empty = false;
|
||||
@@ -305,7 +293,7 @@ function performRequest(endpoint, checkXML, checkTransform) {
|
||||
empty = true;
|
||||
}
|
||||
if (!empty) {
|
||||
restRequest(port, endpoint, xmlData, transformData).then(function (result) {
|
||||
restRequest(backend, endpoint, xmlData, transformData).then(function (result) {
|
||||
document.getElementById("resultArea").innerText = result.result;
|
||||
highlightSyntax("resultArea");
|
||||
document.getElementById("procinfo").innerText = ' Computed using ' + result.processor;
|
||||
@@ -345,7 +333,7 @@ function performFormatRequest(endpoint, checkXML, sourceId, targetId) {
|
||||
const sourceElement = document.getElementById(sourceId);
|
||||
const targetElement = document.getElementById(targetId);
|
||||
const infoElement = document.getElementById("formatinfo");
|
||||
const port = 8082;
|
||||
const backend = "libxml";
|
||||
var xmlData = sourceElement.innerText.trim();
|
||||
|
||||
var empty = false;
|
||||
@@ -356,7 +344,7 @@ function performFormatRequest(endpoint, checkXML, sourceId, targetId) {
|
||||
}
|
||||
|
||||
if (!empty) {
|
||||
restRequest(port, endpoint, xmlData, "").then(function (result) {
|
||||
restRequest(backend, endpoint, xmlData, "").then(function (result) {
|
||||
if (result.status == "OK") {
|
||||
targetElement.innerText = result.result.trim();
|
||||
highlightSyntax(targetElement.id);
|
||||
@@ -386,16 +374,15 @@ function performFormatRequest(endpoint, checkXML, sourceId, targetId) {
|
||||
* @function
|
||||
* @name restRequest
|
||||
* @kind function
|
||||
* @param {any} port of target service
|
||||
* @param {any} backend target backend
|
||||
* @param {any} endpoint of target service
|
||||
* @param {any} xmlData XML that will be sent
|
||||
* @param {any} transformData data used to transform given XML
|
||||
* @returns {Promise<any>}
|
||||
*/
|
||||
async function restRequest(port, endpoint, xmlData, transformData) {
|
||||
const escapeChar = "specialEscapeChar";
|
||||
async function restRequest(backend, endpoint, xmlData, transformData) {
|
||||
|
||||
const addr = window.location.protocol + "//" + window.location.hostname + ":" + port + "/" + endpoint;
|
||||
const addr = window.location.protocol + "//" + window.location.hostname + "/" + backend + "/" + endpoint;
|
||||
|
||||
if (defaultStrings.includes(xmlData)) {
|
||||
xmlData = "<empty/>";
|
||||
|
||||
34
Frontend/assets/scripts/tools/xmlFormatter.js
Normal file
34
Frontend/assets/scripts/tools/xmlFormatter.js
Normal file
@@ -0,0 +1,34 @@
|
||||
/**
|
||||
* This function is executed after the page is loaded.
|
||||
*
|
||||
* @function
|
||||
* @name init
|
||||
* @kind function
|
||||
*/
|
||||
function init() {
|
||||
configurePastingInElement("xmlArea");
|
||||
}
|
||||
|
||||
/**
|
||||
* Function returns processor that will be used to transform XML.
|
||||
* This solution allows to use one function for sending request from every tool
|
||||
*
|
||||
* @function
|
||||
* @name getProcessor
|
||||
* @kind function
|
||||
*/
|
||||
function getProcessor() {
|
||||
return "libxml";
|
||||
}
|
||||
|
||||
/**
|
||||
* Function returns version of XML processor that will be used to transform XML.
|
||||
* This solution allows to use one function for sending request from every tool
|
||||
*
|
||||
* @function
|
||||
* @name getVersion
|
||||
* @kind function
|
||||
*/
|
||||
function getVersion() {
|
||||
return "1.0"
|
||||
}
|
||||
174
Frontend/assets/scripts/tools/xpath.js
Normal file
174
Frontend/assets/scripts/tools/xpath.js
Normal file
@@ -0,0 +1,174 @@
|
||||
|
||||
/**
|
||||
* The `processVersionSelector()` function is responsible for updating the display of the web page
|
||||
* based on the selected processor and version.
|
||||
*
|
||||
* @function
|
||||
* @name processVersionSelector
|
||||
* @kind function
|
||||
* @returns {void}
|
||||
*/
|
||||
function processVersionSelector() {
|
||||
var processor = getProcessor();
|
||||
var hideableOptions = document.getElementsByClassName("hideable");
|
||||
for (let i = 0; i < hideableOptions.length; i++) {
|
||||
hideableOptions[i].style = "display: none;";
|
||||
}
|
||||
if (processor == "xalan" || processor == "libxml") {
|
||||
var xalanOptions = document.getElementsByClassName("xalan");
|
||||
for (let i = 0; i < xalanOptions.length; i++) {
|
||||
xalanOptions[i].style = "";
|
||||
}
|
||||
document.getElementById("versions").selectedIndex = 0;
|
||||
}
|
||||
else {
|
||||
var saxonOptions = document.getElementsByClassName("saxon");
|
||||
for (let i = 0; i < saxonOptions.length; i++) {
|
||||
saxonOptions[i].style = "";
|
||||
}
|
||||
document.getElementById("versions").selectedIndex = 3;
|
||||
|
||||
}
|
||||
processTooltip();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* The `processTooltip()` function is responsible for updating the display of the tooltip based on the selected version of the processor.
|
||||
* It shows or hides different sections of the tooltip based on the selected version.
|
||||
* It also handles the click event on the form and updates the tooltip accordingly.
|
||||
*
|
||||
* @function
|
||||
* @name processTooltip
|
||||
* @kind function
|
||||
*/
|
||||
function processTooltip() {
|
||||
var filter = "collapse" + getVersion();
|
||||
var collList;
|
||||
|
||||
|
||||
if (filter == "collapse3.0") {
|
||||
document.getElementById("tooltipFunctionInfo").innerText = "XPath 3.0 functions";
|
||||
hideList(document.getElementsByName("collapse10"));
|
||||
hideList(document.getElementsByName("collapse20"));
|
||||
showList(document.getElementsByName("collapse30"));
|
||||
hideList(document.getElementsByName("collapse31"));
|
||||
|
||||
} else if (filter == "collapse3.1") {
|
||||
document.getElementById("tooltipFunctionInfo").innerText = "XPath 3.1 functions";
|
||||
hideList(document.getElementsByName("collapse10"));
|
||||
hideList(document.getElementsByName("collapse20"));
|
||||
hideList(document.getElementsByName("collapse30"));
|
||||
showList(document.getElementsByName("collapse31"));
|
||||
} else if (filter == "collapse2.0") {
|
||||
document.getElementById("tooltipFunctionInfo").innerText = "XPath 2.0 functions";
|
||||
hideList(document.getElementsByName("collapse10"));
|
||||
showList(document.getElementsByName("collapse20"));
|
||||
hideList(document.getElementsByName("collapse30"));
|
||||
hideList(document.getElementsByName("collapse31"));
|
||||
} else {
|
||||
document.getElementById("tooltipFunctionInfo").innerText = "XPath 1.0 functions";
|
||||
showList(document.getElementsByName("collapse10"));
|
||||
hideList(document.getElementsByName("collapse20"));
|
||||
hideList(document.getElementsByName("collapse30"));
|
||||
hideList(document.getElementsByName("collapse31"));
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* This function is executed after the page is loaded.
|
||||
*
|
||||
* @function
|
||||
* @name init
|
||||
* @kind function
|
||||
*/
|
||||
function init() {
|
||||
|
||||
// Make sure that only plain text is pasted
|
||||
configurePastingInElement("xmlArea");
|
||||
configurePastingInElement("transformArea");
|
||||
|
||||
//Handle clicks in whole form and set info in tooltip
|
||||
setDefaultContent(document.getElementById("xmlArea"), 'Insert XML here');
|
||||
setDefaultContent(document.getElementById("transformArea"), 'Insert XPath expression here');
|
||||
|
||||
processVersionSelector();
|
||||
processTooltip();
|
||||
tool.addEventListener('change', event => {
|
||||
//Check if script was called from textarea or selector
|
||||
var targetID = event.target.getAttribute('id');
|
||||
if (targetID == "processors") {
|
||||
processVersionSelector();
|
||||
processTooltip();
|
||||
}
|
||||
else if (targetID == "versions") {
|
||||
processTooltip();
|
||||
}
|
||||
|
||||
|
||||
})
|
||||
tool.addEventListener('click', event => {
|
||||
//Check if script was called from textarea or selector
|
||||
var targetID = event.target.getAttribute('id');
|
||||
if (targetID !== "xmlArea" && targetID !== "transformArea") {
|
||||
return;
|
||||
}
|
||||
processTooltip();
|
||||
|
||||
})
|
||||
tool.addEventListener('change', event => {
|
||||
//Check if script was called from textarea or selector
|
||||
var targetID = event.target.getAttribute('id');
|
||||
if (targetID !== "xmlArea" && targetID !== "transformArea") {
|
||||
return;
|
||||
}
|
||||
processTooltip();
|
||||
})
|
||||
|
||||
var triggerList = document.getElementsByClassName("collapseTrigger");
|
||||
for (i = 0; i < triggerList.length; i++) {
|
||||
|
||||
triggerList[i].addEventListener("click", function () {
|
||||
var collapsible = this.parentElement;
|
||||
if (this.tagName == "A") {
|
||||
var collapsibleData = this.nextElementSibling;
|
||||
} else {
|
||||
var collapsibleData = this.parentElement.nextElementSibling;
|
||||
|
||||
}
|
||||
|
||||
|
||||
if (collapsibleData.style.maxHeight > "0px") {
|
||||
collapsibleData.style.maxHeight = "0px";
|
||||
|
||||
this.classList.toggle("active", false);
|
||||
if (!this.classList.contains("collapsibleMini")) {
|
||||
collapsible.classList.toggle("active", false);
|
||||
}
|
||||
|
||||
var subLists1 = collapsibleData.getElementsByClassName("content");
|
||||
var subLists2 = collapsibleData.getElementsByClassName("active");
|
||||
for (j = 0; j < subLists1.length; j++) {
|
||||
subLists1[j].style.maxHeight = "0px";
|
||||
}
|
||||
for (j = 0; j < subLists2.length; j++) {
|
||||
subLists2[j].classList.toggle("active", false);
|
||||
}
|
||||
} else {
|
||||
collapsibleData.style.maxHeight = (collapsibleData.scrollHeight) + "px";
|
||||
|
||||
this.classList.toggle("active", true);
|
||||
if (!this.classList.contains("collapsibleMini")) {
|
||||
collapsible.classList.toggle("active", true);
|
||||
} else {
|
||||
var parentContent = this.closest(".content");
|
||||
parentContent.style.maxHeight = (parentContent.scrollHeight + collapsibleData.scrollHeight) + "px";
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
51
Frontend/assets/scripts/tools/xsd.js
Normal file
51
Frontend/assets/scripts/tools/xsd.js
Normal file
@@ -0,0 +1,51 @@
|
||||
/**
|
||||
* This function is executed after the page is loaded.
|
||||
*
|
||||
* @function
|
||||
* @name init
|
||||
* @kind function
|
||||
*/
|
||||
function init() {
|
||||
// Make sure that only plain text is pasted
|
||||
configurePastingInElement("xmlArea");
|
||||
configurePastingInElement("transformArea");
|
||||
|
||||
//Handle clicks in whole form and set info in tooltip
|
||||
setDefaultContent(document.getElementById("xmlArea"), 'Insert XML here');
|
||||
setDefaultContent(document.getElementById("transformArea"), 'Insert XSD here');
|
||||
|
||||
// refreshTooltip();
|
||||
processTooltip();
|
||||
tool.addEventListener('click', event => {
|
||||
//Check if script was called from textarea or selector
|
||||
var targetID = event.target.getAttribute('id');
|
||||
if (targetID !== "processors" && targetID !== "xmlArea" && targetID !== "transformArea" && targetID !== "versions") {
|
||||
return;
|
||||
}
|
||||
|
||||
processTooltip();
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* The `processTooltip()` function is responsible for updating the display of the tooltip based on the selected version of the processor.
|
||||
* It shows or hides different sections of the tooltip based on the selected version.
|
||||
* It also handles the click event on the form and updates the tooltip accordingly.
|
||||
*
|
||||
* @function
|
||||
* @name processTooltip
|
||||
* @kind function
|
||||
*/
|
||||
function processTooltip() {
|
||||
|
||||
if (getProcessor() == "xalan") {
|
||||
document.getElementById("tooltipFunctionInfo").innerText = "XSLT 1.0 functions";
|
||||
document.getElementById("processorTooltipInfo").innerText = "Supports XSLT 1.0";
|
||||
hideList(document.getElementsByName("collapse30"));
|
||||
} else {
|
||||
document.getElementById("tooltipFunctionInfo").innerText = "XSLT 1.0, 2.0 & 3.0 functions";
|
||||
document.getElementById("processorTooltipInfo").innerText = "Supports XSLT up to 3.0";
|
||||
showList(document.getElementsByName("collapse30"));
|
||||
}
|
||||
}
|
||||
100
Frontend/assets/scripts/tools/xslt.js
Normal file
100
Frontend/assets/scripts/tools/xslt.js
Normal file
@@ -0,0 +1,100 @@
|
||||
/**
|
||||
* The `processTooltip()` function is responsible for updating the display of the tooltip based on the selected version of the processor.
|
||||
* It shows or hides different sections of the tooltip based on the selected version.
|
||||
* It also handles the click event on the form and updates the tooltip accordingly.
|
||||
*
|
||||
* @function
|
||||
* @name processTooltip
|
||||
* @kind function
|
||||
*/
|
||||
function processTooltip() {
|
||||
|
||||
if (getProcessor() == "xalan" || getProcessor() == "libxml") {
|
||||
document.getElementById("tooltipFunctionInfo").innerText = "XSLT 1.0 functions";
|
||||
document.getElementById("processorTooltipInfo").innerText = "Supports XSLT 1.0";
|
||||
hideList(document.getElementsByName("collapse30"));
|
||||
} else {
|
||||
document.getElementById("tooltipFunctionInfo").innerText = "XSLT 1.0, 2.0 & 3.0 functions";
|
||||
document.getElementById("processorTooltipInfo").innerText = "Supports XSLT up to 3.0";
|
||||
showList(document.getElementsByName("collapse30"));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This function is executed after the page is loaded.
|
||||
*
|
||||
* @function
|
||||
* @name init
|
||||
* @kind function
|
||||
*/
|
||||
function init() {
|
||||
// Make sure that only plain text is pasted
|
||||
configurePastingInElement("xmlArea");
|
||||
configurePastingInElement("transformArea");
|
||||
|
||||
//Handle clicks in whole form and set info in tooltip
|
||||
setDefaultContent(document.getElementById("xmlArea"), 'Insert XML here');
|
||||
setDefaultContent(document.getElementById("transformArea"), 'Insert XSLT here');
|
||||
|
||||
// refreshTooltip();
|
||||
processTooltip();
|
||||
tool.addEventListener('click', event => {
|
||||
//Check if script was called from textarea or selector
|
||||
var targetID = event.target.getAttribute('id');
|
||||
if (targetID !== "processors" && targetID !== "xmlArea" && targetID !== "transformArea" && targetID !== "versions") {
|
||||
return;
|
||||
}
|
||||
|
||||
processTooltip();
|
||||
})
|
||||
|
||||
tool.addEventListener('change', event => {
|
||||
//Check if script was called from textarea or selector
|
||||
var targetID = event.target.getAttribute('id');
|
||||
if (targetID !== "processors") {
|
||||
return;
|
||||
}
|
||||
|
||||
processTooltip();
|
||||
|
||||
})
|
||||
|
||||
var triggerList = document.getElementsByClassName("collapseTrigger");
|
||||
for (i = 0; i < triggerList.length; i++) {
|
||||
|
||||
triggerList[i].addEventListener("click", function () {
|
||||
|
||||
var collapsible = this.parentElement;
|
||||
var collapsibleData = this.nextElementSibling;
|
||||
if (collapsibleData.style.maxHeight > "0px") {
|
||||
collapsibleData.style.maxHeight = "0px";
|
||||
|
||||
this.classList.toggle("active", false);
|
||||
if (!this.classList.contains("collapsibleMini")) {
|
||||
collapsible.classList.toggle("active", false);
|
||||
}
|
||||
|
||||
var subLists1 = collapsibleData.getElementsByClassName("content");
|
||||
var subLists2 = collapsibleData.getElementsByClassName("active");
|
||||
for (j = 0; j < subLists1.length; j++) {
|
||||
subLists1[j].style.maxHeight = "0px";
|
||||
}
|
||||
for (j = 0; j < subLists2.length; j++) {
|
||||
subLists2[j].classList.toggle("active", false);
|
||||
}
|
||||
} else {
|
||||
collapsibleData.style.maxHeight = (collapsibleData.scrollHeight) + "px";
|
||||
|
||||
this.classList.toggle("active", true);
|
||||
if (!this.classList.contains("collapsibleMini")) {
|
||||
collapsible.classList.toggle("active", true);
|
||||
} else {
|
||||
var parentContent = this.closest(".content");
|
||||
parentContent.style.maxHeight = (parentContent.scrollHeight + collapsibleData.scrollHeight) + "px";
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
@@ -4,9 +4,7 @@
|
||||
<head>
|
||||
<link rel="stylesheet" href="assets/css/frame.css">
|
||||
<script src="assets/scripts/common/jquery-3.6.0.slim.min.js"></script>
|
||||
<script src="assets/scripts/dyn_host.js"></script>
|
||||
<script src="assets/scripts/frame.js"></script>
|
||||
<!-- <link rel="stylesheet" href="common.css"> -->
|
||||
<link rel="shortcut icon" href="assets/images/favicon.ico" type="image/x-icon">
|
||||
<!-- Meta tags for SEO and SEM -->
|
||||
<title>Release11 Web Tools</title>
|
||||
@@ -22,9 +20,9 @@
|
||||
<div id="leftElements">
|
||||
<div id="logo"><a href="http://release11.com/"><img src="assets/images/logo_czarne.svg" alt="Release11"></a></div>
|
||||
<div id="menu">
|
||||
<a href="#" onclick="changeActiveTools('xmlTool', 'XML')" class="active">XML</a>
|
||||
<a href="#" onclick="changeActiveTools('jsonTool', 'JSON')">JSON</a>
|
||||
<a href="#" onclick="changeActiveTools('restTool', 'REST')">REST</a>
|
||||
<a href="#" onclick="changeActiveTools('XML')" class="active">XML</a>
|
||||
<a href="#" onclick="changeActiveTools('JSON')">JSON</a>
|
||||
<a href="#" onclick="changeActiveTools('REST')">REST</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -34,14 +32,12 @@
|
||||
<div id="content">
|
||||
<div id="leftBar">
|
||||
<ul id="toolList">
|
||||
<li class="dynamic restTool toolListRow" style="display: none;">
|
||||
<a id="rest-mock" href="http://tools.zipper.release11.com:8097/" target="iframe">REST Mock</a>
|
||||
</li>
|
||||
<li class="toolListRow xmlTool"><a href="./tools/xpath.html" target="iframe">XPath</a></li>
|
||||
<li class="toolListRow xmlTool"><a href="./tools/xslt.html" target="iframe">XSLT</a></li>
|
||||
<li class="toolListRow xmlTool"><a href="./tools/xsd.html" target="iframe">XSD</a></li>
|
||||
<li class="toolListRow xmlTool"><a href="tools/xmlFormatter.html" target="iframe">XML Formatter</a></li>
|
||||
<li class="toolListRow jsonTool" style="display: none;"><a href="tools/jsonFormatter.html" target="iframe">JSON Formatter</a></li>
|
||||
<li class="toolListRow restTool"><a href="#" onclick="changeTool('mock');">REST Mock</a></li>
|
||||
<li class="toolListRow xmlTool"><a href="#" onclick="changeTool('xpath');">XPath</a></li>
|
||||
<li class="toolListRow xmlTool"><a href="#" onclick="changeTool('xslt');">XSLT</a></li>
|
||||
<li class="toolListRow xmlTool"><a href="#" onclick="changeTool('xsd');">XSD</a></li>
|
||||
<li class="toolListRow xmlTool"><a href="#" onclick="changeTool('xmlform');">XML Formatter</a></li>
|
||||
<li class="toolListRow jsonTool"><a href="#" onclick="changeTool('jsonform');">JSON Formatter</a></li>
|
||||
</ul>
|
||||
<div id="copyright">
|
||||
Build: [:VERSION:]<br>
|
||||
@@ -53,7 +49,7 @@
|
||||
<a href="mailto:bugs@release11.com">Found a bug?</a>
|
||||
</div>
|
||||
</div>
|
||||
<iframe id="frame" name="iframe" src="./tools/xpath.html" frameborder="0"></iframe>
|
||||
<iframe id="iframe" name="iframe" frameborder="0"></iframe>
|
||||
</div>
|
||||
|
||||
</body>
|
||||
|
||||
@@ -12,8 +12,26 @@ server {
|
||||
add_header Cache-Control "private, no-store, no-cache, must-revalidate, proxy-revalidate, max-age=0";
|
||||
}
|
||||
|
||||
location /java/ {
|
||||
proxy_pass http://xmltools-backend:8081/;
|
||||
proxy_set_header Host $host;
|
||||
}
|
||||
|
||||
location /libxml/ {
|
||||
proxy_pass http://xmltools-libxml-backend/;
|
||||
proxy_set_header Host $host;
|
||||
}
|
||||
|
||||
location /mock/ {
|
||||
proxy_pass http://xmltools-mocked-services:8097/;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header Content-Type $http_content_type;
|
||||
}
|
||||
|
||||
#error_page 404 /404.html;
|
||||
|
||||
|
||||
|
||||
# redirect server error pages to the static page /50x.html
|
||||
#
|
||||
error_page 500 502 503 504 /50x.html;
|
||||
|
||||
@@ -7,10 +7,9 @@
|
||||
|
||||
<link rel="stylesheet" href="../assets/css/tools/r11form.css">
|
||||
<link rel="stylesheet" href="../assets/css/highlight.css">
|
||||
<script src="//cdnjs.cloudflare.com/ajax/libs/highlight.js/11.7.0/highlight.min.js"></script>
|
||||
<script src="../assets/scripts/tools/scripts.js"></script>
|
||||
<script src="../assets/scripts/common/hljs.min.js"></script>
|
||||
<script src="../assets/scripts/tools/jsonFormatter.js"></script>
|
||||
<script src="../assets/scripts/tools/highlight.js"></script>
|
||||
<script src="../assets/scripts/tools/json.js"></script>
|
||||
<script>hljs.highlightAll();</script>
|
||||
</head>
|
||||
|
||||
@@ -32,7 +31,7 @@
|
||||
<button class="action-button active" id="clearXMLButton" style="padding: 3px 10px;"
|
||||
onclick="clearJsonData()">Clear</button>
|
||||
<button class="action-button active" id="defaultXMLButton" style="padding: 3px 10px;"
|
||||
onclick="insertDefaultJson()">Insert default XML</button>
|
||||
onclick="insertDefaultJson()">Insert default JSON</button>
|
||||
</div>
|
||||
</div>
|
||||
<pre>
|
||||
@@ -61,175 +60,5 @@
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<script>
|
||||
const mergeHTMLPlugin = (function () {
|
||||
'use strict';
|
||||
|
||||
var originalStream;
|
||||
|
||||
/**
|
||||
* @param {string} value
|
||||
* @returns {string}
|
||||
*/
|
||||
function escapeHTML(value) {
|
||||
return value
|
||||
.replace(/&/g, '&')
|
||||
.replace(/</g, '<')
|
||||
.replace(/>/g, '>')
|
||||
.replace(/"/g, '"')
|
||||
.replace(/'/g, ''');
|
||||
}
|
||||
|
||||
/* plugin itself */
|
||||
|
||||
/** @type {HLJSPlugin} */
|
||||
const mergeHTMLPlugin = {
|
||||
// preserve the original HTML token stream
|
||||
"before:highlightElement": ({el}) => {
|
||||
originalStream = nodeStream(el);
|
||||
},
|
||||
// merge it afterwards with the highlighted token stream
|
||||
"after:highlightElement": ({el, result, text}) => {
|
||||
if (!originalStream.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
const resultNode = document.createElement('div');
|
||||
resultNode.innerHTML = result.value;
|
||||
result.value = mergeStreams(originalStream, nodeStream(resultNode), text);
|
||||
el.innerHTML = result.value;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {Node} node
|
||||
*/
|
||||
function tag(node) {
|
||||
return node.nodeName.toLowerCase();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Node} node
|
||||
*/
|
||||
function nodeStream(node) {
|
||||
/** @type Event[] */
|
||||
const result = [];
|
||||
(function _nodeStream(node, offset) {
|
||||
for (let child = node.firstChild; child; child = child.nextSibling) {
|
||||
if (child.nodeType === 3) {
|
||||
offset += child.nodeValue.length;
|
||||
} else if (child.nodeType === 1) {
|
||||
result.push({
|
||||
event: 'start',
|
||||
offset: offset,
|
||||
node: child
|
||||
});
|
||||
offset = _nodeStream(child, offset);
|
||||
|
||||
if (!tag(child).match(/br|hr|img|input/)) {
|
||||
result.push({
|
||||
event: 'stop',
|
||||
offset: offset,
|
||||
node: child
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
return offset;
|
||||
})(node, 0);
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {any} original - the original stream
|
||||
* @param {any} highlighted - stream of the highlighted source
|
||||
* @param {string} value - the original source itself
|
||||
*/
|
||||
function mergeStreams(original, highlighted, value) {
|
||||
let processed = 0;
|
||||
let result = '';
|
||||
const nodeStack = [];
|
||||
|
||||
function selectStream() {
|
||||
if (!original.length || !highlighted.length) {
|
||||
return original.length ? original : highlighted;
|
||||
}
|
||||
if (original[0].offset !== highlighted[0].offset) {
|
||||
return (original[0].offset < highlighted[0].offset) ? original : highlighted;
|
||||
}
|
||||
|
||||
return highlighted[0].event === 'start' ? original : highlighted;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Node} node
|
||||
*/
|
||||
function open(node) {
|
||||
/** @param {Attr} attr */
|
||||
function attributeString(attr) {
|
||||
return ' ' + attr.nodeName + '="' + escapeHTML(attr.value) + '"';
|
||||
}
|
||||
|
||||
// @ts-ignore
|
||||
result += '<' + tag(node) + [].map.call(node.attributes, attributeString).join('')
|
||||
+ '>';
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Node} node
|
||||
*/
|
||||
function close(node) {
|
||||
result += '</' + tag(node) + '>';
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Event} event
|
||||
*/
|
||||
function render(event) {
|
||||
(event.event === 'start' ? open : close)(event.node);
|
||||
}
|
||||
|
||||
while (original.length || highlighted.length) {
|
||||
let stream = selectStream();
|
||||
result += escapeHTML(value.substring(processed, stream[0].offset));
|
||||
processed = stream[0].offset;
|
||||
if (stream === original) {
|
||||
/*
|
||||
On any opening or closing tag of the original markup we first close
|
||||
the entire highlighted node stack, then render the original tag along
|
||||
with all the following original tags at the same offset and then
|
||||
reopen all the tags on the highlighted stack.
|
||||
*/
|
||||
nodeStack.reverse().forEach(close);
|
||||
do {
|
||||
render(stream.splice(0, 1)[0]);
|
||||
stream = selectStream();
|
||||
} while (stream === original && stream.length && stream[0].offset === processed);
|
||||
nodeStack.reverse().forEach(open);
|
||||
} else {
|
||||
if (stream[0].event === 'start') {
|
||||
nodeStack.push(stream[0].node);
|
||||
} else {
|
||||
nodeStack.pop();
|
||||
}
|
||||
render(stream.splice(0, 1)[0]);
|
||||
}
|
||||
}
|
||||
return result + escapeHTML(value.substr(processed));
|
||||
}
|
||||
|
||||
return mergeHTMLPlugin;
|
||||
|
||||
}());
|
||||
|
||||
hljs.addPlugin(mergeHTMLPlugin);
|
||||
|
||||
function init() {
|
||||
// Make sure that only plain text is pasted
|
||||
configurePastingInElement("jsonBlock");
|
||||
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -3,55 +3,54 @@
|
||||
<head>
|
||||
<title>R11 MockedServices</title>
|
||||
<meta charset="utf-8">
|
||||
<link rel="stylesheet" href="../css/fontello.css" type="text/css">
|
||||
<link rel="stylesheet" href="../css/main.css" type="text/css">
|
||||
<!-- <link rel="stylesheet" href="css/common.css" type="text/css"> -->
|
||||
<link rel="stylesheet" href="../css/common.css" type="text/css">
|
||||
<link rel="stylesheet" href="../assets/css/tools/mock/fontello.css" type="text/css">
|
||||
<link rel="stylesheet" href="../assets/css/tools/mock/main.css" type="text/css">
|
||||
<link rel="stylesheet" href="../assets/css/tools/mock/common.css" type="text/css">
|
||||
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
|
||||
<!-- <script src="../js/dyn_host.js"></script> -->
|
||||
</head>
|
||||
<body>
|
||||
<body onload="onLoad()">
|
||||
<div class="popup-flex hiddable-container">
|
||||
<div class="popup-body" id="popup-body">
|
||||
<div class="popup-button-close-container">
|
||||
<button type="button" class="popup-button-close"> X </button>
|
||||
</div>
|
||||
<div class="popup-header-table hiddable-popup-option" id="history-headers-table">
|
||||
<table id="header-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>
|
||||
Header Name
|
||||
</th>
|
||||
|
||||
<th>
|
||||
Header Value
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="header-history-table-body">
|
||||
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="popup-request-body hiddable-popup-option" id="history-request-body">
|
||||
<pre class="code-content" id="history-request-body-content"><code id="code-highlight-content"></code></pre>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="container">
|
||||
<div class="tool extended">
|
||||
<div class="tool-context">
|
||||
<div>
|
||||
<h1>MockedServices</h1>
|
||||
</div>
|
||||
<div>
|
||||
<label for="uuid-input" class="block-display">UUID</label>
|
||||
<div id="uuid-edit">
|
||||
<div id="uuid-edit-field" class="bordered-field disabled">
|
||||
<input id="uuid-input" disabled onfocusout="changeUUID(this);" value="UUID" />
|
||||
<button onclick="copyUUIDToClipboard();" class="uuid-inputField-icon modification-button flex-item btn-copy action-button">
|
||||
<span class="material-icons uuid-inputField-icon-span ">content_copy</span>
|
||||
</button>
|
||||
</div>
|
||||
<div id="editableBlock">
|
||||
<input type="checkbox" onchange="changeEditionOfUUID(this)" name="editable" id="editable" value="false"/>
|
||||
<label for="editable">Editable</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="hiddable" id="uuid-validation-strategy">
|
||||
<label><b>UUID generation strategy:</b></label>
|
||||
|
||||
<input type="radio" checked name="uuid-validation-type" value="new" id="generateNew"/>
|
||||
<label for="generateNew">Generate new UUID</label>
|
||||
|
||||
<input type="radio" name="uuid-validation-type" value="restore" id="restore"/>
|
||||
<label for="restore">Restore previous UUID</label>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div>
|
||||
<!-- h2 -->
|
||||
<div id="basicItemData" class="hiddable active"><h2>Your Message</h2></div>
|
||||
<div id="advancedItemData" class="hiddable"><h2>Messaged id: <span id="mockedMessageId">1</span></h2></div>
|
||||
<div><h2>Your Message</h2></div>
|
||||
|
||||
<!-- link -->
|
||||
<div>
|
||||
<label for="messageLink" class="block-display">Link</label>
|
||||
<div id="messageLink" class="bordered-field max-width with-padding disabled-background"><a class="hyperlink" href="www.google.com" target="_blank">www.google.com</a></div>
|
||||
<div id="messageLink" class="bordered-field max-width with-padding disabled-background tooltipped"><a class="hyperlink" href="www.google.com" target="_blank">www.google.com</a></div>
|
||||
<!-- <input id="messageLink" disabled class="bordered-field max-width with-padding" value="http://yourlink.com/r/api/mock/blablabla"> -->
|
||||
</div>
|
||||
<div class="display-space-between max-width">
|
||||
@@ -60,7 +59,7 @@
|
||||
<!-- status -->
|
||||
<div class="max-width small-vertical-margin">
|
||||
<label for="httpStatus">Http Status</label>
|
||||
<input id="httpStatus" type="number" class="bordered-field max-width data-field" value="200" list="httpStatusSuggestion"/>
|
||||
<input id="httpStatus" type="number" class="bordered-field max-width data-field tooltipped" value="200" list="httpStatusSuggestion"/>
|
||||
<datalist id="httpStatusSuggestion">
|
||||
<option value="200">
|
||||
<option value="300">
|
||||
@@ -69,12 +68,11 @@
|
||||
<option value="404">
|
||||
<option value="500">
|
||||
</datalist>
|
||||
|
||||
</div>
|
||||
<!-- content type -->
|
||||
<div class="max-width small-vertical-margin">
|
||||
<label for="typeSelector">Content Type</label>
|
||||
<input id="typeSelector" class="bordered-field max-width data-field" type="text" value="application/xml" list="contentTypes">
|
||||
<input id="typeSelector" class="bordered-field max-width data-field tooltipped" type="text" value="application/xml" list="contentTypes">
|
||||
<datalist id="contentTypes">
|
||||
<option value="application/xml">
|
||||
<option value="application/json">
|
||||
@@ -82,14 +80,14 @@
|
||||
</datalist>
|
||||
</div>
|
||||
</div>
|
||||
<div id="btnSave" class="small-margins half-width with-padding action-button" style="background-color: white; border: 0px;">
|
||||
<div id="btnSave" class="small-margins half-width with-padding action-button tooltipped" style="background-color: white; border: 0px;">
|
||||
<button id="btn-save" class="small-margins half-width with-padding action-button" style="width: 100%; height: 100%;">Save</button>
|
||||
</div>
|
||||
</div>
|
||||
<!-- body -->
|
||||
<div class="small-vertical-margin">
|
||||
<label for="bodyEditor">Body</label>
|
||||
<textarea id="bodyEditor" class="data-field bordered-field max-width with-padding height-300 vertically-resizeable"></textarea>
|
||||
<textarea id="bodyEditor" class="data-field bordered-field max-width with-padding height-300 vertically-resizeable tooltipped"></textarea>
|
||||
</div>
|
||||
<!-- show/hide -->
|
||||
<button id="optional" class="clickable-text highlight switch"><span class="toggleIndicator"></span> show/hide advanced settings</button>
|
||||
@@ -97,8 +95,8 @@
|
||||
<div id="advanced" class="max-width with-padding hiddable">
|
||||
<!-- tab menu -->
|
||||
<div class="tabmenu medium-vertical-margin">
|
||||
<button id="headersTab" class="tabitem active clickable-text big-font">Headers</button>
|
||||
<button id="historyTab" class="tabitem clickable-text big-font">History</button>
|
||||
<button id="headersTab" class="tabitem active clickable-text big-font tooltipped">Headers</button>
|
||||
<button id="historyTab" class="tabitem clickable-text big-font tooltipped">History</button>
|
||||
</div>
|
||||
<!-- container -->
|
||||
<div class="medium-vertical-margin">
|
||||
@@ -120,8 +118,8 @@
|
||||
</tr>
|
||||
</tbody>
|
||||
<tr>
|
||||
<td><input id="headerKeyInput" placeholder="name"></td>
|
||||
<td><input id="headerValueInput" placeholder="value"></td>
|
||||
<td><input id="headerKeyInput" class="tooltipped" placeholder="name"></td>
|
||||
<td><input id="headerValueInput" class="tooltipped" placeholder="value"></td>
|
||||
<td><button id="btn-newRow" class="modification-button btn-add"><i class="icon-plus"></i></button></td>
|
||||
</tr>
|
||||
</table>
|
||||
@@ -129,40 +127,19 @@
|
||||
<!-- history -->
|
||||
<div id="history" class="medium-vertical-margin tabcontent">
|
||||
<div class="block-display max-width">
|
||||
<button id="btn-history-filter" class="clickable-text highlight switch"><span class="toggleIndicator"></span> filter</button>
|
||||
<div id ="history-filter" class="display-space-between max-width small-vertical-margin hiddable">
|
||||
<div class="three-fourth-width display-space-evenly">
|
||||
<div class="block-display half-width with-padding">
|
||||
<label for="historyFrom" class="block-label">From</label>
|
||||
<input id="historyFrom" type="date" class="bordered-field max-width with-padding">
|
||||
<input id="historyTimeFrom" type="time" class="small-vertical-margin bordered-field max-width with-padding">
|
||||
</div>
|
||||
<div class="block-display half-width with-padding">
|
||||
<label for="historyTo" class="block-label">To</label>
|
||||
<input id="historyTo" type="date" class="bordered-field max-width with-padding">
|
||||
<input id="historyTimeTo" type="time" class="small-vertical-margin bordered-field max-width with-padding">
|
||||
</div>
|
||||
</div>
|
||||
<button id="btn-searchHistory" class="quater-width action-button active small-margins">Search</button>
|
||||
</div>
|
||||
<button type="button" class="refresh-button" onclick="refreshHistoryRecords();" >↻</button>
|
||||
|
||||
<div class="max-width centered-content large-vertical-margin overflowedTableContent">
|
||||
<table id="historyTable" class="table-default">
|
||||
<thead>
|
||||
<tr class="bottom-border">
|
||||
<th>Timestamp</th>
|
||||
<th>Type</th>
|
||||
<th>Method</th>
|
||||
<th>Request Body</th>
|
||||
<th>Headers</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<!-- <tr class="even">
|
||||
<td>2021-01-01T10:57:26</td>
|
||||
<td>Client request</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>2021-01-01T10:57:26</td>
|
||||
<td>Client request</td>
|
||||
</tr> -->
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
@@ -172,31 +149,6 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="selectMenuContent" class="tool-extention">
|
||||
<!-- header -->
|
||||
<div>
|
||||
<h2>Message List</h2>
|
||||
</div>
|
||||
<!-- tile list -->
|
||||
<div id="listItems">
|
||||
<!-- <div class="tile">
|
||||
<div class="content">
|
||||
<div class="display-space-between">
|
||||
<div class="centered-vertically">
|
||||
<p>Id: 2</p>
|
||||
<p>Status: 200</p>
|
||||
</div>
|
||||
<div>
|
||||
<button id="test1" class="modification-button btn-tile"><i class="icon-cancel"></i></button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div> -->
|
||||
</div>
|
||||
<div id="new-tile" class="max-width centered-content small-vertical-margin">
|
||||
<button id="btn-newtile" class="modification-button btn-addtile"><i class="icon-plus"></i></button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="tooltip-window lite">
|
||||
<div>
|
||||
@@ -216,36 +168,8 @@
|
||||
<p>To save message, the message must be changed!</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="large-vertical-margin">
|
||||
<div id="btn-newTileTip" class="tip">
|
||||
<h3>Add new message</h3>
|
||||
<p>This button adds new message.</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="large-vertical-margin">
|
||||
<div id="UUIDFieldTip" class="tip">
|
||||
<h3>UUID</h3>
|
||||
<p>UUID is an Unique ID that represents you in API. By UUID your messages is saved in database. You can change it to access your previous configuration of mocked messages</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="large-vertical-margin">
|
||||
<div id="UUIDValidationStrategyTip" class="tip">
|
||||
<h3>UUID Checking Strategy</h3>
|
||||
<p>When you provide invalid UUID you can choose what do with it. You can generate new UUID or restore previous.</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="large-vertical-margin">
|
||||
<div id="UUIDEditionTip" class="tip">
|
||||
<h3>UUID Edition</h3>
|
||||
<p>Unlocks you ability to edit UUID</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="large-vertical-margin">
|
||||
<div id="messagesTip" class="tip">
|
||||
<h3>Message</h3>
|
||||
<p>This is saved messages, with unique id.</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="large-vertical-margin">
|
||||
<div id="httpStatusTip" class="tip">
|
||||
@@ -287,22 +211,12 @@
|
||||
</div>
|
||||
</div>
|
||||
<div id="overlay"></div>
|
||||
<div id="modal-uuidChanged" class="modal">
|
||||
<div class="header">
|
||||
<div>Change UUID info<i class="r-exclamation"></i></div>
|
||||
<button onclick="window.location.reload();">×</button>
|
||||
</div>
|
||||
<div id="changeUUIDSuccess" class="body hiddable uuid-modal-body">Your message UUID has been changed successfully.</div>
|
||||
<div id="newUUID" class="body hiddable uuid-modal-body">You provided wrong UUID! <br> New UUID has been generated!</div>
|
||||
<div id="restoredUUID" class="body hiddable uuid-modal-body">You provided wrong UUID! <br> Old UUID has been restored!</div>
|
||||
<div id="noChgUUID" class="body hiddable uuid-modal-body">You doesn't provide any change to UUID!</div>
|
||||
</div>
|
||||
<div id="modal-confirm" class="modal">
|
||||
<div class="header">
|
||||
<div>Message saved<i class="r-exclamation"></i></div>
|
||||
<button>×</button>
|
||||
</div>
|
||||
<div class="body">Your message has been successfuly saved.<br>You might view it under the link.</div>
|
||||
<div class="body">Your message has been successfully saved.<br>You might view it under the link.</div>
|
||||
</div>
|
||||
<div id="modal-query" class="modal">
|
||||
<div class="header">
|
||||
@@ -311,16 +225,18 @@
|
||||
</div>
|
||||
<div class="body">You haven't saved your message!<br> Do you want to save it?</div>
|
||||
<div class="function">
|
||||
|
||||
<button type = "button" onclick = "updateData()" value = "Display">Save</button>
|
||||
|
||||
<button>No</button>
|
||||
</div>
|
||||
</div>
|
||||
<script type="text/javascript" src="../js/modal.js"></script>
|
||||
<script type="text/javascript" src="../js/uianimation.js"></script>
|
||||
<script type="text/javascript" src="../js/datatransfer.js"></script>
|
||||
<script type="text/javascript" src="../js/historyloader.js"></script>
|
||||
<script type="text/javascript" src="../js/fiddle.js"></script>
|
||||
<script type="text/javascript" src="../assets/scripts/tools/mock/modal.js"></script>
|
||||
<script type="text/javascript" src="../assets/scripts/tools/mock//uianimation.js"></script>
|
||||
<script type="text/javascript" src="../assets/scripts/tools/mock/datatransfer.js"></script>
|
||||
<script type="text/javascript" src="../assets/scripts/tools/mock/historyloader.js"></script>
|
||||
<script type="text/javascript" src="../assets/scripts/tools/mock/fiddle.js"></script>
|
||||
<script type="text/javascript" src="../assets/scripts/tools/mock/popup.js"></script>
|
||||
<script type="text/javascript" src="../assets/scripts/tools/xmlFormatter.js"></script>
|
||||
<script type="text/javascript" src="../assets/scripts/tools/highlight.js"></script>
|
||||
<script type="text/javascript" src="../assets/scripts/common/hljs.min.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -5,8 +5,9 @@
|
||||
<!-- <link rel="stylesheet" href="styles.css"> -->
|
||||
<link rel="stylesheet" href="../assets/css/tools/r11form.css">
|
||||
<link rel="stylesheet" href="../assets/css/highlight.css">
|
||||
<script src="//cdnjs.cloudflare.com/ajax/libs/highlight.js/11.7.0/highlight.min.js"></script>
|
||||
<script src="../assets/scripts/common/hljs.min.js"></script>
|
||||
<script src="../assets/scripts/tools/scripts.js"></script>
|
||||
<script src="../assets/scripts/tools/xmlFormatter.js"></script>
|
||||
<script src="../assets/scripts/tools/highlight.js"></script>
|
||||
<script>hljs.highlightAll();</script>
|
||||
|
||||
@@ -62,20 +63,6 @@
|
||||
|
||||
</div>
|
||||
|
||||
<script>
|
||||
function getProcessor() {
|
||||
return "libxml";
|
||||
}
|
||||
|
||||
function getVersion() {
|
||||
return "1.0"
|
||||
}
|
||||
|
||||
function init() {
|
||||
configurePastingInElement("xmlArea");
|
||||
}
|
||||
</script>
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
<link rel="stylesheet" href="../assets/css/tools/r11form.css">
|
||||
<link rel="stylesheet" href="../assets/css/highlight.css">
|
||||
<script src="../assets/scripts/common/hljs.min.js"></script>
|
||||
<script src="../assets/scripts/tools/xpath.js"></script>
|
||||
<script src="../assets/scripts/tools/scripts.js"></script>
|
||||
<script src="../assets/scripts/tools/highlight.js"></script>
|
||||
<script>hljs.highlightAll();</script>
|
||||
@@ -17115,156 +17116,6 @@
|
||||
|
||||
</div>
|
||||
|
||||
<script>
|
||||
function processVersionSelector() {
|
||||
var processor = getProcessor();
|
||||
var hideableOptions = document.getElementsByClassName("hideable");
|
||||
for (let i = 0; i < hideableOptions.length; i++) {
|
||||
hideableOptions[i].style = "display: none;";
|
||||
}
|
||||
if (processor == "xalan" || processor == "libxml") {
|
||||
var xalanOptions = document.getElementsByClassName("xalan");
|
||||
for (let i = 0; i < xalanOptions.length; i++) {
|
||||
xalanOptions[i].style = "";
|
||||
}
|
||||
document.getElementById("versions").selectedIndex = 0;
|
||||
}
|
||||
else {
|
||||
var saxonOptions = document.getElementsByClassName("saxon");
|
||||
for (let i = 0; i < saxonOptions.length; i++) {
|
||||
saxonOptions[i].style = "";
|
||||
}
|
||||
document.getElementById("versions").selectedIndex = 3;
|
||||
|
||||
}
|
||||
processTooltip();
|
||||
|
||||
}
|
||||
|
||||
function processTooltip() {
|
||||
var filter = "collapse" + getVersion();
|
||||
var collList;
|
||||
|
||||
|
||||
if (filter == "collapse3.0") {
|
||||
document.getElementById("tooltipFunctionInfo").innerText = "XPath 3.0 functions";
|
||||
hideList(document.getElementsByName("collapse10"));
|
||||
hideList(document.getElementsByName("collapse20"));
|
||||
showList(document.getElementsByName("collapse30"));
|
||||
hideList(document.getElementsByName("collapse31"));
|
||||
|
||||
} else if (filter == "collapse3.1") {
|
||||
document.getElementById("tooltipFunctionInfo").innerText = "XPath 3.1 functions";
|
||||
hideList(document.getElementsByName("collapse10"));
|
||||
hideList(document.getElementsByName("collapse20"));
|
||||
hideList(document.getElementsByName("collapse30"));
|
||||
showList(document.getElementsByName("collapse31"));
|
||||
} else if (filter == "collapse2.0") {
|
||||
document.getElementById("tooltipFunctionInfo").innerText = "XPath 2.0 functions";
|
||||
hideList(document.getElementsByName("collapse10"));
|
||||
showList(document.getElementsByName("collapse20"));
|
||||
hideList(document.getElementsByName("collapse30"));
|
||||
hideList(document.getElementsByName("collapse31"));
|
||||
} else {
|
||||
document.getElementById("tooltipFunctionInfo").innerText = "XPath 1.0 functions";
|
||||
showList(document.getElementsByName("collapse10"));
|
||||
hideList(document.getElementsByName("collapse20"));
|
||||
hideList(document.getElementsByName("collapse30"));
|
||||
hideList(document.getElementsByName("collapse31"));
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
var triggerList = document.getElementsByClassName("collapseTrigger");
|
||||
for (i = 0; i < triggerList.length; i++) {
|
||||
|
||||
triggerList[i].addEventListener("click", function () {
|
||||
var collapsible = this.parentElement;
|
||||
if (this.tagName == "A") {
|
||||
var collapsibleData = this.nextElementSibling;
|
||||
} else {
|
||||
var collapsibleData = this.parentElement.nextElementSibling;
|
||||
|
||||
}
|
||||
|
||||
|
||||
if (collapsibleData.style.maxHeight > "0px") {
|
||||
collapsibleData.style.maxHeight = "0px";
|
||||
|
||||
this.classList.toggle("active", false);
|
||||
if (!this.classList.contains("collapsibleMini")) {
|
||||
collapsible.classList.toggle("active", false);
|
||||
}
|
||||
|
||||
var subLists1 = collapsibleData.getElementsByClassName("content");
|
||||
var subLists2 = collapsibleData.getElementsByClassName("active");
|
||||
for (j = 0; j < subLists1.length; j++) {
|
||||
subLists1[j].style.maxHeight = "0px";
|
||||
}
|
||||
for (j = 0; j < subLists2.length; j++) {
|
||||
subLists2[j].classList.toggle("active", false);
|
||||
}
|
||||
} else {
|
||||
collapsibleData.style.maxHeight = (collapsibleData.scrollHeight) + "px";
|
||||
|
||||
this.classList.toggle("active", true);
|
||||
if (!this.classList.contains("collapsibleMini")) {
|
||||
collapsible.classList.toggle("active", true);
|
||||
} else {
|
||||
var parentContent = this.closest(".content");
|
||||
parentContent.style.maxHeight = (parentContent.scrollHeight + collapsibleData.scrollHeight) + "px";
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function init() {
|
||||
// Make sure that only plain text is pasted
|
||||
configurePastingInElement("xmlArea");
|
||||
configurePastingInElement("transformArea");
|
||||
|
||||
//Handle clicks in whole form and set info in tooltip
|
||||
setDefaultContent(document.getElementById("xmlArea"), 'Insert XML here');
|
||||
setDefaultContent(document.getElementById("transformArea"), 'Insert XPath expression here');
|
||||
|
||||
processVersionSelector();
|
||||
processTooltip();
|
||||
tool.addEventListener('change', event => {
|
||||
//Check if script was called from textarea or selector
|
||||
var targetID = event.target.getAttribute('id');
|
||||
if (targetID == "processors") {
|
||||
processVersionSelector();
|
||||
processTooltip();
|
||||
}
|
||||
else if (targetID == "versions") {
|
||||
processTooltip();
|
||||
}
|
||||
|
||||
|
||||
})
|
||||
tool.addEventListener('click', event => {
|
||||
//Check if script was called from textarea or selector
|
||||
var targetID = event.target.getAttribute('id');
|
||||
if (targetID !== "xmlArea" && targetID !== "transformArea") {
|
||||
return;
|
||||
}
|
||||
processTooltip();
|
||||
|
||||
})
|
||||
tool.addEventListener('change', event => {
|
||||
//Check if script was called from textarea or selector
|
||||
var targetID = event.target.getAttribute('id');
|
||||
if (targetID !== "xmlArea" && targetID !== "transformArea") {
|
||||
return;
|
||||
}
|
||||
processTooltip();
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
||||
@@ -6,6 +6,7 @@
|
||||
<link rel="stylesheet" href="../assets/css/tools/r11form.css">
|
||||
<link rel="stylesheet" href="../assets/css/highlight.css">
|
||||
<script src="../assets/scripts/common/hljs.min.js"></script>
|
||||
<script src="../assets/scripts/tools/xsd.js"></script>
|
||||
<script src="../assets/scripts/tools/scripts.js"></script>
|
||||
<script src="../assets/scripts/tools/highlight.js"></script>
|
||||
<script>hljs.highlightAll();</script>
|
||||
@@ -79,45 +80,6 @@
|
||||
|
||||
</div>
|
||||
|
||||
<script>
|
||||
function init() {
|
||||
// Make sure that only plain text is pasted
|
||||
configurePastingInElement("xmlArea");
|
||||
configurePastingInElement("transformArea");
|
||||
|
||||
//Handle clicks in whole form and set info in tooltip
|
||||
setDefaultContent(document.getElementById("xmlArea"), 'Insert XML here');
|
||||
setDefaultContent(document.getElementById("transformArea"), 'Insert XSD here');
|
||||
|
||||
// refreshTooltip();
|
||||
processTooltip();
|
||||
tool.addEventListener('click', event => {
|
||||
//Check if script was called from textarea or selector
|
||||
var targetID = event.target.getAttribute('id');
|
||||
if (targetID !== "processors" && targetID !== "xmlArea" && targetID !== "transformArea" && targetID !== "versions") {
|
||||
return;
|
||||
}
|
||||
|
||||
processTooltip();
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
function processTooltip() {
|
||||
|
||||
if (getProcessor() == "xalan") {
|
||||
document.getElementById("tooltipFunctionInfo").innerText = "XSLT 1.0 functions";
|
||||
document.getElementById("processorTooltipInfo").innerText = "Supports XSLT 1.0";
|
||||
hideList(document.getElementsByName("collapse30"));
|
||||
} else {
|
||||
document.getElementById("tooltipFunctionInfo").innerText = "XSLT 1.0, 2.0 & 3.0 functions";
|
||||
document.getElementById("processorTooltipInfo").innerText = "Supports XSLT up to 3.0";
|
||||
showList(document.getElementsByName("collapse30"));
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
||||
@@ -6,6 +6,7 @@
|
||||
<link rel="stylesheet" href="../assets/css/tools/r11form.css">
|
||||
<link rel="stylesheet" href="../assets/css/highlight.css">
|
||||
<script src="../assets/scripts/common/hljs.min.js"></script>
|
||||
<script src="../assets/scripts/tools/xslt.js"></script>
|
||||
<script src="../assets/scripts/tools/scripts.js"></script>
|
||||
<script src="../assets/scripts/tools/highlight.js"></script>
|
||||
<script>hljs.highlightAll();</script>
|
||||
@@ -1147,93 +1148,6 @@
|
||||
|
||||
</div>
|
||||
|
||||
<script>
|
||||
function processTooltip() {
|
||||
|
||||
if (getProcessor() == "xalan" || getProcessor() == "libxml") {
|
||||
document.getElementById("tooltipFunctionInfo").innerText = "XSLT 1.0 functions";
|
||||
document.getElementById("processorTooltipInfo").innerText = "Supports XSLT 1.0";
|
||||
hideList(document.getElementsByName("collapse30"));
|
||||
} else {
|
||||
document.getElementById("tooltipFunctionInfo").innerText = "XSLT 1.0, 2.0 & 3.0 functions";
|
||||
document.getElementById("processorTooltipInfo").innerText = "Supports XSLT up to 3.0";
|
||||
showList(document.getElementsByName("collapse30"));
|
||||
}
|
||||
}
|
||||
|
||||
var triggerList = document.getElementsByClassName("collapseTrigger");
|
||||
for (i = 0; i < triggerList.length; i++) {
|
||||
|
||||
triggerList[i].addEventListener("click", function () {
|
||||
|
||||
var collapsible = this.parentElement;
|
||||
var collapsibleData = this.nextElementSibling;
|
||||
if (collapsibleData.style.maxHeight > "0px") {
|
||||
collapsibleData.style.maxHeight = "0px";
|
||||
|
||||
this.classList.toggle("active", false);
|
||||
if (!this.classList.contains("collapsibleMini")) {
|
||||
collapsible.classList.toggle("active", false);
|
||||
}
|
||||
|
||||
var subLists1 = collapsibleData.getElementsByClassName("content");
|
||||
var subLists2 = collapsibleData.getElementsByClassName("active");
|
||||
for (j = 0; j < subLists1.length; j++) {
|
||||
subLists1[j].style.maxHeight = "0px";
|
||||
}
|
||||
for (j = 0; j < subLists2.length; j++) {
|
||||
subLists2[j].classList.toggle("active", false);
|
||||
}
|
||||
} else {
|
||||
collapsibleData.style.maxHeight = (collapsibleData.scrollHeight) + "px";
|
||||
|
||||
this.classList.toggle("active", true);
|
||||
if (!this.classList.contains("collapsibleMini")) {
|
||||
collapsible.classList.toggle("active", true);
|
||||
} else {
|
||||
var parentContent = this.closest(".content");
|
||||
parentContent.style.maxHeight = (parentContent.scrollHeight + collapsibleData.scrollHeight) + "px";
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function init() {
|
||||
// Make sure that only plain text is pasted
|
||||
configurePastingInElement("xmlArea");
|
||||
configurePastingInElement("transformArea");
|
||||
|
||||
//Handle clicks in whole form and set info in tooltip
|
||||
setDefaultContent(document.getElementById("xmlArea"), 'Insert XML here');
|
||||
setDefaultContent(document.getElementById("transformArea"), 'Insert XSLT here');
|
||||
|
||||
// refreshTooltip();
|
||||
processTooltip();
|
||||
tool.addEventListener('click', event => {
|
||||
//Check if script was called from textarea or selector
|
||||
var targetID = event.target.getAttribute('id');
|
||||
if (targetID !== "processors" && targetID !== "xmlArea" && targetID !== "transformArea" && targetID !== "versions") {
|
||||
return;
|
||||
}
|
||||
|
||||
processTooltip();
|
||||
})
|
||||
|
||||
tool.addEventListener('change', event => {
|
||||
//Check if script was called from textarea or selector
|
||||
var targetID = event.target.getAttribute('id');
|
||||
if (targetID !== "processors") {
|
||||
return;
|
||||
}
|
||||
|
||||
processTooltip();
|
||||
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
||||
6
Redis/Dockerfile
Normal file
6
Redis/Dockerfile
Normal file
@@ -0,0 +1,6 @@
|
||||
FROM redis:latest
|
||||
|
||||
EXPOSE 6379
|
||||
|
||||
# COPY redis.conf /usr/local/etc/redis/redis.conf
|
||||
CMD [ "redis-server", "--save ''", "--appendonly no" ]
|
||||
@@ -1,3 +1,3 @@
|
||||
url = "http://localhost:5000/minimize"
|
||||
url = "http://localhost/libxml/minimize"
|
||||
data = "@minimize.json"
|
||||
request = POST
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
url = "http://localhost:5000/prettify"
|
||||
url = "http://localhost:5000/libxml/prettify"
|
||||
data = "@prettify.json"
|
||||
request = POST
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#url = "localhost:8081/xpath"
|
||||
url = "localhost:5000/xpath"
|
||||
url = "localhost/java/xpath"
|
||||
#url = "localhost/libxml/xpath"
|
||||
request = "POST"
|
||||
data = "@data.json"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#url = "localhost:8081/xpath"
|
||||
url = "localhost:5000/xpath"
|
||||
url = "localhost/java/xpath"
|
||||
#url = "localhost/libxml/xpath"
|
||||
request = "POST"
|
||||
data = "@dataNS.json"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#url = "http://localhost:8081/xsd"
|
||||
url = "http://localhost:5000/xsd"
|
||||
url = "localhost/java/xsd"
|
||||
#url = "localhost/libxml/xsd"
|
||||
data = "@xsd.json"
|
||||
request = POST
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#url = "http://localhost:8081/xslt"
|
||||
url = "http://localhost:5000/xslt"
|
||||
url = "localhost/java/xslt"
|
||||
#url = "localhost/libxml/xslt"
|
||||
data = "@xslt.json"
|
||||
request = POST
|
||||
|
||||
10037
Tests/Release Tools Tests.postman_collection.json
Normal file
10037
Tests/Release Tools Tests.postman_collection.json
Normal file
File diff suppressed because it is too large
Load Diff
@@ -2,7 +2,8 @@ version: "3"
|
||||
|
||||
services:
|
||||
redis:
|
||||
image: 'redis'
|
||||
container_name: xmltools-redis
|
||||
build: ./Redis
|
||||
restart: "no"
|
||||
|
||||
xmltools-frontend:
|
||||
@@ -10,21 +11,21 @@ services:
|
||||
container_name: xmltools-frontend
|
||||
image: xmltools-frontend
|
||||
ports:
|
||||
- 8086:80
|
||||
- 80:80
|
||||
|
||||
xmltools-backend:
|
||||
build: ./Backend/tools-services
|
||||
container_name: xmltools-backend
|
||||
image: xmltools-backend
|
||||
ports:
|
||||
- 8081:8081
|
||||
- 8081:8081
|
||||
|
||||
xmltools-libxml-backend:
|
||||
build: ./Backend-libXML
|
||||
container_name: xmltools-libxml-backend
|
||||
image: xmltools-libxml-backend
|
||||
ports:
|
||||
- 8082:80
|
||||
- 8082:80
|
||||
|
||||
xmltools-mocked-services:
|
||||
build:
|
||||
@@ -38,6 +39,7 @@ services:
|
||||
- redis
|
||||
environment:
|
||||
SPRING_PROFILES_ACTIVE: DEV
|
||||
TZ: Europe/Warsaw
|
||||
|
||||
swagger:
|
||||
image: "swaggerapi/swagger-ui:latest"
|
||||
|
||||
Reference in New Issue
Block a user