From d5e752ab364cf1fc1aac50b16969a42cf9a701a7 Mon Sep 17 00:00:00 2001 From: pietelite Date: Fri, 17 Apr 2020 12:30:39 -0400 Subject: [PATCH 1/3] Added API for a PrismService for plugin support --- src/main/java/com/helion3/prism/Prism.java | 3 + .../prism/api/services/PrismService.java | 233 ++++++++++++++++++ .../prism/api/services/PrismServiceImpl.java | 129 ++++++++++ 3 files changed, 365 insertions(+) create mode 100644 src/main/java/com/helion3/prism/api/services/PrismService.java create mode 100644 src/main/java/com/helion3/prism/api/services/PrismServiceImpl.java diff --git a/src/main/java/com/helion3/prism/Prism.java b/src/main/java/com/helion3/prism/Prism.java index 384ffa1..5e3fedd 100644 --- a/src/main/java/com/helion3/prism/Prism.java +++ b/src/main/java/com/helion3/prism/Prism.java @@ -45,6 +45,8 @@ import com.helion3.prism.api.parameters.ParameterRadius; import com.helion3.prism.api.parameters.ParameterTime; import com.helion3.prism.api.records.ActionableResult; +import com.helion3.prism.api.services.PrismService; +import com.helion3.prism.api.services.PrismServiceImpl; import com.helion3.prism.api.storage.StorageAdapter; import com.helion3.prism.commands.PrismCommands; import com.helion3.prism.configuration.Config; @@ -179,6 +181,7 @@ public void onInitialization(GameInitializationEvent event) { @Listener public void onPostInitialization(GamePostInitializationEvent event) { getConfiguration().saveConfiguration(); + Sponge.getServiceManager().setProvider(this, PrismService.class, new PrismServiceImpl()); } @Listener diff --git a/src/main/java/com/helion3/prism/api/services/PrismService.java b/src/main/java/com/helion3/prism/api/services/PrismService.java new file mode 100644 index 0000000..5b6032b --- /dev/null +++ b/src/main/java/com/helion3/prism/api/services/PrismService.java @@ -0,0 +1,233 @@ +package com.helion3.prism.api.services; + +import com.google.common.base.Preconditions; +import com.google.common.collect.Range; +import com.google.common.collect.Sets; +import com.helion3.prism.api.data.PrismEvent; +import org.spongepowered.api.command.CommandSource; + +import javax.annotation.Nonnull; +import java.io.Serializable; +import java.util.Date; +import java.util.Optional; +import java.util.Set; +import java.util.UUID; + +public interface PrismService { + + /** + * Queries all events matching the conditions in the {@link Request} and restores the + * original states within every event. + * + * @param source The source requesting the rollback maneuver + * @param conditions The collection of all parameters with which to filter out logged events + * @throws Exception if something unexpected happens + */ + void rollback(@Nonnull CommandSource source, @Nonnull Request conditions) throws Exception; + + /** + * Queries all events matching the conditions in the {@link Request} and restores the + * final states within every event. + * + * @param source The source requesting the restoration maneuver + * @param conditions The collection of all parameters with which to filter out logged events + * @throws Exception if something unexpected happens + */ + void restore(@Nonnull CommandSource source, @Nonnull Request conditions) throws Exception; + + /** + * Queries all events matching the conditions in the {@link Request} and sends + * the command source the matching information. + * + * @param source The source requesting the information + * @param conditions The collection of all parameters with which to filter out logged events + * @throws Exception if something unexpected happens + */ + void lookup(@Nonnull CommandSource source, @Nonnull Request conditions) throws Exception; + + /** + * Create a {@link Request.Builder} to construct a {@link Request} to use in a {@link PrismService}. + * + * @return a builder + */ + @Nonnull + @SuppressWarnings("unused") + static Request.Builder requestBuilder() { + return Request.builder(); + } + + /** + * A store for all filtering information necessary to locate logged events. + */ + class Request implements Serializable { + + private static final long serialVersionUID = 4369983541428028962L; + + private final Set events; + private final Set targets; + private final Set playerUuids; + private final Set worldUuids; + private final Range xRange; + private final Range yRange; + private final Range zRange; + private final Date earliest; + private final Date latest; + private final Set flags; + + private Request(@Nonnull Set events, + @Nonnull Set targets, + @Nonnull Set playerUuids, + @Nonnull Set worldUuids, + Range xRange, + Range yRange, + Range zRange, + Date earliest, + Date latest, + @Nonnull Set flags) { + this.events = events; + this.targets = targets; + this.playerUuids = playerUuids; + this.worldUuids = worldUuids; + this.xRange = xRange; + this.yRange = yRange; + this.zRange = zRange; + this.earliest = earliest; + this.latest = latest; + this.flags = flags; + } + + @Nonnull + public Set getEventId() { + return events; + } + + @Nonnull + public Set getTargets() { + return targets; + } + + @Nonnull + public Set getPlayerUuids() { + return playerUuids; + } + + @Nonnull + public Set getWorldUuids() { + return worldUuids; + } + + @Nonnull + public Optional> getxRange() { + return Optional.ofNullable(xRange); + } + + @Nonnull + public Optional> getyRange() { + return Optional.ofNullable(yRange); + } + + @Nonnull + public Optional> getzRange() { + return Optional.ofNullable(zRange); + } + + @Nonnull + public Optional getEarliest() { + return Optional.ofNullable(earliest); + } + + @Nonnull + public Optional getLatest() { + return Optional.ofNullable(latest); + } + + @Nonnull + public Set getFlags() { + return flags; + } + + @Nonnull + private static Builder builder() { + return new Builder(); + } + + public static class Builder { + + private Set events = Sets.newHashSet(); + private Set targets = Sets.newHashSet(); + private Set playerUuids = Sets.newHashSet(); + private Set worldUuids = Sets.newHashSet(); + private Range xRange = null; + private Range yRange = null; + private Range zRange = null; + private Date earliest = null; + private Date latest = null; + private Set flags = Sets.newHashSet(); + + private Builder() { + } + + public Request build() { + return new Request(events, targets, playerUuids, worldUuids, xRange, yRange, zRange, earliest, latest, flags); + } + + @SuppressWarnings("unused") + public void addEvent(@Nonnull PrismEvent event) { + Preconditions.checkNotNull(event); + this.events.add(event); + } + + @SuppressWarnings("unused") + public void addTarget(@Nonnull String target) { + Preconditions.checkNotNull(target); + this.targets.add(target); + } + + @SuppressWarnings("unused") + public void addPlayerUuid(@Nonnull UUID playerUuid) { + Preconditions.checkNotNull(playerUuid); + this.playerUuids.add(playerUuid); + } + + @SuppressWarnings("unused") + public void addWorldUuid(@Nonnull UUID worldUuid) { + Preconditions.checkNotNull(worldUuid); + this.worldUuids.add(worldUuid); + } + + @SuppressWarnings("unused") + public void setxRange(int lower, int upper) { + this.xRange = Range.closed(lower, upper); + } + + @SuppressWarnings("unused") + public void setyRange(int lower, int upper) { + this.yRange = Range.closed(lower, upper); + } + + @SuppressWarnings("unused") + public void setzRange(int lower, int upper) { + this.zRange = Range.closed(lower, upper); + } + + @SuppressWarnings("unused") + public void setEarliest(Date earliest) { + this.earliest = earliest; + } + + @SuppressWarnings("unused") + public void setLatest(Date latest) { + this.latest = latest; + } + + @SuppressWarnings("unused") + public void addFlag(@Nonnull Object flag) { + Preconditions.checkNotNull(flag); + this.flags.add(flag); + } + + } + + } + +} diff --git a/src/main/java/com/helion3/prism/api/services/PrismServiceImpl.java b/src/main/java/com/helion3/prism/api/services/PrismServiceImpl.java new file mode 100644 index 0000000..4de3400 --- /dev/null +++ b/src/main/java/com/helion3/prism/api/services/PrismServiceImpl.java @@ -0,0 +1,129 @@ +package com.helion3.prism.api.services; + +import com.helion3.prism.api.flags.Flag; +import com.helion3.prism.api.query.ConditionGroup; +import com.helion3.prism.api.query.FieldCondition; +import com.helion3.prism.api.query.MatchRule; +import com.helion3.prism.api.query.QuerySession; +import com.helion3.prism.api.query.Sort; +import com.helion3.prism.commands.ApplierCommand; +import com.helion3.prism.util.AsyncUtil; +import com.helion3.prism.util.DataQueries; +import org.spongepowered.api.command.CommandSource; + +import javax.annotation.Nonnull; +import java.util.regex.Pattern; + +public class PrismServiceImpl implements PrismService { + + @Override + public void rollback(@Nonnull CommandSource source, @Nonnull Request conditions) { + QuerySession session = buildSession(source, conditions); + session.addFlag(Flag.NO_GROUP); + ApplierCommand.runApplier(session, Sort.NEWEST_FIRST); + } + + @Override + public void restore(@Nonnull CommandSource source, @Nonnull Request conditions) { + QuerySession session = buildSession(source, conditions); + session.addFlag(Flag.NO_GROUP); + ApplierCommand.runApplier(session, Sort.OLDEST_FIRST); + } + + @Override + public void lookup(@Nonnull CommandSource source, @Nonnull Request conditions) { + AsyncUtil.lookup(buildSession(source, conditions)); + } + + private QuerySession buildSession(CommandSource source, Request conditions) { + final QuerySession session = new QuerySession(source); + com.helion3.prism.api.query.Query query = session.newQuery(); + + ConditionGroup eventConditionGroup = new ConditionGroup(ConditionGroup.Operator.OR); + conditions.getEventId().forEach(event -> + eventConditionGroup.add(FieldCondition.of( + DataQueries.EventName, + MatchRule.EQUALS, + event.getId()))); + if (!eventConditionGroup.getConditions().isEmpty()) { + query.addCondition(eventConditionGroup); + } + + ConditionGroup targetConditionGroup = new ConditionGroup(ConditionGroup.Operator.OR); + conditions.getTargets().forEach(target -> + targetConditionGroup.add(FieldCondition.of( + DataQueries.Target, + MatchRule.EQUALS, + Pattern.compile(target.replace("_", " "))))); + if (!targetConditionGroup.getConditions().isEmpty()) { + query.addCondition(targetConditionGroup); + } + + ConditionGroup playerConditionGroup = new ConditionGroup(ConditionGroup.Operator.OR); + conditions.getPlayerUuids().forEach(uuid -> + playerConditionGroup.add(FieldCondition.of( + DataQueries.Player, + MatchRule.EQUALS, + uuid.toString()))); + if (!playerConditionGroup.getConditions().isEmpty()) { + query.addCondition(playerConditionGroup); + } + + ConditionGroup worldConditionGroup = new ConditionGroup(ConditionGroup.Operator.OR); + conditions.getWorldUuids().forEach(uuid -> + worldConditionGroup.add(FieldCondition.of( + DataQueries.WorldUuid, + MatchRule.EQUALS, + uuid.toString()))); + if (!worldConditionGroup.getConditions().isEmpty()) { + query.addCondition(worldConditionGroup); + } + + conditions.getxRange().ifPresent(range -> { + query.addCondition(FieldCondition.of( + DataQueries.X, + MatchRule.GREATER_THAN_EQUAL, + range.lowerEndpoint())); + query.addCondition(FieldCondition.of( + DataQueries.X, + MatchRule.LESS_THAN_EQUAL, + range.upperEndpoint())); + }); + conditions.getyRange().ifPresent(range -> { + query.addCondition(FieldCondition.of( + DataQueries.Y, + MatchRule.GREATER_THAN_EQUAL, + range.lowerEndpoint())); + query.addCondition(FieldCondition.of( + DataQueries.Y, + MatchRule.LESS_THAN_EQUAL, + range.upperEndpoint())); + }); + conditions.getzRange().ifPresent(range -> { + query.addCondition(FieldCondition.of( + DataQueries.Z, + MatchRule.GREATER_THAN_EQUAL, + range.lowerEndpoint())); + query.addCondition(FieldCondition.of( + DataQueries.Z, + MatchRule.LESS_THAN_EQUAL, + range.upperEndpoint())); + }); + conditions.getEarliest().ifPresent(earliest -> + query.addCondition(FieldCondition.of( + DataQueries.Created, + MatchRule.GREATER_THAN_EQUAL, + earliest))); + conditions.getLatest().ifPresent(latest -> + query.addCondition(FieldCondition.of( + DataQueries.Created, + MatchRule.LESS_THAN_EQUAL, + latest))); + conditions.getFlags() + .stream() + .filter(o -> o instanceof Flag) + .map(o -> (Flag) o) + .forEach(session::addFlag); + return session; + } +} From 0f13eee4578c28aac4fdaf15616843fc9798398a Mon Sep 17 00:00:00 2001 From: pietelite Date: Tue, 21 Apr 2020 01:00:47 -0400 Subject: [PATCH 2/3] Moved Request object to a new file, fixed WorldUuid parameter, implemented builder chaining (cherry picked from commit 864b66901006ec7e6777b00f51c599a2f3cd5eaf) --- .../prism/api/services/PrismService.java | 185 ---------------- .../prism/api/services/PrismServiceImpl.java | 4 +- .../helion3/prism/api/services/Request.java | 203 ++++++++++++++++++ 3 files changed, 205 insertions(+), 187 deletions(-) create mode 100644 src/main/java/com/helion3/prism/api/services/Request.java diff --git a/src/main/java/com/helion3/prism/api/services/PrismService.java b/src/main/java/com/helion3/prism/api/services/PrismService.java index 5b6032b..19e6fcf 100644 --- a/src/main/java/com/helion3/prism/api/services/PrismService.java +++ b/src/main/java/com/helion3/prism/api/services/PrismService.java @@ -45,189 +45,4 @@ public interface PrismService { */ void lookup(@Nonnull CommandSource source, @Nonnull Request conditions) throws Exception; - /** - * Create a {@link Request.Builder} to construct a {@link Request} to use in a {@link PrismService}. - * - * @return a builder - */ - @Nonnull - @SuppressWarnings("unused") - static Request.Builder requestBuilder() { - return Request.builder(); - } - - /** - * A store for all filtering information necessary to locate logged events. - */ - class Request implements Serializable { - - private static final long serialVersionUID = 4369983541428028962L; - - private final Set events; - private final Set targets; - private final Set playerUuids; - private final Set worldUuids; - private final Range xRange; - private final Range yRange; - private final Range zRange; - private final Date earliest; - private final Date latest; - private final Set flags; - - private Request(@Nonnull Set events, - @Nonnull Set targets, - @Nonnull Set playerUuids, - @Nonnull Set worldUuids, - Range xRange, - Range yRange, - Range zRange, - Date earliest, - Date latest, - @Nonnull Set flags) { - this.events = events; - this.targets = targets; - this.playerUuids = playerUuids; - this.worldUuids = worldUuids; - this.xRange = xRange; - this.yRange = yRange; - this.zRange = zRange; - this.earliest = earliest; - this.latest = latest; - this.flags = flags; - } - - @Nonnull - public Set getEventId() { - return events; - } - - @Nonnull - public Set getTargets() { - return targets; - } - - @Nonnull - public Set getPlayerUuids() { - return playerUuids; - } - - @Nonnull - public Set getWorldUuids() { - return worldUuids; - } - - @Nonnull - public Optional> getxRange() { - return Optional.ofNullable(xRange); - } - - @Nonnull - public Optional> getyRange() { - return Optional.ofNullable(yRange); - } - - @Nonnull - public Optional> getzRange() { - return Optional.ofNullable(zRange); - } - - @Nonnull - public Optional getEarliest() { - return Optional.ofNullable(earliest); - } - - @Nonnull - public Optional getLatest() { - return Optional.ofNullable(latest); - } - - @Nonnull - public Set getFlags() { - return flags; - } - - @Nonnull - private static Builder builder() { - return new Builder(); - } - - public static class Builder { - - private Set events = Sets.newHashSet(); - private Set targets = Sets.newHashSet(); - private Set playerUuids = Sets.newHashSet(); - private Set worldUuids = Sets.newHashSet(); - private Range xRange = null; - private Range yRange = null; - private Range zRange = null; - private Date earliest = null; - private Date latest = null; - private Set flags = Sets.newHashSet(); - - private Builder() { - } - - public Request build() { - return new Request(events, targets, playerUuids, worldUuids, xRange, yRange, zRange, earliest, latest, flags); - } - - @SuppressWarnings("unused") - public void addEvent(@Nonnull PrismEvent event) { - Preconditions.checkNotNull(event); - this.events.add(event); - } - - @SuppressWarnings("unused") - public void addTarget(@Nonnull String target) { - Preconditions.checkNotNull(target); - this.targets.add(target); - } - - @SuppressWarnings("unused") - public void addPlayerUuid(@Nonnull UUID playerUuid) { - Preconditions.checkNotNull(playerUuid); - this.playerUuids.add(playerUuid); - } - - @SuppressWarnings("unused") - public void addWorldUuid(@Nonnull UUID worldUuid) { - Preconditions.checkNotNull(worldUuid); - this.worldUuids.add(worldUuid); - } - - @SuppressWarnings("unused") - public void setxRange(int lower, int upper) { - this.xRange = Range.closed(lower, upper); - } - - @SuppressWarnings("unused") - public void setyRange(int lower, int upper) { - this.yRange = Range.closed(lower, upper); - } - - @SuppressWarnings("unused") - public void setzRange(int lower, int upper) { - this.zRange = Range.closed(lower, upper); - } - - @SuppressWarnings("unused") - public void setEarliest(Date earliest) { - this.earliest = earliest; - } - - @SuppressWarnings("unused") - public void setLatest(Date latest) { - this.latest = latest; - } - - @SuppressWarnings("unused") - public void addFlag(@Nonnull Object flag) { - Preconditions.checkNotNull(flag); - this.flags.add(flag); - } - - } - - } - } diff --git a/src/main/java/com/helion3/prism/api/services/PrismServiceImpl.java b/src/main/java/com/helion3/prism/api/services/PrismServiceImpl.java index 4de3400..b259639 100644 --- a/src/main/java/com/helion3/prism/api/services/PrismServiceImpl.java +++ b/src/main/java/com/helion3/prism/api/services/PrismServiceImpl.java @@ -40,7 +40,7 @@ private QuerySession buildSession(CommandSource source, Request conditions) { com.helion3.prism.api.query.Query query = session.newQuery(); ConditionGroup eventConditionGroup = new ConditionGroup(ConditionGroup.Operator.OR); - conditions.getEventId().forEach(event -> + conditions.getEvents().forEach(event -> eventConditionGroup.add(FieldCondition.of( DataQueries.EventName, MatchRule.EQUALS, @@ -72,7 +72,7 @@ private QuerySession buildSession(CommandSource source, Request conditions) { ConditionGroup worldConditionGroup = new ConditionGroup(ConditionGroup.Operator.OR); conditions.getWorldUuids().forEach(uuid -> worldConditionGroup.add(FieldCondition.of( - DataQueries.WorldUuid, + DataQueries.Location.then(DataQueries.WorldUuid), MatchRule.EQUALS, uuid.toString()))); if (!worldConditionGroup.getConditions().isEmpty()) { diff --git a/src/main/java/com/helion3/prism/api/services/Request.java b/src/main/java/com/helion3/prism/api/services/Request.java new file mode 100644 index 0000000..356036b --- /dev/null +++ b/src/main/java/com/helion3/prism/api/services/Request.java @@ -0,0 +1,203 @@ +package com.helion3.prism.api.services; + +import com.google.common.base.Preconditions; +import com.google.common.collect.Range; +import com.google.common.collect.Sets; +import com.helion3.prism.api.data.PrismEvent; + +import javax.annotation.Nonnull; +import java.io.Serializable; +import java.util.Date; +import java.util.Optional; +import java.util.Set; +import java.util.UUID; + +/** + * A store for all filtering information necessary to locate logged events. + */ +public final class Request implements Serializable { + + private static final long serialVersionUID = 4369983541428028962L; + + /** + * Create a {@link Request.Builder} to construct a {@link Request} to use in a {@link PrismService}. + * + * @return a builder + */ + @Nonnull + public static Builder builder() { + return new Builder(); + } + + private final Set events; + private final Set targets; + private final Set playerUuids; + private final Set worldUuids; + private final Range xRange; + private final Range yRange; + private final Range zRange; + private final Date earliest; + private final Date latest; + + private final Set flags; + + private Request(@Nonnull Set events, + @Nonnull Set targets, + @Nonnull Set playerUuids, + @Nonnull Set worldUuids, + Range xRange, + Range yRange, + Range zRange, + Date earliest, + Date latest, + @Nonnull Set flags) { + this.events = events; + this.targets = targets; + this.playerUuids = playerUuids; + this.worldUuids = worldUuids; + this.xRange = xRange; + this.yRange = yRange; + this.zRange = zRange; + this.earliest = earliest; + this.latest = latest; + this.flags = flags; + } + + @Nonnull + public Set getEvents() { + return events; + } + + @Nonnull + public Set getTargets() { + return targets; + } + + @Nonnull + public Set getPlayerUuids() { + return playerUuids; + } + + @Nonnull + public Set getWorldUuids() { + return worldUuids; + } + + @Nonnull + public Optional> getxRange() { + return Optional.ofNullable(xRange); + } + + @Nonnull + public Optional> getyRange() { + return Optional.ofNullable(yRange); + } + + @Nonnull + public Optional> getzRange() { + return Optional.ofNullable(zRange); + } + + @Nonnull + public Optional getEarliest() { + return Optional.ofNullable(earliest); + } + + @Nonnull + public Optional getLatest() { + return Optional.ofNullable(latest); + } + + @Nonnull + public Set getFlags() { + return flags; + } + + public static class Builder { + + private Set events = Sets.newHashSet(); + private Set targets = Sets.newHashSet(); + private Set playerUuids = Sets.newHashSet(); + private Set worldUuids = Sets.newHashSet(); + private Range xRange = null; + private Range yRange = null; + private Range zRange = null; + private Date earliest = null; + private Date latest = null; + private Set flags = Sets.newHashSet(); + + private Builder() { + } + + public Request build() { + return new Request(events, targets, playerUuids, worldUuids, xRange, yRange, zRange, earliest, latest, flags); + } + + @SuppressWarnings("unused") + public Builder addEvent(@Nonnull PrismEvent event) { + Preconditions.checkNotNull(event); + this.events.add(event); + return this; + } + + @SuppressWarnings("unused") + public Builder addTarget(@Nonnull String target) { + Preconditions.checkNotNull(target); + this.targets.add(target); + return this; + } + + @SuppressWarnings("unused") + public Builder addPlayerUuid(@Nonnull UUID playerUuid) { + Preconditions.checkNotNull(playerUuid); + this.playerUuids.add(playerUuid); + return this; + } + + @SuppressWarnings("unused") + public Builder addWorldUuid(@Nonnull UUID worldUuid) { + Preconditions.checkNotNull(worldUuid); + this.worldUuids.add(worldUuid); + return this; + } + + @SuppressWarnings("unused") + public Builder setxRange(int lower, int upper) { + this.xRange = Range.closed(lower, upper); + return this; + } + + @SuppressWarnings("unused") + public Builder setyRange(int lower, int upper) { + this.yRange = Range.closed(lower, upper); + return this; + } + + @SuppressWarnings("unused") + public Builder setzRange(int lower, int upper) { + this.zRange = Range.closed(lower, upper); + return this; + } + + @SuppressWarnings("unused") + public Builder setEarliest(Date earliest) { + this.earliest = earliest; + return this; + } + + @SuppressWarnings("unused") + public Builder setLatest(Date latest) { + this.latest = latest; + return this; + } + + @SuppressWarnings("unused") + public Builder addFlag(@Nonnull Object flag) { + Preconditions.checkNotNull(flag); + this.flags.add(flag); + return this; + } + + } + +} From b3c205d80b0379f57b6ab40e67a4554736e068f0 Mon Sep 17 00:00:00 2001 From: pietelite Date: Sat, 2 May 2020 23:30:50 -0400 Subject: [PATCH 3/3] Removed unnecessary imports --- .../com/helion3/prism/api/services/PrismService.java | 9 --------- 1 file changed, 9 deletions(-) diff --git a/src/main/java/com/helion3/prism/api/services/PrismService.java b/src/main/java/com/helion3/prism/api/services/PrismService.java index 19e6fcf..4b71f53 100644 --- a/src/main/java/com/helion3/prism/api/services/PrismService.java +++ b/src/main/java/com/helion3/prism/api/services/PrismService.java @@ -1,17 +1,8 @@ package com.helion3.prism.api.services; -import com.google.common.base.Preconditions; -import com.google.common.collect.Range; -import com.google.common.collect.Sets; -import com.helion3.prism.api.data.PrismEvent; import org.spongepowered.api.command.CommandSource; import javax.annotation.Nonnull; -import java.io.Serializable; -import java.util.Date; -import java.util.Optional; -import java.util.Set; -import java.util.UUID; public interface PrismService {