diff --git a/currentmonitor/lantern-dataaccess-currentmonitor/src/main/java/com/lanternsoftware/dataaccess/currentmonitor/MongoCurrentMonitorDao.java b/currentmonitor/lantern-dataaccess-currentmonitor/src/main/java/com/lanternsoftware/dataaccess/currentmonitor/MongoCurrentMonitorDao.java index b0d26f9..0f44ec8 100644 --- a/currentmonitor/lantern-dataaccess-currentmonitor/src/main/java/com/lanternsoftware/dataaccess/currentmonitor/MongoCurrentMonitorDao.java +++ b/currentmonitor/lantern-dataaccess-currentmonitor/src/main/java/com/lanternsoftware/dataaccess/currentmonitor/MongoCurrentMonitorDao.java @@ -1,6 +1,7 @@ package com.lanternsoftware.dataaccess.currentmonitor; import com.lanternsoftware.datamodel.currentmonitor.Account; +import com.lanternsoftware.datamodel.currentmonitor.BillingRate; import com.lanternsoftware.datamodel.currentmonitor.Breaker; import com.lanternsoftware.datamodel.currentmonitor.BreakerConfig; import com.lanternsoftware.datamodel.currentmonitor.BreakerGroup; @@ -28,6 +29,7 @@ import org.slf4j.LoggerFactory; import java.util.ArrayList; import java.util.Calendar; +import java.util.Collection; import java.util.Date; import java.util.List; import java.util.Map; @@ -159,6 +161,32 @@ public class MongoCurrentMonitorDao implements CurrentMonitorDao { putBreakerGroupEnergy(summary); } + private void rebuildSummaries(int _accountId, Collection _rates) { + logger.info("Rebuilding summaries due to a change in {} rates", CollectionUtils.size(_rates)); + HubPowerMinute firstMinute = proxy.queryOne(HubPowerMinute.class, new DaoQuery("account_id", _accountId), DaoSort.sort("minute")); + if (firstMinute == null) + return; + TimeZone tz = getTimeZoneForAccount(_accountId); + Map rates = CollectionUtils.transformToMap(_rates, _r->String.format("%d%d", DaoSerializer.toLong(_r.getBeginEffective()), DaoSerializer.toLong(_r.getEndEffective()))); + for (BillingRate rate : rates.values()) { + Date start = rate.getBeginEffective(); + Date end = rate.getEndEffective(); + Date now = new Date(); + if ((start == null) || start.before(firstMinute.getMinuteAsDate())) + start = firstMinute.getMinuteAsDate(); + if ((end == null) || end.after(now)) + end = now; + rebuildSummaries(_accountId, start, end); + if (rate.isRecursAnnually()) { + while (end.before(now)) { + start = DateUtils.addYears(start, 1, tz); + end = DateUtils.addYears(end, 1, tz); + rebuildSummaries(_accountId, start, end); + } + } + } + } + @Override public void rebuildSummaries(int _accountId) { HubPowerMinute firstMinute = proxy.queryOne(HubPowerMinute.class, new DaoQuery("account_id", _accountId), DaoSort.sort("minute")); @@ -228,8 +256,20 @@ public class MongoCurrentMonitorDao implements CurrentMonitorDao { DaoQuery configQuery = new DaoQuery("_id", String.valueOf(_config.getAccountId())); BreakerConfig oldConfig = proxy.queryOne(BreakerConfig.class, configQuery); if (oldConfig != null) { - proxy.saveEntity("config_archive", DaoSerializer.toDaoEntity(oldConfig)); _config.setVersion(oldConfig.getVersion() + 1); + if (NullUtils.isNotIdentical(_config, oldConfig)) { + DaoEntity oldEntity = DaoSerializer.toDaoEntity(oldConfig); + oldEntity.put("_id", String.format("%d-%d", oldConfig.getAccountId(), oldConfig.getVersion())); + oldEntity.put("account_id", oldConfig.getAccountId()); + oldEntity.put("archive_date", DaoSerializer.toLong(new Date())); + proxy.saveEntity("config_archive", oldEntity); + executor.submit(() -> { + List changedRates = new ArrayList<>(_config.getBillingRates()); + changedRates.removeAll(CollectionUtils.makeNotNull(oldConfig.getBillingRates())); + if (!changedRates.isEmpty()) + rebuildSummaries(_config.getAccountId(), changedRates); + }); + } } proxy.save(_config); } diff --git a/currentmonitor/lantern-datamodel-currentmonitor/src/main/java/com/lanternsoftware/datamodel/currentmonitor/BillingMode.java b/currentmonitor/lantern-datamodel-currentmonitor/src/main/java/com/lanternsoftware/datamodel/currentmonitor/BillingMode.java deleted file mode 100644 index e353294..0000000 --- a/currentmonitor/lantern-datamodel-currentmonitor/src/main/java/com/lanternsoftware/datamodel/currentmonitor/BillingMode.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.lanternsoftware.datamodel.currentmonitor; - -public enum BillingMode { - ANY_DIRECTION, - CONSUMPTION, - PRODUCTION; -} diff --git a/currentmonitor/lantern-datamodel-currentmonitor/src/main/java/com/lanternsoftware/datamodel/currentmonitor/BillingRate.java b/currentmonitor/lantern-datamodel-currentmonitor/src/main/java/com/lanternsoftware/datamodel/currentmonitor/BillingRate.java index 1c52a91..79f431c 100644 --- a/currentmonitor/lantern-datamodel-currentmonitor/src/main/java/com/lanternsoftware/datamodel/currentmonitor/BillingRate.java +++ b/currentmonitor/lantern-datamodel-currentmonitor/src/main/java/com/lanternsoftware/datamodel/currentmonitor/BillingRate.java @@ -5,13 +5,14 @@ import com.lanternsoftware.util.dao.annotations.DBSerializable; import java.util.Calendar; import java.util.Date; +import java.util.Objects; import java.util.TimeZone; @DBSerializable public class BillingRate { private int meter; private int dayBillingCycleStart; - private BillingMode mode; + private GridFlow flow; private double rate; private BillingCurrency currency; private int timeOfDayStart; @@ -38,12 +39,12 @@ public class BillingRate { dayBillingCycleStart = _dayBillingCycleStart; } - public BillingMode getMode() { - return mode; + public GridFlow getFlow() { + return flow; } - public void setMode(BillingMode _mode) { - mode = _mode; + public void setFlow(GridFlow _flow) { + flow = _flow; } public double getRate() { @@ -118,8 +119,8 @@ public class BillingRate { recursAnnually = _recursAnnually; } - public boolean isApplicable(BillingMode _mode, int _meter, double _monthKWh, Date _time, TimeZone _tz) { - if ((mode != BillingMode.ANY_DIRECTION) && (mode != _mode)) + public boolean isApplicable(GridFlow _mode, int _meter, double _monthKWh, Date _time, TimeZone _tz) { + if ((flow != GridFlow.BOTH) && (flow != _mode)) return false; if ((meter != -1) && (_meter != meter)) return false; @@ -160,11 +161,24 @@ public class BillingRate { return rate * _kWh; } + @Override + public boolean equals(Object _o) { + if (this == _o) return true; + if (_o == null || getClass() != _o.getClass()) return false; + BillingRate that = (BillingRate) _o; + return meter == that.meter && dayBillingCycleStart == that.dayBillingCycleStart && Double.compare(that.rate, rate) == 0 && timeOfDayStart == that.timeOfDayStart && timeOfDayEnd == that.timeOfDayEnd && Double.compare(that.monthKWhStart, monthKWhStart) == 0 && Double.compare(that.monthKWhEnd, monthKWhEnd) == 0 && recursAnnually == that.recursAnnually && flow == that.flow && currency == that.currency && Objects.equals(beginEffective, that.beginEffective) && Objects.equals(endEffective, that.endEffective); + } + + @Override + public int hashCode() { + return Objects.hash(meter, dayBillingCycleStart, flow, rate, currency, timeOfDayStart, timeOfDayEnd, monthKWhStart, monthKWhEnd, beginEffective, endEffective, recursAnnually); + } + public BillingRate duplicate() { BillingRate r = new BillingRate(); r.setMeter(meter); r.setDayBillingCycleStart(dayBillingCycleStart); - r.setMode(mode); + r.setFlow(flow); r.setRate(rate); r.setCurrency(currency); r.setTimeOfDayStart(timeOfDayStart); diff --git a/currentmonitor/lantern-datamodel-currentmonitor/src/main/java/com/lanternsoftware/datamodel/currentmonitor/Breaker.java b/currentmonitor/lantern-datamodel-currentmonitor/src/main/java/com/lanternsoftware/datamodel/currentmonitor/Breaker.java index 430cb41..2001613 100644 --- a/currentmonitor/lantern-datamodel-currentmonitor/src/main/java/com/lanternsoftware/datamodel/currentmonitor/Breaker.java +++ b/currentmonitor/lantern-datamodel-currentmonitor/src/main/java/com/lanternsoftware/datamodel/currentmonitor/Breaker.java @@ -1,10 +1,13 @@ package com.lanternsoftware.datamodel.currentmonitor; +import com.lanternsoftware.util.IIdentical; import com.lanternsoftware.util.dao.annotations.DBSerializable; +import java.util.Objects; + @DBSerializable() -public class Breaker { +public class Breaker implements IIdentical { private static final int TANDEM_BREAKER_MASK = 3072; private static final int SPACE_MASK = 1023; private static final int TANDEM_BREAKER_A_MASK = 1024; @@ -137,7 +140,7 @@ public class Breaker { } public double getLowPassFilter() { - return Math.abs(lowPassFilter) < 0.05 ? 1.6: lowPassFilter; + return Math.abs(lowPassFilter) < 0.05 ? 1.6 : lowPassFilter; } public void setLowPassFilter(double _lowPassFilter) { @@ -161,7 +164,7 @@ public class Breaker { } public double getCalibrationFactor() { - return calibrationFactor == 0.0?1.0:calibrationFactor; + return calibrationFactor == 0.0 ? 1.0 : calibrationFactor; } public void setCalibrationFactor(double _calibrationFactor) { @@ -196,15 +199,15 @@ public class Breaker { } public static int portToChip(int _port) { - return (_port < 9)?1:0; + return (_port < 9) ? 1 : 0; } public static int portToPin(int _port) { - return (_port < 9)?_port-1:_port-8; + return (_port < 9) ? _port - 1 : _port - 8; } public static int toPort(int _chip, int _pin) { - return (_chip == 0)?_pin+8:_pin+1; + return (_chip == 0) ? _pin + 8 : _pin + 1; } public static boolean isTandemBreakerA(int _space) { @@ -224,7 +227,7 @@ public class Breaker { } public static int toSpace(int _id) { - return _id & (TANDEM_BREAKER_MASK |SPACE_MASK); + return _id & (TANDEM_BREAKER_MASK | SPACE_MASK); } public static String toSpaceDisplay(int _space) { @@ -238,4 +241,23 @@ public class Breaker { public int getSpaceIndex() { return space & SPACE_MASK; } + + @Override + public boolean equals(Object _o) { + if (this == _o) return true; + if (_o == null || getClass() != _o.getClass()) return false; + Breaker breaker = (Breaker) _o; + return panel == breaker.panel && space == breaker.space; + } + + @Override + public boolean isIdentical(Breaker _o) { + if (this == _o) return true; + return panel == _o.panel && space == _o.space && meter == _o.meter && hub == _o.hub && port == _o.port && sizeAmps == _o.sizeAmps && Double.compare(_o.calibrationFactor, calibrationFactor) == 0 && Double.compare(_o.lowPassFilter, lowPassFilter) == 0 && doublePower == _o.doublePower && Objects.equals(name, _o.name) && Objects.equals(description, _o.description) && polarity == _o.polarity && type == _o.type && Objects.equals(key, _o.key); + } + + @Override + public int hashCode() { + return Objects.hash(panel, space); + } } diff --git a/currentmonitor/lantern-datamodel-currentmonitor/src/main/java/com/lanternsoftware/datamodel/currentmonitor/BreakerConfig.java b/currentmonitor/lantern-datamodel-currentmonitor/src/main/java/com/lanternsoftware/datamodel/currentmonitor/BreakerConfig.java index 178f6ee..3fcf7a3 100644 --- a/currentmonitor/lantern-datamodel-currentmonitor/src/main/java/com/lanternsoftware/datamodel/currentmonitor/BreakerConfig.java +++ b/currentmonitor/lantern-datamodel-currentmonitor/src/main/java/com/lanternsoftware/datamodel/currentmonitor/BreakerConfig.java @@ -1,6 +1,7 @@ package com.lanternsoftware.datamodel.currentmonitor; import com.lanternsoftware.util.CollectionUtils; +import com.lanternsoftware.util.IIdentical; import com.lanternsoftware.util.NullUtils; import com.lanternsoftware.util.dao.DaoSerializer; import com.lanternsoftware.util.dao.annotations.DBSerializable; @@ -8,9 +9,10 @@ import com.lanternsoftware.util.dao.annotations.PrimaryKey; import java.util.ArrayList; import java.util.List; +import java.util.Objects; @DBSerializable(autogen = false) -public class BreakerConfig { +public class BreakerConfig implements IIdentical { @PrimaryKey private int accountId; private List meters; @@ -182,4 +184,23 @@ public class BreakerConfig { public BillingCurrency getCurrency() { return CollectionUtils.getFirst(CollectionUtils.transformToSet(billingRates, BillingRate::getCurrency)); } + + @Override + public boolean equals(Object _o) { + if (this == _o) return true; + if (_o == null || getClass() != _o.getClass()) return false; + BreakerConfig that = (BreakerConfig) _o; + return accountId == that.accountId && CollectionUtils.isEqual(meters, that.meters) && CollectionUtils.isEqual(panels, that.panels) && CollectionUtils.isEqual(breakerHubs, that.breakerHubs) && CollectionUtils.isEqual(breakerGroups, that.breakerGroups) && CollectionUtils.isEqual(billingRates, that.billingRates); + } + + @Override + public boolean isIdentical(BreakerConfig _o) { + if (this == _o) return true; + return accountId == _o.accountId && CollectionUtils.isIdentical(meters, _o.meters) && CollectionUtils.isIdentical(panels, _o.panels) && CollectionUtils.isIdentical(breakerHubs, _o.breakerHubs) && CollectionUtils.isIdentical(breakerGroups, _o.breakerGroups) && CollectionUtils.isEqual(billingRates, _o.billingRates); + } + + @Override + public int hashCode() { + return Objects.hash(accountId, meters, panels, breakerHubs, breakerGroups, billingRates, version); + } } diff --git a/currentmonitor/lantern-datamodel-currentmonitor/src/main/java/com/lanternsoftware/datamodel/currentmonitor/BreakerGroup.java b/currentmonitor/lantern-datamodel-currentmonitor/src/main/java/com/lanternsoftware/datamodel/currentmonitor/BreakerGroup.java index 7643516..44dfd74 100644 --- a/currentmonitor/lantern-datamodel-currentmonitor/src/main/java/com/lanternsoftware/datamodel/currentmonitor/BreakerGroup.java +++ b/currentmonitor/lantern-datamodel-currentmonitor/src/main/java/com/lanternsoftware/datamodel/currentmonitor/BreakerGroup.java @@ -2,18 +2,18 @@ package com.lanternsoftware.datamodel.currentmonitor; import com.lanternsoftware.util.CollectionUtils; +import com.lanternsoftware.util.IIdentical; import com.lanternsoftware.util.NullUtils; import com.lanternsoftware.util.dao.annotations.DBSerializable; import com.lanternsoftware.util.dao.annotations.PrimaryKey; import java.util.ArrayList; -import java.util.Iterator; import java.util.List; import java.util.Objects; import java.util.Set; @DBSerializable() -public class BreakerGroup { +public class BreakerGroup implements IIdentical { @PrimaryKey private String id; private int accountId; private String name; @@ -186,6 +186,15 @@ public class BreakerGroup { return Objects.equals(id, that.id); } + @Override + public boolean isIdentical(BreakerGroup _o) { + if (this == _o) + return true; + if (_o == null) + return false; + return NullUtils.isEqual(id, _o.id) && accountId == _o.accountId && NullUtils.isEqual(name, _o.name) && CollectionUtils.isIdentical(subGroups, _o.subGroups) && CollectionUtils.isIdentical(breakers, _o.breakers); + } + @Override public int hashCode() { return Objects.hash(id); diff --git a/currentmonitor/lantern-datamodel-currentmonitor/src/main/java/com/lanternsoftware/datamodel/currentmonitor/BreakerGroupEnergy.java b/currentmonitor/lantern-datamodel-currentmonitor/src/main/java/com/lanternsoftware/datamodel/currentmonitor/BreakerGroupEnergy.java index 9d101ac..8ae8613 100644 --- a/currentmonitor/lantern-datamodel-currentmonitor/src/main/java/com/lanternsoftware/datamodel/currentmonitor/BreakerGroupEnergy.java +++ b/currentmonitor/lantern-datamodel-currentmonitor/src/main/java/com/lanternsoftware/datamodel/currentmonitor/BreakerGroupEnergy.java @@ -96,8 +96,8 @@ public class BreakerGroupEnergy { double secondFromGrid; for (Map.Entry meter : meters.entrySet()) { double monthkWh = monthFromGrid/3600000; - List consumptionRates = CollectionUtils.filter(_rates, _r->_r.isApplicable(BillingMode.CONSUMPTION, meter.getKey().meter, monthkWh, meter.getKey().minute, timezone)); - List productionRates = CollectionUtils.filter(_rates, _r->_r.isApplicable(BillingMode.PRODUCTION, meter.getKey().meter, monthkWh, meter.getKey().minute, timezone)); + List consumptionRates = CollectionUtils.filter(_rates, _r->_r.isApplicable(GridFlow.FROM, meter.getKey().meter, monthkWh, meter.getKey().minute, timezone)); + List productionRates = CollectionUtils.filter(_rates, _r->_r.isApplicable(GridFlow.TO, meter.getKey().meter, monthkWh, meter.getKey().minute, timezone)); for (int i = 0; i < 60; i++) { secondFromGrid = meter.getValue().usage[i] - meter.getValue().solar[i]; monthFromGrid += secondFromGrid; @@ -351,7 +351,7 @@ public class BreakerGroupEnergy { return charge(_selectedBreakers, true); } - public double charge(Set _selectedBreakers, BillingMode _mode) { + public double charge(Set _selectedBreakers, GridFlow _mode) { return charge(_selectedBreakers, true, _mode); } @@ -359,7 +359,7 @@ public class BreakerGroupEnergy { return charge(_selectedBreakers, _includeSubgroups, null); } - public double charge(Set _selectedBreakers, boolean _includeSubgroups, BillingMode _mode) { + public double charge(Set _selectedBreakers, boolean _includeSubgroups, GridFlow _mode) { double charge = 0.0; if (_includeSubgroups) { for (BreakerGroupEnergy group : CollectionUtils.makeNotNull(subGroups)) { @@ -368,7 +368,7 @@ public class BreakerGroupEnergy { } if ((energyBlocks != null) && ((_selectedBreakers == null) || _selectedBreakers.contains(getGroupId()))) { for (EnergyBlock energy : energyBlocks) { - if ((_mode == null) || ((_mode == BillingMode.PRODUCTION) && energy.getCharge() < 0.0) || (_mode == BillingMode.CONSUMPTION && energy.getCharge() > 0.0)) + if ((_mode == null) || ((_mode == GridFlow.TO) && energy.getCharge() < 0.0) || (_mode == GridFlow.FROM && energy.getCharge() > 0.0)) charge += energy.getCharge(); } } diff --git a/currentmonitor/lantern-datamodel-currentmonitor/src/main/java/com/lanternsoftware/datamodel/currentmonitor/BreakerHub.java b/currentmonitor/lantern-datamodel-currentmonitor/src/main/java/com/lanternsoftware/datamodel/currentmonitor/BreakerHub.java index 68a4526..bb47fcd 100644 --- a/currentmonitor/lantern-datamodel-currentmonitor/src/main/java/com/lanternsoftware/datamodel/currentmonitor/BreakerHub.java +++ b/currentmonitor/lantern-datamodel-currentmonitor/src/main/java/com/lanternsoftware/datamodel/currentmonitor/BreakerHub.java @@ -1,10 +1,13 @@ package com.lanternsoftware.datamodel.currentmonitor; +import com.lanternsoftware.util.IIdentical; import com.lanternsoftware.util.dao.annotations.DBSerializable; +import java.util.Objects; + @DBSerializable -public class BreakerHub { +public class BreakerHub implements IIdentical { private int hub; private double voltageCalibrationFactor; private double portCalibrationFactor; @@ -50,4 +53,23 @@ public class BreakerHub { public void setBluetoothMac(String _bluetoothMac) { bluetoothMac = _bluetoothMac; } + + @Override + public boolean equals(Object _o) { + if (this == _o) return true; + if (_o == null || getClass() != _o.getClass()) return false; + BreakerHub that = (BreakerHub) _o; + return hub == that.hub; + } + + @Override + public boolean isIdentical(BreakerHub _o) { + if (this == _o) return true; + return hub == _o.hub && Double.compare(_o.voltageCalibrationFactor, voltageCalibrationFactor) == 0 && Double.compare(_o.portCalibrationFactor, portCalibrationFactor) == 0 && frequency == _o.frequency && Objects.equals(bluetoothMac, _o.bluetoothMac); + } + + @Override + public int hashCode() { + return Objects.hash(hub); + } } diff --git a/currentmonitor/lantern-datamodel-currentmonitor/src/main/java/com/lanternsoftware/datamodel/currentmonitor/BreakerPanel.java b/currentmonitor/lantern-datamodel-currentmonitor/src/main/java/com/lanternsoftware/datamodel/currentmonitor/BreakerPanel.java index a24ac82..02f5f8d 100644 --- a/currentmonitor/lantern-datamodel-currentmonitor/src/main/java/com/lanternsoftware/datamodel/currentmonitor/BreakerPanel.java +++ b/currentmonitor/lantern-datamodel-currentmonitor/src/main/java/com/lanternsoftware/datamodel/currentmonitor/BreakerPanel.java @@ -1,9 +1,12 @@ package com.lanternsoftware.datamodel.currentmonitor; +import com.lanternsoftware.util.IIdentical; import com.lanternsoftware.util.dao.annotations.DBSerializable; +import java.util.Objects; + @DBSerializable -public class BreakerPanel { +public class BreakerPanel implements IIdentical { private int accountId; private String name; private int index; @@ -49,4 +52,23 @@ public class BreakerPanel { public void setMeter(int _meter) { meter = _meter; } + + @Override + public boolean equals(Object _o) { + if (this == _o) return true; + if (_o == null || getClass() != _o.getClass()) return false; + BreakerPanel that = (BreakerPanel) _o; + return accountId == that.accountId && index == that.index; + } + + @Override + public boolean isIdentical(BreakerPanel _o) { + if (this == _o) return true; + return accountId == _o.accountId && index == _o.index && spaces == _o.spaces && meter == _o.meter && Objects.equals(name, _o.name); + } + + @Override + public int hashCode() { + return Objects.hash(accountId, index); + } } diff --git a/currentmonitor/lantern-datamodel-currentmonitor/src/main/java/com/lanternsoftware/datamodel/currentmonitor/GridFlow.java b/currentmonitor/lantern-datamodel-currentmonitor/src/main/java/com/lanternsoftware/datamodel/currentmonitor/GridFlow.java new file mode 100644 index 0000000..9e0c633 --- /dev/null +++ b/currentmonitor/lantern-datamodel-currentmonitor/src/main/java/com/lanternsoftware/datamodel/currentmonitor/GridFlow.java @@ -0,0 +1,7 @@ +package com.lanternsoftware.datamodel.currentmonitor; + +public enum GridFlow { + BOTH, + FROM, + TO; +} diff --git a/currentmonitor/lantern-datamodel-currentmonitor/src/main/java/com/lanternsoftware/datamodel/currentmonitor/Meter.java b/currentmonitor/lantern-datamodel-currentmonitor/src/main/java/com/lanternsoftware/datamodel/currentmonitor/Meter.java index ebf13f8..76392d2 100644 --- a/currentmonitor/lantern-datamodel-currentmonitor/src/main/java/com/lanternsoftware/datamodel/currentmonitor/Meter.java +++ b/currentmonitor/lantern-datamodel-currentmonitor/src/main/java/com/lanternsoftware/datamodel/currentmonitor/Meter.java @@ -1,9 +1,12 @@ package com.lanternsoftware.datamodel.currentmonitor; +import com.lanternsoftware.util.IIdentical; import com.lanternsoftware.util.dao.annotations.DBSerializable; +import java.util.Objects; + @DBSerializable -public class Meter { +public class Meter implements IIdentical { private int accountId; private int index; private String name; @@ -31,4 +34,24 @@ public class Meter { public void setName(String _name) { name = _name; } + + @Override + public boolean equals(Object _o) { + if (this == _o) return true; + if (_o == null || getClass() != _o.getClass()) return false; + Meter meter = (Meter) _o; + return accountId == meter.accountId && index == meter.index; + } + + @Override + public boolean isIdentical(Meter _o) { + if (this == _o) return true; + if (_o == null) return false; + return accountId == _o.accountId && index == _o.index && Objects.equals(name, _o.name); + } + + @Override + public int hashCode() { + return Objects.hash(accountId, index); + } } diff --git a/currentmonitor/lantern-datamodel-currentmonitor/src/main/java/com/lanternsoftware/datamodel/currentmonitor/dao/BillingRateSerializer.java b/currentmonitor/lantern-datamodel-currentmonitor/src/main/java/com/lanternsoftware/datamodel/currentmonitor/dao/BillingRateSerializer.java index 7711e2c..ec1006b 100644 --- a/currentmonitor/lantern-datamodel-currentmonitor/src/main/java/com/lanternsoftware/datamodel/currentmonitor/dao/BillingRateSerializer.java +++ b/currentmonitor/lantern-datamodel-currentmonitor/src/main/java/com/lanternsoftware/datamodel/currentmonitor/dao/BillingRateSerializer.java @@ -1,7 +1,7 @@ package com.lanternsoftware.datamodel.currentmonitor.dao; import com.lanternsoftware.datamodel.currentmonitor.BillingCurrency; -import com.lanternsoftware.datamodel.currentmonitor.BillingMode; +import com.lanternsoftware.datamodel.currentmonitor.GridFlow; import com.lanternsoftware.datamodel.currentmonitor.BillingRate; import com.lanternsoftware.util.dao.AbstractDaoSerializer; import com.lanternsoftware.util.dao.DaoEntity; @@ -29,7 +29,7 @@ public class BillingRateSerializer extends AbstractDaoSerializer DaoEntity d = new DaoEntity(); d.put("meter", _o.getMeter()); d.put("day_billing_cycle_start", _o.getDayBillingCycleStart()); - d.put("mode", DaoSerializer.toEnumName(_o.getMode())); + d.put("flow", DaoSerializer.toEnumName(_o.getFlow())); d.put("rate", _o.getRate()); d.put("unit", DaoSerializer.toEnumName(_o.getCurrency())); d.put("time_of_day_start", _o.getTimeOfDayStart()); @@ -48,7 +48,7 @@ public class BillingRateSerializer extends AbstractDaoSerializer BillingRate o = new BillingRate(); o.setMeter(DaoSerializer.getInteger(_d, "meter")); o.setDayBillingCycleStart(DaoSerializer.getInteger(_d, "day_billing_cycle_start")); - o.setMode(DaoSerializer.getEnum(_d, "mode", BillingMode.class)); + o.setFlow(DaoSerializer.getEnum(_d, "flow", GridFlow.class, GridFlow.BOTH)); o.setRate(DaoSerializer.getDouble(_d, "rate")); o.setCurrency(DaoSerializer.getEnum(_d, "unit", BillingCurrency.class)); o.setTimeOfDayStart(DaoSerializer.getInteger(_d, "time_of_day_start")); diff --git a/currentmonitor/lantern-service-currentmonitor/src/main/java/com/lanternsoftware/currentmonitor/servlet/ConfigServlet.java b/currentmonitor/lantern-service-currentmonitor/src/main/java/com/lanternsoftware/currentmonitor/servlet/ConfigServlet.java index e48dd6f..e22df18 100644 --- a/currentmonitor/lantern-service-currentmonitor/src/main/java/com/lanternsoftware/currentmonitor/servlet/ConfigServlet.java +++ b/currentmonitor/lantern-service-currentmonitor/src/main/java/com/lanternsoftware/currentmonitor/servlet/ConfigServlet.java @@ -1,8 +1,10 @@ package com.lanternsoftware.currentmonitor.servlet; import com.lanternsoftware.currentmonitor.context.Globals; -import com.lanternsoftware.util.dao.auth.AuthCode; import com.lanternsoftware.datamodel.currentmonitor.BreakerConfig; +import com.lanternsoftware.util.dao.auth.AuthCode; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServletRequest; @@ -10,6 +12,8 @@ import javax.servlet.http.HttpServletResponse; @WebServlet("/config/*") public class ConfigServlet extends SecureServlet { + private static final Logger logger = LoggerFactory.getLogger(ConfigServlet.class); + @Override protected void get(AuthCode _authCode, HttpServletRequest _req, HttpServletResponse _rep) { if (isPath(_req, 0, "bin")) @@ -29,6 +33,7 @@ public class ConfigServlet extends SecureServlet { _rep.setStatus(401); return; } + logger.info("Received config for account {}", config.getAccountId()); Globals.dao.putConfig(config); } } diff --git a/util/lantern-util-common/src/main/java/com/lanternsoftware/util/CollectionUtils.java b/util/lantern-util-common/src/main/java/com/lanternsoftware/util/CollectionUtils.java index 0bc70f1..99ca3f1 100644 --- a/util/lantern-util-common/src/main/java/com/lanternsoftware/util/CollectionUtils.java +++ b/util/lantern-util-common/src/main/java/com/lanternsoftware/util/CollectionUtils.java @@ -177,6 +177,30 @@ public class CollectionUtils { return _arr[_arr.length - 1]; } + public static boolean isEqual(Collection _l1, Collection _l2) { + if (size(_l1) != size(_l2)) + return false; + Iterator i1 = _l1.iterator(); + Iterator i2 = _l2.iterator(); + while (i1.hasNext()) { + if (NullUtils.isNotEqual(i1.next(), i2.next())) + return false; + } + return true; + } + + public static > boolean isIdentical(Collection _l1, Collection _l2) { + if (size(_l1) != size(_l2)) + return false; + Iterator i1 = _l1.iterator(); + Iterator i2 = _l2.iterator(); + while (i1.hasNext()) { + if (NullUtils.isNotIdentical(i1.next(), i2.next())) + return false; + } + return true; + } + public static boolean contains(Collection _coll, T _t) { if (_coll == null) return false; diff --git a/util/lantern-util-common/src/main/java/com/lanternsoftware/util/DateUtils.java b/util/lantern-util-common/src/main/java/com/lanternsoftware/util/DateUtils.java index b0697e2..815dc15 100644 --- a/util/lantern-util-common/src/main/java/com/lanternsoftware/util/DateUtils.java +++ b/util/lantern-util-common/src/main/java/com/lanternsoftware/util/DateUtils.java @@ -1,11 +1,11 @@ package com.lanternsoftware.util; -import java.sql.Time; import java.text.DateFormat; import java.text.SimpleDateFormat; import java.util.Calendar; import java.util.Date; import java.util.GregorianCalendar; +import java.util.Locale; import java.util.TimeZone; public abstract class DateUtils { @@ -405,6 +405,14 @@ public abstract class DateUtils { return dateFormat(_format, _tz).format(_dt); } + public static String formatDate(int _format, TimeZone _tz, Date _dt) { + if (_dt == null) + return null; + DateFormat format = DateFormat.getDateInstance(_format, Locale.getDefault()); + format.setTimeZone(_tz); + return format.format(_dt); + } + public static Date parse(String _format, String _date) { return parse(_format, TimeZone.getTimeZone("UTC"), _date); } diff --git a/util/lantern-util-common/src/main/java/com/lanternsoftware/util/IIdentical.java b/util/lantern-util-common/src/main/java/com/lanternsoftware/util/IIdentical.java new file mode 100644 index 0000000..8d986bd --- /dev/null +++ b/util/lantern-util-common/src/main/java/com/lanternsoftware/util/IIdentical.java @@ -0,0 +1,5 @@ +package com.lanternsoftware.util; + +public interface IIdentical { + boolean isIdentical(T _other); +} diff --git a/util/lantern-util-common/src/main/java/com/lanternsoftware/util/NullUtils.java b/util/lantern-util-common/src/main/java/com/lanternsoftware/util/NullUtils.java index df59a60..60701d3 100644 --- a/util/lantern-util-common/src/main/java/com/lanternsoftware/util/NullUtils.java +++ b/util/lantern-util-common/src/main/java/com/lanternsoftware/util/NullUtils.java @@ -23,6 +23,16 @@ public class NullUtils { return (b == null); } + public static > boolean isNotIdentical(T a, T b) { + return !isIdentical(a, b); + } + + public static > boolean isIdentical(T a, T b) { + if (a != null) + return (b != null) && a.isIdentical(b); + return (b == null); + } + public static boolean isNotEqual(T a, T b, IEquals _equals) { return !isEqual(a, b, _equals); }