package cz.hsrs.db.model; import java.sql.ResultSet; import java.sql.SQLException; import java.text.ParseException; import java.util.Date; import java.util.logging.Level; import cz.hsrs.db.DBObject; import cz.hsrs.db.pool.SQLExecutor; import cz.hsrs.db.util.DateUtil; import cz.hsrs.db.util.UnitUtil; public class UnitPosition implements DBObject { private final int gid; private final long unit_id; private final double x; private final double y; private final double alt; private final String time_stamp; private Date timeStamp; private final double dop; private final double speed; private int group_id; private final String geom; private final String srid; private final String time_received; private final String first_timestamp; public static final String SELECT = "gid, unit_id, time_stamp, st_x(the_geom), st_y(the_geom), speed, st_srid(the_geom) "; private static final String SCHEMA_NAME = "public"; //private static final String ALTITUDE_COLUMN = "altitude"; //private static final String DATASET_TABLE_NAME = "units_positions"; /** * Empty constructor initializes all attributes to null or zero */ public UnitPosition() { speed = Double.NaN; dop = Double.NaN; unit_id = 0; gid = 0; y = Double.NaN; x = Double.NaN; alt = Double.NaN; time_stamp = null; geom = null; srid = null; time_received = null; first_timestamp = null; } /** * Constructor instantiates new object from ResultSet, without altitude! * @param set ResultSet with columns: * gid, unit_id, time_stamp, speed, st_x, st_y, st_srid * @throws SQLException */ public UnitPosition(ResultSet set) throws SQLException { this.gid = set.getInt("gid"); this.unit_id = set.getLong("unit_id"); this.time_stamp = set.getString("time_stamp"); this.speed = set.getDouble("speed"); this.x = set.getDouble("st_x"); this.y = set.getDouble("st_y"); this.alt = Double.NaN; this.geom = createPointString(x, y); this.srid = set.getString("st_srid"); this.dop = Double.NaN; this.time_received = null; this.first_timestamp = null; UnitUtil uUtil = new UnitUtil(); this.group_id = uUtil.getGroupID(unit_id); } /** * Constructor instantiates object from fields * @param unitId - id of unit * @param x - long coordinate * @param y - lat coordinate * @param timeStamp time stamp of position * @throws SQLException */ public UnitPosition(long unitId, double x, double y, Date timeStamp) throws SQLException { this(unitId, x, y, 0, timeStamp, Double.NaN, ""); } /** * Constructor instantiates object from fields * @param unitId - id of unit * @param x - long coordinate * @param y - lat coordinate * @param alt - altitude coordinate * @param timeStamp time stamp of position * @throws SQLException */ public UnitPosition(long unitId, double x, double y, double alt, Date timeStamp) throws SQLException { this(unitId, x, y, alt, timeStamp, Double.NaN, ""); } /** * Constructor for creating UnitPosition from WebService * @param unitId * @param x * @param y * @param alt * @param timeStamp * @param speed * @param srid * @throws SQLException */ public UnitPosition(long unitId, double x, double y, double alt, Date timeStamp, Double speed, String srid) throws SQLException { super(); this.unit_id = unitId; this.gid = getNextGid(); this.x = x; this.y = y; this.alt = alt; this.geom = createPointString(x, y); this.timeStamp = timeStamp; this.speed = speed; this.dop = Double.NaN; this.srid = srid; this.time_stamp = null; this.time_received = null; this.first_timestamp = null; } /** * Constructor for creating UnitPosition object from WebService * @param unitId * @param x * @param y * @param alt * @param timeStamp * @param speed * @param dop * @param srid * @throws SQLException */ public UnitPosition(long unitId, double x, double y, double alt, Date timeStamp, Double speed, Double dop, String srid) throws SQLException { super(); this.unit_id = unitId; this.gid = getNextGid(); this.x = x; this.y = y; this.alt = alt; this.geom = createPointString(x, y); this.timeStamp = timeStamp; this.speed = speed; this.dop = dop; this.srid = srid; this.time_stamp = DateUtil.formatSecsTZ.format(timeStamp); this.time_received = null; this.first_timestamp = null; } /** * Constructor for creating UnitPosition object from DB * @param gid * @param unit_id * @param alt * @param time_string * @param dop * @param speed * @param geom * @param srid * @param receivedString * @param firstTimestampString */ public UnitPosition(int gid, long unit_id, double x, double y, double alt, String time_string, double dop, double speed, String srid, String receivedString, String firstTimestampString) { this.gid = gid; this.unit_id = unit_id; this.x = x; this.y = y; this.alt = alt; this.geom = null; this.time_stamp = time_string; this.dop = dop; this.speed = speed; this.srid = srid; this.time_received = receivedString; this.first_timestamp = firstTimestampString; } /** * Constructor for updating UnitPosition from webservice * @param gid * @param unit_id * @param x * @param y * @param alt * @param timestamp * @param dop * @param speed * @param srid */ public UnitPosition(int gid, long unit_id, double x, double y, double alt, Date timestamp, double dop, double speed, String srid) { this.gid = gid; this.unit_id = unit_id; this.x = x; this.y = y; this.alt = alt; this.geom = this.createPointString(x, y); this.timeStamp = timestamp; this.dop = dop; this.speed = speed; this.srid = srid; this.time_stamp = DateUtil.formatSecsTZ.format(timestamp); this.time_received = null; this.first_timestamp = null; } public double getSpeed() { return speed; } public int getGroup_id() { return group_id; } public double getX() { return x; } public double getY() { return y; } /** * Method returns Altitude of the Positions * @return double value if position is defined, * NULL if altitude is NaN or null */ public Double getAlt(){ if(Double.isNaN(alt)){ return null; } else{ return alt; } } public String getSRID(){ return srid; } /** * Inherited method converts content of ResultSet to UnitPosition object */ public DBObject getDBObject(ResultSet set) throws SQLException { return new UnitPosition(set); } /** * Getter returns gid of unit_position * @return gid */ public int getGid() { return gid; } /** * Method returns geom as String: * "POINT(x y)" * @return String "POINT(x y)" */ public String internalGetGeom() { return geom; } /** * Method returns time stamp of position as Date * if Date time stamp is not set parses it from String time stamp * processes String time stamp in case of using microseconds from DB * @return timestamp of position as Date * @throws SQLException */ public Date internalGetTimestamp() throws SQLException { if (timeStamp != null) { try { return DateUtil.parseTimestamp(time_stamp); } catch (ParseException e) { SQLExecutor.logger.log(Level.SEVERE, e.getMessage()); throw new SQLException("Timestamp of position is not present!"); } } else{ return timeStamp; } } /** * Getter returns Unit_ID * @return unit_id */ public long getUnit_id() { return unit_id; } /** * Method inserts new position into database * @return true if positions was successfully inserted, false otherwise * @throws SQLException is thrown if an Exception occurs during inserting */ public boolean insertToDb() throws SQLException { StringBuffer queryBuff= new StringBuffer(); if(SQLExecutor.isAltitudeEnabled()){ queryBuff.append("INSERT INTO "+SCHEMA_NAME+".units_positions(altitude, the_geom, unit_id, time_stamp, gid, speed, dop) VALUES ("); queryBuff.append(Double.isNaN(this.alt) ? "NULL, " : String.valueOf(this.alt)+", "); } else{ queryBuff.append("INSERT INTO "+SCHEMA_NAME+".units_positions(the_geom, unit_id, time_stamp, gid, speed, dop) VALUES ("); } queryBuff.append("st_geomfromtext('"+ this.geom + "', "+(this.srid.isEmpty() ? "4326" : this.srid)+"), "); queryBuff.append(this.unit_id + ", "); queryBuff.append("timestamp with time zone '" + DateUtil.formatSecsTZ.format(this.timeStamp) + "', "); queryBuff.append(this.gid + ", "); queryBuff.append(Double.isNaN(this.speed) ? "NULL, " : String.valueOf(this.speed)+", "); queryBuff.append(Double.isNaN(this.dop) ? "NULL" : String.valueOf(this.dop)); queryBuff.append(");"); String ins = queryBuff.toString(); int i = SQLExecutor.executeUpdate(ins); /** If there is partitioning on table units_positions, function executeUpdate returns 0. * If there is only units_positions table, function executeUpdate returns 1. */ if (i == 1 || i == 0){ return true; } else{ return false; } } /** * Method returns String to create geometry object in PostGIS * "st_geomfromtext('POINT(x y)', SRID)"; * @return "st_geomfromtext('POINT(x y)', SRID)"; as String */ public String getPostgisString() { if(this.srid == null){ return "st_geomfromtext('" + this.geom + "', 4326)"; } else{ if(this.srid.isEmpty()){ return "st_geomfromtext('" + this.geom + "', 4326)"; } else{ return "st_geomfromtext('" + this.geom + "', "+this.srid+")"; } } } private String createPointString(double x, double y) { return new String("POINT(" + x + " " + y + ")"); } /** * * @return the_geom */ public String getPostgisGeomString() { return this.geom; } /** * * @return the time_stamp */ public String getTime_stamp() { return time_stamp; } /** * Method returns DOP value of Position * @return the dop double value, NULL if dop is NaN or null */ public Double getDop() { if(Double.isNaN(dop)){ return null; } else{ return dop; } } /** * @return the srid */ public String getSrid() { return srid; } /** * @return the time_received * @throws ParseException */ public Date internalGetTimeReceived() throws ParseException { return DateUtil.parseTimestampMicro(this.time_received); } /** * @return the time_received */ public String getReceivedTimestampString() { return this.time_received; } /** * @return the first_timestamp * @throws ParseException */ public Date internalGetFirstTimestamp() throws ParseException { return DateUtil.parseTimestampMicro(this.first_timestamp); } /** * @return the firstTsString */ public String getFirstTimesstamp() { return this.first_timestamp; } /* (non-Javadoc) * @see java.lang.Object#toString() */ @Override public String toString() { return "UnitPosition [unit_id=" + unit_id + ", gid=" + gid + ", speed=" + speed + ", x=" + x + ", y=" + y + ", alt=" + alt + ", time_string=" + time_stamp + ", group_id=" + group_id + ", srid=" + srid + "]"; } /** * Method get next value of sequence for GID * @return next value of GID as integer * @throws SQLException */ private int getNextGid() throws SQLException{ try{ String queryGid = "SELECT nextval('"+SCHEMA_NAME+".units_positions_gid_seq'::regclass);"; ResultSet resId = SQLExecutor.getInstance().executeQuery(queryGid); if(resId.next()){ return resId.getInt(1); } else{ throw new SQLException("Next value of GID cannot be selected!"); } } catch(SQLException e){ throw new SQLException("Next value of GID cannot be selected!"); } } }