From 728e55fc00a4b7b980d6e59f2ce8664859a5c848 Mon Sep 17 00:00:00 2001 From: Anton Tananaev Date: Tue, 26 Feb 2019 19:05:25 -0800 Subject: Refactor computed attributes --- src/org/traccar/BasePipelineFactory.java | 8 +---- src/org/traccar/MainModule.java | 17 ++++++++++ .../traccar/api/resource/AttributeResource.java | 9 ++++-- src/org/traccar/config/Keys.java | 12 +++++++ .../traccar/handler/ComputedAttributesHandler.java | 37 ++++++++++++++-------- .../traccar/handler/ComputedAttributesTest.java | 29 +++++++++-------- 6 files changed, 76 insertions(+), 36 deletions(-) diff --git a/src/org/traccar/BasePipelineFactory.java b/src/org/traccar/BasePipelineFactory.java index 088689fe7..85127fd7a 100644 --- a/src/org/traccar/BasePipelineFactory.java +++ b/src/org/traccar/BasePipelineFactory.java @@ -57,8 +57,6 @@ public abstract class BasePipelineFactory extends ChannelInitializer { private final TrackerServer server; private int timeout; - private ComputedAttributesHandler computedAttributesHandler; - private CommandResultEventHandler commandResultEventHandler; private OverspeedEventHandler overspeedEventHandler; private FuelDropEventHandler fuelDropEventHandler; @@ -77,10 +75,6 @@ public abstract class BasePipelineFactory extends ChannelInitializer { timeout = Context.getConfig().getInteger(Keys.SERVER_TIMEOUT); } - if (Context.getConfig().getBoolean("processing.computedAttributes.enable")) { - computedAttributesHandler = new ComputedAttributesHandler(); - } - if (Context.getConfig().getBoolean("event.enable")) { commandResultEventHandler = new CommandResultEventHandler(); overspeedEventHandler = Context.getOverspeedEventHandler(); @@ -157,7 +151,7 @@ public abstract class BasePipelineFactory extends ChannelInitializer { Main.getInjector().getInstance(MotionHandler.class), Main.getInjector().getInstance(EngineHoursHandler.class), Main.getInjector().getInstance(CopyAttributesHandler.class), - computedAttributesHandler); + Main.getInjector().getInstance(ComputedAttributesHandler.class)); if (Context.getDataManager() != null) { pipeline.addLast(new DefaultDataHandler()); diff --git a/src/org/traccar/MainModule.java b/src/org/traccar/MainModule.java index 34ece8658..f784a1a71 100644 --- a/src/org/traccar/MainModule.java +++ b/src/org/traccar/MainModule.java @@ -21,6 +21,7 @@ import com.google.inject.Provides; import com.google.inject.Singleton; import org.traccar.config.Config; import org.traccar.config.Keys; +import org.traccar.database.AttributesManager; import org.traccar.database.DataManager; import org.traccar.database.IdentityManager; import org.traccar.database.StatisticsManager; @@ -43,6 +44,7 @@ import org.traccar.geolocation.GoogleGeolocationProvider; import org.traccar.geolocation.MozillaGeolocationProvider; import org.traccar.geolocation.OpenCellIdGeolocationProvider; import org.traccar.geolocation.UnwiredGeolocationProvider; +import org.traccar.handler.ComputedAttributesHandler; import org.traccar.handler.CopyAttributesHandler; import org.traccar.handler.DistanceHandler; import org.traccar.handler.EngineHoursHandler; @@ -89,6 +91,11 @@ public class MainModule extends AbstractModule { return Context.getTripsConfig(); } + @Provides + public static AttributesManager provideAttributesManager() { + return Context.getAttributesManager(); + } + @Singleton @Provides public static StatisticsManager provideStatisticsManager(Config config, DataManager dataManager, Client client) { @@ -247,6 +254,16 @@ public class MainModule extends AbstractModule { return null; } + @Singleton + @Provides + public static ComputedAttributesHandler provideComputedAttributesHandler( + Config config, IdentityManager identityManager, AttributesManager attributesManager) { + if (config.getBoolean(Keys.PROCESSING_COMPUTED_ATTRIBUTES_ENABLE)) { + return new ComputedAttributesHandler(config, identityManager, attributesManager); + } + return null; + } + @Override protected void configure() { binder().requireExplicitBindings(); diff --git a/src/org/traccar/api/resource/AttributeResource.java b/src/org/traccar/api/resource/AttributeResource.java index fefc84041..de69d871c 100644 --- a/src/org/traccar/api/resource/AttributeResource.java +++ b/src/org/traccar/api/resource/AttributeResource.java @@ -1,5 +1,5 @@ /* - * Copyright 2017 - 2018 Anton Tananaev (anton@traccar.org) + * Copyright 2017 - 2019 Anton Tananaev (anton@traccar.org) * Copyright 2017 - 2018 Andrey Kunitsyn (andrey@traccar.org) * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -46,12 +46,15 @@ public class AttributeResource extends ExtendedObjectResource { @POST @Path("test") - public Response test(@QueryParam("deviceId") long deviceId, Attribute entity) throws SQLException { + public Response test(@QueryParam("deviceId") long deviceId, Attribute entity) { Context.getPermissionsManager().checkAdmin(getUserId()); Context.getPermissionsManager().checkDevice(getUserId(), deviceId); Position last = Context.getIdentityManager().getLastPosition(deviceId); if (last != null) { - Object result = new ComputedAttributesHandler().computeAttribute(entity, last); + Object result = new ComputedAttributesHandler( + Context.getConfig(), + Context.getIdentityManager(), + Context.getAttributesManager()).computeAttribute(entity, last); if (result != null) { switch (entity.getType()) { case "number": diff --git a/src/org/traccar/config/Keys.java b/src/org/traccar/config/Keys.java index b9bc0c9dc..ce6ad640d 100644 --- a/src/org/traccar/config/Keys.java +++ b/src/org/traccar/config/Keys.java @@ -192,6 +192,18 @@ public final class Keys { public static final ConfigKey PROCESSING_COPY_ATTRIBUTES_ENABLE = new ConfigKey( "processing.copyAttributes.enable", Boolean.class); + /** + * Enable computed attributes processing. + */ + public static final ConfigKey PROCESSING_COMPUTED_ATTRIBUTES_ENABLE = new ConfigKey( + "processing.computedAttributes.enable", Boolean.class); + + /** + * Enable computed attributes processing. + */ + public static final ConfigKey PROCESSING_COMPUTED_ATTRIBUTES_DEVICE_ATTRIBUTES = new ConfigKey( + "processing.computedAttributes.deviceAttributes", Boolean.class); + /** * Boolean flag to enable or disable reverse geocoder. */ diff --git a/src/org/traccar/handler/ComputedAttributesHandler.java b/src/org/traccar/handler/ComputedAttributesHandler.java index 5ceadafdd..153da29b9 100644 --- a/src/org/traccar/handler/ComputedAttributesHandler.java +++ b/src/org/traccar/handler/ComputedAttributesHandler.java @@ -1,5 +1,5 @@ /* - * Copyright 2017 Anton Tananaev (anton@traccar.org) + * Copyright 2017 - 2019 Anton Tananaev (anton@traccar.org) * Copyright 2017 Andrey Kunitsyn (andrey@traccar.org) * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -32,7 +32,10 @@ import org.apache.commons.jexl2.MapContext; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.traccar.BaseDataHandler; -import org.traccar.Context; +import org.traccar.config.Config; +import org.traccar.config.Keys; +import org.traccar.database.AttributesManager; +import org.traccar.database.IdentityManager; import org.traccar.model.Attribute; import org.traccar.model.Device; import org.traccar.model.Position; @@ -42,23 +45,27 @@ public class ComputedAttributesHandler extends BaseDataHandler { private static final Logger LOGGER = LoggerFactory.getLogger(ComputedAttributesHandler.class); - private JexlEngine engine; + private final IdentityManager identityManager; + private final AttributesManager attributesManager; - private boolean mapDeviceAttributes; + private final JexlEngine engine; - public ComputedAttributesHandler() { + private final boolean includeDeviceAttributes; + + public ComputedAttributesHandler( + Config config, IdentityManager identityManager, AttributesManager attributesManager) { + this.identityManager = identityManager; + this.attributesManager = attributesManager; engine = new JexlEngine(); engine.setStrict(true); - engine.setFunctions(Collections.singletonMap("math", (Object) Math.class)); - if (Context.getConfig() != null) { - mapDeviceAttributes = Context.getConfig().getBoolean("processing.computedAttributes.deviceAttributes"); - } + engine.setFunctions(Collections.singletonMap("math", Math.class)); + includeDeviceAttributes = config.getBoolean(Keys.PROCESSING_COMPUTED_ATTRIBUTES_DEVICE_ATTRIBUTES); } private MapContext prepareContext(Position position) { MapContext result = new MapContext(); - if (mapDeviceAttributes) { - Device device = Context.getIdentityManager().getById(position.getDeviceId()); + if (includeDeviceAttributes) { + Device device = identityManager.getById(position.getDeviceId()); if (device != null) { for (Object key : device.getAttributes().keySet()) { result.set((String) key, device.getAttributes().get(key)); @@ -87,14 +94,18 @@ public class ComputedAttributesHandler extends BaseDataHandler { return result; } + /** + * @deprecated logic needs to be extracted to be used in API resource + */ + @Deprecated public Object computeAttribute(Attribute attribute, Position position) throws JexlException { return engine.createExpression(attribute.getExpression()).evaluate(prepareContext(position)); } @Override protected Position handlePosition(Position position) { - Collection attributes = Context.getAttributesManager().getItems( - Context.getAttributesManager().getAllDeviceItems(position.getDeviceId())); + Collection attributes = attributesManager.getItems( + attributesManager.getAllDeviceItems(position.getDeviceId())); for (Attribute attribute : attributes) { if (attribute.getAttribute() != null) { Object result = null; diff --git a/test/org/traccar/handler/ComputedAttributesTest.java b/test/org/traccar/handler/ComputedAttributesTest.java index 8f4f69bcd..a76d8169b 100644 --- a/test/org/traccar/handler/ComputedAttributesTest.java +++ b/test/org/traccar/handler/ComputedAttributesTest.java @@ -3,6 +3,7 @@ package org.traccar.handler; import java.util.Date; import org.junit.Test; +import org.traccar.config.Config; import org.traccar.model.Attribute; import org.traccar.model.Position; @@ -12,9 +13,11 @@ public class ComputedAttributesTest { @Test public void testComputedAttributes() { - Position position = new Position(); - ComputedAttributesHandler computedAttributesHandler = new ComputedAttributesHandler(); + + ComputedAttributesHandler handler = new ComputedAttributesHandler(new Config(), null, null); + Date date = new Date(); + Position position = new Position(); position.setTime(date); position.setSpeed(42); position.setValid(false); @@ -27,40 +30,40 @@ public class ComputedAttributesTest { Attribute attribute = new Attribute(); attribute.setExpression("adc1"); - assertEquals(128, computedAttributesHandler.computeAttribute(attribute, position)); + assertEquals(128, handler.computeAttribute(attribute, position)); attribute.setExpression("!booleanFlag"); - assertEquals(false, computedAttributesHandler.computeAttribute(attribute, position)); + assertEquals(false, handler.computeAttribute(attribute, position)); attribute.setExpression("adc2 * 2 + 50"); - assertEquals(250, computedAttributesHandler.computeAttribute(attribute, position)); + assertEquals(250, handler.computeAttribute(attribute, position)); attribute.setExpression("(bitFlag & 4) != 0"); - assertEquals(true, computedAttributesHandler.computeAttribute(attribute, position)); + assertEquals(true, handler.computeAttribute(attribute, position)); attribute.setExpression("if (event == 42) \"lowBattery\""); - assertEquals("lowBattery", computedAttributesHandler.computeAttribute(attribute, position)); + assertEquals("lowBattery", handler.computeAttribute(attribute, position)); attribute.setExpression("speed > 5 && valid"); - assertEquals(false, computedAttributesHandler.computeAttribute(attribute, position)); + assertEquals(false, handler.computeAttribute(attribute, position)); attribute.setExpression("fixTime"); - assertEquals(date, computedAttributesHandler.computeAttribute(attribute, position)); + assertEquals(date, handler.computeAttribute(attribute, position)); attribute.setExpression("math:pow(adc1, 2)"); - assertEquals(16384.0, computedAttributesHandler.computeAttribute(attribute, position)); + assertEquals(16384.0, handler.computeAttribute(attribute, position)); // modification tests attribute.setExpression("adc1 = 256"); - computedAttributesHandler.computeAttribute(attribute, position); + handler.computeAttribute(attribute, position); assertEquals(128, position.getInteger("adc1")); attribute.setExpression("result = \"fail\""); - computedAttributesHandler.computeAttribute(attribute, position); + handler.computeAttribute(attribute, position); assertEquals("success", position.getString("result")); attribute.setExpression("fixTime = \"2017-10-18 10:00:01\""); - computedAttributesHandler.computeAttribute(attribute, position); + handler.computeAttribute(attribute, position); assertEquals(date, position.getFixTime()); } -- cgit v1.2.3