Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

4th task Dmitriyeva g597 #343

Open
wants to merge 6 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 38 additions & 0 deletions homework-g597-dmitrieva/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,12 @@
<modelVersion>4.0.0</modelVersion>

<artifactId>homework-g597-dmitrieva</artifactId>
<packaging>pom</packaging>
<version>1.0.0</version>

<properties>
<spring.boot.version>1.4.2.RELEASE</spring.boot.version>
</properties>

<dependencies>
<dependency>
Expand All @@ -18,6 +24,38 @@
<version>1.0.0</version>
</dependency>

<dependency>
<groupId>net.sourceforge.jeval</groupId>
<artifactId>jeval</artifactId>
<version>0.9.4</version>
</dependency>

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>${spring.boot.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
<version>${spring.boot.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
<version>${spring.boot.version}</version>
</dependency>
<dependency>
<groupId>com.zaxxer</groupId>
<artifactId>HikariCP</artifactId>
<version>2.5.1</version>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<version>1.4.193</version>
</dependency>

<dependency>
<groupId>ru.mipt.java2016</groupId>
<artifactId>homework-tests</artifactId>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,255 @@
package ru.mipt.java2016.homework.g597.dmitrieva.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.util.*;

@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);
initSchema();
}

public void initSchema() {
LOG.trace("Initializing schema");
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.update("INSERT INTO billing.users VALUES ('username', 'password', TRUE)");
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

это типа для первого запуска, а потом закомментить? это оскорбляет чувства семинаристов, которые не знают о таких подводных камнях изначально
на будущее, для этого есть MERGE.


jdbcTemplate.execute("CREATE TABLE IF NOT EXISTS billing.functions" +
"(username VARCHAR, nameOfFunction VARCHAR, arguments VARCHAR, " +
"expression VARCHAR, PRIMARY KEY (username, nameOfFunction))");
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

а что делает expression?

//jdbcTemplate.update("INSERT INTO billing.functions VALUES ('username','sin', 'a', 'sin(a)')");
//jdbcTemplate.update("INSERT INTO billing.functions VALUES ('username','cos', 'a', 'cos(a)')");
//jdbcTemplate.update("INSERT INTO billing.functions VALUES ('username','tg', 'a', 'tg(a)')");
//jdbcTemplate.update("INSERT INTO billing.functions VALUES ('username','sqrt', 'a', 'sqrt(a)')");
//jdbcTemplate.update("INSERT INTO billing.functions VALUES ('username','pow', 'm, e', 'pow(m, e)')");
//jdbcTemplate.update("INSERT INTO billing.functions VALUES ('username','abs', 'a', 'abs(a)')");
//jdbcTemplate.update("INSERT INTO billing.functions VALUES ('username','sign', 'a', 'sigh(a)')");
//jdbcTemplate.update("INSERT INTO billing.functions VALUES ('username','log', 'a, n', 'log(a, n)')");
//jdbcTemplate.update("INSERT INTO billing.functions VALUES ('username', 'log2', 'a', 'log2(a)')");
//jdbcTemplate.update("INSERT INTO billing.functions VALUES ('username', 'rnd', '', 'rnd()')");
//jdbcTemplate.update("INSERT INTO billing.functions VALUES ('username','max', 'a, b', 'max(a, b)')");
//jdbcTemplate.update("INSERT INTO billing.functions VALUES ('username','min', 'a, b', 'min(a,b)')");
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

каеф


jdbcTemplate.execute("CREATE TABLE IF NOT EXISTS billing.variables " +
"(username VARCHAR, nameOfVariable VARCHAR, valueOfVariable DOUBLE NOT NULL, " +
" PRIMARY KEY (username, nameOfVariable))");

}

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<BillingUser>() {
@Override
public BillingUser mapRow(ResultSet rs, int rowNum) throws SQLException {
return new BillingUser(
rs.getString("username"),
rs.getString("password"),
rs.getBoolean("enabled")
);
}
}
);
}

