Commit a30f0ef2 authored by Vasek Sraier's avatar Vasek Sraier
Browse files

bulk reformatting and import statement optimization

parent c4dc5a64
package inf226.inchat;
import inf226.util.immutable.List;
import inf226.util.Pair;
import inf226.storage.*;
import inf226.storage.Stored;
import inf226.util.Pair;
import inf226.util.immutable.List;
/**
* The Account class holds all information private to
......@@ -15,28 +14,28 @@ public final class Account {
* and a list of channels which the user can post to.
*/
public final Stored<User> user;
public final List<Pair<String,Stored<Channel>>> channels;
public final List<Pair<String, Stored<Channel>>> channels;
public final String password;
public Account(final Stored<User> user,
final List<Pair<String,Stored<Channel>>> channels,
final List<Pair<String, Stored<Channel>>> channels,
final String password) {
this.user = user;
this.channels = channels;
this.password = password;
}
/**
* Create a new Account.
*
* @param user The public User profile for this user.
* @param user The public User profile for this user.
* @param password The login password for this account.
**/
public static Account create(final Stored<User> user,
final String password) {
return new Account(user,List.empty(), password);
return new Account(user, List.empty(), password);
}
/**
* Join a channel with this account.
*
......@@ -44,13 +43,13 @@ public final class Account {
*/
public Account joinChannel(final String alias,
final Stored<Channel> channel) {
Pair<String,Stored<Channel>> entry
= new Pair<String,Stored<Channel>>(alias,channel);
Pair<String, Stored<Channel>> entry
= new Pair<String, Stored<Channel>>(alias, channel);
return new Account
(user,
List.cons(entry,
channels),
password);
List.cons(entry,
channels),
password);
}
......@@ -63,6 +62,6 @@ public final class Account {
public boolean checkPassword(String password) {
return this.password.equals(password);
}
}
package inf226.inchat;
import inf226.storage.DeletedException;
import inf226.storage.Storage;
import inf226.storage.Stored;
import inf226.storage.UpdatedException;
import inf226.util.Maybe;
import inf226.util.Mutable;
import inf226.util.Pair;
import inf226.util.Util;
import inf226.util.immutable.List;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.time.Instant;
import java.util.UUID;
import inf226.storage.*;
import inf226.util.immutable.List;
import inf226.util.*;
/**
* This class stores accounts in the database.
*/
public final class AccountStorage
implements Storage<Account,SQLException> {
implements Storage<Account, SQLException> {
final Connection connection;
final Storage<User,SQLException> userStore;
final Storage<Channel,SQLException> channelStore;
final Storage<User, SQLException> userStore;
final Storage<Channel, SQLException> channelStore;
/**
* Create a new account storage.
*
* @param connection The connection to the SQL database.
* @param userStore The storage for User data.
* @param channelStore The storage for channels.
* @param connection The connection to the SQL database.
* @param userStore The storage for User data.
* @param channelStore The storage for channels.
*/
public AccountStorage(Connection connection,
Storage<User,SQLException> userStore,
Storage<Channel,SQLException> channelStore)
throws SQLException {
Storage<User, SQLException> userStore,
Storage<Channel, SQLException> channelStore)
throws SQLException {
this.connection = connection;
this.userStore = userStore;
this.channelStore = channelStore;
connection.createStatement()
.executeUpdate("CREATE TABLE IF NOT EXISTS Account (id TEXT PRIMARY KEY, version TEXT, user TEXT, password TEXT, FOREIGN KEY(user) REFERENCES User(id) ON DELETE CASCADE)");
connection.createStatement()
.executeUpdate("CREATE TABLE IF NOT EXISTS AccountChannel (account TEXT, channel TEXT, alias TEXT, ordinal INTEGER, PRIMARY KEY(account,channel), FOREIGN KEY(account) REFERENCES Account(id) ON DELETE CASCADE, FOREIGN KEY(channel) REFERENCES Channel(id) ON DELETE CASCADE)");
}
@Override
public Stored<Account> save(Account account)
throws SQLException {
throws SQLException {
final Stored<Account> stored = new Stored<Account>(account);
String sql =
"INSERT INTO Account VALUES('" + stored.identity + "','"
+ stored.version + "','"
+ account.user.identity + "','"
+ account.password + "')";
String sql =
"INSERT INTO Account VALUES('" + stored.identity + "','"
+ stored.version + "','"
+ account.user.identity + "','"
+ account.password + "')";
connection.createStatement().executeUpdate(sql);
// Write the list of channels
final Maybe.Builder<SQLException> exception = Maybe.builder();
final Mutable<Integer> ordinal = new Mutable<Integer>(0);
......@@ -62,78 +66,85 @@ public final class AccountStorage
String alias = element.first;
Stored<Channel> channel = element.second;
final String msql
= "INSERT INTO AccountChannel VALUES('" + stored.identity + "','"
+ channel.identity + "','"
+ alias + "','"
+ ordinal.get().toString() + "')";
try { connection.createStatement().executeUpdate(msql); }
catch (SQLException e) { exception.accept(e) ; }
= "INSERT INTO AccountChannel VALUES('" + stored.identity + "','"
+ channel.identity + "','"
+ alias + "','"
+ ordinal.get().toString() + "')";
try {
connection.createStatement().executeUpdate(msql);
} catch (SQLException e) {
exception.accept(e);
}
ordinal.accept(ordinal.get() + 1);
});
Util.throwMaybe(exception.getMaybe());
return stored;
}
@Override
public synchronized Stored<Account> update(Stored<Account> account,
Account new_account)
throws UpdatedException,
Account new_account)
throws UpdatedException,
DeletedException,
SQLException {
final Stored<Account> current = get(account.identity);
final Stored<Account> updated = current.newVersion(new_account);
if(current.version.equals(account.version)) {
String sql = "UPDATE Account SET" +
" (version,user) =('"
+ updated.version + "','"
+ new_account.user.identity
+ "') WHERE id='"+ updated.identity + "'";
connection.createStatement().executeUpdate(sql);
// Rewrite the list of channels
connection.createStatement().executeUpdate("DELETE FROM AccountChannel WHERE account='" + account.identity + "'");
final Maybe.Builder<SQLException> exception = Maybe.builder();
final Mutable<Integer> ordinal = new Mutable<Integer>(0);
new_account.channels.forEach(element -> {
String alias = element.first;
Stored<Channel> channel = element.second;
final String msql
= "INSERT INTO AccountChannel VALUES('" + account.identity + "','"
+ channel.identity + "','"
+ alias + "','"
+ ordinal.get().toString() + "')";
try { connection.createStatement().executeUpdate(msql); }
catch (SQLException e) { exception.accept(e) ; }
ordinal.accept(ordinal.get() + 1);
});
final Stored<Account> current = get(account.identity);
final Stored<Account> updated = current.newVersion(new_account);
if (current.version.equals(account.version)) {
String sql = "UPDATE Account SET" +
" (version,user) =('"
+ updated.version + "','"
+ new_account.user.identity
+ "') WHERE id='" + updated.identity + "'";
connection.createStatement().executeUpdate(sql);
Util.throwMaybe(exception.getMaybe());
} else {
throw new UpdatedException(current);
}
return updated;
// Rewrite the list of channels
connection.createStatement().executeUpdate("DELETE FROM AccountChannel WHERE account='" + account.identity + "'");
final Maybe.Builder<SQLException> exception = Maybe.builder();
final Mutable<Integer> ordinal = new Mutable<Integer>(0);
new_account.channels.forEach(element -> {
String alias = element.first;
Stored<Channel> channel = element.second;
final String msql
= "INSERT INTO AccountChannel VALUES('" + account.identity + "','"
+ channel.identity + "','"
+ alias + "','"
+ ordinal.get().toString() + "')";
try {
connection.createStatement().executeUpdate(msql);
} catch (SQLException e) {
exception.accept(e);
}
ordinal.accept(ordinal.get() + 1);
});
Util.throwMaybe(exception.getMaybe());
} else {
throw new UpdatedException(current);
}
return updated;
}
@Override
public synchronized void delete(Stored<Account> account)
throws UpdatedException,
DeletedException,
SQLException {
throws UpdatedException,
DeletedException,
SQLException {
final Stored<Account> current = get(account.identity);
if(current.version.equals(account.version)) {
String sql = "DELETE FROM Account WHERE id ='" + account.identity + "'";
connection.createStatement().executeUpdate(sql);
if (current.version.equals(account.version)) {
String sql = "DELETE FROM Account WHERE id ='" + account.identity + "'";
connection.createStatement().executeUpdate(sql);
} else {
throw new UpdatedException(current);
throw new UpdatedException(current);
}
}
@Override
public Stored<Account> get(UUID id)
throws DeletedException,
SQLException {
throws DeletedException,
SQLException {
final String accountsql = "SELECT version,user,password FROM Account WHERE id = '" + id.toString() + "'";
final String channelsql = "SELECT channel,alias,ordinal FROM AccountChannel WHERE account = '" + id.toString() + "' ORDER BY ordinal DESC";
......@@ -144,48 +155,48 @@ public final class AccountStorage
final ResultSet accountResult = accountStatement.executeQuery(accountsql);
final ResultSet channelResult = channelStatement.executeQuery(channelsql);
if(accountResult.next()) {
if (accountResult.next()) {
final UUID version = UUID.fromString(accountResult.getString("version"));
final UUID userid =
UUID.fromString(accountResult.getString("user"));
UUID.fromString(accountResult.getString("user"));
final String password =
accountResult.getString("password");
accountResult.getString("password");
final Stored<User> user = userStore.get(userid);
// Get all the channels associated with this account
final List.Builder<Pair<String,Stored<Channel>>> channels = List.builder();
while(channelResult.next()) {
final UUID channelId =
UUID.fromString(channelResult.getString("channel"));
final List.Builder<Pair<String, Stored<Channel>>> channels = List.builder();
while (channelResult.next()) {
final UUID channelId =
UUID.fromString(channelResult.getString("channel"));
final String alias = channelResult.getString("alias");
channels.accept(
new Pair<String,Stored<Channel>>(
alias,channelStore.get(channelId)));
new Pair<String, Stored<Channel>>(
alias, channelStore.get(channelId)));
}
return (new Stored<Account>(new Account(user,channels.getList(),password),id,version));
return (new Stored<Account>(new Account(user, channels.getList(), password), id, version));
} else {
throw new DeletedException();
}
}
/**
* Look up an account based on their username.
*/
public Stored<Account> lookup(String username)
throws DeletedException,
SQLException {
throws DeletedException,
SQLException {
final String sql = "SELECT Account.id from Account INNER JOIN User ON user=User.id where User.name='" + username + "'";
System.err.println(sql);
final Statement statement = connection.createStatement();
final ResultSet rs = statement.executeQuery(sql);
if(rs.next()) {
final UUID identity =
if (rs.next()) {
final UUID identity =
UUID.fromString(rs.getString("id"));
return get(identity);
}
throw new DeletedException();
}
}
package inf226.inchat;
import inf226.util.immutable.List;
import inf226.storage.Stored;
import inf226.util.immutable.List;
import java.time.Instant;
import java.util.UUID;
/**
* The Channel class represents a channel.
*/
public final class Channel {
public final String name;
public final List<Stored<Event>> events;
/**
* Construct a Channel object from name and events.
*/
public Channel(String name, List<Stored<Event>> events) {
this.name=name;
this.events=events;
this.name = name;
this.events = events;
}
/**
* Post a new event to the channel.
*/
public Channel postEvent(Stored<Event> event) {
return new Channel(name, List.cons(event,events));
return new Channel(name, List.cons(event, events));
}
/**
* The Event class represents different kinds of events
* in a channel, such as "join events" and "message events".
*/
public static class Event {
public static enum Type {
message(0),join(1);
message(0), join(1);
public final Integer code;
Type(Integer code){this.code=code;}
Type(Integer code) {
this.code = code;
}
public static Type fromInteger(Integer i) {
if (i.equals(0))
return message;
......@@ -43,13 +49,15 @@ public final class Channel {
else
throw new IllegalArgumentException("Invalid Channel.Event.Type code:" + i);
}
};
}
;
public final UUID channel;
public final Type type;
public final Instant time;
public final String sender;
public final String message;
/**
* Copy constructor
*/
......@@ -60,38 +68,40 @@ public final class Channel {
if (type.equals(message) && message == null) {
throw new IllegalArgumentException("null in Event creation");
}
this.channel=channel;
this.time =time;
this.sender =sender;
this.type =type;
this.message=message;
this.channel = channel;
this.time = time;
this.sender = sender;
this.type = type;
this.message = message;
}
/**
* Create a message event, which represents a user writing to the channel.
*/
* Create a message event, which represents a user writing to the channel.
*/
public static Event createMessageEvent(UUID channel, Instant time, String sender, String message) {
return new Event( channel,
time,
sender,
Event.Type.message,
message);
return new Event(channel,
time,
sender,
Event.Type.message,
message);
}
/**
* Create a message event, which represents a user joining the channel.
*/
public static Event createJoinEvent(UUID channel,Instant time, String user) {
return new Event( channel,
time,
user,
Event.Type.join,
null);
* Create a message event, which represents a user joining the channel.
*/
public static Event createJoinEvent(UUID channel, Instant time, String user) {
return new Event(channel,
time,
user,
Event.Type.join,
null);
}
/**
* Create a new event with a different message.
*/
*/
public Event setMessage(String message) {
return new Event(channel,time,sender,type,message);
return new Event(channel, time, sender, type, message);
}
}
}
package inf226.inchat;
import inf226.storage.DeletedException;
import inf226.storage.Storage;
import inf226.storage.Stored;
import inf226.storage.UpdatedException;
import inf226.util.Maybe;
import inf226.util.immutable.List;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.time.Instant;
import java.util.UUID;
import java.util.TreeMap;
import java.util.Map;
import java.util.TreeMap;
import java.util.UUID;
import java.util.function.Consumer;
import inf226.storage.*;
import inf226.util.immutable.List;
import inf226.util.*;
/**
* This class stores Channels in a SQL database.
*/
public final class ChannelStorage
implements Storage<Channel,SQLException> {
implements Storage<Channel, SQLException> {
final Connection connection;
/* The waiters object represent the callbacks to
* make when the channel is updated.
*/
private Map<UUID,List<Consumer<Stored<Channel>>>> waiters
= new TreeMap<UUID,List<Consumer<Stored<Channel>>>>();
private Map<UUID, List<Consumer<Stored<Channel>>>> waiters
= new TreeMap<UUID, List<Consumer<Stored<Channel>>>>();
public final EventStorage eventStore;
public ChannelStorage(Connection connection)
throws SQLException {
public ChannelStorage(Connection connection)
throws SQLException {
this.connection = connection;
this.eventStore = new EventStorage(connection);
connection.createStatement()
.executeUpdate("CREATE TABLE IF NOT EXISTS Channel (id TEXT PRIMARY KEY, version TEXT, name TEXT)");
}
@Override
public Stored<Channel> save(Channel channel)
throws SQLException {
throws SQLException {
final Stored<Channel> stored = new Stored<Channel>(channel);
String sql = "INSERT INTO Channel VALUES('" + stored.identity + "','"
+ stored.version + "','"
+ channel.name + "')";
String sql = "INSERT INTO Channel VALUES('" + stored.identity + "','"
+ stored.version + "','"
+ channel.name + "')";
connection.createStatement().executeUpdate(sql);
return stored;
}
@Override
public synchronized Stored<Channel> update(Stored<Channel> channel,
Channel new_channel)
throws UpdatedException,
Channel new_channel)
throws UpdatedException,
DeletedException,