refactoring objects in preparation for:
refactoring journal database to contain object ids for: querying journal for objects
This commit is contained in:
@@ -6,6 +6,7 @@ import static java.util.Optional.*;
|
|||||||
|
|
||||||
import de.srsoftware.tools.Diff;
|
import de.srsoftware.tools.Diff;
|
||||||
import de.srsoftware.tools.Mappable;
|
import de.srsoftware.tools.Mappable;
|
||||||
|
import de.srsoftware.umbrella.core.model.ObjectWithId;
|
||||||
import de.srsoftware.umbrella.core.model.Translatable;
|
import de.srsoftware.umbrella.core.model.Translatable;
|
||||||
import de.srsoftware.umbrella.core.model.UmbrellaUser;
|
import de.srsoftware.umbrella.core.model.UmbrellaUser;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
@@ -14,15 +15,15 @@ import java.util.Map;
|
|||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import org.json.JSONObject;
|
import org.json.JSONObject;
|
||||||
|
|
||||||
public abstract class Event<Payload extends Mappable> {
|
public abstract class Event<Payload extends ObjectWithId> {
|
||||||
|
|
||||||
public enum EventType {
|
public enum EventType {
|
||||||
CREATE,
|
CREATE,
|
||||||
MEMBER_ADDED,
|
MEMBER_ADDED,
|
||||||
UPDATE,
|
UPDATE,
|
||||||
DELETE;
|
DELETE;
|
||||||
}
|
|
||||||
|
|
||||||
|
}
|
||||||
private final UmbrellaUser initiator;
|
private final UmbrellaUser initiator;
|
||||||
private final String module;
|
private final String module;
|
||||||
private final Payload payload;
|
private final Payload payload;
|
||||||
@@ -98,6 +99,10 @@ public abstract class Event<Payload extends Mappable> {
|
|||||||
return module;
|
return module;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public long objectId() {
|
||||||
|
return payload.id();
|
||||||
|
};
|
||||||
|
|
||||||
protected Map<String, Object> oldData() {
|
protected Map<String, Object> oldData() {
|
||||||
return oldData;
|
return oldData;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,6 +36,10 @@ public class ItemEvent extends Event<Item>{
|
|||||||
return t("{user} added \"{item}\" to \"{location}\"", USER,initiator().name(), ITEM, payload().name(), LOCATION, loc);
|
return t("{user} added \"{item}\" to \"{location}\"", USER,initiator().name(), ITEM, payload().name(), LOCATION, loc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long objectId() {
|
||||||
|
return payload().id();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Translatable subject() {
|
public Translatable subject() {
|
||||||
|
|||||||
@@ -78,6 +78,11 @@ public class ProjectEvent extends Event<Project>{
|
|||||||
return t("You can view/edit this project at {base_url}/project/{id}/view",ID,payload().id());
|
return t("You can view/edit this project at {base_url}/project/{id}/view",ID,payload().id());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long objectId() {
|
||||||
|
return payload().id();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Translatable subject() {
|
public Translatable subject() {
|
||||||
return switch (eventType()){
|
return switch (eventType()){
|
||||||
|
|||||||
@@ -62,6 +62,11 @@ public class TransactionEvent extends Event<Transaction> {
|
|||||||
return t("You can view/edit this transaction at {base_url}/account/{id}", ID, payload().accountId());
|
return t("You can view/edit this transaction at {base_url}/account/{id}", ID, payload().accountId());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long objectId() {
|
||||||
|
return payload().id();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Translatable subject() {
|
public Translatable subject() {
|
||||||
var user = initiator().name();
|
var user = initiator().name();
|
||||||
|
|||||||
@@ -68,6 +68,10 @@ public class WikiEvent extends Event<WikiPage>{
|
|||||||
return t("You can view/edit this wiki page at {base_url}/wiki/{id}/view",ID,payload().id());
|
return t("You can view/edit this wiki page at {base_url}/wiki/{id}/view",ID,payload().id());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long objectId() {
|
||||||
|
return payload().id();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Translatable subject() {
|
public Translatable subject() {
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ package de.srsoftware.umbrella.core.model;
|
|||||||
import static de.srsoftware.umbrella.core.Util.mapMarkdown;
|
import static de.srsoftware.umbrella.core.Util.mapMarkdown;
|
||||||
import static de.srsoftware.umbrella.core.constants.Field.*;
|
import static de.srsoftware.umbrella.core.constants.Field.*;
|
||||||
|
|
||||||
import de.srsoftware.tools.Mappable;
|
|
||||||
import de.srsoftware.umbrella.core.api.Owner;
|
import de.srsoftware.umbrella.core.api.Owner;
|
||||||
import de.srsoftware.umbrella.core.constants.Field;
|
import de.srsoftware.umbrella.core.constants.Field;
|
||||||
import java.sql.ResultSet;
|
import java.sql.ResultSet;
|
||||||
@@ -12,16 +11,16 @@ import java.sql.SQLException;
|
|||||||
import java.util.*;
|
import java.util.*;
|
||||||
import org.json.JSONObject;
|
import org.json.JSONObject;
|
||||||
|
|
||||||
public class Item implements Mappable {
|
public class Item extends ObjectWithId {
|
||||||
private long id, ownerNumber; // id is the database key, number the owner-relative id
|
private long ownerNumber; // id is the database key, number the owner-relative id
|
||||||
private Owner owner;
|
private final Owner owner;
|
||||||
private String code, description, name;
|
private String code, description, name;
|
||||||
private Location location;
|
private Location location;
|
||||||
private Collection<Property> properties;
|
private final Collection<Property> properties;
|
||||||
private Set<String> dirtyFields = new HashSet<>();
|
private final Set<String> dirtyFields = new HashSet<>();
|
||||||
|
|
||||||
public Item(long id, Owner owner, long ownerNumber, Location location, String code, String name, String description) {
|
public Item(long id, Owner owner, long ownerNumber, Location location, String code, String name, String description) {
|
||||||
this.id = id;
|
super(id);
|
||||||
this.owner = owner;
|
this.owner = owner;
|
||||||
this.ownerNumber = ownerNumber;
|
this.ownerNumber = ownerNumber;
|
||||||
this.location = location;
|
this.location = location;
|
||||||
@@ -48,15 +47,6 @@ public class Item implements Mappable {
|
|||||||
return !dirtyFields.isEmpty();
|
return !dirtyFields.isEmpty();
|
||||||
}
|
}
|
||||||
|
|
||||||
public long id(){
|
|
||||||
return id;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Item id(long newVal) {
|
|
||||||
id = newVal;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Location location(){
|
public Location location(){
|
||||||
return location;
|
return location;
|
||||||
}
|
}
|
||||||
@@ -121,14 +111,13 @@ public class Item implements Mappable {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Map<String, Object> toMap() {
|
public Map<String, Object> toMap() {
|
||||||
var map = new HashMap<String,Object>();
|
var map = super.map(
|
||||||
map.put(OWNER,owner.toMap());
|
OWNER,owner.toMap(),
|
||||||
map.put(ID,id);
|
LOCATION,location.toMap(),
|
||||||
map.put(LOCATION,location.toMap());
|
Field.CODE,code,
|
||||||
map.put(Field.CODE,code);
|
NAME,name,
|
||||||
map.put(NAME,name);
|
DESCRIPTION,mapMarkdown(description),
|
||||||
map.put(DESCRIPTION,mapMarkdown(description));
|
OWNER_NUMBER,ownerNumber);
|
||||||
map.put(OWNER_NUMBER,ownerNumber);
|
|
||||||
if (properties != null) map.put(PROPERTIES,properties.stream().map(Property::toMap).toList());
|
if (properties != null) map.put(PROPERTIES,properties.stream().map(Property::toMap).toList());
|
||||||
return map;
|
return map;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,30 @@
|
|||||||
|
package de.srsoftware.umbrella.core.model;
|
||||||
|
|
||||||
|
import de.srsoftware.tools.Mappable;
|
||||||
|
import de.srsoftware.umbrella.core.constants.Field;
|
||||||
|
|
||||||
|
import java.security.InvalidParameterException;
|
||||||
|
import java.time.LocalDate;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public abstract class ObjectWithId implements Mappable {
|
||||||
|
private final long id;
|
||||||
|
|
||||||
|
public ObjectWithId(long id){
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long id(){
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Map<String, Object> map(Object ... keysAndValues) {
|
||||||
|
if (keysAndValues.length % 2 != 0) throw new InvalidParameterException("Expected even number of keys and parameters!");
|
||||||
|
var map = new HashMap<String, Object>();
|
||||||
|
map.put(Field.ID,id);
|
||||||
|
for (var idx = 0; idx<keysAndValues.length; idx+=2) map.put(keysAndValues[idx].toString(),keysAndValues[idx+1]);
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -6,27 +6,25 @@ import static de.srsoftware.umbrella.core.Util.mapMarkdown;
|
|||||||
import static de.srsoftware.umbrella.core.constants.Field.*;
|
import static de.srsoftware.umbrella.core.constants.Field.*;
|
||||||
import static de.srsoftware.umbrella.core.model.Status.PREDEFINED;
|
import static de.srsoftware.umbrella.core.model.Status.PREDEFINED;
|
||||||
|
|
||||||
import de.srsoftware.tools.Mappable;
|
|
||||||
import de.srsoftware.umbrella.core.constants.Field;
|
import de.srsoftware.umbrella.core.constants.Field;
|
||||||
import java.sql.ResultSet;
|
import java.sql.ResultSet;
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import org.json.JSONObject;
|
import org.json.JSONObject;
|
||||||
|
|
||||||
public class Project implements Mappable {
|
public class Project extends ObjectWithId {
|
||||||
private final Map<Long,Member> members;
|
private final Map<Long,Member> members;
|
||||||
private final Collection<Status> allowedStates;
|
private final Collection<Status> allowedStates;
|
||||||
private boolean showClosed;
|
private boolean showClosed;
|
||||||
private Long companyId;
|
private Long companyId;
|
||||||
private int status;
|
private int status;
|
||||||
private String name;
|
private String name;
|
||||||
private final long id;
|
|
||||||
private String description;
|
private String description;
|
||||||
private final Set<String> dirtyFields = new HashSet<>();
|
private final Set<String> dirtyFields = new HashSet<>();
|
||||||
private final Map<String,String> tagColors = new HashMap<>();
|
private final Map<String,String> tagColors = new HashMap<>();
|
||||||
|
|
||||||
public Project(long id, String name, String description, int status, Long companyId, boolean showClosed, Map<Long,Member> members, Collection<Status> allowedStates) {
|
public Project(long id, String name, String description, int status, Long companyId, boolean showClosed, Map<Long,Member> members, Collection<Status> allowedStates) {
|
||||||
this.id = id;
|
super(id);
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.description = description;
|
this.description = description;
|
||||||
this.status = status;
|
this.status = status;
|
||||||
@@ -67,10 +65,6 @@ public class Project implements Mappable {
|
|||||||
return members.containsKey(user.id());
|
return members.containsKey(user.id());
|
||||||
}
|
}
|
||||||
|
|
||||||
public long id(){
|
|
||||||
return id;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isDirty() {
|
public boolean isDirty() {
|
||||||
return !dirtyFields.isEmpty();
|
return !dirtyFields.isEmpty();
|
||||||
}
|
}
|
||||||
@@ -126,23 +120,21 @@ public class Project implements Mappable {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Map<String, Object> toMap() {
|
public Map<String, Object> toMap() {
|
||||||
var map = new HashMap<String, Object>();
|
|
||||||
var memberMap = new HashMap<Long,Map<String,Object>>();
|
var memberMap = new HashMap<Long,Map<String,Object>>();
|
||||||
if (members != null) for (var entry : members.entrySet()){
|
if (members != null) for (var entry : members.entrySet()){
|
||||||
memberMap.put(entry.getKey(),entry.getValue().toMap());
|
memberMap.put(entry.getKey(),entry.getValue().toMap());
|
||||||
}
|
}
|
||||||
map.put(ID,id);
|
|
||||||
map.put(NAME,name);
|
|
||||||
map.put(DESCRIPTION,mapMarkdown(description));
|
|
||||||
map.put(STATUS,status);
|
|
||||||
map.put(COMPANY_ID,companyId);
|
|
||||||
map.put(SHOW_CLOSED,showClosed);
|
|
||||||
map.put(MEMBERS,memberMap);
|
|
||||||
var stateMap = new HashMap<Integer,String>();
|
var stateMap = new HashMap<Integer,String>();
|
||||||
for (var state : allowedStates) stateMap.put(state.code(),state.name());
|
for (var state : allowedStates) stateMap.put(state.code(),state.name());
|
||||||
map.put(Field.ALLOWED_STATES,stateMap);
|
return super.map(
|
||||||
map.put(TAG_COLORS,tagColors);
|
NAME,name,
|
||||||
return map;
|
DESCRIPTION,mapMarkdown(description),
|
||||||
|
STATUS,status,
|
||||||
|
COMPANY_ID,companyId,
|
||||||
|
SHOW_CLOSED,showClosed,
|
||||||
|
MEMBERS,memberMap,
|
||||||
|
Field.ALLOWED_STATES,stateMap,
|
||||||
|
TAG_COLORS,tagColors);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -14,17 +14,17 @@ import java.util.HashSet;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
public class Transaction implements Mappable {
|
public class Transaction extends ObjectWithId {
|
||||||
private long accountId, id;
|
private final long accountId;
|
||||||
private LocalDateTime date;
|
private LocalDateTime date;
|
||||||
private IdOrString source, destination;
|
private IdOrString source, destination;
|
||||||
private double amount;
|
private double amount;
|
||||||
private String purpose;
|
private String purpose;
|
||||||
private Set<String> tags;
|
private final Set<String> tags;
|
||||||
private HashSet<String> dirtyFields = new HashSet<>();
|
private final HashSet<String> dirtyFields = new HashSet<>();
|
||||||
|
|
||||||
public Transaction(long id, long accountId, LocalDateTime date, IdOrString source, IdOrString destination, double amount, String purpose, Set<String> tags){
|
public Transaction(long id, long accountId, LocalDateTime date, IdOrString source, IdOrString destination, double amount, String purpose, Set<String> tags){
|
||||||
this.id = id;
|
super(id);
|
||||||
this.accountId = accountId;
|
this.accountId = accountId;
|
||||||
this.date = date;
|
this.date = date;
|
||||||
this.source = source;
|
this.source = source;
|
||||||
@@ -77,10 +77,6 @@ public class Transaction implements Mappable {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public long id(){
|
|
||||||
return id;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isDirty(){
|
public boolean isDirty(){
|
||||||
return !dirtyFields.isEmpty();
|
return !dirtyFields.isEmpty();
|
||||||
}
|
}
|
||||||
@@ -123,8 +119,7 @@ public class Transaction implements Mappable {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Map<String, Object> toMap() {
|
public Map<String, Object> toMap() {
|
||||||
return Map.of(
|
return super.map(
|
||||||
Field.ID, id,
|
|
||||||
Field.ACCOUNT, accountId,
|
Field.ACCOUNT, accountId,
|
||||||
Field.DATE, date.toLocalDate(),
|
Field.DATE, date.toLocalDate(),
|
||||||
Field.SOURCE, source.toMap(),
|
Field.SOURCE, source.toMap(),
|
||||||
|
|||||||
@@ -10,16 +10,14 @@ import static de.srsoftware.umbrella.core.exceptions.UmbrellaException.*;
|
|||||||
import static de.srsoftware.umbrella.core.model.Translatable.t;
|
import static de.srsoftware.umbrella.core.model.Translatable.t;
|
||||||
import static java.lang.String.join;
|
import static java.lang.String.join;
|
||||||
|
|
||||||
import de.srsoftware.tools.Mappable;
|
|
||||||
import de.srsoftware.umbrella.core.api.UserService;
|
import de.srsoftware.umbrella.core.api.UserService;
|
||||||
import java.sql.ResultSet;
|
import java.sql.ResultSet;
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import org.json.JSONObject;
|
import org.json.JSONObject;
|
||||||
|
|
||||||
public class WikiPage implements Mappable {
|
public class WikiPage extends ObjectWithId {
|
||||||
|
|
||||||
private final long id;
|
|
||||||
private String title;
|
private String title;
|
||||||
private int version;
|
private int version;
|
||||||
private final Set<Integer> versions = new TreeSet<>();
|
private final Set<Integer> versions = new TreeSet<>();
|
||||||
@@ -29,7 +27,7 @@ public class WikiPage implements Mappable {
|
|||||||
private boolean guestAllowed = false;
|
private boolean guestAllowed = false;
|
||||||
|
|
||||||
public WikiPage(long id, String title, int version, String content) {
|
public WikiPage(long id, String title, int version, String content) {
|
||||||
this.id = id;
|
super(id);
|
||||||
this.version = version;
|
this.version = version;
|
||||||
this.content = content;
|
this.content = content;
|
||||||
this.title = title;
|
this.title = title;
|
||||||
@@ -60,10 +58,6 @@ public class WikiPage implements Mappable {
|
|||||||
dirtyFields.add(GUEST_ALLOWED);
|
dirtyFields.add(GUEST_ALLOWED);
|
||||||
}
|
}
|
||||||
|
|
||||||
public long id(){
|
|
||||||
return id;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isDirty(String field) {
|
public boolean isDirty(String field) {
|
||||||
return dirtyFields.contains(field);
|
return dirtyFields.contains(field);
|
||||||
}
|
}
|
||||||
@@ -146,8 +140,7 @@ public class WikiPage implements Mappable {
|
|||||||
var memberMap = new HashMap<Long,Map<String,Object>>();
|
var memberMap = new HashMap<Long,Map<String,Object>>();
|
||||||
for (var entry : members.entrySet()) memberMap.put(entry.getKey(),entry.getValue().toMap());
|
for (var entry : members.entrySet()) memberMap.put(entry.getKey(),entry.getValue().toMap());
|
||||||
|
|
||||||
return Map.of(
|
return map(
|
||||||
ID,id,
|
|
||||||
CONTENT,mapMarkdown(content),
|
CONTENT,mapMarkdown(content),
|
||||||
GUEST_ALLOWED,guestAllowed,
|
GUEST_ALLOWED,guestAllowed,
|
||||||
MEMBERS,memberMap,
|
MEMBERS,memberMap,
|
||||||
|
|||||||
@@ -38,11 +38,12 @@ public class SqliteDb extends BaseDb implements JournalDb{
|
|||||||
{2} LONG NOT NULL,
|
{2} LONG NOT NULL,
|
||||||
{3} INTEGER,
|
{3} INTEGER,
|
||||||
{4} VARCHAR(255) NOT NULL,
|
{4} VARCHAR(255) NOT NULL,
|
||||||
{5} VARCHAR(16) NOT NULL,
|
{5} VARCHAR(255),
|
||||||
{6} TEXT
|
{6} VARCHAR(16) NOT NULL,
|
||||||
|
{7} TEXT
|
||||||
);
|
);
|
||||||
""";
|
""";
|
||||||
sql = format(sql,TABLE_JOURNAL,ID,TIMESTAMP,USER_ID,MODULE,ACTION,DESCRIPTION);
|
sql = format(sql,TABLE_JOURNAL,ID,TIMESTAMP,USER_ID,MODULE,ENTITY_ID,ACTION,DESCRIPTION);
|
||||||
try {
|
try {
|
||||||
db.prepareStatement(sql).execute();
|
db.prepareStatement(sql).execute();
|
||||||
} catch (SQLException e) {
|
} catch (SQLException e) {
|
||||||
@@ -54,8 +55,8 @@ public class SqliteDb extends BaseDb implements JournalDb{
|
|||||||
public void logEvent(Event<?> event) {
|
public void logEvent(Event<?> event) {
|
||||||
try {
|
try {
|
||||||
var timestamp = LocalDateTime.now().toEpochSecond(ZoneOffset.UTC);
|
var timestamp = LocalDateTime.now().toEpochSecond(ZoneOffset.UTC);
|
||||||
insertInto(TABLE_JOURNAL,TIMESTAMP,USER_ID,MODULE,ACTION,DESCRIPTION)
|
insertInto(TABLE_JOURNAL,TIMESTAMP,USER_ID,MODULE,ENTITY_ID,ACTION,DESCRIPTION)
|
||||||
.values(timestamp,event.initiator().id(), event.module(), event.eventType(), event.describe())
|
.values(timestamp,event.initiator().id(), event.module(), event.objectId(), event.eventType(), event.describe())
|
||||||
.execute(db).close();
|
.execute(db).close();
|
||||||
} catch (SQLException e) {
|
} catch (SQLException e) {
|
||||||
throw databaseException(ERROR_WRITE_EVENT,event.eventType(),event.initiator().name());
|
throw databaseException(ERROR_WRITE_EVENT,event.eventType(),event.initiator().name());
|
||||||
|
|||||||
Reference in New Issue
Block a user