public void addUser(String username, String password) {
LOG.trace("Adding user " + username);
jdbcTemplate.update("INSERT INTO billing.users VALUES ('" + username + "', '" + password + "', TRUE)");
}

public Double getVariable(String username, String variableName) {
return jdbcTemplate.queryForObject("SELECT username, nameOfVariable, valueOfVariable " +
"FROM billing.variables WHERE username = ? AND nameOfVariable = ?",
new Object[]{username, variableName},
new RowMapper<Double>() {
@Override
public Double mapRow(ResultSet resultSet, int rowNum) throws SQLException {
return resultSet.getDouble("valueOfVariable");
}
}
);
}

Map<String, Double> getVariables(String username) {
try {
return jdbcTemplate.queryForObject(
"SELECT username, nameOfVariable, valueOfVariable FROM billing.variables WHERE username = ?",
new Object[]{username},
new RowMapper<TreeMap<String, Double>>() {
@Override
public TreeMap<String, Double> mapRow(ResultSet resultSet, int rowNum) throws SQLException {
TreeMap<String, Double> selection = new TreeMap<String, Double>();
while (true) {
selection.put(resultSet.getString("nameOfVariable"),
resultSet.getDouble("valueOfVariable"));
if (!resultSet.next()) {
break;
}
}
return selection;
}
}
);
} catch (EmptyResultDataAccessException e) {
return new TreeMap<>();
}
}

boolean deleteVariable(String username, String nameOfVariable) {
try {
getVariable(username, nameOfVariable);
jdbcTemplate.update("DELETE FROM billing.variables WHERE username = ? AND nameOfVariable = ?",
new Object[]{username, nameOfVariable});
return true;
} catch (EmptyResultDataAccessException e) {
return false;
}
}

public void addVariable(String username, String nameOfVariable, Double valueOfVariable) throws ParsingException {
try {
getVariable(username, nameOfVariable);
jdbcTemplate.update("DELETE FROM billing.variables WHERE username = ? AND nameOfVariable = ?",
new Object[]{username, nameOfVariable});
jdbcTemplate.update("INSERT INTO billing.variables VALUES (?, ?, ?)",
new Object[]{username, nameOfVariable, valueOfVariable});
} catch (EmptyResultDataAccessException e) {
jdbcTemplate.update("INSERT INTO billing.variables VALUES (?, ?, ?)",
new Object[]{username, nameOfVariable, valueOfVariable});
}
}

public Function getFunction(String username, String nameOfFunction) {
return jdbcTemplate.queryForObject(
"SELECT username, nameOfFunction, arguments, expression " +
"FROM billing.functions WHERE username = ? AND nameOfFunction = ?",
new Object[]{username, nameOfFunction},
new RowMapper<Function>() {
@Override
public Function mapRow(ResultSet resultSet, int rowNum) throws SQLException {
String nameOfFunction = resultSet.getString("nameOfFunction");
List<String> arguments = Arrays.asList(resultSet.getString("arguments").split(" "));
String expression = resultSet.getString("expression");
return new Function(nameOfFunction, arguments, expression);
}
}
);
}


TreeMap<String, Function> getFunctions(String username) {
try {
return jdbcTemplate.queryForObject("SELECT username, nameOfFunction, arguments, expression" +
" FROM billing.functions WHERE username = ?",
new Object[]{username},
new RowMapper<TreeMap<String, Function>>() {
@Override
public TreeMap<String, Function> mapRow(ResultSet resultSet, int rowNum) throws SQLException {
TreeMap<String, Function> selection = new TreeMap();
while (true) {
String nameOfFunction = resultSet.getString("nameOfFunction");
List<String> arguments = Arrays.asList(resultSet.getString("arguments").split(" "));
String expression = resultSet.getString("expression");
selection.put(nameOfFunction, new Function(nameOfFunction, arguments, expression));
if (!resultSet.next()) {
break;
}
}
return selection;
}
});
} catch (EmptyResultDataAccessException e) {
return new TreeMap<>();
}
}

