From d6b001861945cc60c9ac62badab6cde069f638d5 Mon Sep 17 00:00:00 2001 From: kozlovanadya Date: Sun, 18 Dec 2016 22:03:50 +0300 Subject: [PATCH 1/8] Homework 4 Only calculator --- .../g596/kozlova/task4/Calculator.java | 335 ++++++++++++++++++ 1 file changed, 335 insertions(+) create mode 100644 homework-g596-kozlova/src/main/java/ru/mipt/java2016/homework/g596/kozlova/task4/Calculator.java diff --git a/homework-g596-kozlova/src/main/java/ru/mipt/java2016/homework/g596/kozlova/task4/Calculator.java b/homework-g596-kozlova/src/main/java/ru/mipt/java2016/homework/g596/kozlova/task4/Calculator.java new file mode 100644 index 000000000..fa10071fb --- /dev/null +++ b/homework-g596-kozlova/src/main/java/ru/mipt/java2016/homework/g596/kozlova/task4/Calculator.java @@ -0,0 +1,335 @@ +package ru.mipt.java2016.homework.g596.kozlova.task4; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import ru.mipt.java2016.homework.base.task1.ParsingException; +import java.util.Map; +import java.util.HashMap; +import java.util.LinkedList; +import static java.lang.Character.digit; +import static java.lang.Character.isDigit; +import static java.lang.Character.isLetter; +import static java.lang.Character.isWhitespace; + +public class Calculator { + + public double calculate(String expression) throws ParsingException { + if (expression == null || isSplitedNumbers(expression) || expression.equals("")) { + throw new ParsingException("Bad expressions"); + } + Map variables = new HashMap<>(); + return calc(variables, expression); + } + + private double calc(Map variables, String expression) throws ParsingException { + LinkedList operations = new LinkedList<>(); + LinkedList numbers = new LinkedList<>(); + expression = expression.replaceAll("\\s", ""); + expression = "(" + expression + ")"; + double lastNumber = 0; + boolean readNumber = false; + boolean readVariable = false; + String variable = ""; + boolean isPoint = false; + boolean isSomeAfterPoint = false; + double afterPoint = 1; + boolean canBeUnary = true; + boolean needJump = false; + int jump = -1; + for (int i = 0; i < expression.length(); ++i) { + if (needJump) { + if (i < jump) { + continue; + } + needJump = false; + } + afterPoint /= 10; + char currentSymbol = expression.charAt(i); + if (isDigit(currentSymbol) || currentSymbol == '.' || isLetter(currentSymbol)) { + canBeUnary = false; + if (isDigit(currentSymbol)) { + readNumber = true; + if (isPoint) { + isSomeAfterPoint = true; + lastNumber += afterPoint * digit(currentSymbol, 10); + continue; + } + lastNumber = lastNumber * 10 + digit(currentSymbol, 10); + continue; + } + if (isLetter(currentSymbol)) { + readVariable = true; + variable += currentSymbol; + continue; + } + if (isPoint || !readNumber) { + throw new ParsingException("Bad expression"); + } + isPoint = true; + afterPoint = 1; + continue; + } + if (readNumber || !isPossibleSymbol(currentSymbol)) { + if ((isPoint && !isSomeAfterPoint) || !isPossibleSymbol(currentSymbol)) { + throw new ParsingException("Bad expression"); + } + numbers.push(lastNumber); + lastNumber = 0; + isPoint = false; + readNumber = false; + } + if (readVariable) { + if (!variables.containsKey(variable)) { + if (variable.equals("rnd")) { + int position = i; + if (expression.charAt(position) != '(' || position + 1 >= expression.length() + || expression.charAt(position + 1) != ')') { + throw new ParsingException("Bad expression"); + } + numbers.push(Math.random()); + variable = ""; + readVariable = false; + needJump = true; + jump = position + 2; + continue; + } + if (isFunctionWithOneParameter(variable)) { + StringBuilder firstParameter = new StringBuilder(); + int position = i; + if (expression.charAt(position) != '(') { + throw new ParsingException("Bad expression"); + } + int newBalance = 1; + position += 1; + while (newBalance != 0 && position < expression.length()) { + if (expression.charAt(position) == '(') { + newBalance += 1; + } + if (expression.charAt(position) == ')') { + newBalance -= 1; + } + if (newBalance != 0) { + firstParameter.append(expression.charAt(position)); + } + position += 1; + } + if (position == expression.length() && newBalance != 0) { + throw new ParsingException("Bad expression"); + } + numbers.push(calcFunctionWithOneParameter(variable, + calc(variables, firstParameter.toString()))); + variable = ""; + readVariable = false; + needJump = true; + jump = position; + continue; + } + if (isFunctionWithTwoParameters(variable)) { + StringBuilder firstParameter = new StringBuilder(); + StringBuilder secondParameter = new StringBuilder(); + boolean secondAlready = false; + int position = i; + if (expression.charAt(position) != '(') { + throw new ParsingException("Bad expression"); + } + int newBalance = 1; + position += 1; + while (newBalance != 0 && position < expression.length()) { + if (expression.charAt(position) == '(') { + newBalance += 1; + } + if (expression.charAt(position) == ')') { + newBalance -= 1; + } + if (newBalance != 0) { + if (newBalance == 1 && expression.charAt(position) == ',') { + secondAlready = true; + } else { + if (!secondAlready) { + firstParameter.append(expression.charAt(position)); + } else { + secondParameter.append(expression.charAt(position)); + } + } + } + position += 1; + } + if (position == expression.length() && newBalance != 0) { + throw new ParsingException("Bad expression"); + } + numbers.push(calcFunctionWithTwoParameters(variable, + calc(variables, firstParameter.toString()), + calc(variables, secondParameter.toString()))); + variable = ""; + readVariable = false; + needJump = true; + jump = position; + continue; + } + throw new ParsingException("Bad expression"); + } + numbers.push(Double.parseDouble(variables.get(variable))); + variable = ""; + readVariable = false; + } + if (canBeUnary && (currentSymbol == '+' || currentSymbol == '-')) { + if (currentSymbol == '+') { + currentSymbol = '&'; + } else { + currentSymbol = '@'; + } + } + if (currentSymbol == '(') { + operations.push(currentSymbol); + canBeUnary = true; + continue; + } + if (currentSymbol == ')') { + char last = '^'; + while (operations.size() != 0) { + last = operations.pop(); + if (last == '(') { + break; + } + calcSimpleOperation(last, numbers); + } + canBeUnary = false; + if (last != '(') { + throw new ParsingException("Bad expression"); + } + continue; + } + while (operations.size() != 0) { + char back = operations.pop(); + if (getPriorityOperation(back) >= getPriorityOperation(currentSymbol)) { + calcSimpleOperation(back, numbers); + } else { + operations.push(back); + break; + } + } + operations.push(currentSymbol); + canBeUnary = true; + } + if (numbers.size() != 1 || operations.size() != 0) { + throw new ParsingException("Bad expression"); + } + double answer = numbers.pop(); + return answer; + } + + private boolean isFunctionWithOneParameter(String f) { + return (f.equals("sin") || f.equals("cos") || f.equals("tg") || f.equals("sqrt") || + f.equals("abs") || f.equals("sign")); + } + + private boolean isFunctionWithTwoParameters(String f) { + return (f.equals("pow") || f.equals("log") || f.equals("max") || f.equals("min")); + } + + private void calcSimpleOperation(char symbol, LinkedList numbers) throws ParsingException { + if (isUnary(symbol)) { + if (numbers.size() < 1) { + throw new ParsingException("Not enough operands for unary operation"); + } + if (symbol == '@') { + double x = numbers.pop(); + numbers.push(-x); + } + return; + } + if (numbers.size() < 2) { + throw new ParsingException("Not enough operands for operation"); + } + double x = numbers.pop(); + double y = numbers.pop(); + if (symbol == '+') { + numbers.push(y + x); + } + if (symbol == '-') { + numbers.push(y - x); + } + if (symbol == '*') { + numbers.push(y * x); + } + if (symbol == '/') { + numbers.push(y / x); + } + } + + private Double calcFunctionWithOneParameter(String f, Double x) { + if (f.equals("sin")) { + return Math.sin(x); + } + if (f.equals("cos")) { + return Math.cos(x); + } + if (f.equals("tg")) { + return Math.tan(x); + } + if (f.equals("sqrt")) { + return Math.sqrt(x); + } + if (f.equals("abs")) { + return Math.abs(x); + } + if (f.equals("sign")) { + return Math.signum(x); + } + return 0.0; + } + + private double calcFunctionWithTwoParameters(String f, Double x, Double y) { + if (f.equals("pow")) { + return Math.pow(x, y); + } + if (f.equals("log")) { + return Math.log(x) / Math.log(y); + } + if (f.equals("max")) { + return Math.max(x, y); + } + if (f.equals("min")) { + return Math.min(x, y); + } + return 0.0; + } + + private int getPriorityOperation(char symbol) { + if (isUnary(symbol)) { + return 2; + } + if (symbol == '+' || symbol == '-') { + return 0; + } + if (symbol == '*' || symbol == '/') { + return 1; + } + return -1; + } + + private boolean isUnary(char symbol) { + return (symbol == '&' || symbol == '@'); // & := +, @ := - + } + + private boolean isPossibleSymbol(char symbol) { + return (symbol == '+' || symbol == '-' || symbol == '*' || symbol == '/' || symbol == '(' || symbol == ')'); + } + + private boolean isSplitedNumbers(String expression) { + Character lastSymbol = '^'; + for (int i = 0; i < expression.length(); ++i) { + if ((isDigit(lastSymbol) || lastSymbol == '.' || isLetter(lastSymbol)) && + (isDigit(expression.charAt(i)) || expression.charAt(i) == '.' || isLetter(expression.charAt(i))) && + !(isDigit(expression.charAt(i - 1)) || expression.charAt(i - 1) == '.' || + isLetter(expression.charAt(i - 1)))) { + return true; + } + if (!isWhitespace(expression.charAt(i))) { + lastSymbol = expression.charAt(i); + } + } + return false; + } +} + From a3334dbe899d986e8e4a63e856b7bb723d913780 Mon Sep 17 00:00:00 2001 From: kozlovanadya Date: Sun, 18 Dec 2016 22:10:22 +0300 Subject: [PATCH 2/8] Fixed code style --- .../java2016/homework/g596/kozlova/task4/Calculator.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/homework-g596-kozlova/src/main/java/ru/mipt/java2016/homework/g596/kozlova/task4/Calculator.java b/homework-g596-kozlova/src/main/java/ru/mipt/java2016/homework/g596/kozlova/task4/Calculator.java index fa10071fb..6dca3413b 100644 --- a/homework-g596-kozlova/src/main/java/ru/mipt/java2016/homework/g596/kozlova/task4/Calculator.java +++ b/homework-g596-kozlova/src/main/java/ru/mipt/java2016/homework/g596/kozlova/task4/Calculator.java @@ -1,11 +1,11 @@ package ru.mipt.java2016.homework.g596.kozlova.task4; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import ru.mipt.java2016.homework.base.task1.ParsingException; + import java.util.Map; import java.util.HashMap; import java.util.LinkedList; + import static java.lang.Character.digit; import static java.lang.Character.isDigit; import static java.lang.Character.isLetter; @@ -21,7 +21,8 @@ public double calculate(String expression) throws ParsingException { return calc(variables, expression); } - private double calc(Map variables, String expression) throws ParsingException { + private double calc(Map variables, String expression) + throws ParsingException { LinkedList operations = new LinkedList<>(); LinkedList numbers = new LinkedList<>(); expression = expression.replaceAll("\\s", ""); From 56e57f264419b77ecbfcebbaad334b9c07fdfb97 Mon Sep 17 00:00:00 2001 From: kozlovanadya Date: Sun, 18 Dec 2016 22:22:45 +0300 Subject: [PATCH 3/8] Fixed code style --- .../g596/kozlova/task4/Calculator.java | 121 ++++++++++-------- 1 file changed, 67 insertions(+), 54 deletions(-) diff --git a/homework-g596-kozlova/src/main/java/ru/mipt/java2016/homework/g596/kozlova/task4/Calculator.java b/homework-g596-kozlova/src/main/java/ru/mipt/java2016/homework/g596/kozlova/task4/Calculator.java index 6dca3413b..9df377c8a 100644 --- a/homework-g596-kozlova/src/main/java/ru/mipt/java2016/homework/g596/kozlova/task4/Calculator.java +++ b/homework-g596-kozlova/src/main/java/ru/mipt/java2016/homework/g596/kozlova/task4/Calculator.java @@ -95,30 +95,10 @@ private double calc(Map variables, String expression) continue; } if (isFunctionWithOneParameter(variable)) { - StringBuilder firstParameter = new StringBuilder(); - int position = i; - if (expression.charAt(position) != '(') { - throw new ParsingException("Bad expression"); - } - int newBalance = 1; - position += 1; - while (newBalance != 0 && position < expression.length()) { - if (expression.charAt(position) == '(') { - newBalance += 1; - } - if (expression.charAt(position) == ')') { - newBalance -= 1; - } - if (newBalance != 0) { - firstParameter.append(expression.charAt(position)); - } - position += 1; - } - if (position == expression.length() && newBalance != 0) { - throw new ParsingException("Bad expression"); - } + StringBuilder parameter = new StringBuilder(); + int position = actionsIfOneParameter(expression, i, parameter); numbers.push(calcFunctionWithOneParameter(variable, - calc(variables, firstParameter.toString()))); + calc(variables, parameter.toString()))); variable = ""; readVariable = false; needJump = true; @@ -128,36 +108,7 @@ private double calc(Map variables, String expression) if (isFunctionWithTwoParameters(variable)) { StringBuilder firstParameter = new StringBuilder(); StringBuilder secondParameter = new StringBuilder(); - boolean secondAlready = false; - int position = i; - if (expression.charAt(position) != '(') { - throw new ParsingException("Bad expression"); - } - int newBalance = 1; - position += 1; - while (newBalance != 0 && position < expression.length()) { - if (expression.charAt(position) == '(') { - newBalance += 1; - } - if (expression.charAt(position) == ')') { - newBalance -= 1; - } - if (newBalance != 0) { - if (newBalance == 1 && expression.charAt(position) == ',') { - secondAlready = true; - } else { - if (!secondAlready) { - firstParameter.append(expression.charAt(position)); - } else { - secondParameter.append(expression.charAt(position)); - } - } - } - position += 1; - } - if (position == expression.length() && newBalance != 0) { - throw new ParsingException("Bad expression"); - } + int position = actionsIfTwoParameters(expression, i, firstParameter, secondParameter); numbers.push(calcFunctionWithTwoParameters(variable, calc(variables, firstParameter.toString()), calc(variables, secondParameter.toString()))); @@ -317,11 +268,73 @@ private boolean isPossibleSymbol(char symbol) { return (symbol == '+' || symbol == '-' || symbol == '*' || symbol == '/' || symbol == '(' || symbol == ')'); } + int actionsIfOneParameter(String expression, int i, StringBuilder parameter) + throws ParsingException { + int position = i; + if (expression.charAt(position) != '(') { + throw new ParsingException("Bad expression"); + } + int newBalance = 1; + position += 1; + while (newBalance != 0 && position < expression.length()) { + if (expression.charAt(position) == '(') { + newBalance += 1; + } + if (expression.charAt(position) == ')') { + newBalance -= 1; + } + if (newBalance != 0) { + parameter.append(expression.charAt(position)); + } + position += 1; + } + if (position == expression.length() && newBalance != 0) { + throw new ParsingException("Bad expression"); + } + return position; + } + + int actionsIfTwoParameters(String expression, int i, StringBuilder firstParameter, StringBuilder secondParameter) + throws ParsingException { + int position = i; + boolean secondAlready = false; + if (expression.charAt(position) != '(') { + throw new ParsingException("Bad expression"); + } + int newBalance = 1; + position += 1; + while (newBalance != 0 && position < expression.length()) { + if (expression.charAt(position) == '(') { + newBalance += 1; + } + if (expression.charAt(position) == ')') { + newBalance -= 1; + } + if (newBalance != 0) { + if (newBalance == 1 && expression.charAt(position) == ',') { + secondAlready = true; + } else { + if (!secondAlready) { + firstParameter.append(expression.charAt(position)); + } else { + secondParameter.append(expression.charAt(position)); + } + } + } + position += 1; + } + if (position == expression.length() && newBalance != 0) { + throw new ParsingException("Bad expression"); + } + return position; + } + private boolean isSplitedNumbers(String expression) { Character lastSymbol = '^'; for (int i = 0; i < expression.length(); ++i) { if ((isDigit(lastSymbol) || lastSymbol == '.' || isLetter(lastSymbol)) && - (isDigit(expression.charAt(i)) || expression.charAt(i) == '.' || isLetter(expression.charAt(i))) && + (isDigit(expression.charAt(i)) || expression.charAt(i) == '.' || + isLetter(expression.charAt(i))) && !(isDigit(expression.charAt(i - 1)) || expression.charAt(i - 1) == '.' || isLetter(expression.charAt(i - 1)))) { return true; From ebaeb29126182ff3911af0de875fd49b19aab51e Mon Sep 17 00:00:00 2001 From: kozlovanadya Date: Mon, 19 Dec 2016 14:15:28 +0300 Subject: [PATCH 4/8] g596.kozlova.task4 --- homework-g596-kozlova/pom.xml | 46 +++++ .../g596/kozlova/task4/Application.java | 33 +++ .../g596/kozlova/task4/BillingDao.java | 191 ++++++++++++++++++ .../task4/BillingDatabaseConfiguration.java | 26 +++ .../g596/kozlova/task4/BillingUser.java | 45 +++++ .../g596/kozlova/task4/Calculator.java | 24 ++- .../kozlova/task4/CalculatorController.java | 129 ++++++++++++ .../homework/g596/kozlova/task4/Function.java | 39 ++++ .../task4/SecurityServiceConfiguration.java | 57 ++++++ .../homework/g596/kozlova/task4/Variable.java | 37 ++++ 10 files changed, 622 insertions(+), 5 deletions(-) create mode 100644 homework-g596-kozlova/src/main/java/ru/mipt/java2016/homework/g596/kozlova/task4/Application.java create mode 100644 homework-g596-kozlova/src/main/java/ru/mipt/java2016/homework/g596/kozlova/task4/BillingDao.java create mode 100644 homework-g596-kozlova/src/main/java/ru/mipt/java2016/homework/g596/kozlova/task4/BillingDatabaseConfiguration.java create mode 100644 homework-g596-kozlova/src/main/java/ru/mipt/java2016/homework/g596/kozlova/task4/BillingUser.java create mode 100644 homework-g596-kozlova/src/main/java/ru/mipt/java2016/homework/g596/kozlova/task4/CalculatorController.java create mode 100644 homework-g596-kozlova/src/main/java/ru/mipt/java2016/homework/g596/kozlova/task4/Function.java create mode 100644 homework-g596-kozlova/src/main/java/ru/mipt/java2016/homework/g596/kozlova/task4/SecurityServiceConfiguration.java create mode 100644 homework-g596-kozlova/src/main/java/ru/mipt/java2016/homework/g596/kozlova/task4/Variable.java diff --git a/homework-g596-kozlova/pom.xml b/homework-g596-kozlova/pom.xml index f8aae5c72..e87beabfc 100644 --- a/homework-g596-kozlova/pom.xml +++ b/homework-g596-kozlova/pom.xml @@ -10,6 +10,12 @@ 4.0.0 homework-g596-kozlova + pom + 1.0.0 + + + 1.4.2.RELEASE + @@ -27,6 +33,46 @@ homework-tests 1.0.0 + + net.sourceforge.jeval + jeval + 0.9.4 + + + org.springframework + spring-context + 4.1.6.RELEASE + + + org.springframework.boot + spring-boot-starter-web + ${spring.boot.version} + + + org.springframework.boot + spring-boot-starter-jdbc + ${spring.boot.version} + + + org.springframework.boot + spring-boot-starter-security + ${spring.boot.version} + + + com.zaxxer + HikariCP + 2.5.1 + + + com.h2database + h2 + 1.4.193 + + + ru.mipt.java2016 + homework-tests + 1.0.0 + \ No newline at end of file diff --git a/homework-g596-kozlova/src/main/java/ru/mipt/java2016/homework/g596/kozlova/task4/Application.java b/homework-g596-kozlova/src/main/java/ru/mipt/java2016/homework/g596/kozlova/task4/Application.java new file mode 100644 index 000000000..4e2b7aa69 --- /dev/null +++ b/homework-g596-kozlova/src/main/java/ru/mipt/java2016/homework/g596/kozlova/task4/Application.java @@ -0,0 +1,33 @@ +package ru.mipt.java2016.homework.g596.kozlova.task4; + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.Banner; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.boot.context.embedded.EmbeddedServletContainerCustomizer; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; + +@EnableAutoConfiguration +@Configuration +@ComponentScan(basePackageClasses = Application.class) +public class Application { + + @Bean + public Calculator calculator() { + return Calculator.INSTANCE; + } + + @Bean + public EmbeddedServletContainerCustomizer customizer( + @Value("${ru.mipt.java2016.homework.g596.kozlova.task4.httpPort:9001}") int port) { + return container -> container.setPort(port); + } + + public static void main(String[] args) { + SpringApplication application = new SpringApplication(Application.class); + application.setBannerMode(Banner.Mode.OFF); + application.run(args); + } +} \ No newline at end of file diff --git a/homework-g596-kozlova/src/main/java/ru/mipt/java2016/homework/g596/kozlova/task4/BillingDao.java b/homework-g596-kozlova/src/main/java/ru/mipt/java2016/homework/g596/kozlova/task4/BillingDao.java new file mode 100644 index 000000000..8ef90c3b2 --- /dev/null +++ b/homework-g596-kozlova/src/main/java/ru/mipt/java2016/homework/g596/kozlova/task4/BillingDao.java @@ -0,0 +1,191 @@ +package ru.mipt.java2016.homework.g596.kozlova.task4; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.dao.EmptyResultDataAccessException; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.jdbc.core.RowMapper; +import org.springframework.stereotype.Repository; +import ru.mipt.java2016.homework.base.task1.ParsingException; + +import javax.annotation.PostConstruct; +import javax.sql.DataSource; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Array; +import java.util.Map; +import java.util.HashMap; + +@Repository +public class BillingDao { + + private static final Logger LOG = LoggerFactory.getLogger(BillingDao.class); + + @Autowired + private DataSource dataSource; + private JdbcTemplate jdbcTemplate; + + @PostConstruct + public void postConstruct() { + jdbcTemplate = new JdbcTemplate(dataSource, false); + LOG.trace("Initializing"); + jdbcTemplate.execute("CREATE SCHEMA IF NOT EXISTS billing"); + jdbcTemplate.execute("CREATE TABLE IF NOT EXISTS billing.users " + + "(username VARCHAR PRIMARY KEY, password VARCHAR, enabled BOOLEAN)"); + jdbcTemplate.execute("CREATE TABLE IF NOT EXISTS billing.variables " + + "(username VARCHAR, name VARCHAR, value DOUBLE, expression VARCHAR)"); + createNewUser("userName", "password", true); + } + + public boolean createNewUser(String userName, String password, boolean enabled) { + try { + loadUser(userName); + return false; + } catch (EmptyResultDataAccessException e) { + jdbcTemplate.update("INSERT INTO billing.users VALUES (?, ?, ?)", + new Object[]{userName, password, enabled}); + return true; + } + } + + public BillingUser loadUser(String userName) throws EmptyResultDataAccessException { + LOG.trace("Querying for user " + userName); + return jdbcTemplate.queryForObject( + "SELECT username, password, enabled FROM billing.users WHERE username = ?", + new Object[]{userName}, + new RowMapper() { + @Override + public BillingUser mapRow(ResultSet resultSet, int NumberOfRow) throws SQLException { + return new BillingUser( + resultSet.getString("userName"), + resultSet.getString("password"), + resultSet.getBoolean("enabled") + ); + } + } + ); + } + + public Variable getVariable(String userName, String variable) { + return jdbcTemplate.queryForObject( + "SELECT userName, name, value, expression FROM billing.variables WHERE userName = ? AND name = ?", + new Object[]{userName, variable}, + new RowMapper() { + @Override + public Variable mapRow(ResultSet resultSet, int numberOfRow) throws SQLException { + return new Variable( + resultSet.getString("userName"), + resultSet.getString("name"), + resultSet.getDouble("value"), + resultSet.getString("expression")); + } + } + ); + } + + public Map getVariables(String userName) { + try { + return jdbcTemplate.queryForObject( + "SELECT userName, name, value, expression FROM billing.variables WHERE userName = ?", + new Object[]{userName}, + new RowMapper>() { + @Override + public Map mapRow(ResultSet resultSet, int numberOfRow) throws SQLException { + Map map = new HashMap<>(); + while (!resultSet.next()) { + map.put(resultSet.getString("name"), Double.toString(resultSet.getDouble("value"))); + } + return map; + } + } + ); + } catch (EmptyResultDataAccessException e) { + return new HashMap<>(); + } + } + + public void deleteVariable(String userName, String name) throws ParsingException { + try { + getVariable(userName, name); + jdbcTemplate.update("DELETE FROM billing.variables WHERE userName = ? AND name = ?", + new Object[]{userName, name}); + } catch (EmptyResultDataAccessException e) { + throw new ParsingException("Can't delete"); + } + } + + public void addVariable(String userName, String name, Double value, String expression) throws ParsingException { + try { + getVariable(userName, name); + jdbcTemplate.update("DELETE FROM billing.variables WHERE userName = ? AND name = ?", + new Object[]{userName, name}); + jdbcTemplate.update("INSERT INTO billing.variables VALUES (?, ?, ?, ?)", + new Object[]{userName, name, value, expression}); + } catch (EmptyResultDataAccessException e) { + jdbcTemplate.update("INSERT INTO billing.variables VALUES (?, ?, ?, ?)", + new Object[]{userName, name, value, expression}); + } + } + + public Function getFunction(String userName, String function) { + return jdbcTemplate.queryForObject( + "SELECT userName, name, arguments, expression FROM billing.functions WHERE userName = ? AND name = ?", + new Object[]{userName, function}, + new RowMapper() { + @Override + public Function mapRow(ResultSet resultSet, int numberOfRow) throws SQLException { + return new Function( + resultSet.getString("userName"), + resultSet.getString("name"), + resultSet.getArray("arguments"), + resultSet.getString("expression")); + } + } + ); + } + + public Map getFunctions(String userName) { + try { + return jdbcTemplate.queryForObject( + "SELECT userName, name, arguments, expression FROM billing.functions WHERE userName = ?", + new Object[]{userName}, + new RowMapper>() { + @Override + public Map mapRow(ResultSet resultSet, int numberOfRow) throws SQLException { + Map map = new HashMap<>(); + while (!resultSet.next()) { + map.put(resultSet.getString("name"), Double.toString(resultSet.getDouble("arguments"))); + } + return map; + } + } + ); + } catch (EmptyResultDataAccessException e) { + return new HashMap<>(); + } + } + + public void deleteFunction(String userName, String name) throws ParsingException { + try { + getFunction(userName, name); + jdbcTemplate.update("DELETE FROM billing.functions WHERE userName = ? AND name = ?", + new Object[]{userName, name}); + } catch (EmptyResultDataAccessException e) { + throw new ParsingException("Can't delete"); + } + } + + public void addFunction(String userName, String name, Array arguments, String expression) throws ParsingException { + try { + getVariable(userName, name); + jdbcTemplate.update("DELETE FROM billing.functions WHERE userName = ? AND name = ?", + new Object[]{userName, name}); + jdbcTemplate.update("INSERT INTO billing.functions arguments (?, ?, ?, ?)", + new Object[]{userName, name, arguments, expression}); + } catch (EmptyResultDataAccessException e) { + jdbcTemplate.update("INSERT INTO billing.functions FUNCTION (?, ?, ?, ?)", + new Object[]{userName, name, arguments, expression}); + } + } +} \ No newline at end of file diff --git a/homework-g596-kozlova/src/main/java/ru/mipt/java2016/homework/g596/kozlova/task4/BillingDatabaseConfiguration.java b/homework-g596-kozlova/src/main/java/ru/mipt/java2016/homework/g596/kozlova/task4/BillingDatabaseConfiguration.java new file mode 100644 index 000000000..8f25a70af --- /dev/null +++ b/homework-g596-kozlova/src/main/java/ru/mipt/java2016/homework/g596/kozlova/task4/BillingDatabaseConfiguration.java @@ -0,0 +1,26 @@ +package ru.mipt.java2016.homework.g596.kozlova.task4; + +import com.zaxxer.hikari.HikariConfig; +import com.zaxxer.hikari.HikariDataSource; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import javax.sql.DataSource; + +@Configuration +public class BillingDatabaseConfiguration { + @Bean + public DataSource billingDataSource( + @Value("${ru.mipt.java2016.homework.g596.kozlova.task4.jdbcUrl}") String jdbcUrlAdress, + @Value("${ru.mipt.java2016.homework.g596.kozlova.task4.userName:}") String userName, + @Value("${ru.mipt.java2016.homework.g596.kozlova.task4.password:}") String password + ) { + HikariConfig config = new HikariConfig(); + config.setDriverClassName(org.h2.Driver.class.getName()); + config.setJdbcUrl(jdbcUrlAdress); + config.setUsername(userName); + config.setPassword(password); + return new HikariDataSource(config); + } +} \ No newline at end of file diff --git a/homework-g596-kozlova/src/main/java/ru/mipt/java2016/homework/g596/kozlova/task4/BillingUser.java b/homework-g596-kozlova/src/main/java/ru/mipt/java2016/homework/g596/kozlova/task4/BillingUser.java new file mode 100644 index 000000000..d63a876b4 --- /dev/null +++ b/homework-g596-kozlova/src/main/java/ru/mipt/java2016/homework/g596/kozlova/task4/BillingUser.java @@ -0,0 +1,45 @@ +package ru.mipt.java2016.homework.g596.kozlova.task4; + +public class BillingUser { + + private final String userName; + private final String password; + private final boolean enabled; + + public BillingUser(String u, String p, boolean e) { + if (u.equals(null) || p.equals(null)) { + throw new IllegalArgumentException("Incorrect data"); + } + userName = u; + password = p; + enabled = e; + } + + public String getUserName() { + return userName; + } + + public String getPassword() { + return password; + } + + @Override + public String toString() { + return "BillingUser{ userName='" + userName + "\', password='" + password + '\'' + ", enabled=" + enabled + "}"; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null || getClass() != obj.getClass()) { + return false; + } + BillingUser that = (BillingUser) obj; + if (!userName.equals(that.userName) || !password.equals(that.password) || enabled != that.enabled) { + return false; + } + return true; + } + } \ No newline at end of file diff --git a/homework-g596-kozlova/src/main/java/ru/mipt/java2016/homework/g596/kozlova/task4/Calculator.java b/homework-g596-kozlova/src/main/java/ru/mipt/java2016/homework/g596/kozlova/task4/Calculator.java index 9df377c8a..252fb19bc 100644 --- a/homework-g596-kozlova/src/main/java/ru/mipt/java2016/homework/g596/kozlova/task4/Calculator.java +++ b/homework-g596-kozlova/src/main/java/ru/mipt/java2016/homework/g596/kozlova/task4/Calculator.java @@ -1,9 +1,10 @@ package ru.mipt.java2016.homework.g596.kozlova.task4; import ru.mipt.java2016.homework.base.task1.ParsingException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import java.util.Map; -import java.util.HashMap; import java.util.LinkedList; import static java.lang.Character.digit; @@ -13,11 +14,14 @@ public class Calculator { - public double calculate(String expression) throws ParsingException { + private static final Logger LOG = LoggerFactory.getLogger(Calculator.class); + + public static final Calculator INSTANCE = new Calculator(); + + public double calculate(Map variables, String expression) throws ParsingException { if (expression == null || isSplitedNumbers(expression) || expression.equals("")) { throw new ParsingException("Bad expressions"); } - Map variables = new HashMap<>(); return calc(variables, expression); } @@ -109,6 +113,7 @@ private double calc(Map variables, String expression) StringBuilder firstParameter = new StringBuilder(); StringBuilder secondParameter = new StringBuilder(); int position = actionsIfTwoParameters(expression, i, firstParameter, secondParameter); + LOG.debug(firstParameter + " " + secondParameter); numbers.push(calcFunctionWithTwoParameters(variable, calc(variables, firstParameter.toString()), calc(variables, secondParameter.toString()))); @@ -147,6 +152,7 @@ private double calc(Map variables, String expression) } canBeUnary = false; if (last != '(') { + LOG.debug(Integer.toString(i)); throw new ParsingException("Bad expression"); } continue; @@ -167,12 +173,13 @@ private double calc(Map variables, String expression) throw new ParsingException("Bad expression"); } double answer = numbers.pop(); + LOG.debug(Double.toString(answer) + " " + expression); return answer; } private boolean isFunctionWithOneParameter(String f) { - return (f.equals("sin") || f.equals("cos") || f.equals("tg") || f.equals("sqrt") || - f.equals("abs") || f.equals("sign")); + return f.equals("sin") || f.equals("cos") || f.equals("tg") || f.equals("sqrt") || + f.equals("abs") || f.equals("sign") || f.equals("log2"); } private boolean isFunctionWithTwoParameters(String f) { @@ -228,6 +235,9 @@ private Double calcFunctionWithOneParameter(String f, Double x) { if (f.equals("sign")) { return Math.signum(x); } + if (f.equals("log2")) { + return Math.log(x) / Math.log(2); + } return 0.0; } @@ -345,5 +355,9 @@ private boolean isSplitedNumbers(String expression) { } return false; } + + public boolean isPredefinedFunction(String f) { + return isFunctionWithOneParameter(f) || isFunctionWithTwoParameters(f) || f.equals("rnd"); + } } diff --git a/homework-g596-kozlova/src/main/java/ru/mipt/java2016/homework/g596/kozlova/task4/CalculatorController.java b/homework-g596-kozlova/src/main/java/ru/mipt/java2016/homework/g596/kozlova/task4/CalculatorController.java new file mode 100644 index 000000000..be1e4dcc5 --- /dev/null +++ b/homework-g596-kozlova/src/main/java/ru/mipt/java2016/homework/g596/kozlova/task4/CalculatorController.java @@ -0,0 +1,129 @@ +package ru.mipt.java2016.homework.g596.kozlova.task4; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.core.Authentication; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RequestBody; +import ru.mipt.java2016.homework.base.task1.ParsingException; + +import java.util.Map; +import java.sql.Array; + +import static java.lang.Character.isDigit; +import static java.lang.Character.isLetter; + +@RestController +public class CalculatorController { + + private static final Logger LOG = LoggerFactory.getLogger(CalculatorController.class); + + @Autowired + private Calculator calculator; + @Autowired + private BillingDao billingDao; + + @RequestMapping(path = "/variable/{variableName}", method = RequestMethod.GET, produces = "text/plain") + public String getVariable(Authentication authentication, @PathVariable String variableName) + throws ParsingException { + return billingDao.getVariable(authentication.getName(), variableName).getExpression(); + } + + @RequestMapping(path = "/variable/{variableName}", method = RequestMethod.PUT, consumes = "text/plain", + produces = "text/plain") + public void putVariable(Authentication authentication, @PathVariable String variableName, + @RequestBody String expression) throws ParsingException { + billingDao.addVariable(authentication.getName(), variableName, + calculator.calculate(billingDao.getVariables(authentication.getName()), expression), expression); + } + + @RequestMapping(path = "/variable/{variableName}", method = RequestMethod.DELETE, produces = "text/plain") + public void deleteVariable(Authentication authentication, @PathVariable String variableName) + throws ParsingException { + billingDao.deleteVariable(authentication.getName(), variableName); + } + + @RequestMapping(path = "/variable", method = RequestMethod.GET, produces = "text/plain") + public String getVariables(Authentication authentication) throws ParsingException { + StringBuilder result = new StringBuilder(); + for (Map.Entry entry : billingDao.getVariables(authentication.getName()).entrySet()) { + result.append(entry.getKey()); + result.append("\n"); + } + return result.toString(); + } + + @RequestMapping(path = "/function/{functionName}", method = RequestMethod.GET, produces = "text/plain") + public String getFunction(Authentication authentication, @PathVariable String functionName) + throws ParsingException { + if (calculator.isPredefinedFunction(functionName)) { + throw new ParsingException("This function is already defined"); + } + return billingDao.getFunction(authentication.getName(), functionName).getExpression(); + } + + @RequestMapping(path = "/function/{functionName}", method = RequestMethod.PUT, consumes = "text/plain", + produces = "text/plain") + public void putFunction(Authentication authentication, @PathVariable String functionName, + @RequestParam(value = "arguments", defaultValue = "") Array arguments, + @RequestBody String expression) throws ParsingException { + if (!checkName(functionName)) { + throw new ParsingException("Invalid name"); + } + if (calculator.isPredefinedFunction(functionName)) { + throw new ParsingException("This function is already defined"); + } + billingDao.addFunction(authentication.getName(), functionName, arguments, expression); + } + + @RequestMapping(path = "/function/{functionName}", method = RequestMethod.DELETE, consumes = "text/plain", + produces = "text/plain") + public void deleteFunction(Authentication authentication, @PathVariable String functionName) + throws ParsingException { + billingDao.deleteFunction(authentication.getName(), functionName); + } + + @RequestMapping(path = "/function/", method = RequestMethod.GET, produces = "text/plain") + public String getFunctions(Authentication authentication) throws ParsingException { + StringBuilder result = new StringBuilder(); + for (Map.Entry entry : billingDao.getFunctions(authentication.getName()).entrySet()) { + result.append(entry.getKey()); + result.append("\n"); + } + return result.toString(); + } + + @RequestMapping(path = "/eval", method = RequestMethod.POST, consumes = "text/plain", produces = "text/plain") + public String eval(Authentication authentication, @RequestBody String expression) throws ParsingException { + LOG.debug("Evaluation request: [" + expression + "]"); + double result = calculator.calculate(billingDao.getVariables(authentication.getName()), expression); + LOG.trace("Result: " + Double.toString(result)); + return Double.toString(result); + } + + @RequestMapping(path = "/newUser/{userName}", method = RequestMethod.PUT, + consumes = "text/plain", produces = "text/plain") + public void newUser(@PathVariable String userName, @RequestBody String password) throws ParsingException { + LOG.debug("New user: [" + userName + ' ' + password + "]"); + if (billingDao.createNewUser(userName, password, true)) { + LOG.trace("Success"); + } else { + LOG.trace("Fail"); + } + } + + private static boolean checkName(String name) { + for (int i = 0; i < name.length(); ++i) { + char ch = name.charAt(i); + if (!(isLetter(ch) || ch != '_' || isDigit(ch))) { + return false; + } + } + return true; + } +} \ No newline at end of file diff --git a/homework-g596-kozlova/src/main/java/ru/mipt/java2016/homework/g596/kozlova/task4/Function.java b/homework-g596-kozlova/src/main/java/ru/mipt/java2016/homework/g596/kozlova/task4/Function.java new file mode 100644 index 000000000..7be38e08f --- /dev/null +++ b/homework-g596-kozlova/src/main/java/ru/mipt/java2016/homework/g596/kozlova/task4/Function.java @@ -0,0 +1,39 @@ +package ru.mipt.java2016.homework.g596.kozlova.task4; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.sql.Array; + +public class Function { + + private static final Logger LOG = LoggerFactory.getLogger(Variable.class); + + private String userName; + private String name; + private Array arguments; + private String expression; + + public Function(String u, String n, Array a, String e) { + userName = u; + name = n; + arguments = a; + expression = e; + } + + public String getUserName() { + return userName; + } + + public String getName() { + return name; + } + + public Array getArguments() { + return arguments; + } + + public String getExpression() { + return expression; + } +} \ No newline at end of file diff --git a/homework-g596-kozlova/src/main/java/ru/mipt/java2016/homework/g596/kozlova/task4/SecurityServiceConfiguration.java b/homework-g596-kozlova/src/main/java/ru/mipt/java2016/homework/g596/kozlova/task4/SecurityServiceConfiguration.java new file mode 100644 index 000000000..11373f873 --- /dev/null +++ b/homework-g596-kozlova/src/main/java/ru/mipt/java2016/homework/g596/kozlova/task4/SecurityServiceConfiguration.java @@ -0,0 +1,57 @@ +package ru.mipt.java2016.homework.g596.kozlova.task4; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Configuration; +import org.springframework.dao.EmptyResultDataAccessException; +import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; +import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; +import org.springframework.security.core.userdetails.User; +import org.springframework.security.core.userdetails.UsernameNotFoundException; + +import java.util.Collections; + +@Configuration +@EnableWebSecurity +public class SecurityServiceConfiguration extends WebSecurityConfigurerAdapter { + + private static final Logger LOG = LoggerFactory.getLogger(SecurityServiceConfiguration.class); + + @Autowired + private BillingDao billingDao; + + @Override + protected void configure(HttpSecurity http) throws Exception { + LOG.info("Configuring security"); + http + .httpBasic().realmName("Calculator").and() + .formLogin().disable() + .logout().disable() + .csrf().disable() + .authorizeRequests() + .antMatchers("/eval/**").authenticated() + .antMatchers("/var/**").authenticated() + .anyRequest().permitAll(); + } + + @Autowired + public void registerGlobalAuthentication(AuthenticationManagerBuilder authentication) throws Exception { + LOG.info("Registering global user details service"); + authentication.userDetailsService(userName -> { + try { + BillingUser user = billingDao.loadUser(userName); + return new User( + user.getUserName(), + user.getPassword(), + Collections.singletonList(() -> "AUTHENTICATION") + ); + } catch (EmptyResultDataAccessException e) { + LOG.warn("No such user: " + userName); + throw new UsernameNotFoundException(userName); + } + }); + } +} \ No newline at end of file diff --git a/homework-g596-kozlova/src/main/java/ru/mipt/java2016/homework/g596/kozlova/task4/Variable.java b/homework-g596-kozlova/src/main/java/ru/mipt/java2016/homework/g596/kozlova/task4/Variable.java new file mode 100644 index 000000000..bcfd85310 --- /dev/null +++ b/homework-g596-kozlova/src/main/java/ru/mipt/java2016/homework/g596/kozlova/task4/Variable.java @@ -0,0 +1,37 @@ +package ru.mipt.java2016.homework.g596.kozlova.task4; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class Variable { + + private static final Logger LOG = LoggerFactory.getLogger(Variable.class); + + private String userName; + private String name; + private double value; + private String expression; + + public Variable(String u, String n, double v, String e) { + userName = u; + name = n; + value = v; + expression = e; + } + + public String getUserName() { + return userName; + } + + public String getName() { + return name; + } + + public Double getValue() { + return value; + } + + public String getExpression() { + return expression; + } +} \ No newline at end of file From b4317e582416b23bfe8a27aabf8895c835eb6edd Mon Sep 17 00:00:00 2001 From: kozlovanadya Date: Mon, 19 Dec 2016 14:21:55 +0300 Subject: [PATCH 5/8] Fixed code style --- .../homework/g596/kozlova/task4/BillingDao.java | 2 +- .../homework/g596/kozlova/task4/BillingUser.java | 10 +++++++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/homework-g596-kozlova/src/main/java/ru/mipt/java2016/homework/g596/kozlova/task4/BillingDao.java b/homework-g596-kozlova/src/main/java/ru/mipt/java2016/homework/g596/kozlova/task4/BillingDao.java index 8ef90c3b2..f15007f38 100644 --- a/homework-g596-kozlova/src/main/java/ru/mipt/java2016/homework/g596/kozlova/task4/BillingDao.java +++ b/homework-g596-kozlova/src/main/java/ru/mipt/java2016/homework/g596/kozlova/task4/BillingDao.java @@ -56,7 +56,7 @@ public BillingUser loadUser(String userName) throws EmptyResultDataAccessExcepti new Object[]{userName}, new RowMapper() { @Override - public BillingUser mapRow(ResultSet resultSet, int NumberOfRow) throws SQLException { + public BillingUser mapRow(ResultSet resultSet, int numberOfRow) throws SQLException { return new BillingUser( resultSet.getString("userName"), resultSet.getString("password"), diff --git a/homework-g596-kozlova/src/main/java/ru/mipt/java2016/homework/g596/kozlova/task4/BillingUser.java b/homework-g596-kozlova/src/main/java/ru/mipt/java2016/homework/g596/kozlova/task4/BillingUser.java index d63a876b4..1b1fb42f0 100644 --- a/homework-g596-kozlova/src/main/java/ru/mipt/java2016/homework/g596/kozlova/task4/BillingUser.java +++ b/homework-g596-kozlova/src/main/java/ru/mipt/java2016/homework/g596/kozlova/task4/BillingUser.java @@ -42,4 +42,12 @@ public boolean equals(Object obj) { } return true; } - } \ No newline at end of file + + @Override + public int hashCode() { + int result = userName.hashCode(); + result = 31 * result + password.hashCode(); + result = 31 * result + (enabled ? 1 : 0); + return result; + } +} \ No newline at end of file From a85f6e58febdfc154dbea8e429158c35a37383e0 Mon Sep 17 00:00:00 2001 From: kozlovanadya Date: Tue, 20 Dec 2016 00:24:36 +0300 Subject: [PATCH 6/8] Fixed comments --- homework-g596-kozlova/pom.xml | 5 - .../g596/kozlova/task4/BillingDao.java | 114 +++++++----------- .../kozlova/task4/CalculatorController.java | 29 ++--- .../homework/g596/kozlova/task4/Function.java | 9 +- .../task4/SecurityServiceConfiguration.java | 3 +- 5 files changed, 61 insertions(+), 99 deletions(-) diff --git a/homework-g596-kozlova/pom.xml b/homework-g596-kozlova/pom.xml index e87beabfc..c5af0bc0b 100644 --- a/homework-g596-kozlova/pom.xml +++ b/homework-g596-kozlova/pom.xml @@ -38,11 +38,6 @@ jeval 0.9.4 - - org.springframework - spring-context - 4.1.6.RELEASE - org.springframework.boot spring-boot-starter-web diff --git a/homework-g596-kozlova/src/main/java/ru/mipt/java2016/homework/g596/kozlova/task4/BillingDao.java b/homework-g596-kozlova/src/main/java/ru/mipt/java2016/homework/g596/kozlova/task4/BillingDao.java index f15007f38..02511ff5b 100644 --- a/homework-g596-kozlova/src/main/java/ru/mipt/java2016/homework/g596/kozlova/task4/BillingDao.java +++ b/homework-g596-kozlova/src/main/java/ru/mipt/java2016/homework/g596/kozlova/task4/BillingDao.java @@ -5,15 +5,14 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.dao.EmptyResultDataAccessException; import org.springframework.jdbc.core.JdbcTemplate; -import org.springframework.jdbc.core.RowMapper; import org.springframework.stereotype.Repository; import ru.mipt.java2016.homework.base.task1.ParsingException; import javax.annotation.PostConstruct; import javax.sql.DataSource; import java.sql.ResultSet; -import java.sql.SQLException; -import java.sql.Array; +import java.util.List; +import java.util.Arrays; import java.util.Map; import java.util.HashMap; @@ -35,6 +34,8 @@ public void postConstruct() { "(username VARCHAR PRIMARY KEY, password VARCHAR, enabled BOOLEAN)"); jdbcTemplate.execute("CREATE TABLE IF NOT EXISTS billing.variables " + "(username VARCHAR, name VARCHAR, value DOUBLE, expression VARCHAR)"); + jdbcTemplate.execute("CREATE TABLE IF NOT EXISTS billing.functions " + + "(username VARCHAR, name VARCHAR, arguments VARCHAR, expression VARCHAR)"); createNewUser("userName", "password", true); } @@ -43,8 +44,7 @@ public boolean createNewUser(String userName, String password, boolean enabled) loadUser(userName); return false; } catch (EmptyResultDataAccessException e) { - jdbcTemplate.update("INSERT INTO billing.users VALUES (?, ?, ?)", - new Object[]{userName, password, enabled}); + jdbcTemplate.update("INSERT INTO billing.users VALUES (?, ?, ?)", userName, password, enabled); return true; } } @@ -54,15 +54,9 @@ public BillingUser loadUser(String userName) throws EmptyResultDataAccessExcepti return jdbcTemplate.queryForObject( "SELECT username, password, enabled FROM billing.users WHERE username = ?", new Object[]{userName}, - new RowMapper() { - @Override - public BillingUser mapRow(ResultSet resultSet, int numberOfRow) throws SQLException { - return new BillingUser( - resultSet.getString("userName"), - resultSet.getString("password"), - resultSet.getBoolean("enabled") - ); - } + (ResultSet resultSet, int numberOfRow) -> { + return new BillingUser( resultSet.getString("userName"), resultSet.getString("password"), + resultSet.getBoolean("enabled")); } ); } @@ -71,15 +65,12 @@ public Variable getVariable(String userName, String variable) { return jdbcTemplate.queryForObject( "SELECT userName, name, value, expression FROM billing.variables WHERE userName = ? AND name = ?", new Object[]{userName, variable}, - new RowMapper() { - @Override - public Variable mapRow(ResultSet resultSet, int numberOfRow) throws SQLException { - return new Variable( - resultSet.getString("userName"), - resultSet.getString("name"), - resultSet.getDouble("value"), - resultSet.getString("expression")); - } + (ResultSet resultSet, int numberOfRow) -> { + return new Variable( + resultSet.getString("userName"), + resultSet.getString("name"), + resultSet.getDouble("value"), + resultSet.getString("expression")); } ); } @@ -89,15 +80,12 @@ public Map getVariables(String userName) { return jdbcTemplate.queryForObject( "SELECT userName, name, value, expression FROM billing.variables WHERE userName = ?", new Object[]{userName}, - new RowMapper>() { - @Override - public Map mapRow(ResultSet resultSet, int numberOfRow) throws SQLException { - Map map = new HashMap<>(); - while (!resultSet.next()) { - map.put(resultSet.getString("name"), Double.toString(resultSet.getDouble("value"))); - } - return map; + (ResultSet resultSet, int numberOfRow) -> { + Map map = new HashMap<>(); + while (!resultSet.next()) { + map.put(resultSet.getString("name"), Double.toString(resultSet.getDouble("value"))); } + return map; } ); } catch (EmptyResultDataAccessException e) { @@ -108,57 +96,46 @@ public Map mapRow(ResultSet resultSet, int numberOfRow) throws S public void deleteVariable(String userName, String name) throws ParsingException { try { getVariable(userName, name); - jdbcTemplate.update("DELETE FROM billing.variables WHERE userName = ? AND name = ?", - new Object[]{userName, name}); + jdbcTemplate.update("DELETE FROM billing.variables WHERE userName = ? AND name = ?", userName, name); } catch (EmptyResultDataAccessException e) { throw new ParsingException("Can't delete"); } } public void addVariable(String userName, String name, Double value, String expression) throws ParsingException { - try { - getVariable(userName, name); - jdbcTemplate.update("DELETE FROM billing.variables WHERE userName = ? AND name = ?", - new Object[]{userName, name}); - jdbcTemplate.update("INSERT INTO billing.variables VALUES (?, ?, ?, ?)", - new Object[]{userName, name, value, expression}); - } catch (EmptyResultDataAccessException e) { - jdbcTemplate.update("INSERT INTO billing.variables VALUES (?, ?, ?, ?)", - new Object[]{userName, name, value, expression}); - } + jdbcTemplate.update("MERGE INTO billing.variables VALUES (?, ?, ?, ?)", userName, name, value, expression); } public Function getFunction(String userName, String function) { return jdbcTemplate.queryForObject( "SELECT userName, name, arguments, expression FROM billing.functions WHERE userName = ? AND name = ?", new Object[]{userName, function}, - new RowMapper() { - @Override - public Function mapRow(ResultSet resultSet, int numberOfRow) throws SQLException { - return new Function( - resultSet.getString("userName"), - resultSet.getString("name"), - resultSet.getArray("arguments"), - resultSet.getString("expression")); - } + (ResultSet resultSet, int numberOfRow) -> { + String name = resultSet.getString("name"); + List arguments = Arrays.asList(resultSet.getString("arguments").split(" ")); + String expression = resultSet.getString("expression"); + return new Function(userName, name, arguments, expression); } ); } - public Map getFunctions(String userName) { + public Map getFunctions(String userName) { try { return jdbcTemplate.queryForObject( "SELECT userName, name, arguments, expression FROM billing.functions WHERE userName = ?", new Object[]{userName}, - new RowMapper>() { - @Override - public Map mapRow(ResultSet resultSet, int numberOfRow) throws SQLException { - Map map = new HashMap<>(); - while (!resultSet.next()) { - map.put(resultSet.getString("name"), Double.toString(resultSet.getDouble("arguments"))); + (ResultSet resultSet, int numberOfRow) -> { + Map map = new HashMap<>(); + while (true) { + String name = resultSet.getString("name"); + List arguments = Arrays.asList(resultSet.getString("arguments").split(" ")); + String expression = resultSet.getString("expression"); + map.put(name, new Function(userName, name, arguments, expression)); + if (!resultSet.next()) { + break; } - return map; } + return map; } ); } catch (EmptyResultDataAccessException e) { @@ -169,23 +146,14 @@ public Map mapRow(ResultSet resultSet, int numberOfRow) throws S public void deleteFunction(String userName, String name) throws ParsingException { try { getFunction(userName, name); - jdbcTemplate.update("DELETE FROM billing.functions WHERE userName = ? AND name = ?", - new Object[]{userName, name}); + jdbcTemplate.update("DELETE FROM billing.functions WHERE userName = ? AND name = ?", userName, name); } catch (EmptyResultDataAccessException e) { throw new ParsingException("Can't delete"); } } - public void addFunction(String userName, String name, Array arguments, String expression) throws ParsingException { - try { - getVariable(userName, name); - jdbcTemplate.update("DELETE FROM billing.functions WHERE userName = ? AND name = ?", - new Object[]{userName, name}); - jdbcTemplate.update("INSERT INTO billing.functions arguments (?, ?, ?, ?)", - new Object[]{userName, name, arguments, expression}); - } catch (EmptyResultDataAccessException e) { - jdbcTemplate.update("INSERT INTO billing.functions FUNCTION (?, ?, ?, ?)", - new Object[]{userName, name, arguments, expression}); - } + public void addFunction(String userName, String name, List arguments, String expression) + throws ParsingException { + jdbcTemplate.update("MERGE INTO billing.functions VALUES (?, ?, ?, ?)", userName, name, arguments, expression); } } \ No newline at end of file diff --git a/homework-g596-kozlova/src/main/java/ru/mipt/java2016/homework/g596/kozlova/task4/CalculatorController.java b/homework-g596-kozlova/src/main/java/ru/mipt/java2016/homework/g596/kozlova/task4/CalculatorController.java index be1e4dcc5..d85a5b68f 100644 --- a/homework-g596-kozlova/src/main/java/ru/mipt/java2016/homework/g596/kozlova/task4/CalculatorController.java +++ b/homework-g596-kozlova/src/main/java/ru/mipt/java2016/homework/g596/kozlova/task4/CalculatorController.java @@ -12,13 +12,14 @@ import org.springframework.web.bind.annotation.RequestBody; import ru.mipt.java2016.homework.base.task1.ParsingException; +import java.util.List; import java.util.Map; -import java.sql.Array; import static java.lang.Character.isDigit; import static java.lang.Character.isLetter; @RestController +@RequestMapping(produces = "text/plain") public class CalculatorController { private static final Logger LOG = LoggerFactory.getLogger(CalculatorController.class); @@ -28,21 +29,20 @@ public class CalculatorController { @Autowired private BillingDao billingDao; - @RequestMapping(path = "/variable/{variableName}", method = RequestMethod.GET, produces = "text/plain") + @RequestMapping(path = "/variable/{variableName}", method = RequestMethod.GET) public String getVariable(Authentication authentication, @PathVariable String variableName) throws ParsingException { return billingDao.getVariable(authentication.getName(), variableName).getExpression(); } - @RequestMapping(path = "/variable/{variableName}", method = RequestMethod.PUT, consumes = "text/plain", - produces = "text/plain") + @RequestMapping(path = "/variable/{variableName}", method = RequestMethod.PUT, consumes = "text/plain") public void putVariable(Authentication authentication, @PathVariable String variableName, @RequestBody String expression) throws ParsingException { billingDao.addVariable(authentication.getName(), variableName, calculator.calculate(billingDao.getVariables(authentication.getName()), expression), expression); } - @RequestMapping(path = "/variable/{variableName}", method = RequestMethod.DELETE, produces = "text/plain") + @RequestMapping(path = "/variable/{variableName}", method = RequestMethod.DELETE) public void deleteVariable(Authentication authentication, @PathVariable String variableName) throws ParsingException { billingDao.deleteVariable(authentication.getName(), variableName); @@ -58,7 +58,7 @@ public String getVariables(Authentication authentication) throws ParsingExceptio return result.toString(); } - @RequestMapping(path = "/function/{functionName}", method = RequestMethod.GET, produces = "text/plain") + @RequestMapping(path = "/function/{functionName}", method = RequestMethod.GET) public String getFunction(Authentication authentication, @PathVariable String functionName) throws ParsingException { if (calculator.isPredefinedFunction(functionName)) { @@ -67,10 +67,9 @@ public String getFunction(Authentication authentication, @PathVariable String fu return billingDao.getFunction(authentication.getName(), functionName).getExpression(); } - @RequestMapping(path = "/function/{functionName}", method = RequestMethod.PUT, consumes = "text/plain", - produces = "text/plain") + @RequestMapping(path = "/function/{functionName}", method = RequestMethod.PUT, consumes = "text/plain") public void putFunction(Authentication authentication, @PathVariable String functionName, - @RequestParam(value = "arguments", defaultValue = "") Array arguments, + @RequestParam(value = "arguments", defaultValue = "") List arguments, @RequestBody String expression) throws ParsingException { if (!checkName(functionName)) { throw new ParsingException("Invalid name"); @@ -81,24 +80,23 @@ public void putFunction(Authentication authentication, @PathVariable String func billingDao.addFunction(authentication.getName(), functionName, arguments, expression); } - @RequestMapping(path = "/function/{functionName}", method = RequestMethod.DELETE, consumes = "text/plain", - produces = "text/plain") + @RequestMapping(path = "/function/{functionName}", method = RequestMethod.DELETE) public void deleteFunction(Authentication authentication, @PathVariable String functionName) throws ParsingException { billingDao.deleteFunction(authentication.getName(), functionName); } - @RequestMapping(path = "/function/", method = RequestMethod.GET, produces = "text/plain") + @RequestMapping(path = "/function/", method = RequestMethod.GET) public String getFunctions(Authentication authentication) throws ParsingException { StringBuilder result = new StringBuilder(); - for (Map.Entry entry : billingDao.getFunctions(authentication.getName()).entrySet()) { + for (Map.Entry entry : billingDao.getFunctions(authentication.getName()).entrySet()) { result.append(entry.getKey()); result.append("\n"); } return result.toString(); } - @RequestMapping(path = "/eval", method = RequestMethod.POST, consumes = "text/plain", produces = "text/plain") + @RequestMapping(path = "/eval", method = RequestMethod.POST, consumes = "text/plain") public String eval(Authentication authentication, @RequestBody String expression) throws ParsingException { LOG.debug("Evaluation request: [" + expression + "]"); double result = calculator.calculate(billingDao.getVariables(authentication.getName()), expression); @@ -106,8 +104,7 @@ public String eval(Authentication authentication, @RequestBody String expression return Double.toString(result); } - @RequestMapping(path = "/newUser/{userName}", method = RequestMethod.PUT, - consumes = "text/plain", produces = "text/plain") + @RequestMapping(path = "/newUser/{userName}", method = RequestMethod.PUT, consumes = "text/plain") public void newUser(@PathVariable String userName, @RequestBody String password) throws ParsingException { LOG.debug("New user: [" + userName + ' ' + password + "]"); if (billingDao.createNewUser(userName, password, true)) { diff --git a/homework-g596-kozlova/src/main/java/ru/mipt/java2016/homework/g596/kozlova/task4/Function.java b/homework-g596-kozlova/src/main/java/ru/mipt/java2016/homework/g596/kozlova/task4/Function.java index 7be38e08f..29fbc4b53 100644 --- a/homework-g596-kozlova/src/main/java/ru/mipt/java2016/homework/g596/kozlova/task4/Function.java +++ b/homework-g596-kozlova/src/main/java/ru/mipt/java2016/homework/g596/kozlova/task4/Function.java @@ -3,7 +3,8 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.sql.Array; +import java.util.ArrayList; +import java.util.List; public class Function { @@ -11,10 +12,10 @@ public class Function { private String userName; private String name; - private Array arguments; + private List arguments = new ArrayList<>(); private String expression; - public Function(String u, String n, Array a, String e) { + public Function(String u, String n, List a, String e) { userName = u; name = n; arguments = a; @@ -29,7 +30,7 @@ public String getName() { return name; } - public Array getArguments() { + public List getArguments() { return arguments; } diff --git a/homework-g596-kozlova/src/main/java/ru/mipt/java2016/homework/g596/kozlova/task4/SecurityServiceConfiguration.java b/homework-g596-kozlova/src/main/java/ru/mipt/java2016/homework/g596/kozlova/task4/SecurityServiceConfiguration.java index 11373f873..70ac97207 100644 --- a/homework-g596-kozlova/src/main/java/ru/mipt/java2016/homework/g596/kozlova/task4/SecurityServiceConfiguration.java +++ b/homework-g596-kozlova/src/main/java/ru/mipt/java2016/homework/g596/kozlova/task4/SecurityServiceConfiguration.java @@ -33,7 +33,8 @@ protected void configure(HttpSecurity http) throws Exception { .csrf().disable() .authorizeRequests() .antMatchers("/eval/**").authenticated() - .antMatchers("/var/**").authenticated() + .antMatchers("/variable/**").authenticated() + .antMatchers("/function/**").authenticated() .anyRequest().permitAll(); } From c8345386df27cba024b2e98b534bdc258ed15db7 Mon Sep 17 00:00:00 2001 From: kozlovanadya Date: Tue, 20 Dec 2016 00:31:19 +0300 Subject: [PATCH 7/8] Fixed code style --- .../g596/kozlova/task4/BillingDao.java | 66 +++++++++---------- 1 file changed, 33 insertions(+), 33 deletions(-) diff --git a/homework-g596-kozlova/src/main/java/ru/mipt/java2016/homework/g596/kozlova/task4/BillingDao.java b/homework-g596-kozlova/src/main/java/ru/mipt/java2016/homework/g596/kozlova/task4/BillingDao.java index 02511ff5b..83a805cde 100644 --- a/homework-g596-kozlova/src/main/java/ru/mipt/java2016/homework/g596/kozlova/task4/BillingDao.java +++ b/homework-g596-kozlova/src/main/java/ru/mipt/java2016/homework/g596/kozlova/task4/BillingDao.java @@ -54,10 +54,10 @@ public BillingUser loadUser(String userName) throws EmptyResultDataAccessExcepti return jdbcTemplate.queryForObject( "SELECT username, password, enabled FROM billing.users WHERE username = ?", new Object[]{userName}, - (ResultSet resultSet, int numberOfRow) -> { - return new BillingUser( resultSet.getString("userName"), resultSet.getString("password"), - resultSet.getBoolean("enabled")); - } + (ResultSet resultSet, int numberOfRow) -> { + return new BillingUser (resultSet.getString("userName"), resultSet.getString("password"), + resultSet.getBoolean("enabled")); + } ); } @@ -65,12 +65,12 @@ public Variable getVariable(String userName, String variable) { return jdbcTemplate.queryForObject( "SELECT userName, name, value, expression FROM billing.variables WHERE userName = ? AND name = ?", new Object[]{userName, variable}, - (ResultSet resultSet, int numberOfRow) -> { - return new Variable( - resultSet.getString("userName"), - resultSet.getString("name"), - resultSet.getDouble("value"), - resultSet.getString("expression")); + (ResultSet resultSet, int numberOfRow) -> { + return new Variable( + resultSet.getString("userName"), + resultSet.getString("name"), + resultSet.getDouble("value"), + resultSet.getString("expression")); } ); } @@ -80,13 +80,13 @@ public Map getVariables(String userName) { return jdbcTemplate.queryForObject( "SELECT userName, name, value, expression FROM billing.variables WHERE userName = ?", new Object[]{userName}, - (ResultSet resultSet, int numberOfRow) -> { - Map map = new HashMap<>(); - while (!resultSet.next()) { - map.put(resultSet.getString("name"), Double.toString(resultSet.getDouble("value"))); - } - return map; + (ResultSet resultSet, int numberOfRow) -> { + Map map = new HashMap<>(); + while (!resultSet.next()) { + map.put(resultSet.getString("name"), Double.toString(resultSet.getDouble("value"))); } + return map; + } ); } catch (EmptyResultDataAccessException e) { return new HashMap<>(); @@ -110,12 +110,12 @@ public Function getFunction(String userName, String function) { return jdbcTemplate.queryForObject( "SELECT userName, name, arguments, expression FROM billing.functions WHERE userName = ? AND name = ?", new Object[]{userName, function}, - (ResultSet resultSet, int numberOfRow) -> { - String name = resultSet.getString("name"); - List arguments = Arrays.asList(resultSet.getString("arguments").split(" ")); - String expression = resultSet.getString("expression"); - return new Function(userName, name, arguments, expression); - } + (ResultSet resultSet, int numberOfRow) -> { + String name = resultSet.getString("name"); + List arguments = Arrays.asList(resultSet.getString("arguments").split(" ")); + String expression = resultSet.getString("expression"); + return new Function(userName, name, arguments, expression); + } ); } @@ -124,19 +124,19 @@ public Map getFunctions(String userName) { return jdbcTemplate.queryForObject( "SELECT userName, name, arguments, expression FROM billing.functions WHERE userName = ?", new Object[]{userName}, - (ResultSet resultSet, int numberOfRow) -> { - Map map = new HashMap<>(); - while (true) { - String name = resultSet.getString("name"); - List arguments = Arrays.asList(resultSet.getString("arguments").split(" ")); - String expression = resultSet.getString("expression"); - map.put(name, new Function(userName, name, arguments, expression)); - if (!resultSet.next()) { - break; - } + (ResultSet resultSet, int numberOfRow) -> { + Map map = new HashMap<>(); + while (true) { + String name = resultSet.getString("name"); + List arguments = Arrays.asList(resultSet.getString("arguments").split(" ")); + String expression = resultSet.getString("expression"); + map.put(name, new Function(userName, name, arguments, expression)); + if (!resultSet.next()) { + break; } - return map; } + return map; + } ); } catch (EmptyResultDataAccessException e) { return new HashMap<>(); From 14f5a223c84afe54b91afa9ec79cc9822bbcf45f Mon Sep 17 00:00:00 2001 From: kozlovanadya Date: Tue, 20 Dec 2016 00:33:36 +0300 Subject: [PATCH 8/8] Fixed code style --- .../mipt/java2016/homework/g596/kozlova/task4/BillingDao.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/homework-g596-kozlova/src/main/java/ru/mipt/java2016/homework/g596/kozlova/task4/BillingDao.java b/homework-g596-kozlova/src/main/java/ru/mipt/java2016/homework/g596/kozlova/task4/BillingDao.java index 83a805cde..314edfaa3 100644 --- a/homework-g596-kozlova/src/main/java/ru/mipt/java2016/homework/g596/kozlova/task4/BillingDao.java +++ b/homework-g596-kozlova/src/main/java/ru/mipt/java2016/homework/g596/kozlova/task4/BillingDao.java @@ -55,7 +55,7 @@ public BillingUser loadUser(String userName) throws EmptyResultDataAccessExcepti "SELECT username, password, enabled FROM billing.users WHERE username = ?", new Object[]{userName}, (ResultSet resultSet, int numberOfRow) -> { - return new BillingUser (resultSet.getString("userName"), resultSet.getString("password"), + return new BillingUser(resultSet.getString("userName"), resultSet.getString("password"), resultSet.getBoolean("enabled")); } ); @@ -71,7 +71,7 @@ public Variable getVariable(String userName, String variable) { resultSet.getString("name"), resultSet.getDouble("value"), resultSet.getString("expression")); - } + } ); }