diff --git a/src/main/java/ru/ulstu/fc/config/MvcConfiguration.java b/src/main/java/ru/ulstu/fc/config/MvcConfiguration.java index 809147e..32dd437 100644 --- a/src/main/java/ru/ulstu/fc/config/MvcConfiguration.java +++ b/src/main/java/ru/ulstu/fc/config/MvcConfiguration.java @@ -2,6 +2,7 @@ package ru.ulstu.fc.config; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.http.CacheControl; import org.springframework.web.servlet.LocaleResolver; import org.springframework.web.servlet.config.annotation.InterceptorRegistry; import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; @@ -10,6 +11,8 @@ import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; import org.springframework.web.servlet.i18n.CookieLocaleResolver; import org.springframework.web.servlet.i18n.LocaleChangeInterceptor; +import java.util.concurrent.TimeUnit; + @Configuration public class MvcConfiguration implements WebMvcConfigurer { @Override @@ -23,7 +26,11 @@ public class MvcConfiguration implements WebMvcConfigurer { public void addResourceHandlers(ResourceHandlerRegistry registry) { registry .addResourceHandler("/webjars/**") - .addResourceLocations("/webjars/"); + .addResourceLocations("/webjars/") + .setCacheControl(CacheControl.maxAge(60, TimeUnit.SECONDS) + .noTransform() + .mustRevalidate()); + ; } @Bean diff --git a/src/main/java/ru/ulstu/fc/config/SecurityConfiguration.java b/src/main/java/ru/ulstu/fc/config/SecurityConfiguration.java index be6b4ea..a07da1e 100644 --- a/src/main/java/ru/ulstu/fc/config/SecurityConfiguration.java +++ b/src/main/java/ru/ulstu/fc/config/SecurityConfiguration.java @@ -28,7 +28,7 @@ public class SecurityConfiguration { log.debug("Security enabled"); http - .headers(headers -> headers.frameOptions(HeadersConfigurer.FrameOptionsConfig::disable)) + .headers(headers -> headers.frameOptions(HeadersConfigurer.FrameOptionsConfig::sameOrigin)) .csrf(AbstractHttpConfigurer::disable) .authorizeHttpRequests(auth -> auth.requestMatchers("/").permitAll() diff --git a/src/main/java/ru/ulstu/fc/rule/controller/FuzzyRuleController.java b/src/main/java/ru/ulstu/fc/rule/controller/FuzzyRuleController.java index 7febe09..a19f79f 100644 --- a/src/main/java/ru/ulstu/fc/rule/controller/FuzzyRuleController.java +++ b/src/main/java/ru/ulstu/fc/rule/controller/FuzzyRuleController.java @@ -1,5 +1,6 @@ package ru.ulstu.fc.rule.controller; +import jakarta.servlet.http.HttpServletResponse; import jakarta.validation.Valid; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; @@ -8,16 +9,29 @@ import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.ResponseBody; import ru.ulstu.fc.rule.model.FuzzyRuleForm; +import ru.ulstu.fc.rule.model.FuzzyTerm; +import ru.ulstu.fc.rule.model.Variable; import ru.ulstu.fc.rule.service.FuzzyRuleService; +import ru.ulstu.fc.rule.service.FuzzyTermService; +import ru.ulstu.fc.rule.service.VariableService; + +import java.util.List; @Controller @RequestMapping("rule") public class FuzzyRuleController { - private final FuzzyRuleService ruleService; + private final FuzzyRuleService fuzzyRuleService; + private final VariableService variableService; + private final FuzzyTermService fuzzyTermService; - public FuzzyRuleController(FuzzyRuleService ruleService) { - this.ruleService = ruleService; + public FuzzyRuleController(FuzzyRuleService fuzzyRuleService, + VariableService variableService, + FuzzyTermService fuzzyTermService) { + this.fuzzyRuleService = fuzzyRuleService; + this.variableService = variableService; + this.fuzzyTermService = fuzzyTermService; } @GetMapping("/edit/{projectId}/{ruleId}") @@ -26,7 +40,7 @@ public class FuzzyRuleController { model.addAttribute("projectId", projectId); model.addAttribute("fuzzyRuleForm", (id != null && id != 0) - ? new FuzzyRuleForm(id, ruleService.getById(id)) + ? new FuzzyRuleForm(id, fuzzyRuleService.getById(id)) : new FuzzyRuleForm(id, projectId)); return "rule/edit"; } @@ -37,15 +51,32 @@ public class FuzzyRuleController { model.addAttribute("projectId", fuzzyRuleForm.getProjectId()); return "rule/edit"; } - ruleService.save(fuzzyRuleForm); + fuzzyRuleService.save(fuzzyRuleForm); return "redirect:/project/edit/" + fuzzyRuleForm.getProjectId(); } @PostMapping(value = "save", params = "delete") public String delete(FuzzyRuleForm fuzzyRuleForm) { if (fuzzyRuleForm != null && fuzzyRuleForm.getId() != null) { - ruleService.delete(fuzzyRuleForm); + fuzzyRuleService.delete(fuzzyRuleForm); } return "redirect:/project/edit/" + fuzzyRuleForm.getProjectId(); } + + @ResponseBody + @GetMapping("/getVariables/{projectId}") + public List getVariables(@PathVariable("projectId") Integer projectId, + final HttpServletResponse response) { + response.addHeader("Cache-Control", "max-age=60, must-revalidate, no-transform"); + //TODO: return DTO without terms + return variableService.getAllByProject(projectId); + } + + @ResponseBody + @GetMapping("/getFuzzyTerms/{variableId}") + public List getTerms(@PathVariable("variableId") Integer variableId, + final HttpServletResponse response) { + response.addHeader("Cache-Control", "max-age=60, must-revalidate, no-transform"); + return fuzzyTermService.getByVariableId(variableId); + } } diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index 05d3866..9274ab1 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -9,7 +9,6 @@ logging.level.javax.management.remote.rmi=off logging.level.java.rmi.server=off logging.level.org.apache.tomcat=INFO logging.level.org.apache.tomcat.util.net=WARN -extractor.custom-projects-dir= server.error.include-stacktrace=always server.error.include-exception=true server.error.include-message=always diff --git a/src/main/resources/public/js/fuzzyRule.js b/src/main/resources/public/js/fuzzyRule.js new file mode 100644 index 0000000..b675619 --- /dev/null +++ b/src/main/resources/public/js/fuzzyRule.js @@ -0,0 +1,253 @@ +// Rules parsing +// antecedent +function getAntecedent(rule) { + let withoutIf = rule.split('if'); + return withoutIf[1].trim().split('then')[0].trim(); +} + +// TODO: remove duplicate +function getAntecedentComponents(antecedent) { + return antecedent.split('and').map((i) => i.trim()); +} + +// consequent +function getConsequent(rule) { + let withoutIf = rule.split('if'); + return withoutIf[1].trim().split('then')[1].trim(); +} + +// TODO: remove duplicate +function getConsequentComponents(consequent) { + return consequent.split('and').map((i) => i.trim()); +} + +// common +function getVariable(variableComponents) { + return variableComponents.split('is')[0].trim(); +} + +function getVariableValue(variableComponents) { + return variableComponents.split('is')[1].trim(); +} + +// Rules creation + +/* exported MessageTypesEnum */ +let MessageTypesEnum = { + INFO: "info", + SUCCESS: "success", + WARNING: "warning", + DANGER: "danger" +}; +Object.freeze(MessageTypesEnum); + +function isEmpty(value) { + if (typeof value === "function") { + return false; + } + return (value == null || value.length === 0); +} + +/* exported showFeedbackMessage */ +function showFeedbackMessage(message, type) { + alert(type + ' ' + message); +} + +/* exported errorHandler */ +function errorHandler(response, callBack, errorCallBack) { + if (!isEmpty(response.error)) { + // TODO: add l10n + // showFeedbackMessage(response.error.code + ": " + response.error.message, MessageTypesEnum.DANGER); + if (!isEmpty(errorCallBack)) { + errorCallBack(response.data); + } + throw response.error.code + ": " + response.error.message + + " / Details: " + response.error.data; + } + if (!isEmpty(callBack)) { + callBack(response); + } +} + +/* exported getFromRest */ +function getFromRest(url, callBack) { + $.ajax({ + url: url, + method: 'get', + cache: true, + dataType: 'json', + success: function (response) { + errorHandler(response, callBack); + } + }); +} + +/* exported createRule */ +function createRule() { + let ruleString = "if "; + let inp = $('.selectpicker.inputVar').children(':selected').map(function () { + return $(this).text(); + }).get(); + let inpVal = $('.selectpicker.inputVal').children(':selected').map(function () { + return $(this).text(); + }).get(); + let out = $('.selectpicker.outVar').children(':selected').map(function () { + return $(this).text(); + }).get(); + let outVal = $('.selectpicker.outVal').children(':selected').map(function () { + return $(this).text(); + }).get(); + for (let i = 0; i < inp.length; i++) { + if (i > 0) { + ruleString += ' and '; + } + ruleString += inp[i] + " is " + inpVal[i]; + } + ruleString += " then "; + for (let i = 0; i < out.length; i++) { + if (i > 0) { + ruleString += ' and '; + } + ruleString += out[i] + " is " + outVal[i]; + } + $('#ruleContent').val(ruleString); +} + +/* exported fillSelect */ +function fillSelect(selectElement, values, selectedVal) { + $(selectElement).html(""); + $.each(values, function (key, value) { + $(selectElement).append($("