boolean deleteFunction(String username, String nameOfFunction) {
try {
getFunction(username, nameOfFunction);
jdbcTemplate.update("DELETE FROM billing.functions WHERE username = ? AND nameOfFunction = ?",
new Object[]{username, nameOfFunction});
return true;
} catch (EmptyResultDataAccessException e) {
return false;
}
}

void addFunction(String username, String nameOfFunction, List<String> arguments, String expression) {
// Заменяем в функции все вхождения переменных на их значения
int beginIndexOfVariable = 0;
int endIndexOfVariable = 0;
boolean isReadingVariable = false;
for (int i = 0; i < expression.length(); i++) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ммм, парсинг в классе для работы с базой данных. KPACUBO.
это бы взять, да упрятать в какой-нибудь класс специально для этого предназначенный.
и всё же пока непонятно, зачем тебе вообще здесь что-то парсить, ведь у тебя уже сюда приходят все необходимые данные, но есть какой-то непонятный expression в БД.

// Нашли что-то, что начинается с буквы -- возможно, это переменная
if (Character.isLetter(expression.charAt(i)) && !isReadingVariable) {
beginIndexOfVariable = i;
endIndexOfVariable = i; // ???
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

без комментария непонятно было, что происходит, а теперь всё встало на свои места

isReadingVariable = true;
continue;
}
// находимся в процессе чтения переменной (если это она)
if ((Character.isLetterOrDigit(expression.charAt(i)) || expression.charAt(i) == '_') && isReadingVariable) {
endIndexOfVariable = i;
continue;
}
if (!(Character.isLetterOrDigit(expression.charAt(i)) || expression.charAt(i) == '_')
&& isReadingVariable) {
isReadingVariable = false;
String variable = expression.substring(beginIndexOfVariable, endIndexOfVariable + 1);
// Если мы нашли не переменную, а какую-то функцию, то ничего с ней делать не хотим
if (getFunctions(username).containsKey(variable)) {
continue;
}
// Если какую-то переменную мы нашли, но в списке переменных это пользователя ее нет,
// значит, это просто аргумент функции и можно расслабиться
if (!getVariables(username).containsKey(variable)) {
continue;
}
// Если же это действительно переменная, добавленная пользователем,
// то получаем ее значение
String value = getVariable(username, variable).toString();
// Заменяем ее первое вхождение на значение
expression.replaceFirst(variable, value);
// Дальше обновляем счетчик и снова ищем какую-нибудь переменную
i = 0;
}
}
try {
getFunction(username, nameOfFunction);
jdbcTemplate.update("DELETE FROM billing.functions WHERE username = ? AND nameOfFunction = ?",
new Object[]{username, nameOfFunction});
String stringOfArguments = String.join(" ", arguments);
jdbcTemplate.update("INSERT INTO billing.functions VALUES (?, ?, ?, ?)",
new Object[]{username, nameOfFunction, stringOfArguments, expression});
} catch (EmptyResultDataAccessException e) {
String stringArguments = String.join(" ", arguments);
jdbcTemplate.update("INSERT INTO billing.functions VALUES (?, ?, ?, ?)",
new Object[]{username, nameOfFunction, stringArguments, expression});
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package ru.mipt.java2016.homework.g597.dmitrieva.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.g597.dmitriyeva.task4.jdbcUrl:jdbc:h2:~/test}") String jdbcUrl,
@Value("${ru.mipt.java2016.homework.g597.dmitriyeva.task4.username:}") String username,
@Value("${ru.mipt.java2016.homework.g597.dmitriyeva.task4.password:}") String password
) {
HikariConfig config = new HikariConfig();
config.setDriverClassName(org.h2.Driver.class.getName());
config.setJdbcUrl(jdbcUrl);
config.setUsername(username);
config.setPassword(password);
return new HikariDataSource(config);
}
}
Loading