modules/core/domain/src/main/java/org/rhq/core/domain/measurement/MeasurementData.java
| 4
modules/core/domain/src/main/java/org/rhq/core/domain/measurement/MeasurementDataNumeric.java
| 5
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/measurement/MeasurementDataManagerBean.java
| 36 +
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/measurement/MeasurementDataManagerLocal.java
| 2
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/MetricHandlerBean.java
| 200 +++++++++-
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/MetricHandlerLocal.java
| 65 +++
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/domain/NumericDataPoint.java
| 65 +++
7 files changed, 360 insertions(+), 17 deletions(-)
New commits:
commit 685a93c8b98e796173e5830159b33aa8350676a0
Author: Heiko W. Rupp <hwr(a)redhat.com>
Date: Fri Dec 30 17:02:00 2011 +0100
Support submission of (numerical) metrics into the server and retrieval of raw numeric
values.
diff --git
a/modules/core/domain/src/main/java/org/rhq/core/domain/measurement/MeasurementData.java
b/modules/core/domain/src/main/java/org/rhq/core/domain/measurement/MeasurementData.java
index d0d26ab..d22689f 100644
---
a/modules/core/domain/src/main/java/org/rhq/core/domain/measurement/MeasurementData.java
+++
b/modules/core/domain/src/main/java/org/rhq/core/domain/measurement/MeasurementData.java
@@ -82,6 +82,10 @@ public abstract class MeasurementData implements Serializable {
this.setName(request.getName());
}
+ protected MeasurementData(long timestamp, int scheduleId) {
+ this(new MeasurementDataPK(timestamp,scheduleId));
+ }
+
public int getScheduleId() {
return id.scheduleId;
}
diff --git
a/modules/core/domain/src/main/java/org/rhq/core/domain/measurement/MeasurementDataNumeric.java
b/modules/core/domain/src/main/java/org/rhq/core/domain/measurement/MeasurementDataNumeric.java
index 4e82c43..d0bf41f 100644
---
a/modules/core/domain/src/main/java/org/rhq/core/domain/measurement/MeasurementDataNumeric.java
+++
b/modules/core/domain/src/main/java/org/rhq/core/domain/measurement/MeasurementDataNumeric.java
@@ -59,6 +59,11 @@ public class MeasurementDataNumeric extends MeasurementData implements
Serializa
this.rawNumericType = request.getRawNumericType();
}
+ public MeasurementDataNumeric(long collectionTime, int scheduleId,Double value) {
+ super(collectionTime,scheduleId);
+ this.value = value;
+ }
+
@Deprecated
// Have to make this protected so that people only use the constructor taking a
request (so the name can be set for live values)
public MeasurementDataNumeric(MeasurementDataPK md, Double value) {
diff --git
a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/measurement/MeasurementDataManagerBean.java
b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/measurement/MeasurementDataManagerBean.java
index 7ffb8e1..7bb7c8f 100644
---
a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/measurement/MeasurementDataManagerBean.java
+++
b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/measurement/MeasurementDataManagerBean.java
@@ -20,6 +20,7 @@ package org.rhq.enterprise.server.measurement;
import java.sql.Connection;
import java.sql.PreparedStatement;
+import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
@@ -176,9 +177,9 @@ public class MeasurementDataManagerBean implements
MeasurementDataManagerLocal,
long start = System.currentTimeMillis();
// TODO GH: Deal with offset (this is only for situations where the clock
doesn't match on the agent)
- /*
+ /*
* even if these methods check for null/empty collections, they cross the EJB
boundary and so unnecessarily
- * start transactions. by checking the null/emptiness of a collection here, by
only create transactions
+ * start transactions. by checking the null/emptiness of a collection here, by
only create transactions
* when real work will be done;
*/
if (report.getNumericData() != null &&
!report.getNumericData().isEmpty()) {
@@ -799,6 +800,37 @@ public class MeasurementDataManagerBean implements
MeasurementDataManagerLocal,
return values;
}
+ @Override
+ public List<MeasurementDataNumeric> findRawData(Subject subject, int
scheduleId, long startTime, long endTime) {
+
+ List<MeasurementDataNumeric> result = new
ArrayList<MeasurementDataNumeric>();
+ String table = MeasurementDataManagerUtility.getCurrentRawTable();
+ Connection connection = null;
+ PreparedStatement ps = null;
+ ResultSet rs = null;
+ try {
+ connection = rhqDs.getConnection();
+ ps = connection.prepareStatement( // TODO supply real impl that spans
multiple tables
+ "SELECT time_stamp,value FROM " + table + " WHERE
schedule_id= ? AND time_stamp BETWEEN ? AND ?");
+ ps.setLong(1,scheduleId);
+ ps.setLong(2,startTime);
+ ps.setLong(3,endTime);
+ rs = ps.executeQuery();
+
+ while (rs.next()) {
+ MeasurementDataNumeric point = new
MeasurementDataNumeric(rs.getLong(1),scheduleId,rs.getDouble(2));
+ result.add(point);
+ }
+ } catch (SQLException e) {
+ e.printStackTrace(); // TODO: Customise this generated block
+ } finally {
+ JDBCUtil.safeClose(connection, ps, rs);
+ }
+
+
+ return result;
+ }
+
private List<MeasurementDataRequest>
createRequests(List<MeasurementDefinition> definitions) {
List<MeasurementDataRequest> requests = new
ArrayList<MeasurementDataRequest>();
for (MeasurementDefinition definition : definitions) {
diff --git
a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/measurement/MeasurementDataManagerLocal.java
b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/measurement/MeasurementDataManagerLocal.java
index e80f16a..4ea8302 100644
---
a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/measurement/MeasurementDataManagerLocal.java
+++
b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/measurement/MeasurementDataManagerLocal.java
@@ -189,4 +189,6 @@ public interface MeasurementDataManagerLocal {
List<List<MeasurementDataNumericHighLowComposite>>
findDataForResource(Subject subject, int resourceId,
int[] definitionIds, long beginTime, long endTime, int numPoints);
+
+ List<MeasurementDataNumeric> findRawData(Subject subject, int scheduleId, long
startTime, long endTime);
}
\ No newline at end of file
diff --git
a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/MetricHandlerBean.java
b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/MetricHandlerBean.java
index 99dd6fe..ba9785c 100644
---
a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/MetricHandlerBean.java
+++
b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/MetricHandlerBean.java
@@ -18,18 +18,34 @@
*/
package org.rhq.enterprise.server.rest;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.PrintWriter;
import java.net.URI;
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
import java.util.ArrayList;
+import java.util.Collection;
import java.util.Date;
+import java.util.HashSet;
import java.util.List;
+import java.util.Set;
import javax.ejb.EJB;
import javax.ejb.Stateless;
import javax.interceptor.Interceptors;
+import javax.sql.DataSource;
+import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.PUT;
import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
+import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.CacheControl;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.EntityTag;
@@ -38,6 +54,7 @@ import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Request;
import javax.ws.rs.core.Response;
+import javax.ws.rs.core.StreamingOutput;
import javax.ws.rs.core.UriBuilder;
import javax.ws.rs.core.UriInfo;
@@ -45,9 +62,13 @@ import org.jboss.cache.Fqn;
import org.rhq.core.domain.common.EntityContext;
import org.rhq.core.domain.measurement.DataType;
+import org.rhq.core.domain.measurement.MeasurementDataNumeric;
import org.rhq.core.domain.measurement.MeasurementDefinition;
import org.rhq.core.domain.measurement.MeasurementSchedule;
import org.rhq.core.domain.measurement.composite.MeasurementDataNumericHighLowComposite;
+import org.rhq.core.util.jdbc.JDBCUtil;
+import org.rhq.enterprise.server.RHQConstants;
+import org.rhq.enterprise.server.measurement.util.MeasurementDataManagerUtility;
import org.rhq.enterprise.server.resource.ResourceManagerLocal;
import org.rhq.enterprise.server.rest.domain.Link;
import org.rhq.enterprise.server.rest.domain.MetricAggregate;
@@ -55,6 +76,7 @@ import org.rhq.enterprise.server.measurement.MeasurementAggregate;
import org.rhq.enterprise.server.measurement.MeasurementDataManagerLocal;
import org.rhq.enterprise.server.measurement.MeasurementScheduleManagerLocal;
import org.rhq.enterprise.server.rest.domain.MetricSchedule;
+import org.rhq.enterprise.server.rest.domain.NumericDataPoint;
/**
* Deal with metrics
@@ -62,6 +84,7 @@ import org.rhq.enterprise.server.rest.domain.MetricSchedule;
*/
@Interceptors(SetCallerInterceptor.class)
@Stateless
+(a)javax.annotation.Resource(name = "RHQ_DS", mappedName =
RHQConstants.DATASOURCE_JNDI_NAME)
public class MetricHandlerBean extends AbstractRestBean implements MetricHandlerLocal {
@EJB
@@ -71,6 +94,10 @@ public class MetricHandlerBean extends AbstractRestBean implements
MetricHandle
@EJB
ResourceManagerLocal resMgr;
+ @javax.annotation.Resource(name = "RHQ_DS")
+ private DataSource rhqDs;
+
+
private static final long EIGHT_HOURS = 8 * 3600L * 1000L;
@Override
@@ -87,20 +114,7 @@ public class MetricHandlerBean extends AbstractRestBean implements
MetricHandle
startTime = endTime - EIGHT_HOURS;
}
-
- MeasurementSchedule schedule;
- schedule = getFromCache(scheduleId,MeasurementSchedule.class);
- if (schedule==null) {
- schedule = scheduleManager.getScheduleById(caller,scheduleId);
- if (schedule==null) {
- throw new StuffNotFoundException("Schedule with id " +
scheduleId);
- }
- else
- putToCache(scheduleId,MeasurementSchedule.class,schedule);
- }
-
- if (schedule.getDefinition().getDataType()!= DataType.MEASUREMENT)
- throw new IllegalArgumentException("Schedule [" + scheduleId +
"] is not a (numerical) metric");
+ MeasurementSchedule schedule = obtainSchedule(scheduleId);
MeasurementAggregate aggr = dataManager.getAggregate(caller, scheduleId,
startTime, endTime);
MetricAggregate res = new MetricAggregate(scheduleId,
aggr.getMin(),aggr.getAvg(),aggr.getMax());
@@ -156,6 +170,28 @@ public class MetricHandlerBean extends AbstractRestBean implements
MetricHandle
return builder.build();
}
+ /**
+ * Get the schedule for the passed schedule id
+ * @param scheduleId id to look up
+ * @return schedule
+ * @throws StuffNotFoundException if there is no schedule with the passed id
+ */
+ private MeasurementSchedule obtainSchedule(int scheduleId) {
+ MeasurementSchedule schedule;
+ schedule = getFromCache(scheduleId,MeasurementSchedule.class);
+ if (schedule==null) {
+ schedule = scheduleManager.getScheduleById(caller,scheduleId);
+ if (schedule==null) {
+ throw new StuffNotFoundException("Schedule with id " +
scheduleId);
+ }
+ else
+ putToCache(scheduleId,MeasurementSchedule.class,schedule);
+ }
+
+ if (schedule.getDefinition().getDataType()!= DataType.MEASUREMENT)
+ throw new IllegalArgumentException("Schedule [" + scheduleId +
"] is not a (numerical) metric");
+ return schedule;
+ }
private MetricAggregate fill(MetricAggregate res,
List<MeasurementDataNumericHighLowComposite> list, int scheduleId,
boolean hideEmpty) {
long minTime=Long.MAX_VALUE;
@@ -180,7 +216,6 @@ public class MetricHandlerBean extends AbstractRestBean implements
MetricHandle
return res;
}
- @Override
@GET
@Path("data")
@Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML,
MediaType.TEXT_HTML})
@@ -382,4 +417,139 @@ public class MetricHandlerBean extends AbstractRestBean implements
MetricHandle
return Response.ok(ret,httpHeaders.getAcceptableMediaTypes().get(0)).build();
}
+
+ @GET
+ @Path("data/{scheduleId}/raw")
+ public StreamingOutput getMetricDataRaw(@PathParam("scheduleId") int
scheduleId,
+ @QueryParam("startTime") long
startTime,
+ @QueryParam("endTime") long
endTime,
+ long duration,
+ Request request,
+ HttpHeaders headers) {
+
+
+ if (endTime==0)
+ endTime = System.currentTimeMillis();
+ if (startTime==0)
+ startTime = endTime - EIGHT_HOURS;
+ if (duration>0) // overrides start time
+ startTime = endTime - duration*1000L; // duration is in seconds
+
+ if (startTime < System.currentTimeMillis()-7L*86400*1000)
+ throw new IllegalArgumentException("Start time is older than 7
days");
+
+ // Check if the schedule exists
+ obtainSchedule(scheduleId);
+
+ RawNumericJsonStreamingOutput so = new RawNumericJsonStreamingOutput();
+ so.scheduleId = scheduleId;
+ so.startTime = startTime;
+ so.endTime = endTime;
+
+
+ return so;
+ }
+
+ @Override
+ @PUT
+ @Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
+ @Consumes({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
+ @Path("data/{scheduleId}/raw/{timeStamp}")
+ public Response putMetricValue(@PathParam("scheduleId") int scheduleId,
@PathParam("timeStamp") long timestamp,
+ NumericDataPoint point, @Context HttpHeaders headers)
{
+
+ MeasurementSchedule schedule = obtainSchedule(scheduleId);
+
+ Set<MeasurementDataNumeric> data = new
HashSet<MeasurementDataNumeric>(1);
+ data.add(new
MeasurementDataNumeric(point.getTimeStamp(),scheduleId,point.getValue()));
+
+ dataManager.addNumericData(data);
+
+ return Response.ok().build(); // TODO correct code?
+ }
+
+
+ @Override
+ @POST
+ @Path("data/raw")
+ @Consumes({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
+ public Response postMetricValues(Collection<NumericDataPoint> points, @Context
HttpHeaders headers) {
+
+ Set<MeasurementDataNumeric> data = new
HashSet<MeasurementDataNumeric>(points.size());
+ for (NumericDataPoint point : points) {
+ data.add(new MeasurementDataNumeric(point.getTimeStamp(),
point.getScheduleId(),point.getValue()));
+ }
+
+ dataManager.addNumericData(data);
+
+ return Response.ok().build();
+
+ }
+
+ /**
+ * Write the numeric data points to the output stream in JSON encoding
+ * without creating tons of objects in the middle to have them marshalled
+ * by JAX-RS
+ */
+ private class RawNumericJsonStreamingOutput implements StreamingOutput {
+
+ int scheduleId;
+ long startTime;
+ long endTime;
+
+ @Override
+ public void write(OutputStream outputStream) throws IOException,
WebApplicationException {
+
+ String[] tables =
MeasurementDataManagerUtility.getTables(startTime,endTime);
+ StringBuilder sb = new StringBuilder();
+ for (int i = 0 ; i < tables.length ; i ++) {
+ sb.append("SELECT time_stamp,value FROM ");
+ sb.append(tables[i]);
+ sb.append(" WHERE schedule_id = ? AND time_stamp BETWEEN ? AND
?");
+ if (i < tables.length-1)
+ sb.append(" UNION ALL ");
+ }
+
+
+
+
+ Connection connection = null;
+ PreparedStatement ps = null;
+ ResultSet rs = null;
+ try {
+ connection = rhqDs.getConnection();
+ ps = connection.prepareStatement( sb.toString() );
+ for (int i = 0; i < tables.length ; i++) {
+ ps.setInt(i * 3 + 1, scheduleId);
+ ps.setLong(i*3+2,startTime);
+ ps.setLong(i*3+3,endTime);
+ }
+ rs = ps.executeQuery();
+
+ PrintWriter pw = new PrintWriter(outputStream);
+ pw.println("[");
+ while (rs.next()) {
+ pw.print("{");
+ pw.print("\"scheduleId\":");
+ pw.print(scheduleId);
+ pw.print(", ");
+ pw.print("\"timeStamp\":");
+ pw.print(rs.getLong(1));
+ pw.print(", ");
+ pw.print("\"value\":");
+ pw.print(rs.getLong(2));
+ pw.print("}");
+ if (!rs.isLast())
+ pw.print(",\n");
+ }
+ pw.println("]");
+ pw.flush();
+ pw.close();
+ } catch (SQLException e) {
+ log.error(e);
+ } finally {
+ JDBCUtil.safeClose(connection, ps, rs);
+ }
+ }
+ }
}
diff --git
a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/MetricHandlerLocal.java
b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/MetricHandlerLocal.java
index 6631ef4..2c75a55 100644
---
a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/MetricHandlerLocal.java
+++
b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/MetricHandlerLocal.java
@@ -18,12 +18,14 @@
*/
package org.rhq.enterprise.server.rest;
+import java.util.Collection;
import java.util.List;
import javax.ejb.Local;
import javax.ws.rs.Consumes;
import javax.ws.rs.DefaultValue;
import javax.ws.rs.GET;
+import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
@@ -34,10 +36,12 @@ import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Request;
import javax.ws.rs.core.Response;
+import javax.ws.rs.core.StreamingOutput;
import javax.ws.rs.core.UriInfo;
import org.rhq.enterprise.server.rest.domain.MetricAggregate;
import org.rhq.enterprise.server.rest.domain.MetricSchedule;
+import org.rhq.enterprise.server.rest.domain.NumericDataPoint;
/**
* Deal with metrics
@@ -76,16 +80,77 @@ public interface MetricHandlerLocal {
@Path("data/resource/{resourceId}")
List<MetricAggregate>
getAggregatesForResource(@PathParam("resourceId") int resourceId);
+ /**
+ * Get information about the schedule
+ * @param scheduleId id of the schedule
+ * @param request Injected request
+ * @param headers Injected http headers
+ * @param uriInfo Injected Uri
+ * @return the schedule
+ */
@GET
@Path("/schedule/{id}")
@Produces({MediaType.APPLICATION_JSON,MediaType.APPLICATION_XML,MediaType.TEXT_HTML})
Response getSchedule(@PathParam("id") int scheduleId, @Context Request
request, @Context HttpHeaders headers,
@Context UriInfo uriInfo);
+ /**
+ * Update a schedule. Currently change of collection interval and enabled/disabled
state are supported.
+ * @param scheduleId Id of the schedule to update
+ * @param in Modified schedule object
+ * @param headers Injected http headers
+ * @return Result of updating
+ */
@PUT
@Path("/schedule/{id}")
@Consumes({MediaType.APPLICATION_JSON,MediaType.APPLICATION_XML})
@Produces({MediaType.APPLICATION_JSON,MediaType.APPLICATION_XML})
Response updateSchedule(@PathParam("id") int scheduleId, MetricSchedule
in,@Context HttpHeaders headers);
+ /**
+ * Expose the raw metrics for the given schedule
+ * @param scheduleId Schedule id
+ * @param startTime Start time, if 0 and duration=, start time = 8h before endTime
+ * @param endTime End time. If 0, now is used
+ * @param duration Duration in seconds. If duration=0, startTime is used
+ * @param request Injected Request headers
+ * @param headers Injected HttpHeaders
+ * @return a JSON encoded stream of numerical values
+ */
+ @GET
+ @Path("data/{scheduleId}/raw")
+ @Produces({MediaType.APPLICATION_JSON})
+ StreamingOutput getMetricDataRaw(@PathParam("scheduleId") int scheduleId,
+ @QueryParam("startTime") long startTime,
+ @QueryParam("endTime") long endTime,
+ @QueryParam("duration") long duration,
+ @Context Request request,
+ @Context HttpHeaders headers);
+
+ /**
+ * Submit a single (numerical) metric value to the server.
+ * @param scheduleId Id of the schedule to submit to
+ * @param timestamp Timestamp of the entry
+ * @param point Datapoint of class NumericDataPoint
+ * @param headers Injected HTTP headers
+ * @return
+ */
+ @PUT
+ @Produces({MediaType.APPLICATION_JSON,MediaType.APPLICATION_XML})
+ @Consumes({MediaType.APPLICATION_JSON,MediaType.APPLICATION_XML})
+ @Path("data/{scheduleId}/raw/{timeStamp}")
+ Response putMetricValue(@PathParam("scheduleId")int scheduleId,
+ @PathParam("timeStamp")long timestamp,
NumericDataPoint point,
+ @Context HttpHeaders headers);
+
+ /**
+ * Submit a series of (numerical) metric values to the server
+ * @param points Collection of NumericDataPoint entries
+ * @param headers Injected HTTP headers
+ * @return
+ */
+ @POST
+ @Path("data/raw")
+ @Consumes({MediaType.APPLICATION_JSON,MediaType.APPLICATION_XML})
+ Response postMetricValues(Collection<NumericDataPoint> points, @Context
HttpHeaders headers);
}
diff --git
a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/domain/NumericDataPoint.java
b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/domain/NumericDataPoint.java
new file mode 100644
index 0000000..e1ef904
--- /dev/null
+++
b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/domain/NumericDataPoint.java
@@ -0,0 +1,65 @@
+package org.rhq.enterprise.server.rest.domain;
+
+import javax.xml.bind.annotation.XmlAttribute;
+import javax.xml.bind.annotation.XmlRootElement;
+
+/**
+ * One numerical data point of a schedule.
+ * This point does not contain the schedule id, as it is expected
+ * to be used to return lists of data points for a schedule.
+ *
+ * Xml names for the item and the attributes are shortened to
+ * conserve space when transferring to clients
+ *
+ * @author Heiko W. Rupp
+ */
+@XmlRootElement
+public class NumericDataPoint {
+
+ long timeStamp;
+ Double value;
+ private int scheduleId;
+
+ @SuppressWarnings("unused")
+ public NumericDataPoint() {
+ // Needed for JAXB
+ }
+
+ public NumericDataPoint(long timeStamp, Double value) {
+ this.timeStamp = timeStamp;
+ this.value = value;
+ }
+
+ public NumericDataPoint(long timeStamp, int scheduleId, Double value) {
+ this.timeStamp = timeStamp;
+ this.scheduleId = scheduleId;
+ this.value = value;
+ }
+
+ @XmlAttribute
+ public long getTimeStamp() {
+ return timeStamp;
+ }
+
+ @XmlAttribute
+ public Double getValue() {
+ return value;
+ }
+
+ @XmlAttribute
+ public int getScheduleId() {
+ return scheduleId;
+ }
+
+ public void setScheduleId(int scheduleId) {
+ this.scheduleId = scheduleId;
+ }
+
+ public void setTimeStamp(long timeStamp) {
+ this.timeStamp = timeStamp;
+ }
+
+ public void setValue(Double value) {
+ this.value = value;
+ }
+}