Sammoa-commits
Threads by month
- ----- 2026 -----
- June
- May
- April
- March
- February
- January
- ----- 2025 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
August 2012
- 4 participants
- 171 discussions
10 Aug '12
Author: fdesbois
Date: 2012-08-10 13:56:16 +0200 (Fri, 10 Aug 2012)
New Revision: 390
Url: http://forge.codelutin.com/repositories/revision/sammoa/390
Log:
refs #1378 : improve GPS errors + always register a GeoPoint for observation, route ...
Added:
trunk/sammoa-application/src/main/java/org/
trunk/sammoa-application/src/main/java/org/dinopolis/
trunk/sammoa-application/src/main/java/org/dinopolis/gpstool/
trunk/sammoa-application/src/main/java/org/dinopolis/gpstool/gpsinput/
trunk/sammoa-application/src/main/java/org/dinopolis/gpstool/gpsinput/SafeGPSSerialDevice.java
trunk/sammoa-application/src/main/java/org/dinopolis/gpstool/gpsinput/nmea/
trunk/sammoa-application/src/main/java/org/dinopolis/gpstool/gpsinput/nmea/SafeGPSNmeaDataProcessor.java
Removed:
trunk/sammoa-application/src/main/java/fr/ulr/sammoa/application/device/gps/SammoaGPSSerialDevice.java
trunk/sammoa-application/src/main/java/gnu/
Modified:
trunk/sammoa-application/src/main/java/fr/ulr/sammoa/application/device/gps/BaseGpsHandler.java
trunk/sammoa-application/src/main/java/fr/ulr/sammoa/application/device/gps/FakeGpsHandler.java
trunk/sammoa-application/src/main/java/fr/ulr/sammoa/application/device/gps/GpsHandlerGpsylon.java
trunk/sammoa-application/src/main/java/fr/ulr/sammoa/application/device/gps/GpsLocationEvent.java
trunk/sammoa-application/src/main/java/fr/ulr/sammoa/application/flightController/FlightControllerDefault.java
trunk/sammoa-persistence/src/main/java/fr/ulr/sammoa/persistence/GeoPoints.java
trunk/sammoa-persistence/src/main/xmi/sammoa.zargo
trunk/sammoa-ui-swing/src/main/java/fr/ulr/sammoa/ui/swing/flight/FlightUIHandler.java
Modified: trunk/sammoa-application/src/main/java/fr/ulr/sammoa/application/device/gps/BaseGpsHandler.java
===================================================================
--- trunk/sammoa-application/src/main/java/fr/ulr/sammoa/application/device/gps/BaseGpsHandler.java 2012-08-10 11:53:45 UTC (rev 389)
+++ trunk/sammoa-application/src/main/java/fr/ulr/sammoa/application/device/gps/BaseGpsHandler.java 2012-08-10 11:56:16 UTC (rev 390)
@@ -29,6 +29,7 @@
import fr.ulr.sammoa.application.device.DeviceStateListener;
import fr.ulr.sammoa.application.device.DeviceTechnicalException;
import fr.ulr.sammoa.persistence.GeoPoint;
+import fr.ulr.sammoa.persistence.GeoPoints;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -195,33 +196,35 @@
protected GeoPoint location;
+ protected GeoPoint lastLocation;
+
protected int nbFailures;
@Override
public void run() {
- GeoPoint lastLocation = location;
-
location = getCurrentLocation();
- // reset nbFailures if currentLocation is defined
- if (location != null) {
+ boolean sameLocation = GeoPoints.equal(location, lastLocation);
+
+ logger.debug("sameLocation={} [{} :: {}]", new Object[]{sameLocation, location, lastLocation});
+
+ // reset nbFailures if location hasn't changed
+ if (sameLocation) {
+ nbFailures++;
+ } else {
nbFailures = 0;
- } else {
- nbFailures++;
}
+ location.setCaptureDelay(nbFailures * config.getCheckPeriod());
+
// Data is unavailable
- if (location == null && nbFailures >= nbFailuresMax) {
- setState(DeviceState.ERROR,
- new DeviceTechnicalException(BaseGpsHandler.this,
- String.format("The GPS signal is lost after %d seconds ! " +
- "The application will try again in %d seconds",
- config.getTimeout(),
- config.getCheckPeriod())
- )
- );
+ if (GeoPoints.isCoordinatesEmpty(location) || sameLocation && nbFailures >= nbFailuresMax) {
+ DeviceTechnicalException error = onError(location);
+
+ setState(DeviceState.ERROR, error);
+
// GPS is recording
} else {
@@ -232,6 +235,10 @@
listener.locationChanged(new GpsLocationEvent(BaseGpsHandler.this, lastLocation, location));
}
}
+
+ lastLocation = location;
}
};
+
+ protected abstract DeviceTechnicalException onError(GeoPoint location);
}
Modified: trunk/sammoa-application/src/main/java/fr/ulr/sammoa/application/device/gps/FakeGpsHandler.java
===================================================================
--- trunk/sammoa-application/src/main/java/fr/ulr/sammoa/application/device/gps/FakeGpsHandler.java 2012-08-10 11:53:45 UTC (rev 389)
+++ trunk/sammoa-application/src/main/java/fr/ulr/sammoa/application/device/gps/FakeGpsHandler.java 2012-08-10 11:56:16 UTC (rev 390)
@@ -107,6 +107,11 @@
}
@Override
+ protected DeviceTechnicalException onError(GeoPoint location) {
+ return null;
+ }
+
+ @Override
public void close() throws DeviceTechnicalException {
setState(DeviceState.NO_DEVICE, null);
}
@@ -134,7 +139,7 @@
}
return result;
}
-
+
protected class GpsPointGenerator implements Runnable {
@Override
@@ -147,7 +152,7 @@
int count = MAX_POINTS;
- while (true && count != 0) {
+ while (count != 0) {
try {
Thread.sleep(2000);
Modified: trunk/sammoa-application/src/main/java/fr/ulr/sammoa/application/device/gps/GpsHandlerGpsylon.java
===================================================================
--- trunk/sammoa-application/src/main/java/fr/ulr/sammoa/application/device/gps/GpsHandlerGpsylon.java 2012-08-10 11:53:45 UTC (rev 389)
+++ trunk/sammoa-application/src/main/java/fr/ulr/sammoa/application/device/gps/GpsHandlerGpsylon.java 2012-08-10 11:56:16 UTC (rev 390)
@@ -25,18 +25,19 @@
package fr.ulr.sammoa.application.device.gps;
-import com.google.common.base.Objects;
import fr.ulr.sammoa.application.device.DeviceState;
import fr.ulr.sammoa.application.device.DeviceTechnicalException;
import fr.ulr.sammoa.persistence.GeoPoint;
import fr.ulr.sammoa.persistence.GeoPointImpl;
+import fr.ulr.sammoa.persistence.GeoPoints;
import gnu.io.CommPortIdentifier;
import org.dinopolis.gpstool.gpsinput.GPSDataProcessor;
import org.dinopolis.gpstool.gpsinput.GPSDevice;
import org.dinopolis.gpstool.gpsinput.GPSException;
import org.dinopolis.gpstool.gpsinput.GPSPosition;
import org.dinopolis.gpstool.gpsinput.GPSSerialDevice;
-import org.dinopolis.gpstool.gpsinput.nmea.GPSNmeaDataProcessor;
+import org.dinopolis.gpstool.gpsinput.SafeGPSSerialDevice;
+import org.dinopolis.gpstool.gpsinput.nmea.SafeGPSNmeaDataProcessor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -61,14 +62,16 @@
protected GPSPosition lastPosition;
- protected GPSPosition lastSendPosition;
-
protected float lastAltitude;
protected float lastSpeed;
+ protected int lastNumberSatellites;
+
protected boolean deviceInitialized;
+ protected boolean opened;
+
public GpsHandlerGpsylon(GpsConfig config) {
super(config);
}
@@ -87,9 +90,9 @@
if (!deviceInitialized) {
- gpsDataProcessor = new GPSNmeaDataProcessor();
+ gpsDataProcessor = new SafeGPSNmeaDataProcessor();
- gpsDevice = new SammoaGPSSerialDevice();
+ gpsDevice = new SafeGPSSerialDevice();
Hashtable<String, Object> options = new Hashtable<String, Object>();
options.put(GPSSerialDevice.PORT_NAME_KEY, getConfig().getDevice());
@@ -105,30 +108,19 @@
deviceInitialized = true;
}
- if (logger.isTraceEnabled()) {
- Enumeration portList = CommPortIdentifier.getPortIdentifiers();
+ logAvailablePorts("beforeOpen");
- while (portList.hasMoreElements()) {
- CommPortIdentifier portId = (CommPortIdentifier) portList.nextElement();
- if (portId.getPortType() == CommPortIdentifier.PORT_SERIAL) {
- logger.trace("Available SERIAL port : " + portId.getName());
- }
- }
- }
-
gpsDataProcessor.open();
- gpsDataProcessor.addGPSDataChangeListener(
- GPSDataProcessor.LOCATION, gpsDataProcessorListener);
- gpsDataProcessor.addGPSDataChangeListener(
- GPSDataProcessor.ALTITUDE, gpsDataProcessorListener);
- gpsDataProcessor.addGPSDataChangeListener(
- GPSDataProcessor.SPEED, gpsDataProcessorListener);
+ gpsDataProcessor.addGPSDataChangeListener(gpsDataProcessorListener);
logger.info("Connected to GPS device");
setState(DeviceState.READY, null);
+ opened = true;
+ logAvailablePorts("openedSuccessful");
+
} catch (GPSException ex) {
setState(DeviceState.NO_DEVICE, null);
@@ -147,18 +139,14 @@
logger.info("Closing GPS device...");
try {
- gpsDataProcessor.removeGPSDataChangeListener(
- GPSDataProcessor.LOCATION, gpsDataProcessorListener);
- gpsDataProcessor.removeGPSDataChangeListener(
- GPSDataProcessor.ALTITUDE, gpsDataProcessorListener);
- gpsDataProcessor.removeGPSDataChangeListener(
- GPSDataProcessor.SPEED, gpsDataProcessorListener);
+ gpsDataProcessor.removeGPSDataChangeListener(gpsDataProcessorListener);
gpsDataProcessor.close();
logger.info("GPS device is closed");
setState(DeviceState.NO_DEVICE, null);
+ opened = false;
} catch (GPSException e) {
setState(DeviceState.ERROR, null);
@@ -170,24 +158,99 @@
@Override
public GeoPoint getCurrentLocation() {
- GeoPoint result = null;
+ if (logger.isTraceEnabled()) {
+ logger.trace("Ask lastPosition = {}", lastPosition);
+ }
- logger.trace("Ask lastPosition = {}", lastPosition);
+// if (!Objects.equal(lastPosition, lastSendPosition) && lastPosition != null) {
+//
+// result = new GeoPointImpl(lastPosition.getLatitude(), lastPosition.getLongitude());
+// result.setAltitude(lastAltitude);
+// result.setSpeed(lastSpeed);
+// // FIXME-fdesbois-2012-07-02 : ensure time with GPS value and not system timestamp
+// result.setRecordTime(new Date());
+//
+// lastSendPosition = lastPosition;
+// }
- if (!Objects.equal(lastPosition, lastSendPosition) && lastPosition != null) {
+ double latitude = lastPosition != null
+ ? lastPosition.getLatitude() : GeoPoints.EMPTY_COORDINATE;
+ double longitude = lastPosition != null
+ ? lastPosition.getLongitude() : GeoPoints.EMPTY_COORDINATE;
- result = new GeoPointImpl(lastPosition.getLatitude(), lastPosition.getLongitude());
- result.setAltitude(lastAltitude);
- result.setSpeed(lastSpeed);
- // FIXME-fdesbois-2012-07-02 : ensure time with GPS value and not system timestamp
- result.setRecordTime(new Date());
+ GeoPoint result = new GeoPointImpl(latitude, longitude);
+ result.setAltitude(lastAltitude);
+ result.setSpeed(lastSpeed);
+ // FIXME-fdesbois-2012-07-02 : ensure time with GPS value and not system timestamp
+ result.setRecordTime(new Date());
- lastSendPosition = lastPosition;
+ if (logger.isWarnEnabled() && lastPosition == null) {
+ logger.warn("Retrieve a location without any coordinates : {}", result);
}
return result;
}
@Override
+ protected DeviceTechnicalException onError(GeoPoint location) {
+
+ DeviceTechnicalException result = null;
+
+ logAvailablePorts("checkIsOpened");
+
+ // TODO checkIsOpened
+ // Send error when device is connected :
+ // RXTX fhs_lock() Error: creating lock file: /var/lock/LCK..ttyUSB0: File exists
+ // No error when device is disconnected
+ // --> close handler
+ // Maybe with chance on next plug we will keep the same PORT
+
+ if (logger.isDebugEnabled()) {
+ logger.debug("ERROR on GPS, nbSatellites = {} : geoPoint = {}", lastNumberSatellites, location);
+ }
+
+ if (!opened) {
+ start();
+
+ } else {
+
+ if (GeoPoints.isCoordinatesEmpty(location)) {
+
+ result = new DeviceTechnicalException(this,
+ "GPS is not ready, turn it on or wait for it to find satellites");
+
+ } else {
+
+ if (lastNumberSatellites == 0) {
+ result = new DeviceTechnicalException(this,
+ "GPS signal lost, there is no available satellite found");
+
+ } else {
+ result = new DeviceTechnicalException(this,
+ "GPS signal lost, please check the connection port");
+ }
+ }
+ }
+ return result;
+ }
+
+ protected void logAvailablePorts(String method) {
+
+ if (logger.isInfoEnabled()) {
+
+ logger.info("GPS configuration port {} [{}]", config.getDevice(), method);
+
+ Enumeration portList = CommPortIdentifier.getPortIdentifiers();
+
+ while (portList.hasMoreElements()) {
+ CommPortIdentifier portId = (CommPortIdentifier) portList.nextElement();
+ if (portId.getPortType() == CommPortIdentifier.PORT_SERIAL) {
+ logger.info("## Available SERIAL port : {}", portId.getName());
+ }
+ }
+ }
+ }
+
+ @Override
protected void finalize() throws Throwable {
close();
super.finalize();
@@ -221,7 +284,9 @@
String property = evt.getPropertyName();
- logger.trace("Gps data received {} {}", property, evt.getNewValue());
+ if (logger.isTraceEnabled()) {
+ logger.trace("Gps data received {} {}", property, evt.getNewValue());
+ }
if (GPSDataProcessor.LOCATION.equals(property)) {
lastPosition = (GPSPosition) evt.getNewValue();
@@ -231,6 +296,9 @@
} else if (GPSDataProcessor.SPEED.equals(property)) {
lastSpeed = (Float) evt.getNewValue();
+
+ } else if (GPSDataProcessor.NUMBER_SATELLITES.equals(property)) {
+ lastNumberSatellites = (Integer) evt.getNewValue();
}
}
};
Modified: trunk/sammoa-application/src/main/java/fr/ulr/sammoa/application/device/gps/GpsLocationEvent.java
===================================================================
--- trunk/sammoa-application/src/main/java/fr/ulr/sammoa/application/device/gps/GpsLocationEvent.java 2012-08-10 11:53:45 UTC (rev 389)
+++ trunk/sammoa-application/src/main/java/fr/ulr/sammoa/application/device/gps/GpsLocationEvent.java 2012-08-10 11:56:16 UTC (rev 390)
@@ -38,7 +38,9 @@
protected GeoPoint newValue;
- public GpsLocationEvent(GpsHandler source, GeoPoint oldValue, GeoPoint newValue) {
+ public GpsLocationEvent(GpsHandler source,
+ GeoPoint oldValue,
+ GeoPoint newValue) {
this.source = source;
this.oldValue = oldValue;
this.newValue = newValue;
Deleted: trunk/sammoa-application/src/main/java/fr/ulr/sammoa/application/device/gps/SammoaGPSSerialDevice.java
===================================================================
--- trunk/sammoa-application/src/main/java/fr/ulr/sammoa/application/device/gps/SammoaGPSSerialDevice.java 2012-08-10 11:53:45 UTC (rev 389)
+++ trunk/sammoa-application/src/main/java/fr/ulr/sammoa/application/device/gps/SammoaGPSSerialDevice.java 2012-08-10 11:56:16 UTC (rev 390)
@@ -1,67 +0,0 @@
-package fr.ulr.sammoa.application.device.gps;
-/*
- * #%L
- * SAMMOA :: Application
- * $Id:$
- * $HeadURL:$
- * %%
- * Copyright (C) 2012 UMS 3462, Code Lutin
- * %%
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public
- * License along with this program. If not, see
- * <http://www.gnu.org/licenses/gpl-3.0.html>.
- * #L%
- */
-
-import gnu.io.RXTXHack;
-import gnu.io.RXTXPort;
-import org.dinopolis.gpstool.gpsinput.GPSException;
-import org.dinopolis.gpstool.gpsinput.GPSSerialDevice;
-
-/**
- * There is an issue with closing on {@link gnu.io.SerialPort}. See
- * <a href="https://forums.oracle.com/forums/thread.jspa?threadID=1292323">
- * https://forums.oracle.com/forums/thread.jspa?threadID=1292323
- * </a>
- *
- * Note that only the {@link RXTXHack} works... Maybe the upgrade of rxtx.jar could
- * works (not in maven repo).
- * <p/>
- * The issue is probably from {@link org.dinopolis.gpstool.gpsinput.nmea.GPSNmeaDataProcessor}
- * that creates a daemon thread to read the serialPort InputStream. There is
- * no way to kill properly this thread before closing serialPort.
- *
- * Created: 06/08/12
- *
- * @author fdesbois <florian.desbois(a)codelutin.com>
- */
-public class SammoaGPSSerialDevice extends GPSSerialDevice {
-
- @Override
- public void close() throws GPSException {
- if (serial_port_ != null) {
-
-// serial_port_.removeEventListener();
-// try {
-// serial_port_.getOutputStream().flush();
-// serial_port_.getOutputStream().close();
-// serial_port_.getInputStream().close();
-// } catch (IOException e) {
-// throw Throwables.propagate(e);
-// }
-// serial_port_.close();
-
- RXTXHack.closeRxtxPort((RXTXPort) serial_port_);
- }
- }
-}
Modified: trunk/sammoa-application/src/main/java/fr/ulr/sammoa/application/flightController/FlightControllerDefault.java
===================================================================
--- trunk/sammoa-application/src/main/java/fr/ulr/sammoa/application/flightController/FlightControllerDefault.java 2012-08-10 11:53:45 UTC (rev 389)
+++ trunk/sammoa-application/src/main/java/fr/ulr/sammoa/application/flightController/FlightControllerDefault.java 2012-08-10 11:56:16 UTC (rev 390)
@@ -43,6 +43,7 @@
import fr.ulr.sammoa.persistence.FlightDAO;
import fr.ulr.sammoa.persistence.GeoPoint;
import fr.ulr.sammoa.persistence.GeoPointDAO;
+import fr.ulr.sammoa.persistence.GeoPoints;
import fr.ulr.sammoa.persistence.Observation;
import fr.ulr.sammoa.persistence.ObservationDAO;
import fr.ulr.sammoa.persistence.ObservationStatus;
@@ -102,7 +103,7 @@
protected Set<FlightControllerListener> listeners;
- protected GeoPoint lastLocation;
+// protected GeoPoint lastLocation;
public FlightControllerDefault(SammoaContext context,
Flight flight) {
@@ -570,8 +571,9 @@
TopiaContext transaction = persistence.beginTransaction();
try {
+ GeoPoint location = gpsHandler.getCurrentLocation();
- Date currentDate = saveGPS(transaction, gpsHandler.getCurrentLocation(), flight);
+ Date currentDate = saveGPS(transaction, location, flight);
ObserverPosition observer;
if (currentRoute == null) {
@@ -597,7 +599,7 @@
startTime = timeLog.log(startTime, "observation()", "Commited");
- fireObservationAdded(observation);
+ fireObservationAdded(observation, location);
timeLog.log(startTime, "observation()", "Fired");
@@ -807,7 +809,7 @@
} else {
- lastLocation = geoPoint;
+// lastLocation = geoPoint;
if (logger.isTraceEnabled()) {
logger.trace("Create GPS Point : {}", geoPoint);
@@ -827,9 +829,9 @@
return result;
}
- protected void fireObservationAdded(Observation observation) {
+ protected void fireObservationAdded(Observation observation, GeoPoint location) {
for (FlightControllerListener listener : listeners) {
- listener.onObservationAdded(new ObservationEvent(this, observation, lastLocation));
+ listener.onObservationAdded(new ObservationEvent(this, observation, location));
}
}
@@ -882,8 +884,8 @@
@Override
public void locationChanged(GpsLocationEvent event) {
GeoPoint newLocation = event.getNewValue();
- if (newLocation != null/* && newLocation.getTopiaId() == null*/) {
- lastLocation = newLocation;
+ if (!GeoPoints.isCoordinatesEmpty(newLocation) /* && newLocation.getTopiaId() == null*/) {
+// lastLocation = newLocation;
newLocation.setFlight(flight);
persistence.delayEntityCreation(newLocation);
}
Copied: trunk/sammoa-application/src/main/java/org/dinopolis/gpstool/gpsinput/SafeGPSSerialDevice.java (from rev 389, trunk/sammoa-application/src/main/java/fr/ulr/sammoa/application/device/gps/SammoaGPSSerialDevice.java)
===================================================================
--- trunk/sammoa-application/src/main/java/org/dinopolis/gpstool/gpsinput/SafeGPSSerialDevice.java (rev 0)
+++ trunk/sammoa-application/src/main/java/org/dinopolis/gpstool/gpsinput/SafeGPSSerialDevice.java 2012-08-10 11:56:16 UTC (rev 390)
@@ -0,0 +1,60 @@
+package org.dinopolis.gpstool.gpsinput;
+/*
+ * #%L
+ * SAMMOA :: Application
+ * $Id:$
+ * $HeadURL:$
+ * %%
+ * Copyright (C) 2012 UMS 3462, Code Lutin
+ * %%
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program. If not, see
+ * <http://www.gnu.org/licenses/gpl-3.0.html>.
+ * #L%
+ */
+
+import com.google.common.base.Throwables;
+
+import java.io.IOException;
+
+/**
+ * There is an issue with closing on {@link gnu.io.SerialPort}. See
+ * <a href="https://forums.oracle.com/forums/thread.jspa?threadID=1292323">
+ * https://forums.oracle.com/forums/thread.jspa?threadID=1292323
+ * </a>
+ *
+ * Proper close. Need to use also {@link org.dinopolis.gpstool.gpsinput.nmea.SafeGPSNmeaDataProcessor}
+ * which is listener on the serial device
+ *
+ * Created: 06/08/12
+ *
+ * @author fdesbois <florian.desbois(a)codelutin.com>
+ */
+public class SafeGPSSerialDevice extends GPSSerialDevice {
+
+ @Override
+ public void close() throws GPSException {
+ if (serial_port_ != null) {
+
+ serial_port_.removeEventListener();
+ try {
+ serial_port_.getOutputStream().flush();
+ serial_port_.getOutputStream().close();
+ serial_port_.getInputStream().close();
+ } catch (IOException e) {
+ throw Throwables.propagate(e);
+ }
+ serial_port_.close();
+ }
+ }
+}
Property changes on: trunk/sammoa-application/src/main/java/org/dinopolis/gpstool/gpsinput/SafeGPSSerialDevice.java
___________________________________________________________________
Added: svn:keywords
+ Author Date Id Revision HeadURL
Added: svn:eol-style
+ native
Added: trunk/sammoa-application/src/main/java/org/dinopolis/gpstool/gpsinput/nmea/SafeGPSNmeaDataProcessor.java
===================================================================
--- trunk/sammoa-application/src/main/java/org/dinopolis/gpstool/gpsinput/nmea/SafeGPSNmeaDataProcessor.java (rev 0)
+++ trunk/sammoa-application/src/main/java/org/dinopolis/gpstool/gpsinput/nmea/SafeGPSNmeaDataProcessor.java 2012-08-10 11:56:16 UTC (rev 390)
@@ -0,0 +1,90 @@
+package org.dinopolis.gpstool.gpsinput.nmea;
+
+import org.dinopolis.gpstool.gpsinput.GPSException;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.List;
+
+/**
+ * Created: 10/08/12
+ *
+ * @author fdesbois <florian.desbois(a)codelutin.com>
+ */
+public class SafeGPSNmeaDataProcessor extends GPSNmeaDataProcessor {
+
+ @Override
+ public void open() throws GPSException {
+
+ if (gps_device_ == null) {
+ throw new GPSException("no GPSDevice set!");
+ }
+
+ try {
+ gps_device_.open();
+ open_ = true;
+ in_stream_ = gps_device_.getInputStream();
+ // start this runnable as thread:
+ read_thread_ = new Thread(this, "GPSNmeaDataProcessor");
+
+ // >> START fix
+ // Remove daemon line from superclass implementation
+
+// read_thread_.setDaemon(true); // so thread is finished after exit of application
+ // << END fix
+
+ read_thread_.start();
+
+ OutputStream outStream = gps_device_.getOutputStream();
+ outStream.write(INIT_HOT_START.getBytes());
+ outStream.write(13);
+ outStream.write(10);
+
+ } catch (IOException e) {
+ throw new GPSException(e.getMessage());
+ }
+ }
+
+ @Override
+ public void close() throws GPSException {
+// for (Object rawDataListener : raw_data_listener_) {
+// removeGPSRawDataListener((GPSRawDataListener) rawDataListener);
+// }
+ if (read_thread_ != null) {
+ read_thread_.interrupt();
+ read_thread_ = null;
+ }
+ super.close();
+ }
+
+ @Override
+ protected void processGSA(NMEA0183Sentence sentence) {
+// if (logger_nmea_.isDebugEnabled())
+// logger_nmea_.debug("GSA detected: " + sentence);
+ List data_fields = sentence.getDataFields();
+ Integer[] satellites_ids = new Integer[12];
+ String pdop = (String) data_fields.get(14);
+ String hdop = (String) data_fields.get(15);
+ String vdop = (String) data_fields.get(16);
+// int valid_fix = Integer.parseInt((String) data_fields.get(1));
+
+ for (int i = 0; i < 12; i++) {
+ String id = (String) data_fields.get(i + 2);
+ if (id != null && id.length() > 0) {
+ satellites_ids[i] = Integer.parseInt(id);
+ }
+ }
+
+ // >> START fix
+ // Resolve NumberFormatException on new Float with empty String
+
+ changeGPSData(PDOP, pdop.isEmpty() ? 0 : new Float(pdop));
+
+ changeGPSData(HDOP, hdop.isEmpty() ? 0 : new Float(hdop));
+
+ changeGPSData(VDOP, vdop.isEmpty() ? 0 : new Float(vdop));
+ // << END fix
+
+ changeGPSData(IDS_SATELLITES, satellites_ids);
+ }
+}
Property changes on: trunk/sammoa-application/src/main/java/org/dinopolis/gpstool/gpsinput/nmea/SafeGPSNmeaDataProcessor.java
___________________________________________________________________
Added: svn:keywords
+ Author Date Id Revision HeadURL
Added: svn:eol-style
+ native
Modified: trunk/sammoa-persistence/src/main/java/fr/ulr/sammoa/persistence/GeoPoints.java
===================================================================
--- trunk/sammoa-persistence/src/main/java/fr/ulr/sammoa/persistence/GeoPoints.java 2012-08-10 11:53:45 UTC (rev 389)
+++ trunk/sammoa-persistence/src/main/java/fr/ulr/sammoa/persistence/GeoPoints.java 2012-08-10 11:56:16 UTC (rev 390)
@@ -24,6 +24,7 @@
*/
import com.google.common.base.Function;
+import com.google.common.base.Objects;
import com.google.common.collect.FluentIterable;
import com.google.common.collect.Lists;
import com.google.common.collect.Ordering;
@@ -38,10 +39,43 @@
*/
public final class GeoPoints {
+ public static final double EMPTY_COORDINATE = -1;
+
private GeoPoints() {
// static class do not have instanciation
}
+ public static boolean equal(GeoPoint geoPoint1, GeoPoint geoPoint2) {
+
+ boolean result = geoPoint1 == null && geoPoint2 == null;
+
+ if (geoPoint1 != null && geoPoint2 != null) {
+
+ result = Objects.equal(geoPoint1.getLatitude(), geoPoint2.getLatitude());
+ result &= Objects.equal(geoPoint1.getLongitude(), geoPoint2.getLongitude());
+ result &= Objects.equal(geoPoint1.getAltitude(), geoPoint2.getAltitude());
+ result &= Objects.equal(geoPoint1.getSpeed(), geoPoint2.getSpeed());
+ }
+ return result;
+ }
+
+ public static boolean isCoordinatesEmpty(GeoPoint geoPoint) {
+ return geoPoint.getLatitude() == GeoPoints.EMPTY_COORDINATE
+ && geoPoint.getLongitude() == GeoPoints.EMPTY_COORDINATE;
+ }
+
+ public static Function<GeoPoint, Date> toDate() {
+ return TO_DATE_FUNCTION;
+ }
+
+ /**
+ *
+ * @param geoPoints
+ * @param dates
+ * @return
+ * @deprecated useless method since GPS save same points at exact observation or route time
+ */
+ @Deprecated
public static List<GeoPoint> getClosestPoints(List<GeoPoint> geoPoints, Iterable<Date> dates) {
List<GeoPoint> result = Lists.newArrayList();
@@ -65,59 +99,6 @@
return result;
}
- public static Function<GeoPoint, Date> toDate() {
- return TO_DATE_FUNCTION;
- }
-
- protected static Function<GeoPoint, Date> TO_DATE_FUNCTION = new Function<GeoPoint, Date>() {
-
- @Override
- public Date apply(GeoPoint input) {
- return input.getRecordTime();
- }
- };
-
-// protected static Date getClosestDate(List<Date> source, Date date) {
-// int index = getClosestDateIndex(0, source, date);
-// Date result = source.get(index);
-// return result;
-// }
-//
-// protected static Date getClosestDate(List<Date> source, Date date) {
-// int size = source.size();
-// for (int index = 0; index < size; index++) {
-//
-// int nextIndex = index + 1;
-// if (nextIndex < size) {
-//
-// Date before = source.get(index);
-// Date after = source.get(nextIndex);
-//
-// // If the date is equal or before we take the current index
-// if (date.equals(before) || date.before(before)) {
-// return before;
-//
-// // If the date is before the next date, we check which one
-// // of the before and after is the nearest value and we return
-// // its index
-// } else if (date.before(after)) {
-//
-// long diffBefore = date.getTime() - before.getTime();
-// long diffAfter = after.getTime() - date.getTime();
-//
-// if (diffBefore <= diffAfter) {
-// return before;
-//
-// } else {
-// return after;
-// }
-// }
-// }
-// }
-// // We loop over the whole list, so we return the last date
-// return source.get(size - 1);
-// }
-
protected static int getClosestDateIndex(int startIndex, List<Date> source, Date date) {
int size = source.size();
for (int index = startIndex; index < size; index++) {
@@ -153,18 +134,12 @@
return size - 1;
}
-// protected static Date getNearestDate(List<Date> dates, Date currentDate) {
-// long minDiff = -1;
-// long currentTime = currentDate.getTime();
-// Date minDate = null;
-// for (Date date : dates) {
-// long diff = Math.abs(currentTime - date.getTime());
-// if ((minDiff == -1) || (diff < minDiff)) {
-// minDiff = diff;
-// minDate = date;
-// }
-// }
-// return minDate;
-// }
+ protected static Function<GeoPoint, Date> TO_DATE_FUNCTION = new Function<GeoPoint, Date>() {
+ @Override
+ public Date apply(GeoPoint input) {
+ return input.getRecordTime();
+ }
+ };
+
}
Modified: trunk/sammoa-persistence/src/main/xmi/sammoa.zargo
===================================================================
--- trunk/sammoa-persistence/src/main/xmi/sammoa.zargo 2012-08-10 11:53:45 UTC (rev 389)
+++ trunk/sammoa-persistence/src/main/xmi/sammoa.zargo 2012-08-10 11:56:16 UTC (rev 390)
@@ -1,159 +1,150 @@
-PK��@sammoa.argo�TM��0�ﯰr����B�K�Z��ʍ��Hv����zƱ�8�v%�RT�{��a�L�M���E=��Es�X-t��;BB���f�
+PK�X
+Asammoa.argo�TM��0�ﯰr����B�K�Z��ʍ��Hv����zƱ�8�v%�RT�{��a�L�M���E=��Es�X-t��;BB���f�
��ʌ��Q��hE>Eh��w���dEN�m
�s,�"Q]0\&V[p��&_����C�y��졤�WL<`{}�j)B-��qi���`z�G)Aiw.��#�V�8ŋ>����5�ڣ�-Jt�<����K����B��g9��=�r����#����Y�㢼hϼu`@G4�Ù�^�Kn�*p�����G;N���Ї
�7����(�Q�h�cprk(B�v���s�7M�#ݠ���̼���<���d,S=�������.�4c����p��Lk%�X���f��|Bh\�i�����v�����/��?7���
VMjK��F��\V��%iL�/Լ*,��&)ʓ2����K�me`_>7vJ��|'ҍ��'��L�U�MW��,×�҆m�n,uC뼁�cI�dN�0/�����8�_��;�v��\-�
-�:��laM���-o����,�5:-�+�=ѩ����hD���)��d��TVs�PK��,�=�PK��@sammoa_Diagrammedeclasses.pgml�]ms�8��>�B�[wU����L�e;�\�2I*�����֔,юv%ѥ���������cR�7�
-�(��Mj,���ht?��ӟ��M_��r�_�@A4�������_�o_/~��O������_?����
-w����e�"��b��`W��G��b�J�/�.���x�.J��'ç�pv�\
-W��o��b=Z���zr��/ﯧ������A��B��<'B����E��C�ë�q��x��w��3�/�ϚElX�Q��h��7욟���y{������X�)���{��r0aS��#�����L���i��q8]F?.W�"�Wߞ��L��_;?���b����݅��я��j1yX�"��l�_�#{ou��<N�S���Q<��_`�`J�?ٯټ�F�
-�o��<L��&�z��������pm�^�q��"���iĽ�������t��7��2pw?�>��������K4y��b#G����OO��~r������?V���0p$�*G�� �혍۩�`��X��c<_�b3��v�MV��d��E�lw_>�ӱ�U������������d4܈�u4g�~��7���|���O�'wn����"{�(�I�ˤk�s�H&�(J�e��߹'["�uU�1�K+yoo������V���
-_p���B�5�[��:Ea��2���k&^�^�Ϧ*��@�f�k6����J�^K%�-�?MW?&ط�շ?=���A2�OE�M����F_�bR��%����X�zZQ.$��D�\f[�u<{.V3��N�x�N�P�UC*U����b�T��e��j�c�v!��<6�Vh����*�- ��wLf�O�J��+���r����i��!�6^��B%�n�a�#^�8;
-.V�G��#��b�,��|l�7���E=ހ�W8�^��5+g+�o�o��5+�ƣ��z��c�?��4�+�*���ݳ����d-������wb}x�������|��@7_EO��𬟁���1�d�Ig}�mp���y�ճ>F����QW��^�Q#��&�N����SZ3�x�� ���8�gB�ifL(��BBL�a��.@�`�Z�؏ !!&��8p���1��[�QYDY�����$��L�s��H�q�SY�M�!%"��l���>!$D�$m�r�9V"��h�ݭ��^W5�Rd���I
-<'"��xP�yt���!%������
-��x��R������Q<֯t���;X��o���u�l�Nߺ���N���
-"���8K.F�8Xn���v �
-�
-��lj�%`��po����&v3��l����e����[��oI���CY�C8P��{..l�"�w��{�Ȼ�q�g�P�u�ּ.ɫH%4u�z��.�$��fNJۅ_��:խ�&�]��w�g:���{jy_��}�u7BJ�Fwن�u�/� �۠y+r�l�Ye�l|;��3T6�F�N-�L'�� )�Xq��1����?^�ݗz��{��#��@�@������u%�n�:�\5�����n*�&U@�r:�����x}s�A\�k�wh)�H��5������"���E,�����]Z)��q>�\{����x4I�Lv��*{�2^/F�u<����L����9��}��|t{��vs�/VA�����E��6��o>��H���Ev�O���C�Gd�h���S��ysT��%6��,�O���s?��F��(~ ��a�d#�g�9��?.�}-�,4�
-=�O��]���2J��L�
-�qC�e=]M���;Y};�ו���B07��m(�⼙�/��x%j��O��O��q��j%�z�Q`�9m(��_���#�p�K��O�;�L��a�6�S�ȶ��K�#��S<�`q�F����l����*�ث8���9;
-+l:�g7x
->�
-�B�u�k�tv�)-���44��~�f�H��cH�HH�i�Wδ4��dǗ��mit4�ܞ�Q"�хa�ʰ}y�F�Qu�g����_�ߔ�F�EFz"�i��b`��{�?ਾ������.x���澫u���
-�a�ל�iH��\�n��E'"�WԞ&_QQ��v>�L��o���o
-vT��DtA=m��F14�r� (����M�8Zt�ZEb����a={���s�ᣋ��:Nt���$�?)q!e�ia���"�T��a�a��w��"'�hkK��hsh���e���থpk+��psp�� ED)M$��-vփ�'��
-������u�z�9��/ï�x��C�B�-u�CΗ:�}2{;���a)��2g=ڼ6N��������|m��p���b`h
-x�A�����I���c��K�����Y�8��W���/=\�eB[�8�F��r�kV�u�]�����h�k�r���A���5�UϬ��,�!Ե�8Fh>n[YήC^<��r����9Η9�e!�
-1��!|*�����a��G�K�k
-������çB�u�0n��P����a�I�S��TE�>{
-�dR˹͗��.��):�6�J�[��
-��٬���hUb��'
-��=����k�B$_���<"j;�9U2���#B骖����`2�����d"�O�p~�y@�mP0b���_��|y��s�q�*|j]�j���?�����<��*a{k]�k���~��j�I9غz}=�<�W���[״j�v]�vB
-[�^9��La�{�uX_�M�;Lm�3+��A�k��m�5��B����Ζ}��jc$g����q��*/�&�'�\\7���\x���K�G��z�?�a�)�w�ݭ�@�k��Uy̜*O�ǒ ƭԛ�<�n$U}���
-><k�X�yL
-MĢ3ּ��Iշ�8c��)/O�mRB��8c�O�Ϩ�'������������mzvS�6�%�[�CK9U�^d/�"�:ʒN"q<��)^����.��!z���z<�+#���=��j��$�Q���W���dȱƟ�C^���)�Yq5X:�x)�P9-��j=�uI���U������<�㙙W��s\���ȇ�
-F>�|P
-�6f���Z/&cv$[yJ���.r�.�E�)lT~����{����`je�5)�;NY��L7OM�R�ׅ�{�������$5�A��,�
-����Gû;�C/?�j#�=�<�O��"�u>N��@-uT~
-�~��~�dѾ����hQ�y�y4��k�1W0���F�����ڔ�u��E<3Y���@W��G�G=z|���,��i��ۤ
-�t6�y4������� ʳ�Āh�l9B��&�ɔ����FI�R蜗����/:Z�����̩S�U�#T#�D��CM�8R�r��?�'���$
-��� ���]~�7�h ���vX(��\��N�f:t���L��g�<;,/%��u�aw�g�)^- �Ͼ5�N�Y� m�o�rw�w]9N��P�T�"t4g���9�;_��՟LO�ۇr��;Ic%�Y��Ǧ��v)w�B��v���q~�Ef�)�+<����cM�����ڤ�m���Y�^���-�����M^�%G�|�'kzŵߴ��ꆟӾ�A��e�����N$7���T���EvOy����A�}��7
-����"̭7
-����nt�9��m����!�{����4hzoP�1��=���w�_�^��a��6��OiW|��M]�i�-��~�oS
-�B
-��@�$�:�������Y�4���JT����nU!��&�-����|�A�F4��Sd�͛ygP�$T|���{S���)ͩA*>����k������U�FQW�i�^�Ю~�]R|�]l=?�";���v��I�)���J�{�yt����3pg�ư�P�{W ��1�!� L-*p��PI|W02�1�0��fC��G�i�[�j'��k[���u5�nRk*�j�J������F������M����������"�eE5F9O�r�*�kr<� �:l6���zrv,w�`���&E��4�ݲ��zj�5��}2��unX!\}��%\�g�x�3S��M5���0��$(��K�B8�80� �4��$.z(�ü���M?`�w�p��cȁp��g XPr�NA��$�9zN����A�Υp2��]��5?�}m̷�ֲ�r+r�7>US�Io|V("�a�[k��`�V�x�M̷ו��71Qob�o��D�61�V��_!�)���Ƅ��6&j������ј�ڵ6����#�6f����Ƽ��Ǽ��Ǽ9��Ѝ����,�bf�T�!�a�ڋyw�¼9����C�'�yS�D��E�0�
-L8��
-L�x)��*�b����)\31sM�On��|=ے2��#�P��)�Tw���ʢ����v3�{�m���(�\!S�ϗIJUV2�4M��#���dJ��#a�0p%U
-+�!��*�6�grP�-����.�^D"�t���V��-��� �!AT�E�|�vq�V��?y�T:di6}����ʚb�O���v��M���<qͼ�d��m�<s�h�h��~�g�h��)E4u�t�I���C$N��P1�yt�f����ݻ�R~}�4.E��5���~�s5�n9ʺ6:����p������߮.���t��S�
-���AZMWH�G�����V��3���Eu
-c�bش��\롓��n�=�J��V(�o��6װ��w�Q�w�rRx�MB/����K:��U����p<���mP :a�&��<8��9b��<n�(��~��<�m�H�x��h��YP�������a�;�Mu"�Ҳ�y��io3����,�B(�0�Y���e��A�9!\�ӎ��չ.�@v�ozoc�_�oB��72�s?�`�� 轕i�([���Dcd�\js��9�z�3��j�ˍ�rO�-�J�o�A�0s�&3̮�R�
-��o��9�%>!����E�Θl�H8n�a֒֘�o�l���L3��%5��{��4㥩*�Ո_ �R��s�%����c��A�fӷ�ܟi� L3Q{�D��g�i�*�wL3wV��L3Y4��0�N4�Q�D��L����ڠbf����O��~�)gAy
-�L�J��.�n��e�e
-�u叿,jR��Q�Ծ��]��� �>�" 3��Q�Uj�� C�Ծs�Gdj�"�!�a�8j_n��*�z�p�/,^�aN{^���{x�����h��8���7�w7�ʯ5�s8j���+/�E��/���aW��S��NG]�]�r��>���o���7=̊BW��Ծ��Qh7-��Z�I�`x���Z|���!�R���QB��*�j�$�W���V�T�C�߾��@����/�<TF^�sq���$Xz��xJ#���){
-�T�v{�R�P~<�� PB��
-U֨��ź�� `J�t��IkO�H���ٻ�㣲�3d����
-�j㭖 �V�X��q�ZF���b;E��G�H�O�8�t��E�b�n����)�uױ�;�u�'x�:馀��c`�h�8^k�ƣ��z�z?��4�MwQ>�'��.QhF��E��6��K��.j+�w����S��@��6.��[�'�q�W����^^��zX/{���+jXO�I�EvS��7�pX���+v�V((��Gp{���)Yo;�X,ՠ[k���L^��� �8�vd���|�/B�S�D�1y}��6l�������HhZT?"}7$� �X_�mv�Gw��>[�3����nA��A�D���?�p�D}nI
-6g�RLN���=�z��W}�e�|�#í�T_G�0wT"n���w��������+��Vv���cAn�F�[ߧ�&��E��}�M������0��6�ћ���N!�Mî���2����8�, G$��c^¢��2�N͏�I�q ��|��䔱�#a�Hy�)�
-��GT�*������T,a��:bt��Q)PE�x��H�N*K��lM�'��C*c�'��:�6�TƆl�T�U2tG*K��22�LK^K�;0�<�,�I��Ϥ����|�b���qJA��{=�����b��f�����@fYwQg�@S�I�z=�<�l��'��c�A����#��|��h6�L
-�*w���qsU�_=���Y���d�j���+�������<Y%oNG�G �p�G2WXF���éH\�U���1����h��|��6�*�{�����$��QVA1����e�FP]r���6\�{�?����U�i���u��ip��.�S����gjx�>(a05��#����)VQ;r�}*s����0GC@�i��N�i:�'
-�f�Th-���hSl��B�8��O1��l���uᬗ�d���(~�E=x@�mQ>U�}[��mQ8����
-�DzLY��ֲ4�\��vh�4Nf��55lء�Bvޞv�lu��ވ���S��H����J�
-V:��EƤ�v�e ��CIo��rISx�L:m�^��ם�A�s
-b/��D�/Q��)J�n�msh��a�+��_�-�5���+u�����k�7�3���6�+�%8{�
-�kn����˶0yM��kTH^s�<Z?�3�]�9�?�RiTU*�容&=����7%�� xSTI]s��2Z�����d�՟�I��^�i#��kTH\s��-���jޚ+����*9kMIp�e�<z�Ur�j�Èg�E {�/���4��-[A�{���)��et�0����j=N �kv`��-� ��:��sR�9��tw1N�1���:[�ݺ�U�/��h�b!��;��H�@|�j�Nj!RDAݻ�l!ʩ;� R]��Y4��B�K}7b<��{1['��r�zl�x�*X�j/����.����'� >A�&[4&I�0�d�I�����J��n�H�v/?D(b5yZL�����y-�Ouƅ���v�C� �'%���r��<4��%��r��
-/�Ǟ�t����<���?���"��*D�����$ʔiT7ɜ�SU�V���d�烈��ڟL'�o�MV�c���3�������Ǯ.��xE�DsS2���p%�F��:�l�pDi��M�,����o.׃Y��L���`�����TB�i�/\ϣA��L�~9����1^��.�9�G���r�V�ϟ����;�9��� w
-]��2�*w��cS���%�EG����"�U���%��l��_��D��m69GI@��圤�K�(G��f����~3ʷ�&֣{�#���+{�S�V�q���>9RF��z�w��h-KC�����ğ��*G[G�Σ���I~�6����|����h���=�e����M(�d���V�.�m����W�\���h�&�{̤�5�F�Z�S�o����|6��eQ�.�
-�}u�Jؓо)���Bg��n�:�@Z����ת�(%iU�~;���q8�L��v�r��v�m�J�9�\�\��f����Y6�"츠B�m>�lEH@Ql�%�!�+.�DnK�T\�?N���W\�?,�(���l�J!�,�������SvSEnnغ�u��9\�5�Hc��k.�m��`~X�#�[Xr�ΎQ����_a�.�v鯰��.M~�I��RZ���^�����P�jO~F@��K/!i���A�cgl.4�g��a����7>��q��_nNC�N�1��#�3����OI�p��܇`g�ۓ��ƍ�q�¸��y��Z�u�gBθ_�K��o�ɬ�8Q[
-�6�L|neمZ�u8�K�xn�Q�M��Sy����
-Gq�AMg�,�Ɣ�Q{6
-p?�gh�W�34D�:J�Ui��Fl���j����z��02?C�IL&)0
-svF:�r���q4�u��X���d��a={��R�%=�v�qc���e�)�n9�&��C�8�����4ZE�CvO>�'힞�#T9:l���{o�Vc{�����緗Agi���}��j��/Qy�=V�a��*Y����!%1@����<-/�`;
-�;��0`�sP���M�o�_�;�]Ժ(`���|d��0XK �@�d��<hہ@��v�"ȭG]��H�U�-�]��P`(����
-�/G�i�u�`�ν!}| �a�!p�G��C�Y
-?��?N�T�70������/Cn=�7��hw�y���|g^���yi,�ܾu��n�6���P`���:{F����ַ;� �m����Ӿ㪹�w��f��à���[�9N`h��9:}���嶺m�B?�5�na�����4G?�p��S$J��fH���-l�^c�)�Ù��l�^C�0�o���9�E���E����~Q��}õ���-�o�pm|ot}�IZdX��[�rT�s
-uՔ��aV�a+����ҖdW��._���ȡ�����
-]��q�
-/OP�%B�u�S�C��_hj
-�;^Z-��!��Bq�JFW�c^g�C���^k��E�rIA�1k��Y�hH �h[�UVi�d��A�����+�����v�����q������q��D˔7�l���0�tu�:�<e��t"�<�����L���/z�y���j�)�n�܋p���i2O��B�����
-�)�j�,��|l�8�@�V"�n�@@ML�����fb9��L��S�5C
-��j3Q�!R�2���t��zV���+�6{HY��yH�TS�-��C�G�V�#W
-��w �D�]�ں�x�զ|�m����"�_y�E(|o�5y-�[}֣䴍Q�Z�H�����ar��#��
-��>�1��
-�Ӧ��C_�fg���v���*_m[j����� jc��QR�����Mm�}�ݼ�c�r�:�u6�#�QC۞�v*��UFN�w#��9zb_��=k�m�R�L�&��l�.���%xJ`�[��խ�F�=%���t���^�mOl�*�W<��]���z,=�������N�8��jF�l�r�k\�Z�tL0�����3�l� ��)�m�P������ж����.5}�e�D���Ӫ!'���=�2��? ���=�bh{�d�̽
-�u�]�0��9�*�y�U�����QV�U��*w�pk�����Q.�Tq��Պc�x��r2Մ2x�(���W*��+<�L�5eGs��*L~�y�$�����NQ���[g�g��2��3�gv�1sc(q�o:q�cG�>��W�A�R���a���щlN�\���Ҫ�yu0�sWKlN\�]�ڜA�mN@��6g�q��t�6g�ۜ�[�9��ۜW�zƺ��6����:M�21��S�����V#5�>!;�Y��}:�� �<H�%���)���dT�w�ʨ
-�l���S�q�����*5�ߺUv�*���
-��h� �]
-��Ұ�v)էM���̂�qX�--��׃�R"d��O��g)����P���1�^�I�*4nѐznDp�����P�q~6*ɜ��ș"��3� �������P�}��95ne���Z�bcF�ҵ�<-&�D�.�ђ��T�\hELGK�؉�QT�S}+
-�Fm*n����
-��W��`�7ps�_�j�9��#������"�E+X���ͱ�J'�9\��
-���I���4�N0��t J���/vJ��
-�Ԯĝ;�N��9e�4i6�\v3ɣh�7��e��d�7��j
-�D��s�^��ƣF����~2���%Ys�吭�h0��є��G�M�����S�!�dxh[�8�9�0N��n���F8i|#T��5DZo/=̪>\+����G�(��c���M��]P�,���sBA+T��W<�+��X�"1��)��6B��̔O�} =c"���D����d��A�/��"��j�._�ή�5��"�1���`�r��M����#��%�o�J�w6��\�ә����14R
-[��n���6��o� ���06�6��ي�'�g/f�n����L�UYVnk�$8��a�(�cWr�=Ò^ay��]J`N��T�()���o�r[��m����ȑ2r��
-)�U<��:.�r[l#X=Ƌ�=����[ĵVt+y�����TUѭ:�T�w�����&�*�B�`".T�R�QsK7u+q�� [Ӂ���{:
-��/����=�
-oW(�%+oO���Q�ժ�j�?q��JL���'�ou��nu
-)
-T�Y�ȅ�T��4�et�I�p��V:�*-��^K��P;���/��ߔViI��H��B�Wii�o?�z%"
-Q�|mIq{J����jm�������.���f�-�fQd������f!����"�|�����.!9D�;d��p���n��_����)R�vX����Q)8�֣R��Q�j���XB��~�I�4=���C%���P���_�,�} x9pmmؖT t�i[R�"�l˲D�B���J��9��BS>��-[�8��4an߶l}�@��[�-[�(�ΎQ��}۲�}m�o۶l|_���#E�S��1����
-
-���Z�a�A�J-�����by}|�P�]pyx��R�yի�R�i�*�^��r�~��l5�Z����m���Zg��Zk��p��F��@�n߂��n�Z�ߺ �ф��kAn߆��n�Z�߶�5݈%���3��x�����
-/��<}���l���PKʣ~*��PK��@&sammoa_Diagrammedecasdutilisation.pgmlMN=o�0��+�7�ٵAuM 0�1Q�d`���aY"qd'U~|������ݻw��Os'���m�q ���P�G��l7��eޕ���l:�\/��D`$���c�:����|�L�d�8m�n�����Xu��"����1���4TrR*�����M��9U�����o�� �n��gV��I�������л��z�Y��:��d�PKǒV9�PK��@sammoa.todoeO�j�0<�_��.YnkW6�M��{��Xk#P�ERL?�5%Ѕeg��aV�/�,`�ƙ�H�3��Tz���ٝ�HɾI����Н?�ģBҞ���J�H��*%a%�u�|��
+�:��laM���-o����,�5:-�+�=ѩ����hD���)��d��TVs�PK��,�=�PK�X
+Asammoa_Diagrammedeclasses.pgml�]m��6���_����Lbo�k�u���L�nkk+��8c�j�)�8��������$o$�$Q$��T,�4��ht?��ӟ�x�����$��y�ΝW�p6�Ɠ�ӛW��߾�_
+�����������_?�^��
+w����e�*���x9~ůH~���|�L�͟·�h�/��O�O����b9\NF�-���h��������������5�����y���^3'D����0xd�;D?�����?>���$���9|�j��k0��.^}��_���<Z�l.��<9��O�?%���<�
+�� �7u�����_�2YL����t��X��0Z~{ �2 �����a��.��?����a����~������A��y�L��!ҟG�4��y�g�)��I����7�����0����6�������pn������w�p�Ξ���F��w�ǛW�����������o����/K>r�NP�_���ٙ'7|���2�c)IG���6p�� y�N�q;e�����f�Dl������r8��J���ˇh:V������w�~���b9y���kq�
+g|կ|{?�����}|�JU,��G
+����ĻT�?Ǐ�B����P���]x�!�^W�3�����vs�,P�Hm�*O���w�+T[��U��Sd�iS/��a�����t����sdk6ޡf�/f ̑A���P����t�c��v����'�'��$��'���@_�
+ؠ�31���3ik ��zZS.$ç�r�H����e8_>sܶ�y[
+CqWU)U1�
+%�0����d֔�|�BJ�x"6�Vh����2�-1��w\ffO�J1�K����b����i��#~��q�q�� �/F������#N�Gj�t�p6��7-��E=ހ�W8�q��%��^o�o��%xO��pz5��8�Q4
+��R���~�,A~�p?y��lY�wP�w�;1�\�>��A���d�n6��-çp^���1Je�Ig}�]��1���g}���Y���Y�Q#��&�N���SY3�xv� ��C��� !�43&��g
+� !)&�1��w�S�y�D�
+<O8��ј�ݒ/��("��E��[HDَ &�)�p�E�����ЦG���a6}Dh���"B��F��+ٍ�5��F�P�U
+��4�� �d�����!-T>��AH��x����:�-�Ņt�i�i)A~��+�u�u���`Av,��ӳ�`9��Su��u17�����.����y����К{��������po����9&s~��{:����"�^f�-X����z����!�kz�=
+ K>r����ș:�.y\�(y]�5�K�* M��̚�E�����Xs���T[����$���.�L�w��{O-���/��FHK�0��ې���%6��hEn�
+?�l��g��{��F����i�����;"%k.�&�]���Nj��B�|/�MĹh�7��ݿ�*��-��Ę���{���M)ФhU�tw�Z�n.>�k`��-����&X#V=Z[[��6��%�� �"�K� �>P�5Χ�i�*���"M�5�Â�L��V�Qx�f�=����+qN�]�v��n�vn����#(��a�?��m}��C4�{��{~ڼ�b?"_E�|]=e�[4G�ORr`}i��ğ��?��o����L>�{���K���g���B�>��s��Qص<>.�X��+��/7�_V���o����a~U���(�*��
+�\P�7���l-e-z��u�IC�?̂�.W2.�@��
+�ӆb~�_�?r+.y�\�)~� �=,׆z
+��v~�����M����l@�� ]0���p��U��]��6������zDŽ�Pb]f��%��AhBK�?���$�_��C R'��R"�E���3-M�4���w�u[�&�ct�(tti؞6lOv�Ш>� �~|X���/E�Qb��KdR?ij��8�/�p�b�K�꙲���jGE��c����5�R5$Z{.
+p7����.*jf�W������6�l��ي aGU�ND�đ�
+∡q�}A���^o��E��U� F�m�V���N|tw�ĉ�q7����%.��?#�*]����=�"�/����\�mcɳm�q8�Hvܴncųn��0��h��T����z�Ť�U��"�=c��l�����$Z�����K������~�<_O��`P����Y���M�ӯI�'��F��7�X�\4�D���^x��g=�R�s삩�������Y����W��q�%^x��pˬLm
+��p.���Y)�Yt������Y˙�gߥ�k���Y=�YC�k�q��lܶ��]��
+#�g�7:��"ô(��&&<�O�>�V�?cU�x�YM���>�c�T���ƭu��ߜ?� ����>���!�Lj9��B����� E���T��S]��2�M�m�Z��d�A��'�qOy�T�����s�GDmg5'J�s�yD�!]�2j4_LP0��}��ί?衿
+FN���˻�/�?~.<�S-��Am*��C-B}��������g�S-l�am*��c�c�����^6)�T��[����?`�C�ٮ��N�a˚c
+���g[����ߌ�#��=����g��&��V]����#d9a���l�7�
+�1Fr���wO�"�6�4.=����A=������T]T��q`,���SA�Ь�v���_�ͬ�C�T1�K�@�Vo�'긻�T�9Z7�`֜������Egl��GU�Ls�
+�S]��ڤ�*�9c�O�Ϩ�%��I~XEOZ�L�Ӈ6�ݔ��v �F���RN����I���d�H�����2�[{ݥ^=�Op^Ӝ�*��t����W~&��b��彂��� �JymF'���j�t�B��rZ95z��h���������,�ㅛW��s\�x���
+F>��_�1f�/�\�&c~$[1-�J����s���6*>�c�=�ګ�p�2��',T`���4�M�� �~�y:IuЂ/>���=����n�O�P��O���~���t8����5PKG}��F!���Y��f��)��c^|�M��z�5��¯�n/��C�1��G]C�v=WY��R�T��G]D=||��˴,���o��d�t6�y4�V�諩 *��䀨�l9B���ɔ�����FI�R蜳�����C�N�T��i�jp�jW�H�>��F*R�2��;���˃8
+��l��F�.�̚E4�h�ID;,^2��v�pS�]x~��ɳ�$��������:갻��[/��g����,��6́�G�����'��(wX)g8���+��ʝ�Q��O����B��$ʝ������k�CS�<����v!�F����8=��2�4�44 �q�1�E�Wwvvm��zTZ�n�w~u�'#mu3�ɫ�����h�A/���6��^ވsڵ9�eV�l�#���4݉����қ�J��?�����;��з�zsP���Aa���zsP�oZ~��A�n7��-W2�:�}oP8��{��M�
+*5�Z������Π����\�]j#���vw��I�������Y�W�6��*�����N��3>�qM�ّ��UH��˭Duo|��V��i<�"|`��'mD<E�|�W��wUK�7Mnk��Ҝ��惯?���.>�@��+�Z��u���������%��'��V���S/�^�Hc��D��h���ןGg��-�q�����hy���>F=�䏉En�h����VF=����!_ޣ�4���I1�ƖF=�j]��ujMi]�@�W7����8سq�Y1ަ�&��[�����(��QΨF�&��T�^ͦ^�B�CΎ�4q5���f�]6P\�M�r��F<�ʌ+ă+��֮ă�L�l2fJ�|S
+�r:�=�*�n�R�@�)r�;�>�*���}�1��p�m�8���\i�X
+r`�ɉ��3��(9M� ��H`��S@�é�r�@p)�Ƽ��kc^_�s��Ƽ���m�@X�K��ۘ�Mf�D�ۘ�Z�>{�r�;mb^_��n��D��Y�&&궉y]Σ�\�hX�{�lۘ��6fl�Fc�k7ژ��}F*ژ��w4�Ʋ�ƪ�f~�\7f�~43��S��p�-̛r/�,L�m��NL�[��'?�`��n��7�N4�YT�����o��č70��
+q��</f������03�Ļ�F��V�R��<�c�t�!����١ZY�=�=�z�o�`��f묁�Rȕ2��l�$Te-S�Д;�:>L�8��J�R��V��RI��{.E�RL[�R�E��I7M�m�K݊���bDZ�'h�iI[���K%�A�f�'L��N��)�>Ĵ)Ek�Z���[���̛�����,�1��6��Z�z��F͜�D����$�HO�G�T2��Gwi���/>ܽ�/��'H�B���iE��������Qv�Q6��0���4��w�����vyq�U7H1�A� Y��Ш
+�j�B�=2�n�G[�Op{T�4145�5�a��
+�������d+�[�����L�ڎߥD�ߥ�I�I7I���?/�p�VcVf��E�H�#x�~)����W�������#�� �F��x��U��v�4=��<M#&GȜʆ�1�'^�Il�#Y��-�KqN;[���`fQB�� �B�]�0/�5�<� ຟv��,��p��^�{��*�x�q#�<��VW��2+�ʗ��)��1׃ڜ�4mN����}��Z���I������]?e�����K�Tm�b��Ru�o�O�0s�����I���m1�Z�3����jQ�4c֘f(���߃]��(Me�F4��U"\H���X-1���3�
+�4��=��L3&1�d�Mp�f�6�,Q4o�fQ�f�hSaN�h��_��Q�f���?�A�H̜�7W���|Ŝb�L�J��.�n��e�e
+�u叿UXԤnh���}���6��I�>�" R��Q�Uj�� �ԾS�GTj�&��a�8j_f�+�z��/,^/iN;^/��{x�����X��qvS�o��n�U\k�g�>��qWQ �@�_���î�N��:uw�<��S��>�Z��>��aV��z�ˡ��\���qS)�bǮŁG`0�m�w*ʱ��ŗn�a*���$T�K�R�K\{����m
+�0A�8���+��Xi�y��m��:��D��wɉ�0B�[���אHe`�w�(EPOw��{
+|-D*�Pm�Z�^l������Hw�N� i��4�i�1b|TU�A�Ls:�![ma��2�hK�8NQ˨�Q],`�ȣ���i��T�'��~��'[=��n�:.F�ul��n�1��N� �n ��9�r�5�O��pz5�=��hgUwQ1���.�hF��E��ֻ�K��.j+�w����ӥ�@��6.��Y�G� �W��������^V��zX/}��K+zXO�I�!����t8�'v�U?�n+�Z�!��=�vX���-�>,�Z�[k�����Z�~�$�ۑ=R �id/8�OA�5����|�a;�4>��`MB���A��˹!�U��eA!�f'}t��p���9cL�a�L����?�J���u��%)ٜYK39�{��{��n_��:�L��G�[٩��,�a�:�D��ǭ�To�����p+;���1� �N#í�So~~�"��}�M������1��6�1����}A!�͊]�Ie;g�8)��'$��cV¢��2�$N͎�I�q ��l����#i�Hy�)���GX�*������D,a��:bt��Q%PE�x��H�N*K��lM�'��B*��B$��:�6�TƇl�T�Q2tK*� ��2*�LKQ�;0���,�I��Ϥ����l����qJ@�%���TV��d�X~3����} �����C`U�I �z=�"�|��&��e�A����#��|���y8�V@�� ��[i ��z�z0=�����4Z�$�W �����y:�J^����@d�6�T��.�P6�+,h�c�6�J�6HYcj�
+���H�����n*�����6���fJYŰx3x�i~yɥ�F�p�`��6��{>~��r��L��
+D��6pOۀÏ�xu>��:P�n<S��������0^����X�S�F������Q��c�
+���;B������0��Dk��5F��b[5�8�><��ec4(�g�%���E���-��
+9�]�E�PT��mQ��E��[NP��7���1�g�F˲��%�C3�q4;4��a�����v�C/T��vh�F*ء�=%�t��-UQ�a��}x[dL:m�^��7;��vh�A.i
+/��I��Ћ���2���rn���-Q�@�?;EI�MQbl�pN���B ��0�2[�����m�H���vq�>�,{m���b^��ר���!����<:K<��m��ls����횼F��57#F��Gg��ʹk�q�H���a�)RJ��Ri-w���m�hD��� 2�M)rt��R�\����dY$���\Sgn'��j�k�gS%qm��4�����5*%�����-ڠ�˕�]f&����(�u��D�8��FM[Se��c�(�� �^�֨��V"U����\$�7_!�||?Iry��*��S-iM���4��\�n�=M��q�8Z�#C9�n1��=�r�ڲ*�sS#�s��2�sSo�s���K�+�
+���&�� S�XM�z4|�]K��t�Mo#1��l)�$���,���j�Tb�SmLrK�R'h���R��RF�bظT))����6zNV
+����s6p_1Tv,A�%u���\�2�q�2� +�勆ä����B�R@:(�bn���`ٙM[���|����/�p�_x�3A���s��Q3���j��_N���.w�k��<����c�4�O�u�����^��<�5�*Qvq�����4��ǩ�v�8]�����Wك*����k��'���[z����#���)i?�i��kJ]>\U'��T}��e���s�g�n�,������2S���j�����t8���ץ'��D�W�p%���������(���6z6��q���,|������ο�����2�yv�(���3�.6���)�Y�XL�D�:�@L�e��E��c���m����&�0�ͮ��!I�9J`���������y3ʶ�&���є$
+�h�����#��#G��;Z��%M�E!��^Wy��D���u��4���M�������՛��0����N4
+�����5S� �,7��(߅��m��Q��X�K�����U~��t�h�(C��
+�u�����??G�
+uh����}9�R�c&EU�I �}I�2ԓ]�"�uh5��^����*t�Y���@�8|�L�UX�^ �pC�n��ؕ`r.�,ʹ;�<Y%���E�qA��|,R�,�(r����8:K�C,���/�̖*(q��Xi.qX&Q��I鬵ʿi\C%I7I1����d�uE.�,4�����A�\ԑ�<����^��&���.��oa��:;F��k�m�pa~۵ւ��35"}Js���˓�}%~FF�����);�,&i��� �3�V�g��ᰌ��7>��q���_fNC�N�!��#�3�����9�=���Q�=�d>|;#�ݎ�>n$�ۓƭU����"g��>r��|8[��~;�g]������h�Kf�+pYE��$A���8�� FTq�T]����E��;FP�� K���Ш=���34�����Ѕ����#�J�H4L�x
+CYg5���Pe20e��d��0�`g$�(�-�yT�&��n���h��̞>��¹��k�Î
+n�v����c`�4A�-F�5��L�W���q8
+�a��S��)�'S�x�jG����|��-�jl�9l�z{it��X5ا����@Ě���c�@T
+T%�!�
+��*}HA����9�����`�̜dj0�9hQ@�&��b���Z��ִ����k d�������o;��oa �֮���H��� ����P���
+�}m�ߜ���@��ȩZ���[y6���:|5�N��xH�A�'X���I���&�avҴM�e �Gpy����������д����V���#�y�۷.[�^�&��A�����B�Ξ���}����m�o۸l|w��ѻn.�m7e��������<�#��+���FOC6��d�
+Q�����-�=�q�n�����}n�DA7�� `7z����k,3��?ӵ���k�b��M��w���u�h;����/��o����E�m��oFon�I�K��wk\��|�����x9�j�ػ�0��c~�
+��_$�1)>`u����p4rh�����@�ox��#��t��~�e�B�r=��PS ��9dyL�H �k]-�y5|~�0��X˽�/"�K
+��YK�N�FC�B�֨�J�^ 3��5��@�N�DJ�P����_��K��_����$`�Z��;�e�M,]S�I,Ŧ��� ZF��t���>f8.ܔ|�.>WLwK7�^?�O�Y�D�K7���`N�VKg1g�J���=`%��V �Ą��b��j&�����D�9E31��z��6�"]*�l\�@W*�g5[�"nӇe����J59�B�>D{q�j5"��{���|��H��U?����Zm�gQq�ƨx-���5c�����hy���۰%�m����E� �&�m�[�yDV@����=h6=lx�H5?��D���V�zXh�R�$���qP�����˘��жp�mbh[���f]�X����@H�����fRh���<rW9QGލ�����Y�f���5$RsM��]B'�K`Z`[X��5��F����a:}`{��6�۪��4��Ae�+l�Kf7���2�j�tVͨ�m].=���(�� �^B�Lm�0���*�����1��m���5���p���/�8�7�V��V9)��D��!W!�QrZ����C.��gOՖ9+��D�0a�e:�<g�C�r�G�X宗�He�[���r�6V�-� �*�@GSP�86�G�Y(G� PM�
+�����U����� eC�����쮒��a:Ja(��<�cT��z�@��3��3�Q����v[e��P��t����~��y��A�S���a���ёlN�\���ª�y�7��sWlN��]�ڜ~�mN@��6��q��t�6��ۜ�ns��9/���u���m�
+�ۮ��7����HO�y�f+�X����1ٱ�U���dzJa���σ�_�?m��2�x��*��ZUA��ңt`
+:n��S�[��n��J�;�F�)R��.���vi�t���ӦP��vf��8���xW��Av)����YE� ���S��c��ā$Z��hH���A��1� ��F�S2��9Sđr�bd��&�qC��m�IS����4��{�t�1�\�ZN��E,\�/�p�_z�\"f�%Y�D�h*e���֣6%7`�
+��
+����#g�o� ����Sx�xS9C����d%�7��N�(Y��pI�:*��:�����;�X!��(e_|S��*]�6�U�
+w�0d:���甚��|���s��$����@�����q�W�y8��./�j��������s��.Κ,�|ͅ���lNE�n�qT�iz�qt3~
+?D�cG2��Ɖtӭ�a��'�o�Zyw
+���+^����
+u�0�%�|L�!?����*�~�|N�i�
+~���g�<9����AzO�/���j�e�}R�K�*���ig[����|� �����/�E�m�|I;����>���V|P�;|m��r�>���_��&��7yg}���u��L�xy���FjŖ�y����y���7��l@q�����F�:[a������������$[�E��I�,&�:v�q�3,���Yۦf4ZC���r[��v,�E\���'�i#�}ސr[�o��B*��7��c4��PTt��֊n�/#Q���*+�UG���n
+�t���Q�U(L�jZ�5jn��n�"N2dk:К[;O�Y��5�ҽ�V�-�J��T�ʹZ��]������n�����b��F�0w�kHa��ͺF-��'3T�1 'q`¹��[�Dʴt"�z-m�2R퐻w�|zSX�%A� m*aB\��uH_��RF����,��fZ����jm���f�Vm�fi��VK�h2�A�`�J�������"�|������/!5D�9d��t��Mo*�_����1R�vX����Q)8�֣R��Q�r���XB��~�I�4=�b�CŹ9����� ^�,��} x9mmؖT"t�h[R�"�lˢD�\���J��9��B�>��-[�8��4�an߶l}�@��[�-[�(�Ύ���}۲�}m�o۶l|_�ے���)������
+*6*Vj!V���y(x�$����1D�q�e���J-��IT��J-�e��z�*���Ѳ5j�n2Z�%����~��ִ��X�F��@�n߂em�`��o݄em4ak�y�۷aY�mX���6bYӍX��T4n3FrLL#��崘�Ͽzz�����PK���Yh*��PK�X
+A&sammoa_Diagrammedecasdutilisation.pgmlMN=o�0��+�7�ٵAuM 0�1Q�d`���aY"qd'U~|������ݻw��Os'���m�q ���P�G��l7��eޕ���l:�\/��D`$���c�:����|�L�d�8m�n�����Xu��"����1���4TrR*�����M��9U�����o�� �n��gV��I�������л��z�Y��:��d�PKǒV9�PK�X
+Asammoa.todoeO�j�0<�_��.YnkW6�M��{��Xk#P�ERL?�5%Ѕeg��aV�/�,`�ƙ�H�3��Tz���ٝ�HɾI����Н?�ģBҞ���J�H��*%a%�u�|��
���,���\�l�v�
-l�:�L�A;��Nx�{�i7�����D�7��=�l5�^8�0�@h�@���h^PZ���ˢ����CYV�j*8�5���ӓ��LB�l�)�?�~�$?PKP����KPK��@sammoa_profile.profile�����Q(K-*���S�UP2�3PRH�K�O��K ����Z()��qq��e��qqr�䔦g恘���>
+l�:�L�A;��Nx�{�i7�����D�7��=�l5�^8�0�@h�@���h^PZ���ˢ����CYV�j*8�5���ӓ��LB�l�)�?�~�$?PKP����KPK�X
+Asammoa_profile.profile�����Q(K-*���S�UP2�3PRH�K�O��K ����Z()��qq��e��qqr�䔦g恘���>
�z& Q}�0�
-�����������b<��SR�S�R�K�����+�,EȂ9PK8��7y�PK��@
-sammoa.xmi�]�v�8�����陓t���!)*�I�$˙�&��v��^��HHf�"��q's���w{�٫}�͛�,@��(��?��x�L�@���
-�BՏo?������ʟ���F�]ӳlwJo�tyf�T�ݏ���^�<�������~������iÛM���f8�#7ȏ/��&�h6���#��%r�NKi�����2��+�f���������7�������!
- ����y��!i���%��(��p��1Fn�P���ۤ�������y�7�[4�lt���?���?\���D7Ϛ��VKi�_���Z��/�^S�����Q!���ܸ����;��ǯ^���̘�&��,�( �����V���Z
-���7�'=10��!y��#I�W����X���Y�|�ٙ��-]7Z�Z�&��A�WgF��|�\�]{��7J}���<�R���96�mƟB� '���[�S7>`4y���D;菃�G�Jۥ��\-G�������g�/\6z3zw���z/��U8�6��/�O�m�����B��l�0P�h���q��Ǹs������oV�Jw��GF��:(�>�Ǔm��o�<O�q.FG��a��߁���߾����SP�̼�"+NFeCﲬb^ȉ���_#{��X����9��)�Y|V�sgF�1�U�s�̀U�Q�8z�d|�:E�o��X�}E��s�d�<x~��0e�߿�G�*/����ѻ���}�+�L�HPLҀ���o�yf��Y�-��ȣ�z��������=�(�;������:s2��( ����M�AL�۷o��FG?<ӎ1r�݇�`T�a2�T\0������
-ω��&�S��Wb��1���e�?Xy&z����)Xy�Ţ���I/G�����_�yI��L�@����P@&��
-0��A��/�g�=B���軭o_�QH�Ml:62d�d�ПC/�C��o_�}u;~�����GY�SL����$�3?4Ve�?�-9�;ʼn�JrEa=�*��I��DO"����I�̙�Y�
-�R ~�k䅯o ���������|:�#9�r:r��"�J��g�:d)����!⠡�w�/Dn>z�'�k�4�L��
-פvV��=�:�)T��[��L�{s2ڭH!�n�@k��-Im�A����n�j�]��Y�]9��S�"RL��1�pxU��q!#�;Q�f^��n<�<�{�#�"$�NXh��������&���e�A,�d~����3�i&���Y��ћhL�u]� �����A�.m��R9��Y��FMz��]�.�o�Zu�p�����gG���U�\?��;"�(��r��?|v����P�r��e[~X4ܕ5�u�W�s;�o��q�r~4R�<R�F/�\"�>K;����9�0��ǚ�Z&L\p�?|;�0�y����l�8�3���~3n��B&~����ߘ`?>Α|?}���l�p�64�zm*q�i��5���$����^*�v`�m"�X�ϣ�c�<Q$��Lo?��ABD�
-�Uflң�'7��Sf��e�[�B?2 ېs�`_c9�='�dz�%ߕf��t������O?6�9��-m�+�L�L.����T�_*�|���AO$��|T�5S��� 3g�_�y��(D�����d�=�����9|^4s�?='k��M�\��FK=��Z�~A��n����n����26���˹�F�͘q �B|��u`�o����oK�����������?�.�KAk{3�������vx�R��<|U7�z`�
-l�^����*��v�k��n:
-�'�V�_r�ӆBf�ef��J�ѻR�����͛Jw�/��R��G��])fRo��yܾ�?,�܅�݇�2���=�G��pԿ���'��V�_���$_��4��+�Bí\lf����yz�Og.ve�vpo������-�?�Fn��X�Cө��ˇ���qnp]"���4�s�d�<G��T�mj-�q.K��QF s���(!��r�������/��Xߘ�$����չ��h��@�i��z2-���9m<`������Z�hcTΊ��Էɵ���
-̞Ug��Oad~Ͳ���������CWQ���&314\��Қ\��5y�A2��%1�8�Oƒ2]ʵ�$�1ɴqSmim�jiM�+g�vЫ:�>��#������n�����@H������V���ɓQ��h�b1Y���y*��*���Bq��~�u����~M)m1v �b{��.�n�1����XE�ke��F����S��;2J���L����}��^u;lt�>�D�U_��^_2�Jk����"^Oʶ|Ge���sH�����&�1�B�5w:x�LlP{<>~�o�Y��%36'�`at���;Y�W��w�\�*A�|t�)C���Td��r*fؠ��J����i�Qr�����n{�&�)�� 6:*�F�_�'��I��%٧S�&�m<Ps���^��\W����w��j�<���+��)R�����3�Xݍ�c�A��q����n�"�ſ���R��)����&O,nTp�(N2n��(�~���3s�ƨ�6��?�s�352�
-�Ix
-��d`�䉥�|r�8�6VM42w��sXU|���������N�+fM,N,��:�<XO|d@�����q3�Ug
OEg+�ѫ�:`Xj�p�e��o:x��OCQ�K�ƣ%[n�0�UI���)�I�.Z�\[�-�7���Z�Z�R�9d��^�+$3+N�X�,��ˍ��@H����p�̫��a��}/{�n�����k����&a�#ޠ���#,����
-Ë�r"�d�B2�ZҴ�ݲA��
-��)zv�״ ��n�Pm4Q��5���[>1�Bȝ���K�I7)Jߨ��c%Wy�����X�^���S�{!���V{����*���X �ׂ���L�\��(D���>A�����CfHO�l��{�ȉ'�>�9(Q?L�˞+uX�c�`!�Bh1��@�����:i�U��?��Xv0������F-'��+�
-�kH��Ur h�mST���3bk��mh:���|4XӺ=���삙&!2�Tl���K��!v���_V���\3�}����a7���ѡN��6�����h{+��#�0(�>gt�$mvPf�]H>&D�<X�d��JK.L-��L�e�'ы�s.J�Z�cȆ��*�p9[6K�>�dv.
-�w�,�HM�E�%(�G)�e����HS0�(L �� ��AE��y�iUPD
-��с�����(�k����+�V+��Q�Vkuۆ�E�N��[*�P�yu���?�-.}o�m� ),�ܲ�%�nU����M�_����$s0��Kuklu[:e�Ѷ�Iif��ʵ��B��[*��n!�Rq�r�Uz���R��|cIӻ��xL�ݞi`� �#�g��*}�X���2Mn^��I�_a��)�
+�����������b<��SR�S�R�K�����+�,EȂ9PK8��7y�PK�X
+A
+sammoa.xmi�]ݖ�8r�ߧ���cϜL�E��({�>�u���=�=���9 ���H
+z��k�.�q����IPM�(��?��xa�$�,
+_
+����~�9�#��s�?+/�Z���]ӳlwJ���~ta�T��O��^�<�k�捗�;�
+^������5o6�ц.��`�L\#?�TB�|�lNۍ|[�FSE�+������Jxw�4�j��?(
+}^�#�o�����!
+ ����y��!i���%��(��p��1Fn�P���ۤ�������e�7�Y4S�5��[?(>~�l)����D�/�ꅪ*�ƫF���)�D��+����+*��ܸ�ʟ��3��Ǐ^��x͘�&��,�( ��y��V���ߩ5���7�;=10��!���-I�W����xH��y���V�����R�-ܙ��&R_]�z�U}�2Z��'�Q��]��l桗��ͱiOl3~��9���z^���F��/��h�q��\i�%�WK)�~w�5t�l���F}oF���=�����mλ�=��H�m��:8P�˦
+�z��^����;/���_�|�r�U�k�u="
+��{n� xzAOv}Ǯ��2Eƥ�v��~w�[��~�J�xws��H�y1EV���(�0tFE��@n�}�-��h��_��2G��9�?2���̙Q���7�:�91 3`v�9�)߾Nт|���>V�o_�c��.�(�(1LY������'|�a���4|�|��'2�?(&i@T�ŷ���lr/��B��O��o�Ww���^�|���/j�#������DJ��&t�xjmS���[e/���g�1#������E�������&�����WpxIF��J`R<%�0Q�ɪXv@��ʓX���&6�BR���9�E�/�^�b;����� ���<��������L��`���'� ^���{���g[߾���v��T6"�
+�]"#��Ћ��P1�����Ww!��m�ǾO_ʊ�b:��}����ά�P[��
+A���
+A��S�(�!W�3���0 s��I�r��b%s&�W���_�y��[�2��Sy{$4���OǢx(G�/�B%��V"���M�t�R���l�����Q��q���<�\s��g�dV�&�[�rG�葻P��PI;$O!C`:��7'�nE
+YP�p�Z�h�ؒ�'M�D�Mk��F���Aϐ�n�\D�Iu�b6&�j�cD~'���ꢼ�ލg��~o�ydS����
+�r�{;^T��$�P��=��z��O�X�;i�;����v,�it&:stӺ.Y�N�Z��� ^���t��t�ɬQSR�^�rש��۶V]6�d��/��S�@w�%��vG�*
+�\���7�9�;���v�-?,�˚�:ի���7���9l�<�}�Wÿ�����_O�Ҧn`�cN(L4Zc�Ь &��������U���m�f�D�n���7O�`.?VC�دM0�g�|7}���l�p�0��ttı��;�Sg�x�7�.��>��h��&���y4vl�� �������ې5H��Za<ʌMz�|����&D�����d�[�B?2 ې3Z��6��Оr��Y���J�}Y�c��|Tͧ/�՜�ᖶߗ@&n&���NV���/�h>O�f@���2/�ٚ9���
+f��_�Y���{�Dyx���p����͜��O/�Zbb�%�%�B�.-<A�����GD�u�X[���l�e���E��\g#�v�8�M!.p|����w������nW�:�������pt_Z�i�}�Al�G,�)��Wm+�Gf�����@��ם&W!-�Q����(���Z�;�
+�ӆBf�hc��J��B�:��O��5��b_�9ΥN���ݻB̤ΐ��}��_B�˻�7E�!u;�����{%��N����}�rï���^�\|b��
-,0���-��ϛ��WZ����ŵ�"|�6��IF�;��x�6�VaG/N�����k�g�6=ߺ�g� ��A1u��c&ZH.��+��' 0cT p<wj��8 �Ӓ���f8X�N�^� 0�+�P@&8 �,K��#A�f>� ����>3g�2��(���I� P,W9����7d!�c��Z� &q�S�Ce�ాe��W9���q����ND�>�Ϡ�#"�_0��B� �|u*����M���e����hVq��X�����P��!��r7�V a���0g����i�#��;r���;���ܳ����M��Z�Q@gF;'��@��ak��M���fߝ:�R,-�Z�8}�Ǐ�Hp�H��4��R�,y��>�Mu��Q�}-
-��E�@���d����:�1�
-�/�D�j\��%/]�CDN�C�q@�:�n�ٳP@jW��Mq�`� ա�Nq��
-$0����= ND�:��]nZ���z�2�,&��8}�R<���@�[���0�wB�,y���E�a�C���s���J`�96�ԑc�Z�:�܄��:=��=p��4��6�qb�q㎥�s�r�-��N�I���(B !�0ա�XP��pFC҇���k�ʚ�`&�}.aӴ��P�bi��kH�R�\��0j���z��ѵb#�l��ٵ0{{��ٸ,jo�Ax� /�O����0}L�Ar�$p��A�,-��0}�~Luh^�Q�� ȵ��e����aA����A�i�@�x3<C� �ς�̈́�p�T�c�D�na6�3�3�1�-�>��P�-ա��KB��B���j;��g�:�Z�Sn���v<�;��g1qg��A�Y�Cea�,�a����.��[�����3�6E������#�B1����X@J^ᛢ�D9>�p�~jo�z����S�w!N 89Sj�|S|P\r�,;I�H ��b�$��T��ֻ�/��t�p�n�^�-���:=,����
-�U�i�`iQF�0�`�:T���D�5�b��:2�:��aM�t\ڸ��m1=�7���~���}y0�W���a��
-���kF��]3��_#b�����B���-wt
-�WD7G>aQ�}��I��("=W�'b�1!��a�'۵VZr�jI7g-��Tw��d���s.J�Z�c�&7��s��d�l���OɌ�h�ƈ��g�B"�E� ���C&�̭`n'�ܔ��ܖǐM��:]!�Ζ#&W22�+��{���fs��-�-&�����-ա��=�������ş�d�ukO��FRU A��������9ա��g�1˴γh�O�;,7��G����N` \,�[�P9�-�tX'�p��AE�T����x�o�R�,��8}p/�` �YD�_p|�a�V��"�ů��a��1.�TX$�1�t+/!�ӗw�
-��r,�4f¶�:=�`a3rKB݅h�C�'�j1E!�郚��F����fS�ĩ�����0��H�FL��\k���� �b N ��:�<�@�^������jGJq�����q��uz@�G�V=���(p��;��|-(�@�>�,Hu��A|X0��)8���@�O��C3�cr���,�����'�����rl-���0}��3ա�P �Mf?[��q��z[Ղ�!3���6��)I����.J��w��$�H����d˟NU�4S���'��I�mE�k����x�gk1�����q���b�����GH���*���,Ɵ$A 8�Rj�*��]Q
-G��bX�RR�@XK�:T6��kɎf`�gN�xj�c�P� ;eJ&�u������O��Z��kIqas7"LB9hv�!Nl@�:��t���4 ��^�*R�����j�:��w��s��݀�<-y:�!nNu c�[�c�{�p@���T���q�:�$��r�6�Oy{�s�Y�@8��PY��"�m�ՑA���T���'�a�����l�1I1�7�8}�&Hu��Y >&�Gۖ R �2����ؒ �P�8eC�dEXn.��V��
-�[~*O���ů;�UtFB��9����|!+�k�B@�4?�1r%+7ա�*n���:��ڞ��� ��:���%~��*'��b`@�>@�T�j�Y�f�%�qO�=�y*+���V�q^M�Ա�BL�S{�},|����I�a�+�Β'��AB�T�j*8�U��2�VǢ��cj��w���{���4|��h1GB$�3!�����8���%���8 ��b�y%���T���ִ��( �ς�Y��,R�������Hq��pa!<�p 7݊5( ��b
-bK�Sj���\�Ș�[p��P���Z;��g�d
-��s��Mq�`� ա�[*���g�̎�U
-��Uh�.u��9�l�k�π2l-
-��4Hu�fY��ʉ�Ȍ��P�KǞ>�̭=u=|Ґ��Q$������Bo��z=jPt��u{8G���c������6}��K�]��r�y�_#�Y��f���5��5"����1s1��X.
-�z����>G>a�%�n�6��(w8�� Q.O��]k�%W�-������*�lز?ȱ�����R����aoӮ�f��-��c�S2#7��1b���v�,�HM�E�% v���'m�=��t�*@Y[[���V�Ϊ�:�|�-:,Tn��G��,�e�YL}yq���|�x��a�qS���1]�8ZL�Vq� qk�CՁ`�C��Q����B5tS7�[Ap*��C){r����̎���ӌ��˗߫",(
-�*���Y���rG��)|D�P���ڗ:Ӹgә��KكZ;�l̵DK���? .�ܳ���r��?R�c߽�is�V|�=�_NF�L*��l�SL]l�vS������ә>5��<WdhL��cՃ�[ط�)���_�b�M�>�.�z.�q�u�䪉4ӊ�s.Ƨ"A`�aI��S���T9+ī")J�� p����:-;���LlǓ"C��Q@��W�$B?�X��͒cĠ"�J2���6�6G��f����X�h96�ٛt:m�2��j�5�+j��9s�F� �vU�4'���ǽ��`lj��F�>�
-n0�d]C�fVq&�8B03��o�(&?�8}b�N ��I����i���N<�P��56.3�*n�9�7�_��*��b��'g�*k�.�i���⭻�Uc��:��3F������N�Z��h�f��Vq%,��-f�haQ7�0�ՂR��L��\�����YR=,�]JPě��
-b_=� )�"n�fd��"f��E�E|YvE���O.P�k��l�� �7���f�3y�Š���<{zx�z��=L�P��L�O���#��^���XZ�å��;F@h���:�1��M՜�4���֊)a#N_�MzA`�)�B8y)el���O�mr�V����(7�8�2��LB:dQ��gA��� �zG�u��,��3P}[~�:�#N���?@�SB�67���6:��h��8��/�^���
+�r���ά��[�;�:s�+�ϰ��x�w��U/�oa�)&0r�O�b=M�>�.o�z.ǹ�u�d�z�L�͑�e��{�S�����|ƥ,e�'��
+uO)!��b��|c�{ǃ||c���7&9��CĦչ��h��@��&S�l�<�6�m���h��|��6>�
+Gs�\pV�>��M�%��W`��48�x
+c �k�ΐj���]]��R��5�C��BZ���9Z�'�w�\,����l,�>ӥ\yK��L�5Uo�TK[hҘX���Nّ����W�O�����^�wLAH������Vě��g����d�*b�����h�UrN���2�����G:n�}�B�b�(@��n���n�1����XI�kE�ņ����S��;4
+��Í��0v�X�V����Y��*UTE<�3��"1�J+��O�"^Oʶ|Fi�xČ9$>x�٨xL���;<f&6�<�>��^/��hČ�I.X��:>�NV����'�|�S%��N=g������֫3���7� |ZNJ��<9=�n�ф�1�c�5�FSc��v����2�#�u��$�t��$���{ZfZ��kc�������NM+����1�s%8EJ�x�`f��1vJ!�5Oj��V�nW-�^��@_"5,�?��ya����A���1��,��s��V8J@<3Gfi���a���S>>S#3����砑�I&L�X*0��g���clcUD#seD����Av�檫bvV^X:M\'�5�8}�(^�T�`=qɀ��c��i3Uo���ެ�G���`�a)!��2m�tp���(��.)=�[K ���0�UJ���,�I�.Z�\[�+��6���Z�Z�R��9d��^�+$�3+N�X�,������@H�����s���U��0�о#Ǟ>��l��5����4��0�oQ�b��:Tņ� ���5�d!�y^F-i��n� �x��QVJ��=�����u}�[f�I�6�H��
+���q�'_���Ի�ai>�&E�֙~��*�!�SU�_ �K���S�*u/!��j��X]]E�1����ӑBq��`����`�BD�=Z���BB���I���y�9�d?�#;%�� �~�s��Kr�,�Z*3�>�1��.�N�=��6Ԃg��b��
+v����P�`� (��@ �R��@�ۦ (\��g�ք�a�-����h���;8#ـ�&!2�ɨ���ޗ��1v�s��/+�bz��>v����a7���աN��6������h{+7G>aP�}�t�$m������A�1!����'۵VZrajI7g�,9�^��KQ��Z�bl�
+�c.g��ѱO72{��8��,�HM�E�%(�G)�e����DS0�(L��(��^I��y�iu��(��'�Sz�?F�^�u}��\��Z��ܴ��nV�;�V5l����|��
+^[�|o�m� )<<�e%���6=6�~Ղ�����$�]ڲ�V[mQF
+K�ԑ�d��h\��)�
+��2m��,�/�Z��JK��7��V[� ˄��֘�?Ԙq6������J�+c���kT;��+L�qʬB̝������mA�+��~X�⚤���X�$�{7������ы�=� <�̵�3v��o��3�H�aj/�����1-$�إ�G8��1* 8�;�����i��glf8X����^(!0�+�P@&8 �,K[G���|zT ė�]f��e�P�O�ɓ*A�X�r�sn�B0���14�L�� �T�j#��vG��b�>��Ԙ{ :�(0ќ�9��p ��|�a��(Hu(m���n3I����g���-9B�|��,y��3��H����S�\\��{�;fbܼ�C�y���-N�ة�ի���k�}�H�is��� �Y����:lΧ:��|}�bn�&h0��;�����^lh1>$���@��ak��5���ͮ;u �X�O�`q�2O"���\���tM��Y�J,]�4��P�Sq�Zp�� �7�I,,N�Nu 2�݈/ΦEPu@���bނ}�T�
+〸u��,~�gP@jW.�Mq�`� ա�Nq��
+$0�����= ND�:T���6�����=�~�S^@�>�.��p[�ͭ�[L�!u�<G�"l��0ա�ƀ���:��J`�96ړc�V�C{����:?��=p�R�V�a�����M�y�k0�Z��!��di>Q�Ba�Ci�� �!�
+I�ۥ�9$�,jrH�����j�M3�CY���b�!
+fHAr��¨�R��m�F��6�ٶ0{{��٘������
+A�X9�6��a��n��8K�. ��Y��14a�`���0P��Q�� ȵ��c��3��~N����A�i�@� n��!���gN�f��A�Y�C�1@���F�����y��S�Q�@��P��%!DP��jb���4��Tv��&7�ln;ĝI�3��3q� �,ա�0P������.��;���g�m>�w7�d�o="�%�!8U�_ƺR��-'��ᖳ�S{�ԛ4d$��S�q�ə�P���B1��?Xv�*�@����?H��.}#,�:3#�ۇ��bcAOe��N��Â*o{���[p�f��eFA�Ci=�O�_�AZL�u���q�l6
+kҦra��62���.��M�E&�߲��PLze��#�YA�s����k������+6r����%�F˔��"���͑OXb�#b7I�=����Óa�1!��a�'۵VZr�jI7g-��T��fd���s)J�Z�S�Mf6���l�>:�!Gf�F�4F�1>]�+�(�h"5�]��xl��zW����C�݆(3�8&��)�&�M��Fgˉ�;22�K�����fs��-��'�����-ա����w����ş�d�ukO��FRY A��������9ա��gq�eZ�h�O��/6t�G����J` \,�[�P9�-�tX'��4��p��AE�T���a��w���\)~�sO�>8���0���u���8>���\+�_���W�E�0{s����A�,��2��KH���cC�K�ņ���-���8X،ܒFw!���#��OQq��&D�C���9F�Yכq��d�w�L���肩�|��k�սz` �՜B� ��T���ۋ�|�1�C�H)�<�?;7���(�ˇ�Ђ��#�aGQ��9E����^#��s阂����
+dx�*8038&��AA�����ܬ�x2���*���Y �֜�J��=S���d��eNj���S-�
+�0SŶ 4fHIr��vyP�,���FҌA�zPI���T5K7uJ)�z2AX�4�V��x�7��lͧ|�8}P>.ա�:Cl�Y��� �PER�����$�R�C�R��+
+BᨽS\��YJJk�T��Ɵw-��
+lt� ��Fk��5a�Lوh].%)<`��-��<�ZR|��&���;�ـ�6 R*l:��7}$M��W���dj>�y���<�������Cf7��4O����S�Lp�qL}/���4�j��A1�T�
+�D�\��f�)���|N8KG�SJ�SB�VS�[ȠG];����Xl�41A3ہcLR��M N� R*l���h�2A*! @��ÂC�[r�
+�l�6�",7�C�DI��-?�'�����*��C�}�j`K\�����r!�R��������PNw�Jnp~���|�H�R���?���eg>0 N�@�C9��¬{7�%�qO䀞�<�����Vk�8��a���"��у��!��I :ܤ���eg��w �}�C9���R͖ڴ�P4M]��q�)�y���P@��� � ΄�:��w���;?���G��� 6zS��[����?s�f!N T�Hu�B�/rE����h^��Bx��@f
+�kP@���Ė *b�:T��#�(�1�36/8&� աڑ1�;��Mw|o�v�V=(�h>�����A�C�s�n!ԉ�
+�M��-fV�!���s�4�����?Ȱ5'4�� ա�em�*'�{`C��C�F�=}��[��z��!]G�гk2�lfz��[�ӡE�z��3}��=F�z`��7^`����$�+��P.�?G���2��皑�c�
+�o�����L ���h{+}�|�"2�4�I��;D����0�����'۵VZr�ڒn�.���-���+~Υ(Uk-O06�m�ձ�/g��ѱ92C7��1b���2��(�h"5�]��x�%w�����|���Idilma��sXU�>8���PXh�:�ȱ-Xr��3�����A}�T���b�sS���1]�8�O�Vq� qk�Cف`�C���,u�c�Ќ��2[Ap*��C)r��M�)G��'y�=�WEx�t�{|�����xO w����#���Z��]�Rg:�l:s�z9���N23-���j���M�Y@J��9<Rb߽�is�V|�}ÿ�H�L*�݀l�UjL]l�vS��l���L��|V�+"S��X����mwJ�����X�Cө��˛���q�p�-�j"ʹ<���H�iX�k�T��8U.r�H%k� p����:-;���LlǓ"C��I@��W�$B?�X����cD�$�
+2��Nm2m���;�a-�OƚN˱�Τ�l ��Ume�`/�&��̕
+a���Z�9i4��<�';N4�t4��mp� &���s7��3�����,�CD>����;tq OZ�/]����n�
�N�0�Lmd+��%���#�` «8��d�O,��U��ꌊi�KS�V�����~Z|�#Ӭ뱠5ړ��i2mX��\ ���ʌ<-,�ff��S�q�ɖ����u5��%@��K �x���� F��� IQ��������y����芘��\���0�����ol�ƺ�Y��A�^A�#$0�y������=L�P��L�W�����N���XZ�Å��;
+F@h��2tm�1b6��9��,lj���)a#N_�MzA`�9�B8y)el���O�]r��V����(��8�2��LB:dQ��gN��� �zG�U��,��3P}W~6r:�#N���?@�sB�7���6:��h��8��/�^�G�
�
-�()0��U(@P�D��z١�Y�&�
-N
-���U�)��,-��S�
-�\�'����1�] ��b�K�S*��ȿ����ff�:�!�͑=��Z�01��a�ik~� A Ӎ�\��0��L�9qJ��$�ϲ��:�NJu�X�o���K�k�9�S�O�@(��(��+��t+$P�]�@��Ť:� �"�dv�ݶ��I<&�v�i�m�Wc��w�=9C���@���,���A�Ce��֭,\���Di�x��x��_�1��5��-y`��&"�VL�V�ܬ𗳝�plV�L�(��b���AE,̒����h��Ь��8�RG�U+9>��;á�}�¡ٽ�_j���i�-�q��C���[!6F�\���������Y>lτ,�qP8�������� J�|c�,�O'g�����h�#S���w�?�|qX�U�!�f|q��@�������L�-l�3�u+}&��P��H���ߐ �o�u�d����I�?�l����\�k�`�����3�A
-�}Ӥ�NQ
-��k��c�42���@W�P;r��n��#=���
-m2���zn�Ɋ*a�O?�;-,�肎̈(����d��~Y���#�����%�����?^Ȗ�4��z:��n�������gOO�O�l�
-Yϧ8B"�}��l��k���/NW\�I�+��УV���y�Yo�&�{4��۵��3���9�l���#����⨉���F)
-k���Pa�%25z~��
-����W�0Z����7��c�v?=��b�Y����fc+V�d^ SD�Vfȍ�����o5_���{�k�y���B�")D��1#G��2w��>��a��G���_��?t ��(
-�wz�_p�̽�W��3?����m��7�������O�7��z!
-���^��Al����LG�]r{�v[I�t�i�N��7�D;X[��7����
-Q��7��Z�*��yO�����8K���3���m����n��*p;��?����{�
-cd��|��PK��� ��PK��@��,�=�sammoa.argoPK��@ʣ~*��vsammoa_Diagrammedeclasses.pgmlPK��@ǒV9�&�,sammoa_Diagrammedecasdutilisation.pgmlPK��@P����K�-sammoa.todoPK��@8��7y�/sammoa_profile.profilePK��@��� ��
-�/sammoa.xmiPK�P
\ No newline at end of file
+�((0��U(@P�D����C��Mr�-0�!�� �S0dYZ���3(�����c,�@���$`� 2��:����K����@�h6G�v�*���ܦ�����OX��L7br����2-��u(��4?��Nj�;)�P`k5�1��.1�
+䘚O%? ��_��ᡠ���&ӭ�@v-i���P����� ��Fê7&�L�f�l5�^����i�L��}Os@��@������w\��p}�Ff����Q�d���l���j�-3恥M��Z1�Z�s��o�v2ñY�3q�|�� l���X�9'^9�(�Yq�8�R'�M/8>��;á�C,áك�_Z��y�-�p��c�Y���:��|>i��b�&vgB�8(�x��z[���
+�� J��c���ɘ}+-?,��������7��0��8drÌ���\�V�o4��V�8s]��g���N+�O�
+ ���Z�R&1:
+H�e�3�6�jy�E���,�sf�6��o��)��St�xl�$��tpi
+�g�n�����荖�O&X�0����9YR%,��ǘc磅%�ӑq�R3�����-�ZX\2��0;=\P[�@zx��Q����F㝭������n�� ��~���4�$Φ���|�#$��=�m�|�}jc�E��K? }e��U��7YM����Y�{4����ؙhY�9�l�<�3�/�"��&~f3JQX�'�
+3,��ѳ�<l!������嚬���=㵻鹝�cϊ�Ǖ7�X��2'�� ���2Cn�����Z�U�h�����
+��|��g"nj��܉z3�!V��#��|ў܋�($����Ce�E������;�� ����b�^g���{���\�Q�P
+�M�E
+bc_n��v:R풯�k���'O_<��[AN�����ox+�?�f������rV1~Ϻ� ���|h�Xƛ>?��p��>!����r[ngr��˿}|OW@a����7�PKn�V�/ �PK�X
+A��,�=�sammoa.argoPK�X
+A���Yh*��vsammoa_Diagrammedeclasses.pgmlPK�X
+AǒV9�&*-sammoa_Diagrammedecasdutilisation.pgmlPK�X
+AP����KL.sammoa.todoPK�X
+A8��7y�i/sammoa_profile.profilePK�X
+An�V�/ �
+&0sammoa.xmiPK��P
\ No newline at end of file
Modified: trunk/sammoa-ui-swing/src/main/java/fr/ulr/sammoa/ui/swing/flight/FlightUIHandler.java
===================================================================
--- trunk/sammoa-ui-swing/src/main/java/fr/ulr/sammoa/ui/swing/flight/FlightUIHandler.java 2012-08-10 11:53:45 UTC (rev 389)
+++ trunk/sammoa-ui-swing/src/main/java/fr/ulr/sammoa/ui/swing/flight/FlightUIHandler.java 2012-08-10 11:56:16 UTC (rev 390)
@@ -898,15 +898,16 @@
public void locationChanged(GpsLocationEvent event) {
GeoPoint location = event.getNewValue();
- if (location != null) {
+ if (!GeoPoints.isCoordinatesEmpty(location)) {
+
// Add the GeoPoint to the layer
if (flightLayer != null) {
flightLayer.addGeoPoint(location);
}
// Center the map on the location if mapFollow is activated
- if (getModel().isMapFollow()) {
+ if (getModel() != null && getModel().isMapFollow()) {
MapBean mapBean = getOverlayMapPanel().getMapBean();
LatLonPoint center = new LatLonPoint.Double(
location.getLatitude(), location.getLongitude());
1
0
Author: fdesbois
Date: 2012-08-10 13:53:45 +0200 (Fri, 10 Aug 2012)
New Revision: 389
Url: http://forge.codelutin.com/repositories/revision/sammoa/389
Log:
Add more doc
Modified:
trunk/src/site/resources/ulr-sammoa-echange-data.svg
trunk/src/site/rst/gps.rst
trunk/src/site/rst/import-export.rst
trunk/src/site/rst/index.rst
Modified: trunk/src/site/resources/ulr-sammoa-echange-data.svg
===================================================================
(Binary files differ)
Modified: trunk/src/site/rst/gps.rst
===================================================================
--- trunk/src/site/rst/gps.rst 2012-08-10 11:45:40 UTC (rev 388)
+++ trunk/src/site/rst/gps.rst 2012-08-10 11:53:45 UTC (rev 389)
@@ -139,3 +139,26 @@
Sous linux, ajouter un user au groupe "uucp":
usermod -aG uucp myuser
+
+
+Comment gérer les connexions/déconnexions et les erreurs GPS
+--------------------------------------------------------------
+
+TODO non implémenté
+
+- si aucun satellite > erreur à remonter (LED rouge) : "Pas de satellite"
+
+- si je continue à recevoir toujours la même donnée > vérifier si le port est accessible ::
+
+ Enumeration portList = CommPortIdentifier.getPortIdentifiers();
+
+ while (portList.hasMoreElements()) {
+ CommPortIdentifier portId = (CommPortIdentifier) portList.nextElement();
+ if (portId.getPortType() == CommPortIdentifier.PORT_SERIAL) {
+ logger.trace("Accessible SERIAL port with device : " + portId.getName());
+ }
+ }
+
+- si le port n'est plus accessible > erreur à remonter (LED rouge) : "pas de GPS"
+
+- si un autre ou plusieurs port potentiels sont disponibles > popup avec le choix du port
Modified: trunk/src/site/rst/import-export.rst
===================================================================
--- trunk/src/site/rst/import-export.rst 2012-08-10 11:45:40 UTC (rev 388)
+++ trunk/src/site/rst/import-export.rst 2012-08-10 11:53:45 UTC (rev 389)
@@ -29,6 +29,23 @@
:Author: fdesbois <florian.desbois(a)codelutin.com>
:Date: $Date$
+Echange de données
+------------------
+
+Le schéma ci-dessous reprend les principaux échanges de données possibles entre les différentes stations de travail.
+Chaque bloc bleue représente un type de station :
+
+- Central : Ordinateur avec la base de données centrale contenant toutes les données
+- Saisie : Ordinateur pour la saisie en vol
+- Validation: Ordinateur pour la validation des données
+- Suivi : Ordinateur pour le suivi et la préparation des vols
+
+A noter que ce sont des rôles de station de travail, une seule même machine physique peut avoir tous ces différents rôles.
+
+.. image:: ulr-sammoa-echange-data.png
+
+TODO explications supplémentaires sur les étapes
+
Import référentiels
-------------------
@@ -123,7 +140,7 @@
Espèces (CSV)
~~~~~~~~~~~~~
-L'import des observateurs est possible depuis l'interface d'édition d'une
+L'import des espèces est possible depuis l'interface d'édition d'une
région.
Le fichier doit être encodé en UTF-8. Le caractère de séparation est
@@ -147,8 +164,7 @@
Trois types de SHP peuvent être exportés :
- Points GPS : ensemble des points GPS capturés associés au vol
-- Effort : conditions d'observations, détails des routes et coordonnées GPS du
- tracée de l'avion.
+- Effort : conditions d'observations, détails des routes et coordonnées GPS.
- Observation : observations et coordonnées GPS des points sur lesquels ont
été effectuées ces observations.
Modified: trunk/src/site/rst/index.rst
===================================================================
--- trunk/src/site/rst/index.rst 2012-08-10 11:45:40 UTC (rev 388)
+++ trunk/src/site/rst/index.rst 2012-08-10 11:53:45 UTC (rev 389)
@@ -67,14 +67,44 @@
Premiers pas
------------
+Version 0.5
+~~~~~~~~~~~
+
+1. Une fois l'application démarré, il faut créer une nouvelle campagne via le bouton "New" à côté de la
+ liste déroulante des campagnes sur la page d'accueil.
+
+2. La région "FR-METRO" pour "France Métropolitaine" existe par défaut. Vous pouvez l'éditer via le bouton "Edit"
+ ou en créer une nouvelle avec le bouton "New".
+
+3. C'est lors de l'édition d'une région que l'on peut `importer les espèces
+ <import-export.html#especes-csv>`_ .
+
+4. De retour sur l'édition d'une campagne on peut choisir les fichiers pour :
+
+ - `Importer les strates
+ <import-export.html##fichier-de-strate-dbf>`_
+
+ - `Importer les transects
+ <import-export.html##fichier-de-transect-dbf>`_
+
+ - `Importer les observateurs
+ <import-export.html#observateurs-csv>`_
+
+5. Une fois la campagne prête, vous pouvez créer un nouveau vol depuis la page d'accueil avec le bouton "On Board".
+ L'écran principal s'affiche, vous pouvez désormais préparer le plan de vol avec les transects et les observateurs.
+
+6. Une fois le plan de vol préparé, vous pouvez lancer le vol via le bouton START
+ et commencer ainsi la saisie de l'effort et des observations.
+
Version 0.3
+~~~~~~~~~~~
1. Une fois l'application démarré, elle vous demande de créer une campagne.
2. Une fois la campagne créée, il faut configurer les fichiers de référentiels strates et
transects depuis le menu "File > Configuration". Attention ces fichiers doivent respecter un
certain formalisme défini dans la rubrique `Import
- <import-export.html#Fichiers_SHP_transectsstrates>`_ . Une fois les fichiers modifiés,
+ <import-export.html#fichier-de-transect-dbf>`_ . Une fois les fichiers modifiés,
l'application est redémarrée.
3. SAMMOA nécessite un import des observateurs depuis le menu "Data > Import observers (csv)".
1
0
r388 - trunk/sammoa-application/src/main/java/fr/ulr/sammoa/application/flightController
by tchemit@users.forge.codelutin.com 10 Aug '12
by tchemit@users.forge.codelutin.com 10 Aug '12
10 Aug '12
Author: tchemit
Date: 2012-08-10 13:45:40 +0200 (Fri, 10 Aug 2012)
New Revision: 388
Url: http://forge.codelutin.com/repositories/revision/sammoa/388
Log:
remove milli-secondes on geoPoins date
Modified:
trunk/sammoa-application/src/main/java/fr/ulr/sammoa/application/flightController/FlightControllerDefault.java
Modified: trunk/sammoa-application/src/main/java/fr/ulr/sammoa/application/flightController/FlightControllerDefault.java
===================================================================
--- trunk/sammoa-application/src/main/java/fr/ulr/sammoa/application/flightController/FlightControllerDefault.java 2012-08-10 11:15:27 UTC (rev 387)
+++ trunk/sammoa-application/src/main/java/fr/ulr/sammoa/application/flightController/FlightControllerDefault.java 2012-08-10 11:45:40 UTC (rev 388)
@@ -800,7 +800,7 @@
result = new Date();
// always remove milli-seconds
- DateUtils.setMilliseconds(result, 0);
+ result = DateUtils.setMilliseconds(result, 0);
if (logger.isWarnEnabled()) {
logger.warn("No GPS point at {}", result);
}
@@ -816,7 +816,7 @@
result = geoPoint.getRecordTime();
// always remove milli-seconds
- DateUtils.setMilliseconds(result, 0);
+ geoPoint.setRecordTime(result = DateUtils.setMilliseconds(result, 0));
GeoPointDAO dao = SammoaDAOHelper.getGeoPointDAO(transaction);
1
0
r387 - trunk/sammoa-ui-swing/src/main/resources/fr/ulr/sammoa/persistence
by tchemit@users.forge.codelutin.com 10 Aug '12
by tchemit@users.forge.codelutin.com 10 Aug '12
10 Aug '12
Author: tchemit
Date: 2012-08-10 13:15:27 +0200 (Fri, 10 Aug 2012)
New Revision: 387
Url: http://forge.codelutin.com/repositories/revision/sammoa/387
Log:
fix validation message
Modified:
trunk/sammoa-ui-swing/src/main/resources/fr/ulr/sammoa/persistence/Route-error-validation.xml
Modified: trunk/sammoa-ui-swing/src/main/resources/fr/ulr/sammoa/persistence/Route-error-validation.xml
===================================================================
--- trunk/sammoa-ui-swing/src/main/resources/fr/ulr/sammoa/persistence/Route-error-validation.xml 2012-08-10 10:07:50 UTC (rev 386)
+++ trunk/sammoa-ui-swing/src/main/resources/fr/ulr/sammoa/persistence/Route-error-validation.xml 2012-08-10 11:15:27 UTC (rev 387)
@@ -118,7 +118,7 @@
<field-validator type="stringlength" short-circuit="true">
<param name="minLength">2</param>
<param name="maxLength">2</param>
- <message>sammoa.validator.route.subjectiveConditions.badLength##minLength</message>
+ <message>sammoa.validator.route.subjectiveConditions.badLength##${minLength}</message>
</field-validator>
<field-validator type="regex" short-circuit="true">
1
0
r386 - in trunk: sammoa-application/src/main/java/fr/ulr/sammoa/application/map sammoa-persistence/src/main/java/fr/ulr/sammoa/persistence
by tchemit@users.forge.codelutin.com 10 Aug '12
by tchemit@users.forge.codelutin.com 10 Aug '12
10 Aug '12
Author: tchemit
Date: 2012-08-10 12:07:50 +0200 (Fri, 10 Aug 2012)
New Revision: 386
Url: http://forge.codelutin.com/repositories/revision/sammoa/386
Log:
refs #1203: Export SHP (retains observations and add more logs)
Modified:
trunk/sammoa-application/src/main/java/fr/ulr/sammoa/application/map/ExportMapService.java
trunk/sammoa-persistence/src/main/java/fr/ulr/sammoa/persistence/Observations.java
Modified: trunk/sammoa-application/src/main/java/fr/ulr/sammoa/application/map/ExportMapService.java
===================================================================
--- trunk/sammoa-application/src/main/java/fr/ulr/sammoa/application/map/ExportMapService.java 2012-08-10 10:07:01 UTC (rev 385)
+++ trunk/sammoa-application/src/main/java/fr/ulr/sammoa/application/map/ExportMapService.java 2012-08-10 10:07:50 UTC (rev 386)
@@ -52,6 +52,7 @@
import fr.ulr.sammoa.persistence.Transect;
import fr.ulr.sammoa.persistence.TransectFlight;
import org.nuiton.topia.TopiaContext;
+import org.nuiton.util.PeriodDates;
import org.nuiton.util.TimeLog;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -413,6 +414,13 @@
for (Route route : routes) {
+ if (logger.isDebugEnabled()) {
+ logger.debug("Export Observations from route {} - {} (flight end time {})",
+ new Object[]{route.getBeginTime(),
+ route.getRouteType(),
+ flight.getEndDate()}
+ );
+ }
nextRouteIndex++;
boolean routeIsLeg = Routes.isRouteLeg(route);
@@ -423,6 +431,38 @@
effortGroup = null;
}
+ // compute route period
+ Date beginTime = route.getBeginTime();
+ Date routeEndTime;
+
+ if (nextRouteIndex < nbRoutes) {
+
+ // use next route begin time
+ Route nextRoute = routes.get(nextRouteIndex);
+ routeEndTime = nextRoute.getBeginTime();
+ } else {
+
+ // use flight end date
+ routeEndTime = flight.getEndDate();
+ }
+ Preconditions.checkState(routeEndTime.after(beginTime),
+ String.format("Route debut de route %s - fin de route %s", beginTime, routeEndTime));
+
+ PeriodDates routePeriod =
+ new PeriodDates(beginTime, routeEndTime);
+
+ // Get observations for this route
+ List<Observation> routeObservations =
+ Observations.retainsObservations(observations,
+ routePeriod);
+
+ if (logger.isDebugEnabled()) {
+ logger.debug("Export Observations from route {} [{}-{}] nb observations {}",
+ new Object[]{beginTime,
+ routeEndTime,
+ routeObservations.size()}
+ );
+ }
if (!Routes.isRouteAccepted(route, routeTypes, strates)) {
// not selected route
@@ -440,26 +480,6 @@
fillRouteTypeRecord(flight, route, effortGroup, routeRecord);
- // get routeEndTime
- Date routeEndTime;
-
- if (nextRouteIndex < nbRoutes) {
-
- // use next route begin time
- Route nextRoute = routes.get(nextRouteIndex);
- routeEndTime = nextRoute.getBeginTime();
- } else {
-
- // use flight end date
- routeEndTime = flight.getEndDate();
- }
-
- // Get observations for this route
- List<Observation> routeObservations =
- Observations.getObservations(observations,
- route.getBeginTime(),
- routeEndTime);
-
// get best geo points for each observation
Iterable<GeoPoint> observationGeoPoints =
GeoPoints.getClosestPoints(
Modified: trunk/sammoa-persistence/src/main/java/fr/ulr/sammoa/persistence/Observations.java
===================================================================
--- trunk/sammoa-persistence/src/main/java/fr/ulr/sammoa/persistence/Observations.java 2012-08-10 10:07:01 UTC (rev 385)
+++ trunk/sammoa-persistence/src/main/java/fr/ulr/sammoa/persistence/Observations.java 2012-08-10 10:07:50 UTC (rev 386)
@@ -92,16 +92,16 @@
}
};
- public static List<Observation> getObservations(List<Observation> observations,
- Date beginTime,
- Date endTime) {
+ public static List<Observation> retainsObservations(List<Observation> observations,
+ PeriodDates periodDate) {
- PeriodDates periodDate = new PeriodDates(beginTime, endTime);
-
List<Observation> result = Lists.newArrayList();
- for (Observation observation : observations) {
+ Iterator<Observation> itr = observations.iterator();
+ while (itr.hasNext()) {
+ Observation observation = itr.next();
Date observationTime = observation.getObservationTime();
if (periodDate.between(observationTime)) {
+ itr.remove();
result.add(observation);
}
}
1
0
10 Aug '12
Author: tchemit
Date: 2012-08-10 12:07:01 +0200 (Fri, 10 Aug 2012)
New Revision: 385
Url: http://forge.codelutin.com/repositories/revision/sammoa/385
Log:
svn ignore logback-test.xml on main resources
Modified:
trunk/sammoa-ui-swing/src/main/resources/
Property changes on: trunk/sammoa-ui-swing/src/main/resources
___________________________________________________________________
Added: svn:ignore
+ logback-test.xml
1
0
r384 - trunk/sammoa-application/src/main/java/fr/ulr/sammoa/application/flightController
by tchemit@users.forge.codelutin.com 10 Aug '12
by tchemit@users.forge.codelutin.com 10 Aug '12
10 Aug '12
Author: tchemit
Date: 2012-08-10 12:05:55 +0200 (Fri, 10 Aug 2012)
New Revision: 384
Url: http://forge.codelutin.com/repositories/revision/sammoa/384
Log:
remove milli-secondes on geoPoins date
Modified:
trunk/sammoa-application/src/main/java/fr/ulr/sammoa/application/flightController/FlightControllerDefault.java
Modified: trunk/sammoa-application/src/main/java/fr/ulr/sammoa/application/flightController/FlightControllerDefault.java
===================================================================
--- trunk/sammoa-application/src/main/java/fr/ulr/sammoa/application/flightController/FlightControllerDefault.java 2012-08-10 09:29:39 UTC (rev 383)
+++ trunk/sammoa-application/src/main/java/fr/ulr/sammoa/application/flightController/FlightControllerDefault.java 2012-08-10 10:05:55 UTC (rev 384)
@@ -53,6 +53,7 @@
import fr.ulr.sammoa.persistence.SammoaDAOHelper;
import fr.ulr.sammoa.persistence.SammoaPersistence;
import fr.ulr.sammoa.persistence.TransectFlight;
+import org.apache.commons.lang3.time.DateUtils;
import org.nuiton.topia.TopiaContext;
import org.nuiton.topia.TopiaException;
import org.nuiton.topia.TopiaRuntimeException;
@@ -797,6 +798,9 @@
Date result;
if (geoPoint == null) {
result = new Date();
+
+ // always remove milli-seconds
+ DateUtils.setMilliseconds(result, 0);
if (logger.isWarnEnabled()) {
logger.warn("No GPS point at {}", result);
}
@@ -811,6 +815,9 @@
result = geoPoint.getRecordTime();
+ // always remove milli-seconds
+ DateUtils.setMilliseconds(result, 0);
+
GeoPointDAO dao = SammoaDAOHelper.getGeoPointDAO(transaction);
geoPoint.setFlight(flight);
1
0
r383 - trunk/sammoa-ui-swing/src/main/java/fr/ulr/sammoa/ui/swing/observations
by tchemit@users.forge.codelutin.com 10 Aug '12
by tchemit@users.forge.codelutin.com 10 Aug '12
10 Aug '12
Author: tchemit
Date: 2012-08-10 11:29:39 +0200 (Fri, 10 Aug 2012)
New Revision: 383
Url: http://forge.codelutin.com/repositories/revision/sammoa/383
Log:
fixes #1396: Table des routes non ?\195?\169ditable sur certaines cellules (utilisation d'un seul constructeur sur les m?\195?\169tas d'un mod?\195?\168le de tableau)
Modified:
trunk/sammoa-ui-swing/src/main/java/fr/ulr/sammoa/ui/swing/observations/ObservationTableModel.java
trunk/sammoa-ui-swing/src/main/java/fr/ulr/sammoa/ui/swing/observations/RouteTableModel.java
Modified: trunk/sammoa-ui-swing/src/main/java/fr/ulr/sammoa/ui/swing/observations/ObservationTableModel.java
===================================================================
--- trunk/sammoa-ui-swing/src/main/java/fr/ulr/sammoa/ui/swing/observations/ObservationTableModel.java 2012-08-09 18:35:24 UTC (rev 382)
+++ trunk/sammoa-ui-swing/src/main/java/fr/ulr/sammoa/ui/swing/observations/ObservationTableModel.java 2012-08-10 09:29:39 UTC (rev 383)
@@ -128,15 +128,15 @@
public enum ObservationColumn {
- OBSERVATION_NUMBER(false, Observation.PROPERTY_OBSERVATION_NUMBER),
+ OBSERVATION_NUMBER(false, String.class, Observation.PROPERTY_OBSERVATION_NUMBER),
OBSERVATION_TIME(false, Date.class, Observation.PROPERTY_OBSERVATION_TIME),
- OBSERVER(false,
+ OBSERVER(false,String.class,
Observation.PROPERTY_OBSERVER_POSITION,
ObserverPosition.PROPERTY_OBSERVER,
Observer.PROPERTY_INITIALS
),
POD_SIZE(true, int.class, Observation.PROPERTY_POD_SIZE),
- SPECIES(true, Observation.PROPERTY_SPECIES, Species.PROPERTY_CODE) {
+ SPECIES(true, String.class, Observation.PROPERTY_SPECIES, Species.PROPERTY_CODE) {
@Override
public void setValue(Observation bean, Object value, Region region) {
String newValue = (String) value;
@@ -159,10 +159,10 @@
}
}
},
- AGE(true, Observation.PROPERTY_AGE),
+ AGE(true, String.class, Observation.PROPERTY_AGE),
DEC_ANGLE(true, int.class, Observation.PROPERTY_DEC_ANGLE),
- CUE(true, Observation.PROPERTY_CUE),
- BEHAVIOUR(true, Observation.PROPERTY_BEHAVIOUR) {
+ CUE(true, String.class, Observation.PROPERTY_CUE),
+ BEHAVIOUR(true, String.class, Observation.PROPERTY_BEHAVIOUR) {
@Override
public void setValue(Observation bean, Object value, Region region) {
String newValue = (String) value;
@@ -173,9 +173,9 @@
}
},
SWIM_DIR(true, int.class, Observation.PROPERTY_SWIM_DIR),
- CALVES(true, Observation.PROPERTY_CALVES),
+ CALVES(true, String.class, Observation.PROPERTY_CALVES),
PHOTO(true, boolean.class, Observation.PROPERTY_PHOTO),
- COMMENT(true, Observation.PROPERTY_COMMENT),
+ COMMENT(true, String.class, Observation.PROPERTY_COMMENT),
OBSERVATION_STATUS(true, ObservationStatus.class, Observation.PROPERTY_OBSERVATION_STATUS),
DELETED(true, boolean.class, Observation.PROPERTY_DELETED),
CIRCLE_BACK(true, Observation.class, "circleBack") {
@@ -198,11 +198,6 @@
private final String columnName;
private ObservationColumn(boolean editable,
- String... beanProperties) {
- this(editable, String.class, beanProperties);
- }
-
- private ObservationColumn(boolean editable,
Class<?> type,
String... beanProperties) {
this.editable = editable;
Modified: trunk/sammoa-ui-swing/src/main/java/fr/ulr/sammoa/ui/swing/observations/RouteTableModel.java
===================================================================
--- trunk/sammoa-ui-swing/src/main/java/fr/ulr/sammoa/ui/swing/observations/RouteTableModel.java 2012-08-09 18:35:24 UTC (rev 382)
+++ trunk/sammoa-ui-swing/src/main/java/fr/ulr/sammoa/ui/swing/observations/RouteTableModel.java 2012-08-10 09:29:39 UTC (rev 383)
@@ -127,10 +127,10 @@
protected enum RouteColumn {
- EFFORT_NUMBER(false, Route.PROPERTY_EFFORT_NUMBER),
+ EFFORT_NUMBER(false, String.class, Route.PROPERTY_EFFORT_NUMBER),
BEGIN_TIME(false, Date.class, Route.PROPERTY_BEGIN_TIME),
- ROUTE_TYPE(false, Route.PROPERTY_ROUTE_TYPE),
- TRANSECT(false,
+ ROUTE_TYPE(false, String.class, Route.PROPERTY_ROUTE_TYPE),
+ TRANSECT(false,String.class,
Route.PROPERTY_TRANSECT_FLIGHT,
TransectFlight.PROPERTY_TRANSECT,
Transect.PROPERTY_NAME
@@ -163,10 +163,10 @@
GLARE_SEVERITY(true, int.class, Route.PROPERTY_GLARE_SEVERITY),
GLARE_UNDER(true, boolean.class, Route.PROPERTY_GLARE_UNDER),
CLOUD_COVER(true, int.class, Route.PROPERTY_CLOUD_COVER),
- SUBJECTIVE_CONDITIONS(true, Route.PROPERTY_SUBJECTIVE_CONDITIONS),
- UNEXPECTED_LEFT(true, Route.PROPERTY_UNEXPECTED_LEFT),
- UNEXEPECTED_RIGHT(true, Route.PROPERTY_UNEXPECTED_RIGHT),
- COMMENT(true, Route.PROPERTY_COMMENT),
+ SUBJECTIVE_CONDITIONS(true, String.class, Route.PROPERTY_SUBJECTIVE_CONDITIONS),
+ UNEXPECTED_LEFT(true, String.class, Route.PROPERTY_UNEXPECTED_LEFT),
+ UNEXEPECTED_RIGHT(true, String.class, Route.PROPERTY_UNEXPECTED_RIGHT),
+ COMMENT(true, String.class, Route.PROPERTY_COMMENT),
DELETED(true, boolean.class, Route.PROPERTY_DELETED);
private final boolean editable;
@@ -177,13 +177,7 @@
private final String columnName;
-
private RouteColumn(boolean editable,
- String... beanProperties) {
- this(editable, null, beanProperties);
- }
-
- private RouteColumn(boolean editable,
Class<?> type,
String... beanProperties) {
this.editable = editable;
1
0
r382 - in trunk: sammoa-persistence/src/main/java/fr/ulr/sammoa/persistence sammoa-ui-swing/src/main/java/fr/ulr/sammoa/ui/swing sammoa-ui-swing/src/main/java/fr/ulr/sammoa/ui/swing/action sammoa-ui-swing/src/main/resources/i18n
by fdesbois@users.forge.codelutin.com 09 Aug '12
by fdesbois@users.forge.codelutin.com 09 Aug '12
09 Aug '12
Author: fdesbois
Date: 2012-08-09 20:35:24 +0200 (Thu, 09 Aug 2012)
New Revision: 382
Url: http://forge.codelutin.com/repositories/revision/sammoa/382
Log:
fixes #1394 : add tooltips
Modified:
trunk/sammoa-persistence/src/main/java/fr/ulr/sammoa/persistence/Routes.java
trunk/sammoa-ui-swing/src/main/java/fr/ulr/sammoa/ui/swing/MainUI.jaxx
trunk/sammoa-ui-swing/src/main/java/fr/ulr/sammoa/ui/swing/action/AddAction.java
trunk/sammoa-ui-swing/src/main/java/fr/ulr/sammoa/ui/swing/action/BeginAction.java
trunk/sammoa-ui-swing/src/main/java/fr/ulr/sammoa/ui/swing/action/CenterObservationAction.java
trunk/sammoa-ui-swing/src/main/java/fr/ulr/sammoa/ui/swing/action/CircleBackAction.java
trunk/sammoa-ui-swing/src/main/java/fr/ulr/sammoa/ui/swing/action/EndAction.java
trunk/sammoa-ui-swing/src/main/java/fr/ulr/sammoa/ui/swing/action/LeftObservationAction.java
trunk/sammoa-ui-swing/src/main/java/fr/ulr/sammoa/ui/swing/action/NextAction.java
trunk/sammoa-ui-swing/src/main/java/fr/ulr/sammoa/ui/swing/action/NextTransectAction.java
trunk/sammoa-ui-swing/src/main/java/fr/ulr/sammoa/ui/swing/action/RightObservationAction.java
trunk/sammoa-ui-swing/src/main/java/fr/ulr/sammoa/ui/swing/action/StartAction.java
trunk/sammoa-ui-swing/src/main/java/fr/ulr/sammoa/ui/swing/action/StopAction.java
trunk/sammoa-ui-swing/src/main/resources/i18n/sammoa-ui-swing_en_GB.properties
Modified: trunk/sammoa-persistence/src/main/java/fr/ulr/sammoa/persistence/Routes.java
===================================================================
--- trunk/sammoa-persistence/src/main/java/fr/ulr/sammoa/persistence/Routes.java 2012-08-09 17:53:27 UTC (rev 381)
+++ trunk/sammoa-persistence/src/main/java/fr/ulr/sammoa/persistence/Routes.java 2012-08-09 18:35:24 UTC (rev 382)
@@ -91,6 +91,7 @@
boolean result = Objects.equal(o1.getRouteType(), o2.getRouteType());
result &= Objects.equal(o1.getTransectFlight(), o2.getTransectFlight());
+ result &= Objects.equal(o1.getCircleBackCause(), o2.getCircleBackCause());
result &= Objects.equal(o1.isDeleted(), o2.isDeleted());
Modified: trunk/sammoa-ui-swing/src/main/java/fr/ulr/sammoa/ui/swing/MainUI.jaxx
===================================================================
--- trunk/sammoa-ui-swing/src/main/java/fr/ulr/sammoa/ui/swing/MainUI.jaxx 2012-08-09 17:53:27 UTC (rev 381)
+++ trunk/sammoa-ui-swing/src/main/java/fr/ulr/sammoa/ui/swing/MainUI.jaxx 2012-08-09 18:35:24 UTC (rev 382)
@@ -23,6 +23,8 @@
#L%
-->
<JFrame id='mainFrame' onWindowClosing='getHandler().closeSammoa()'
+ width='800'
+ height='600'
implements='fr.ulr.sammoa.ui.swing.SammoaUI<MainUIHandler>'>
<import>
Modified: trunk/sammoa-ui-swing/src/main/java/fr/ulr/sammoa/ui/swing/action/AddAction.java
===================================================================
--- trunk/sammoa-ui-swing/src/main/java/fr/ulr/sammoa/ui/swing/action/AddAction.java 2012-08-09 17:53:27 UTC (rev 381)
+++ trunk/sammoa-ui-swing/src/main/java/fr/ulr/sammoa/ui/swing/action/AddAction.java 2012-08-09 18:35:24 UTC (rev 382)
@@ -27,8 +27,11 @@
import fr.ulr.sammoa.ui.swing.SammoaUIContext;
import org.nuiton.util.Resource;
+import javax.swing.*;
import java.awt.event.ActionEvent;
+import static org.nuiton.i18n.I18n._;
+
/**
* Created: 03/07/12
*
@@ -38,6 +41,7 @@
public AddAction(SammoaUIContext context) {
super(Resource.getIcon("/icons/action-add.png"), context);
+ putValue(Action.SHORT_DESCRIPTION, _("sammoa.action.add.tip"));
}
@Override
Modified: trunk/sammoa-ui-swing/src/main/java/fr/ulr/sammoa/ui/swing/action/BeginAction.java
===================================================================
--- trunk/sammoa-ui-swing/src/main/java/fr/ulr/sammoa/ui/swing/action/BeginAction.java 2012-08-09 17:53:27 UTC (rev 381)
+++ trunk/sammoa-ui-swing/src/main/java/fr/ulr/sammoa/ui/swing/action/BeginAction.java 2012-08-09 18:35:24 UTC (rev 382)
@@ -28,8 +28,11 @@
import fr.ulr.sammoa.ui.swing.SammoaUIContext;
import org.nuiton.util.Resource;
+import javax.swing.*;
import java.awt.event.ActionEvent;
+import static org.nuiton.i18n.I18n._;
+
/**
* Created: 03/07/12
*
@@ -39,6 +42,7 @@
public BeginAction(SammoaUIContext context) {
super(Resource.getIcon("/icons/playback_play.png"), context);
+ putValue(Action.SHORT_DESCRIPTION, _("sammoa.action.begin.tip"));
}
@Override
Modified: trunk/sammoa-ui-swing/src/main/java/fr/ulr/sammoa/ui/swing/action/CenterObservationAction.java
===================================================================
--- trunk/sammoa-ui-swing/src/main/java/fr/ulr/sammoa/ui/swing/action/CenterObservationAction.java 2012-08-09 17:53:27 UTC (rev 381)
+++ trunk/sammoa-ui-swing/src/main/java/fr/ulr/sammoa/ui/swing/action/CenterObservationAction.java 2012-08-09 18:35:24 UTC (rev 382)
@@ -26,6 +26,8 @@
import fr.ulr.sammoa.persistence.Position;
import fr.ulr.sammoa.ui.swing.SammoaUIContext;
+import javax.swing.*;
+
import static org.nuiton.i18n.I18n._;
/**
@@ -37,5 +39,6 @@
public CenterObservationAction(SammoaUIContext context) {
super(_("sammoa.observation.observations.center"), context, Position.NAVIGATOR);
+ putValue(Action.SHORT_DESCRIPTION, _("sammoa.action.center.tip"));
}
}
Modified: trunk/sammoa-ui-swing/src/main/java/fr/ulr/sammoa/ui/swing/action/CircleBackAction.java
===================================================================
--- trunk/sammoa-ui-swing/src/main/java/fr/ulr/sammoa/ui/swing/action/CircleBackAction.java 2012-08-09 17:53:27 UTC (rev 381)
+++ trunk/sammoa-ui-swing/src/main/java/fr/ulr/sammoa/ui/swing/action/CircleBackAction.java 2012-08-09 18:35:24 UTC (rev 382)
@@ -34,6 +34,8 @@
import java.awt.event.ActionEvent;
import java.util.List;
+import static org.nuiton.i18n.I18n._;
+
/**
* Created: 03/07/12
*
@@ -47,6 +49,7 @@
public CircleBackAction(SammoaUIContext context) {
super(CIRCLE_BACK_ICON, context);
+ putValue(Action.SHORT_DESCRIPTION, _("sammoa.action.circleBack.tip"));
}
@Override
Modified: trunk/sammoa-ui-swing/src/main/java/fr/ulr/sammoa/ui/swing/action/EndAction.java
===================================================================
--- trunk/sammoa-ui-swing/src/main/java/fr/ulr/sammoa/ui/swing/action/EndAction.java 2012-08-09 17:53:27 UTC (rev 381)
+++ trunk/sammoa-ui-swing/src/main/java/fr/ulr/sammoa/ui/swing/action/EndAction.java 2012-08-09 18:35:24 UTC (rev 382)
@@ -27,8 +27,11 @@
import fr.ulr.sammoa.ui.swing.SammoaUIContext;
import org.nuiton.util.Resource;
+import javax.swing.*;
import java.awt.event.ActionEvent;
+import static org.nuiton.i18n.I18n._;
+
/**
* Created: 03/07/12
*
@@ -38,6 +41,7 @@
public EndAction(SammoaUIContext context) {
super(Resource.getIcon("/icons/playback_stop.png"), context);
+ putValue(Action.SHORT_DESCRIPTION, _("sammoa.action.end.tip"));
}
@Override
Modified: trunk/sammoa-ui-swing/src/main/java/fr/ulr/sammoa/ui/swing/action/LeftObservationAction.java
===================================================================
--- trunk/sammoa-ui-swing/src/main/java/fr/ulr/sammoa/ui/swing/action/LeftObservationAction.java 2012-08-09 17:53:27 UTC (rev 381)
+++ trunk/sammoa-ui-swing/src/main/java/fr/ulr/sammoa/ui/swing/action/LeftObservationAction.java 2012-08-09 18:35:24 UTC (rev 382)
@@ -26,6 +26,8 @@
import fr.ulr.sammoa.persistence.Position;
import fr.ulr.sammoa.ui.swing.SammoaUIContext;
+import javax.swing.*;
+
import static org.nuiton.i18n.I18n._;
/**
@@ -37,5 +39,6 @@
public LeftObservationAction(SammoaUIContext context) {
super(_("sammoa.observation.observations.left"), context, Position.FRONT_LEFT);
+ putValue(Action.SHORT_DESCRIPTION, _("sammoa.action.left.tip"));
}
}
Modified: trunk/sammoa-ui-swing/src/main/java/fr/ulr/sammoa/ui/swing/action/NextAction.java
===================================================================
--- trunk/sammoa-ui-swing/src/main/java/fr/ulr/sammoa/ui/swing/action/NextAction.java 2012-08-09 17:53:27 UTC (rev 381)
+++ trunk/sammoa-ui-swing/src/main/java/fr/ulr/sammoa/ui/swing/action/NextAction.java 2012-08-09 18:35:24 UTC (rev 382)
@@ -27,8 +27,11 @@
import fr.ulr.sammoa.ui.swing.SammoaUIContext;
import org.nuiton.util.Resource;
+import javax.swing.*;
import java.awt.event.ActionEvent;
+import static org.nuiton.i18n.I18n._;
+
/**
* Created: 03/07/12
*
@@ -38,6 +41,7 @@
public NextAction(SammoaUIContext context) {
super(Resource.getIcon("/icons/playback_next.png"), context);
+ putValue(Action.SHORT_DESCRIPTION, _("sammoa.action.next.tip"));
}
@Override
Modified: trunk/sammoa-ui-swing/src/main/java/fr/ulr/sammoa/ui/swing/action/NextTransectAction.java
===================================================================
--- trunk/sammoa-ui-swing/src/main/java/fr/ulr/sammoa/ui/swing/action/NextTransectAction.java 2012-08-09 17:53:27 UTC (rev 381)
+++ trunk/sammoa-ui-swing/src/main/java/fr/ulr/sammoa/ui/swing/action/NextTransectAction.java 2012-08-09 18:35:24 UTC (rev 382)
@@ -27,9 +27,11 @@
import fr.ulr.sammoa.ui.swing.SammoaUIContext;
import org.nuiton.util.Resource;
-import javax.swing.JComponent;
+import javax.swing.*;
import java.awt.event.ActionEvent;
+import static org.nuiton.i18n.I18n._;
+
/**
* Created: 03/07/12
*
@@ -41,6 +43,7 @@
public NextTransectAction(SammoaUIContext context) {
super(Resource.getIcon("/icons/action-next-transect.png"), context);
+ putValue(Action.SHORT_DESCRIPTION, _("sammoa.action.nextTransect.tip"));
}
@Override
Modified: trunk/sammoa-ui-swing/src/main/java/fr/ulr/sammoa/ui/swing/action/RightObservationAction.java
===================================================================
--- trunk/sammoa-ui-swing/src/main/java/fr/ulr/sammoa/ui/swing/action/RightObservationAction.java 2012-08-09 17:53:27 UTC (rev 381)
+++ trunk/sammoa-ui-swing/src/main/java/fr/ulr/sammoa/ui/swing/action/RightObservationAction.java 2012-08-09 18:35:24 UTC (rev 382)
@@ -26,6 +26,8 @@
import fr.ulr.sammoa.persistence.Position;
import fr.ulr.sammoa.ui.swing.SammoaUIContext;
+import javax.swing.*;
+
import static org.nuiton.i18n.I18n._;
/**
@@ -37,5 +39,6 @@
public RightObservationAction(SammoaUIContext context) {
super(_("sammoa.observation.observations.right"), context, Position.FRONT_RIGHT);
+ putValue(Action.SHORT_DESCRIPTION, _("sammoa.action.right.tip"));
}
}
Modified: trunk/sammoa-ui-swing/src/main/java/fr/ulr/sammoa/ui/swing/action/StartAction.java
===================================================================
--- trunk/sammoa-ui-swing/src/main/java/fr/ulr/sammoa/ui/swing/action/StartAction.java 2012-08-09 17:53:27 UTC (rev 381)
+++ trunk/sammoa-ui-swing/src/main/java/fr/ulr/sammoa/ui/swing/action/StartAction.java 2012-08-09 18:35:24 UTC (rev 382)
@@ -27,8 +27,11 @@
import fr.ulr.sammoa.ui.swing.SammoaUIContext;
import org.nuiton.util.Resource;
+import javax.swing.*;
import java.awt.event.ActionEvent;
+import static org.nuiton.i18n.I18n._;
+
/**
* Created: 05/07/12
*
@@ -38,6 +41,7 @@
public StartAction(SammoaUIContext context) {
super(Resource.getIcon("/icons/playback_play.png"), context);
+ putValue(Action.SHORT_DESCRIPTION, _("sammoa.action.start.tip"));
}
@Override
Modified: trunk/sammoa-ui-swing/src/main/java/fr/ulr/sammoa/ui/swing/action/StopAction.java
===================================================================
--- trunk/sammoa-ui-swing/src/main/java/fr/ulr/sammoa/ui/swing/action/StopAction.java 2012-08-09 17:53:27 UTC (rev 381)
+++ trunk/sammoa-ui-swing/src/main/java/fr/ulr/sammoa/ui/swing/action/StopAction.java 2012-08-09 18:35:24 UTC (rev 382)
@@ -27,8 +27,11 @@
import fr.ulr.sammoa.ui.swing.SammoaUIContext;
import org.nuiton.util.Resource;
+import javax.swing.*;
import java.awt.event.ActionEvent;
+import static org.nuiton.i18n.I18n._;
+
/**
* Created: 05/07/12
*
@@ -38,6 +41,7 @@
public StopAction(SammoaUIContext context) {
super(Resource.getIcon("/icons/playback_stop.png"), context);
+ putValue(Action.SHORT_DESCRIPTION, _("sammoa.action.stop.tip"));
}
@Override
Modified: trunk/sammoa-ui-swing/src/main/resources/i18n/sammoa-ui-swing_en_GB.properties
===================================================================
--- trunk/sammoa-ui-swing/src/main/resources/i18n/sammoa-ui-swing_en_GB.properties 2012-08-09 17:53:27 UTC (rev 381)
+++ trunk/sammoa-ui-swing/src/main/resources/i18n/sammoa-ui-swing_en_GB.properties 2012-08-09 18:35:24 UTC (rev 382)
@@ -4,16 +4,20 @@
sammoa.about.message=About Sammoa
sammoa.action.about=About
sammoa.action.about.tip=About
+sammoa.action.add.tip=ADD \: create a new LEG route for the current Transect (the observation conditions have changed)
+sammoa.action.begin.tip=BEGIN \: begin effort to create a new LEG route for the next selected Transect
sammoa.action.break.tip=Break
sammoa.action.cancel=Cancel
sammoa.action.cancelExport=Cancel
+sammoa.action.center.tip=CENTER \: create a new Observation for the navigator's observer
sammoa.action.choose.export.directory=Accept
-sammoa.action.circleback.tip=Circle Back
+sammoa.action.circleBack.tip=CIRCLE-BACK \: create a CIRCLE_BACK route for this observation as cause
sammoa.action.close=Close
sammoa.action.configuration=Configuration
sammoa.action.configuration.tip=Configuration
sammoa.action.create=Create
sammoa.action.edit=Edit
+sammoa.action.end.tip=END \: end effort and create a new TRANSIT route
sammoa.action.export=Export
sammoa.action.exportEffortsMap=Export Efforts
sammoa.action.exportGeoPointsMap=Export GPS Points
@@ -22,25 +26,26 @@
sammoa.action.home=Home
sammoa.action.home.tip=Home
sammoa.action.import=Import
+sammoa.action.left.tip=LEFT \: create a new Observation for the observer on the left side
sammoa.action.locale.fr=fr
sammoa.action.locale.fr.tip=French
sammoa.action.locale.uk=en
sammoa.action.locale.uk.tip=English
sammoa.action.new=New
-sammoa.action.next.tip=Next
+sammoa.action.next.tip=NEXT \: end previous effort and create a new LEG route for the next selected Transect
+sammoa.action.nextTransect.tip=NEXT TRANSECT \: choose this transect to be the next one
sammoa.action.onBoard=On Board
-sammoa.action.play.tip=Play
sammoa.action.quitExportMaps=Quit
sammoa.action.reload.actions=Reload actions
sammoa.action.reload.gps=Reload GPS
sammoa.action.reload.ui=Reload sammoa ui
+sammoa.action.right.tip=RIGHT \: create a new Observation for the observer on the right side
sammoa.action.save=Save
sammoa.action.site=Site
sammoa.action.site.tip=Display project site
+sammoa.action.start.tip=START \: start the flight and create a new TRANSIT route
sammoa.action.startExport=Start
-sammoa.action.startFlight.tip=Start the flight
-sammoa.action.stop.tip=Stop
-sammoa.action.stopFlight.tip=Stop the flight
+sammoa.action.stop.tip=STOP \: stop the flight. No other actions on routes and observations could be done after stop.
sammoa.action.validation=Validation
sammoa.config.category.applications=Application
sammoa.config.category.applications.description=Application
1
0
r381 - in trunk: sammoa-application/src/main/java/fr/ulr/sammoa/application sammoa-application/src/main/java/fr/ulr/sammoa/application/map sammoa-application/src/test/java/fr/ulr/sammoa/application/map sammoa-persistence/src/main/java/fr/ulr/sammoa/persistence src/site/rst
by tchemit@users.forge.codelutin.com 09 Aug '12
by tchemit@users.forge.codelutin.com 09 Aug '12
09 Aug '12
Author: tchemit
Date: 2012-08-09 19:53:27 +0200 (Thu, 09 Aug 2012)
New Revision: 381
Url: http://forge.codelutin.com/repositories/revision/sammoa/381
Log:
refs #1203: Export SHP
Modified:
trunk/sammoa-application/src/main/java/fr/ulr/sammoa/application/FlightService.java
trunk/sammoa-application/src/main/java/fr/ulr/sammoa/application/map/ExportMapService.java
trunk/sammoa-application/src/main/java/fr/ulr/sammoa/application/map/LegStatus.java
trunk/sammoa-application/src/test/java/fr/ulr/sammoa/application/map/ExportMapServiceTest.java
trunk/sammoa-persistence/src/main/java/fr/ulr/sammoa/persistence/Observations.java
trunk/sammoa-persistence/src/main/java/fr/ulr/sammoa/persistence/Routes.java
trunk/src/site/rst/import-export.rst
Modified: trunk/sammoa-application/src/main/java/fr/ulr/sammoa/application/FlightService.java
===================================================================
--- trunk/sammoa-application/src/main/java/fr/ulr/sammoa/application/FlightService.java 2012-08-09 17:26:32 UTC (rev 380)
+++ trunk/sammoa-application/src/main/java/fr/ulr/sammoa/application/FlightService.java 2012-08-09 17:53:27 UTC (rev 381)
@@ -25,6 +25,7 @@
package fr.ulr.sammoa.application;
import com.google.common.base.Preconditions;
+import com.google.common.base.Predicate;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
@@ -57,6 +58,7 @@
import org.nuiton.topia.TopiaContext;
import org.nuiton.topia.TopiaException;
import org.nuiton.topia.TopiaRuntimeException;
+import org.nuiton.util.PeriodDates;
import org.nuiton.util.TimeLog;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -96,6 +98,8 @@
public List<Flight> getFlights(Campaign campaign) {
+ Preconditions.checkNotNull(campaign);
+
long start = TimeLog.getTime();
List<Flight> result;
@@ -119,9 +123,65 @@
return result;
}
-
+
+ public Iterable<Flight> getFlights(Campaign campaign,
+ Date beginDate,
+ Date endDate) {
+
+ TopiaContext transaction = persistence.beginTransaction();
+ try {
+
+ Iterable<Flight> result = getFlights(transaction, campaign, beginDate, endDate);
+ return result;
+
+ } finally {
+ persistence.endTransaction(transaction);
+ }
+
+ }
+
+ public Iterable<Flight> getFlights(TopiaContext transaction,
+ Campaign campaign,
+ Date beginDate,
+ Date endDate) {
+
+ Preconditions.checkNotNull(campaign);
+ Preconditions.checkNotNull(beginDate);
+ Preconditions.checkNotNull(endDate);
+
+ long start = TimeLog.getTime();
+
+ List<Flight> campaignFlights;
+ try {
+
+ FlightDAO dao = SammoaDAOHelper.getFlightDAO(transaction);
+
+ campaignFlights = dao.findAllByCampaign(campaign);
+ Collections.sort(campaignFlights, Flights.onDate());
+
+ } catch (TopiaException e) {
+ throw new TopiaRuntimeException(e);
+
+ }
+
+ // Filter on period
+ final PeriodDates period = new PeriodDates(beginDate, endDate);
+ Iterable<Flight> result = Iterables.filter(campaignFlights, new Predicate<Flight>() {
+
+ @Override
+ public boolean apply(Flight input) {
+ return period.between(input.getBeginDate());
+ }
+ });
+
+ timeLog.log(start, "getFlights(" + campaign.getCode() + ")");
+
+ return result;
+ }
+
public Flight getFlight(String flightId) {
+ Preconditions.checkNotNull(flightId);
long start = TimeLog.getTime();
Flight result;
@@ -129,15 +189,15 @@
TopiaContext transaction = persistence.beginTransaction();
try {
FlightDAO dao = SammoaDAOHelper.getFlightDAO(transaction);
-
+
result = dao.findByTopiaId(flightId);
- Preconditions.checkArgument(result != null,
+ Preconditions.checkArgument(result != null,
String.format("%s doesn't exist", flightId));
if (logger.isInfoEnabled()) {
- logger.info(String.format("Loading flight %d [%s]",
- result.getFlightNumber(),
- result.getTopiaId())
+ logger.info("Loading flight {} [{}]",
+ result.getFlightNumber(),
+ result.getTopiaId()
);
}
@@ -173,7 +233,7 @@
TopiaContext transaction = persistence.beginTransaction();
try {
FlightDAO dao = SammoaDAOHelper.getFlightDAO(transaction);
-
+
String systemId = config.getSystemId();
int startNumber = config.getFlightNumber();
@@ -181,11 +241,11 @@
result = dao.createByNaturalId(systemId, flightNumber, campaign);
result.setPlatformType(PlatformType.SIMPLE);
-
+
if (logger.isInfoEnabled()) {
- logger.info(String.format("Create new flight %d for campaign %s",
- flightNumber,
- campaign.getCode())
+ logger.info("Create new flight {} for campaign {}",
+ flightNumber,
+ campaign.getCode()
);
}
@@ -207,8 +267,8 @@
*
* @param flight Flight where observers are retrieved
* @return the List of allowed Observer
+ * @see ObserverPosition
* @since 0.3
- * @see ObserverPosition
*/
public List<Observer> getFlightObserverForPositions(Flight flight) {
@@ -228,10 +288,22 @@
public List<GeoPoint> getFlightGeoPoints(Flight flight) {
- List<GeoPoint> result;
TopiaContext transaction = persistence.beginTransaction();
try {
+ List<GeoPoint> result = getFlightGeoPoints(transaction, flight);
+ return result;
+ } finally {
+ persistence.endTransaction(transaction);
+ }
+
+ }
+
+ public List<GeoPoint> getFlightGeoPoints(TopiaContext transaction, Flight flight) {
+
+ List<GeoPoint> result;
+
+ try {
GeoPointDAO dao = SammoaDAOHelper.getGeoPointDAO(transaction);
result = dao.findAllByFlightOrderedByRecordTime(flight);
@@ -239,8 +311,6 @@
} catch (TopiaException e) {
throw new TopiaRuntimeException(e);
- } finally {
- persistence.endTransaction(transaction);
}
return result;
}
@@ -288,7 +358,7 @@
* necessary. Note that all {@link TransectFlight} have link with
* {@link AutoSaveListener} to manage modifications.
*
- * @param flight The flight
+ * @param flight The flight
* @param fromIndex Index where transects will be added
* @param transects The list of transect to add
* @return the resulting TransectFlight added
@@ -296,7 +366,7 @@
public List<TransectFlight> addTransects(Flight flight, int fromIndex, Iterable<Transect> transects) {
List<TransectFlight> result = Lists.newArrayList();
-
+
TopiaContext transaction = persistence.beginTransaction();
try {
@@ -312,7 +382,7 @@
// referential.persistTransectIfNecessary(transaction, transect);
TransectFlight transectFlight = createTransectFlight(
- transaction, transect, flight);
+ transaction, transect, flight);
logger.debug("Add transect {} to the flight {}",
transect.getName(), flight.getFlightNumber());
@@ -333,7 +403,7 @@
Collections.reverse(result);
return result;
}
-
+
public Map<Transect, Long> getTransectRealNbTimes(Collection<Transect> transects) {
Map<Transect, Long> result;
@@ -366,20 +436,35 @@
*/
public List<Route> getRoutes(Flight flight) {
- List<Route> result;
TopiaContext transaction = persistence.beginTransaction();
try {
+ List<Route> result = getRoutes(transaction, flight);
+ return result;
+ } finally {
+ persistence.endTransaction(transaction);
+ }
+ }
+
+ /**
+ * Retrieve the list of {@link Route} associated to the given {@code flight}.
+ *
+ * @param flight Flight
+ * @return the List of Route matching the {@code flight}
+ */
+ public List<Route> getRoutes(TopiaContext transaction, Flight flight) {
+
+ List<Route> result;
+ try {
+
RouteDAO dao = SammoaDAOHelper.getRouteDAO(transaction);
result = dao.findAllByFlightOrderedByBeginTime(flight);
} catch (TopiaException e) {
throw new TopiaRuntimeException(e);
+ }
- } finally {
- persistence.endTransaction(transaction);
- }
return result;
}
@@ -407,7 +492,7 @@
}
return result;
}
-
+
public TransectFlight getLastTransectDone(Flight flight) {
TransectFlight result;
@@ -416,7 +501,7 @@
RouteDAO dao = SammoaDAOHelper.getRouteDAO(transaction);
- Route route = dao.findLastByFlightAndType(flight, RouteType.LEG);
+ Route route = dao.findLastByFlightAndType(flight, RouteType.LEG);
if (route != null) {
result = route.getTransectFlight();
@@ -436,10 +521,20 @@
public List<Observation> getObservations(Flight flight) {
- List<Observation> result;
TopiaContext transaction = persistence.beginTransaction();
try {
+ List<Observation> result = getObservations(transaction, flight);
+ return result;
+ } finally {
+ persistence.endTransaction(transaction);
+ }
+ }
+ public List<Observation> getObservations(TopiaContext transaction, Flight flight) {
+
+ List<Observation> result;
+ try {
+
ObservationDAO dao = SammoaDAOHelper.getObservationDAO(transaction);
result = dao.findAllByFlightOrderedByObservationTime(flight);
@@ -447,12 +542,10 @@
} catch (TopiaException e) {
throw new TopiaRuntimeException(e);
- } finally {
- persistence.endTransaction(transaction);
}
return result;
}
-
+
public void setRouteObserverByPosition(Route route,
Observer observer,
Position position) {
@@ -463,7 +556,7 @@
ObserverPositionDAO observerPositionDAO =
SammoaDAOHelper.getObserverPositionDAO(transaction);
-
+
ObserverPosition observerPosition =
Iterables.find(observerPositions, ObserverPositions.withPosition(position));
@@ -489,12 +582,12 @@
}
}
}
-
+
observerPosition.setObserver(observer);
observerPositionDAO.update(observerPosition);
debugObserverPositions("Update", observerPositions);
-
+
transaction.commitTransaction();
} catch (TopiaException e) {
@@ -567,18 +660,18 @@
Route previousRoute,
TransectFlight transectFlight)
throws TopiaException {
-
+
Preconditions.checkArgument(transectFlight != null, "You can't create a leg without any transect");
Route result = createRoute(transaction, flight, beginTime, RouteType.LEG, previousRoute, transectFlight);
RouteDAO dao = SammoaDAOHelper.getRouteDAO(transaction);
-
+
result.setTransectFlight(transectFlight);
int effortNumber = dao.getLastEffortNumber(flight);
result.setEffortNumber(effortNumber);
-
+
return result;
}
@@ -588,7 +681,7 @@
Route previousRoute,
Observation circleBackCause)
throws TopiaException {
-
+
Preconditions.checkArgument(circleBackCause != null, "You can't create a route without any observation cause");
Route result = createRoute(transaction, flight, beginTime, RouteType.CIRCLE_BACK, previousRoute, null);
@@ -626,21 +719,21 @@
}
// Prepare observer positions
- Collection<ObserverPosition> observerPositions =
+ Collection<ObserverPosition> observerPositions =
createRouteObserverPositions(transaction, previousRoute, transectFlight, flight);
result.setObserverPosition(observerPositions);
return result;
}
-
+
protected Collection<ObserverPosition> createRouteObserverPositions(TopiaContext transaction,
Route previousRoute,
TransectFlight transectFlight,
- Flight flight)
+ Flight flight)
throws TopiaException {
-
+
Collection<ObserverPosition> result;
-
+
if (previousRoute != null) {
// Prepare position depends on transect change
@@ -662,20 +755,20 @@
}
result = copyObserverPositions(transaction, previousRoute.getObserverPosition());
- }
- } else {
+ }
+ } else {
if (logger.isDebugEnabled()) {
logger.debug("Create default observerPositions from flight");
}
result = createObserverPositions(transaction, flight);
- }
- return result;
+ }
+ return result;
}
- protected Collection<ObserverPosition> createObserverPositions(TopiaContext transaction,
- Flight flight)
+ protected Collection<ObserverPosition> createObserverPositions(TopiaContext transaction,
+ Flight flight)
throws TopiaException {
Collection<ObserverPosition> result = Lists.newArrayList();
@@ -712,10 +805,10 @@
}
debugObserverPositions("Create", result);
-
+
return result;
}
-
+
protected Collection<ObserverPosition> copyObserverPositions(TopiaContext transaction,
Collection<ObserverPosition> observerPositions)
throws TopiaException {
@@ -723,10 +816,10 @@
Collection<ObserverPosition> result = Lists.newArrayList();
debugObserverPositions("Copy", observerPositions);
-
+
ObserverPositionDAO observerPositionDAO =
SammoaDAOHelper.getObserverPositionDAO(transaction);
-
+
for (ObserverPosition source : observerPositions) {
ObserverPosition target = observerPositionDAO.create();
@@ -736,10 +829,10 @@
}
debugObserverPositions("Result of copy", result);
-
- return result;
+
+ return result;
}
-
+
protected void debugObserverPositions(String title, Iterable<ObserverPosition> observerPositions) {
if (logger.isTraceEnabled()) {
Modified: trunk/sammoa-application/src/main/java/fr/ulr/sammoa/application/map/ExportMapService.java
===================================================================
--- trunk/sammoa-application/src/main/java/fr/ulr/sammoa/application/map/ExportMapService.java 2012-08-09 17:26:32 UTC (rev 380)
+++ trunk/sammoa-application/src/main/java/fr/ulr/sammoa/application/map/ExportMapService.java 2012-08-09 17:53:27 UTC (rev 381)
@@ -30,17 +30,28 @@
import com.bbn.openmap.omGraphics.OMGraphic;
import com.bbn.openmap.omGraphics.OMPoint;
import com.google.common.base.Preconditions;
-import com.google.common.base.Predicate;
-import com.google.common.collect.Iterables;
import com.google.common.collect.Maps;
+import fr.ulr.sammoa.application.FlightService;
import fr.ulr.sammoa.application.SammoaConfig;
import fr.ulr.sammoa.application.SammoaContext;
import fr.ulr.sammoa.persistence.Campaign;
import fr.ulr.sammoa.persistence.Flight;
import fr.ulr.sammoa.persistence.GeoPoint;
+import fr.ulr.sammoa.persistence.GeoPoints;
+import fr.ulr.sammoa.persistence.Observation;
+import fr.ulr.sammoa.persistence.Observations;
+import fr.ulr.sammoa.persistence.ObserverPosition;
+import fr.ulr.sammoa.persistence.Position;
import fr.ulr.sammoa.persistence.Region;
+import fr.ulr.sammoa.persistence.Route;
+import fr.ulr.sammoa.persistence.RouteType;
+import fr.ulr.sammoa.persistence.Routes;
import fr.ulr.sammoa.persistence.SammoaPersistence;
-import org.nuiton.util.PeriodDates;
+import fr.ulr.sammoa.persistence.Species;
+import fr.ulr.sammoa.persistence.Strate;
+import fr.ulr.sammoa.persistence.Transect;
+import fr.ulr.sammoa.persistence.TransectFlight;
+import org.nuiton.topia.TopiaContext;
import org.nuiton.util.TimeLog;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -48,6 +59,8 @@
import java.io.File;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.Iterator;
import java.util.List;
import java.util.Map;
@@ -89,15 +102,14 @@
dataModel.getExportDirectory(),
dataModel.getExportFilename());
}
+
long startTime = TimeLog.getTime();
- Campaign campaign = dataModel.getCampaign();
- Region region = campaign.getRegion();
// * uniquement pour un parcours de type LEG, sinon la cellule sera vide
// ** uniquement pour un parcours de type CIRCLE_BACK, sinon la cellule sera vide
DbfTableModelBuilder builder = new DbfTableModelBuilder()
- .stringColumn("REGION") // (campaign.region.code)
+ .stringColumn("REGION") // (region.code)
.stringColumn("CAMPAIGN") // (campaign.code)
.integerColumn("SECTOR") // * (route.transectFlight.transect.strate.sector.sectorNumber)
.stringColumn("STRATE_TYPE") // * (route.transectFlight.transect.strate.strateType.code)
@@ -107,9 +119,9 @@
.integerColumn("FLIGHT") // (route.flight.flightNumber)
.stringColumn("COMPUTER") // (route.flight.systemId)
.stringColumn("ROUTE_TYPE") // (route.routeType.name)
- .stringColumn("EFFORT_GROUP") // * ()
- .stringColumn("EFFORT") // * ()
- .stringColumn("STATUS") // * (LegStatus.name)
+ .stringColumn("EFFORT_GROUP") // * (voir doc)
+ .stringColumn("EFFORT") // * (voir doc)
+ .stringColumn("STATUS") // * (voir doc)
.dateColumn("DATE") // (route.beginTime)
.stringColumn("HHMMSS") // (format(route.beginTime, "HHmmss"))
.integerColumn("SEA_STATE") // (route.seaState)
@@ -133,73 +145,160 @@
.doubleColumn("SPEED", 19, 11) // (geoPoint.speed)
.doubleColumn("ALTITUDE", 19, 11) // (geoPoint.altitude)
.stringColumn("GPS_TIME") // (format(geoPoint.recordTime, "HHmmss"))
- .stringColumn("AIRCRAFT") // (route.flight.planeImmatriculation)
+ .stringColumn("AIRCRAFT") // (route.flight.immatriculation)
.stringColumn("COMMENT") // (route.comment)
.build();
EsriGraphicList graphicList = new EsriPointList();
- List<Flight> campaignFlights = context.getFlightService().getFlights(dataModel.getCampaign());
- // Filter on period
- final PeriodDates period = new PeriodDates(dataModel.getBeginDate(), dataModel.getEndDate());
- Iterable<Flight> flights = Iterables.filter(campaignFlights, new Predicate<Flight>() {
+ FlightService flightService = context.getFlightService();
- @Override
- public boolean apply(Flight input) {
- return period.between(input.getBeginDate());
- }
- });
+ Campaign campaign = dataModel.getCampaign();
+ Region region = campaign.getRegion();
- // Export for each flight
- for (Flight flight : flights) {
+ List<RouteType> routeTypes = dataModel.getRouteTypes();
+ List<Strate> strates = dataModel.getStrates();
- if (logger.isInfoEnabled()) {
- logger.info("Export GeoPoints from flight {} - {} - {} - {}",
- new Object[]{flight.getFlightNumber(),
- flight.getSystemId(),
- campaign.getCode(),
- region.getCode()}
- );
- }
+ TopiaContext tx = context.getPersistence().beginTransaction();
- List<GeoPoint> geoPoints = context.getFlightService().getFlightGeoPoints(flight);
+ try {
+ // get flights for campaign (and between begin - end date)
+ Iterable<Flight> flights = flightService.getFlights(
+ tx,
+ campaign,
+ dataModel.getBeginDate(),
+ dataModel.getEndDate());
- // One record by GeoPoint
- for (GeoPoint geoPoint : geoPoints) {
+ // Export for each flight
+ for (Flight flight : flights) {
- Map<String, Object> record = Maps.newHashMap();
+ if (logger.isInfoEnabled()) {
+ logger.info("Export Efforts from flight {} - {} - {} - {}",
+ new Object[]{flight.getFlightNumber(),
+ flight.getSystemId(),
+ campaign.getCode(),
+ region.getCode()}
+ );
+ }
- record.put("REGION", region.getCode());
- record.put("CAMPAIGN", campaign.getCode());
- record.put("FLIGHT", flight.getFlightNumber());
- record.put("COMPUTER", flight.getSystemId());
- record.put("DATE", geoPoint.getRecordTime());
- record.put("HHMMSS", timeFormat.format(geoPoint.getRecordTime()));
- record.put("LAT", geoPoint.getLatitude());
- record.put("LON", geoPoint.getLongitude());
- record.put("SPEED", geoPoint.getSpeed());
- record.put("ALTITUDE", geoPoint.getAltitude());
+ // common properties for the flight
+ Map<String, Object> commonRecord = Maps.newHashMap();
+ fillFlightRecord(campaign, region, flight, commonRecord);
- builder.addValues(record);
+ // get all routes of this flight
+ List<Route> routes = flightService.getRoutes(tx, flight);
- if (logger.isTraceEnabled()) {
- logger.trace("Record={}", record);
+ // get all geo points for this flight
+ List<GeoPoint> geoPoints = flightService.getFlightGeoPoints(tx, flight);
+
+ // get best geo points for each route
+ Iterable<GeoPoint> routeGeoPoints =
+ GeoPoints.getClosestPoints(geoPoints, Routes.toDates(routes));
+
+ // to iterate on geoPoints
+ Iterator<GeoPoint> geoPointIterator = routeGeoPoints.iterator();
+
+ // to keep current effort group identifier
+ String effortGroup = null;
+
+ for (Route route : routes) {
+
+ if (logger.isTraceEnabled()) {
+ logger.trace("Export Efforts from route {} - {}",
+ new Object[]{route.getBeginTime(),
+ route.getRouteType()}
+ );
+ }
+
+ // get geoPoint associated with this route
+ GeoPoint geoPoint = geoPointIterator.next();
+
+ // is current route a leg ?
+ boolean routeIsLeg = Routes.isRouteLeg(route);
+
+ if (!routeIsLeg) {
+
+ if (effortGroup != null) {
+
+ // previous route was a leg
+ // need to create a end row (to close the group)
+
+ Map<String, Object> record = Maps.newHashMap();
+ record.putAll(commonRecord);
+
+ // add route data
+ fillRouteRecord(flight,
+ route,
+ effortGroup,
+ LegStatus.END,
+ record);
+
+ // add geoPoint data and flush
+ fillGeoPointRecordAndFlush(geoPoint,
+ record,
+ builder,
+ graphicList);
+ }
+
+ // reset effort group
+ // will be recomputed by first next leg route
+ effortGroup = null;
+ }
+
+ boolean routeIsValid = Routes.isRouteAccepted(route,
+ routeTypes,
+ strates);
+
+ if (routeIsValid) {
+
+ // selected route = one row on dbf
+
+ Map<String, Object> record = Maps.newHashMap();
+ record.putAll(commonRecord);
+
+ LegStatus legStatus = null;
+
+ if (routeIsLeg) {
+
+ if (effortGroup == null) {
+
+ // this is the first route of the leg group
+ legStatus = LegStatus.BEGIN;
+
+ // compute the unique effortGroup for this group
+ effortGroup = computeEffortGroup(flight, route);
+ } else {
+
+ // group already began, just add a route to it
+ legStatus = LegStatus.ADD;
+ }
+
+ }
+
+ // add route data
+ fillRouteRecord(flight, route, effortGroup, legStatus, record);
+
+
+ // add geoPoint data and flush
+ fillGeoPointRecordAndFlush(geoPoint,
+ record,
+ builder,
+ graphicList);
+ }
}
-
- OMGraphic graphic = new OMPoint(geoPoint.getLatitude(), geoPoint.getLongitude());
- graphicList.add(graphic);
}
- }
- startTime = timeLog.log(startTime, "exportGeoPointsMap", "after building EsriGraphicList and DbfTableModel");
+ startTime = timeLog.log(
+ startTime,
+ "exportEffortsMap",
+ "after building EsriGraphicList and DbfTableModel");
- // Execute export with EsriShapeExport
- DbfTableModel tableModel = builder.getModel();
- String pathFile = new File(dataModel.getExportDirectory(), dataModel.getExportFilename()).getAbsolutePath();
- EsriShapeExport shapeExport = new EsriShapeExport(graphicList, tableModel, pathFile);
- shapeExport.export();
+ flushExport(builder, dataModel, graphicList);
- timeLog.log(startTime, "exportEffortsMap", "after EsriShapeExport execution");
+ timeLog.log(startTime, "exportEffortsMap", "after EsriShapeExport execution");
+ } finally {
+ context.getPersistence().endTransaction(tx);
+ }
}
public void exportObservationsMap(ExportMapModel dataModel) {
@@ -214,11 +313,7 @@
}
long startTime = TimeLog.getTime();
- Campaign campaign = dataModel.getCampaign();
- Region region = campaign.getRegion();
-
// * uniquement pour un parcours de type LEG, sinon la cellule sera vide
- // ** uniquement pour un parcours de type CIRCLE_BACK, sinon la cellule sera vide
DbfTableModelBuilder builder = new DbfTableModelBuilder()
.stringColumn("REGION") // (campaign.region.code)
.stringColumn("CAMPAIGN") // (campaign.code)
@@ -230,9 +325,9 @@
.integerColumn("FLIGHT") // (route.flight.flightNumber)
.stringColumn("COMPUTER") // (route.flight.systemId)
.stringColumn("ROUTE_TYPE") // (route.routeType.name)
- .stringColumn("EFFORT_GROUP") // * ()
- .stringColumn("EFFORT") // * ()
- .stringColumn("OBSERVATION") // ()
+ .stringColumn("EFFORT_GROUP") // * (voir doc)
+ .stringColumn("EFFORT") // * (voir doc)
+ .stringColumn("OBSERVATION") // (voir doc)
.dateColumn("DATE") // (observation.beginTime)
.stringColumn("HHMMSS") // (format(observation.beginTime, "HHmmss"))
.stringColumn("TAXON") // (observation.species.type)
@@ -248,7 +343,7 @@
.stringColumn("BEHAVIOUR") // (observation.behaviour)
.integerColumn("SWIM_DIR") // (observation.swimDir)
.stringColumn("CALVES") // (observation.calves)
- .stringColumn("PHOTO") // (observation.photo)
+ .booleanColumn("PHOTO") // (observation.photo)
.stringColumn("OBSERVER") // (observation.observerPosition.observer.initials)
.stringColumn("SIDE") // (observation.observerPosition.observer.position.name)
.stringColumn("STATUS") // (observation.observationStatus.name)
@@ -258,77 +353,179 @@
.doubleColumn("SPEED", 19, 11) // (geoPoint.speed)
.doubleColumn("ALTITUDE", 19, 11) // (geoPoint.altitude)
.stringColumn("GPS_TIME") // (format(geoPoint.recordTime, "HHmmss"))
- .stringColumn("AIRCRAFT") // (observation.flight.planeImmatriculation)
+ .stringColumn("AIRCRAFT") // (flight.immatriculation)
.stringColumn("COMMENT") // (observation.comment)
.build();
EsriGraphicList graphicList = new EsriPointList();
- List<Flight> campaignFlights = context.getFlightService().getFlights(dataModel.getCampaign());
- // Filter on period
- final PeriodDates period = new PeriodDates(dataModel.getBeginDate(), dataModel.getEndDate());
- Iterable<Flight> flights = Iterables.filter(campaignFlights, new Predicate<Flight>() {
+ Campaign campaign = dataModel.getCampaign();
+ Region region = campaign.getRegion();
+ List<RouteType> routeTypes = dataModel.getRouteTypes();
+ List<Strate> strates = dataModel.getStrates();
- @Override
- public boolean apply(Flight input) {
- return period.between(input.getBeginDate());
- }
- });
+ TopiaContext tx = context.getPersistence().beginTransaction();
- // Export for each flight
+ try {
+ FlightService flightService = context.getFlightService();
- for (Flight flight : flights) {
+ // get flights for campaign (and between begin - end date)
+ Iterable<Flight> flights = flightService.getFlights(
+ tx,
+ campaign,
+ dataModel.getBeginDate(),
+ dataModel.getEndDate());
- if (logger.isInfoEnabled()) {
- logger.info("Export GeoPoints from flight {} - {} - {} - {}",
- new Object[]{flight.getFlightNumber(),
- flight.getSystemId(),
- campaign.getCode(),
- region.getCode()}
- );
- }
+ // Export for each flight
- List<GeoPoint> geoPoints = context.getFlightService().getFlightGeoPoints(flight);
+ for (Flight flight : flights) {
- // One record by GeoPoint
- for (GeoPoint geoPoint : geoPoints) {
+ if (logger.isInfoEnabled()) {
+ logger.info("Export Observations from flight {} - {} - {} - {}",
+ new Object[]{flight.getFlightNumber(),
+ flight.getSystemId(),
+ campaign.getCode(),
+ region.getCode()}
+ );
+ }
- Map<String, Object> record = Maps.newHashMap();
+ // get all observations for this flight
+ List<Observation> observations =
+ flightService.getObservations(tx, flight);
- record.put("REGION", region.getCode());
- record.put("CAMPAIGN", campaign.getCode());
- record.put("FLIGHT", flight.getFlightNumber());
- record.put("COMPUTER", flight.getSystemId());
- record.put("DATE", geoPoint.getRecordTime());
- record.put("HHMMSS", timeFormat.format(geoPoint.getRecordTime()));
- record.put("LAT", geoPoint.getLatitude());
- record.put("LON", geoPoint.getLongitude());
- record.put("SPEED", geoPoint.getSpeed());
- record.put("ALTITUDE", geoPoint.getAltitude());
+ // apply species filter
+ Observations.removeOtherSpecies(observations,
+ dataModel.getSpecies());
- builder.addValues(record);
+ // get all routes of this flight
+ List<Route> routes = flightService.getRoutes(tx, flight);
- if (logger.isTraceEnabled()) {
- logger.trace("Record={}", record);
+ // get all geo points for this flight
+ List<GeoPoint> routeGeoPoints =
+ flightService.getFlightGeoPoints(tx, flight);
+
+ Map<String, Object> flightRecord = Maps.newHashMap();
+ fillFlightRecord(campaign, region, flight, flightRecord);
+
+ int nextRouteIndex = 0;
+ int nbRoutes = routes.size();
+ String effortGroup = null;
+
+ for (Route route : routes) {
+
+ nextRouteIndex++;
+
+ boolean routeIsLeg = Routes.isRouteLeg(route);
+
+ if (!routeIsLeg) {
+
+ // new group will be computed at next leg route
+ effortGroup = null;
+ }
+
+ if (!Routes.isRouteAccepted(route, routeTypes, strates)) {
+
+ // not selected route
+ continue;
+ }
+
+ Map<String, Object> routeRecord = Maps.newHashMap();
+ routeRecord.putAll(flightRecord);
+
+ if (routeIsLeg && effortGroup == null) {
+
+ // compute effort group id
+ effortGroup = computeEffortGroup(flight, route);
+ }
+
+ fillRouteTypeRecord(flight, route, effortGroup, routeRecord);
+
+ // get routeEndTime
+ Date routeEndTime;
+
+ if (nextRouteIndex < nbRoutes) {
+
+ // use next route begin time
+ Route nextRoute = routes.get(nextRouteIndex);
+ routeEndTime = nextRoute.getBeginTime();
+ } else {
+
+ // use flight end date
+ routeEndTime = flight.getEndDate();
+ }
+
+ // Get observations for this route
+ List<Observation> routeObservations =
+ Observations.getObservations(observations,
+ route.getBeginTime(),
+ routeEndTime);
+
+ // get best geo points for each observation
+ Iterable<GeoPoint> observationGeoPoints =
+ GeoPoints.getClosestPoints(
+ routeGeoPoints,
+ Observations.toDates(routeObservations));
+
+ // to iterate on geoPoints
+ Iterator<GeoPoint> geoPointIterator =
+ observationGeoPoints.iterator();
+
+ for (Observation observation : routeObservations) {
+
+ Map<String, Object> record = Maps.newHashMap();
+ record.putAll(routeRecord);
+
+ String observationId = computeObservationId(flight, observation);
+ record.put("OBSERVATION", observationId);
+
+ fillDateRecord(observation.getObservationTime(), record);
+
+ Species species = observation.getSpecies();
+ if (species != null) {
+ record.put("TAXON", species.getType());
+ record.put("GROUP", species.getGroupName());
+ record.put("FAMILY", species.getFamily());
+ record.put("SPECIES", species.getCode());
+ record.put("SPECIES_NAME", species.getCommonName());
+ record.put("SPECIES_LATIN", species.getLatinName());
+ }
+ record.put("POD_SIZE", observation.getPodSize());
+ record.put("AGE", observation.getAge());
+ record.put("DEC_ANGLE", observation.getDecAngle());
+ record.put("CUE", observation.getCue());
+ record.put("BEHAVIOUR", observation.getBehaviour());
+ record.put("SWIM_DIR", observation.getSwimDir());
+ record.put("CALVES", observation.getCalves());
+ record.put("PHOTO", observation.isPhoto());
+ record.put("OBSERVER", observation.getObserverPosition().getObserver().getInitials());
+ record.put("SIDE", observation.getObserverPosition().getPosition().getName());
+ record.put("STATUS", observation.getObservationStatus().getName());
+ record.put("COMMENT", observation.getComment());
+
+ GeoPoint geoPoint = geoPointIterator.next();
+
+ // add geoPoint data and flush
+ fillGeoPointRecordAndFlush(geoPoint,
+ record,
+ builder,
+ graphicList);
+
+ }
}
-
- OMGraphic graphic = new OMPoint(geoPoint.getLatitude(), geoPoint.getLongitude());
- graphicList.add(graphic);
}
- }
- startTime = timeLog.log(startTime, "exportObservationsMap", "after building EsriGraphicList and DbfTableModel");
+ startTime = timeLog.log(startTime, "exportObservationsMap", "after building EsriGraphicList and DbfTableModel");
- // Execute export with EsriShapeExport
- DbfTableModel tableModel = builder.getModel();
- String pathFile = new File(dataModel.getExportDirectory(), dataModel.getExportFilename()).getAbsolutePath();
- EsriShapeExport shapeExport = new EsriShapeExport(graphicList, tableModel, pathFile);
- shapeExport.export();
+ flushExport(builder, dataModel, graphicList);
- timeLog.log(startTime, "exportObservationsMap", "after EsriShapeExport execution");
+ timeLog.log(startTime, "exportObservationsMap", "after EsriShapeExport execution");
+ } finally {
+ context.getPersistence().endTransaction(tx);
+ }
}
public void exportGeoPointsMap(ExportMapModel dataModel) {
+
Preconditions.checkNotNull(dataModel.getCampaign());
Preconditions.checkNotNull(dataModel.getBeginDate());
Preconditions.checkNotNull(dataModel.getEndDate());
@@ -341,14 +538,12 @@
long startTime = TimeLog.getTime();
- Campaign campaign = dataModel.getCampaign();
- Region region = campaign.getRegion();
-
DbfTableModelBuilder builder = new DbfTableModelBuilder()
.stringColumn("REGION")
.stringColumn("CAMPAIGN")
.integerColumn("FLIGHT")
.stringColumn("COMPUTER")
+ .stringColumn("AIRCRAFT")
.dateColumn("DATE")
.stringColumn("HHMMSS")
.doubleColumn("LAT", 19, 11)
@@ -357,68 +552,214 @@
.doubleColumn("ALTITUDE", 19, 11)
.build();
- EsriGraphicList graphicList = new EsriPointList();
- List<Flight> campaignFlights = context.getFlightService().getFlights(dataModel.getCampaign());
+ Campaign campaign = dataModel.getCampaign();
+ Region region = campaign.getRegion();
- // Filter on period
- final PeriodDates period = new PeriodDates(dataModel.getBeginDate(), dataModel.getEndDate());
- Iterable<Flight> flights = Iterables.filter(campaignFlights, new Predicate<Flight>() {
+ FlightService flightService = context.getFlightService();
- @Override
- public boolean apply(Flight input) {
- return period.between(input.getBeginDate());
- }
- });
+ // get flights for campaign (and between begin - end date)
+ Iterable<Flight> flights = flightService.getFlights(campaign,
+ dataModel.getBeginDate(),
+ dataModel.getEndDate());
+ EsriGraphicList graphicList = new EsriPointList();
+
// Export for each flight
for (Flight flight : flights) {
if (logger.isInfoEnabled()) {
- logger.info(String.format("Export GeoPoints from flight %d - %s - %s - %s",
- flight.getFlightNumber(),
- flight.getSystemId(),
- campaign.getCode(),
- region.getCode())
+ logger.info("Export GeoPoints from flight {} - {} - {} - {}",
+ new Object[]{flight.getFlightNumber(),
+ flight.getSystemId(),
+ campaign.getCode(),
+ region.getCode()}
);
}
- List<GeoPoint> geoPoints = context.getFlightService().getFlightGeoPoints(flight);
+ List<GeoPoint> geoPoints =
+ flightService.getFlightGeoPoints(flight);
+ Map<String, Object> commonRecord = Maps.newHashMap();
+ fillFlightRecord(campaign, region, flight, commonRecord);
+
// One record by GeoPoint
for (GeoPoint geoPoint : geoPoints) {
Map<String, Object> record = Maps.newHashMap();
+ record.putAll(commonRecord);
- record.put("REGION", region.getCode());
- record.put("CAMPAIGN", campaign.getCode());
- record.put("FLIGHT", flight.getFlightNumber());
- record.put("COMPUTER", flight.getSystemId());
- record.put("DATE", geoPoint.getRecordTime());
- record.put("HHMMSS", timeFormat.format(geoPoint.getRecordTime()));
- record.put("LAT", geoPoint.getLatitude());
- record.put("LON", geoPoint.getLongitude());
- record.put("SPEED", geoPoint.getSpeed());
- record.put("ALTITUDE", geoPoint.getAltitude());
+ fillDateRecord(geoPoint.getRecordTime(), record);
- builder.addValues(record);
-
- if (logger.isTraceEnabled()) {
- logger.trace("Record={}", record);
- }
-
- OMGraphic graphic = new OMPoint(geoPoint.getLatitude(), geoPoint.getLongitude());
- graphicList.add(graphic);
+ // add geoPoint data and flush
+ fillGeoPointRecordAndFlush(geoPoint,
+ record,
+ builder,
+ graphicList);
}
}
- startTime = timeLog.log(startTime, "exportGeoPointsMap", "after building EsriGraphicList and DbfTableModel");
+ startTime = timeLog.log(startTime, "exportGeoPointsMap",
+ "after building EsriGraphicList and DbfTableModel");
- // Execute export with EsriShapeExport
+ flushExport(builder, dataModel, graphicList);
+
+ timeLog.log(startTime, "exportGeoPointsMap",
+ "after EsriShapeExport execution");
+ }
+
+ protected void flushExport(DbfTableModelBuilder builder,
+ ExportMapModel dataModel,
+ EsriGraphicList graphicList) {
+
DbfTableModel tableModel = builder.getModel();
- String pathFile = new File(dataModel.getExportDirectory(), dataModel.getExportFilename()).getAbsolutePath();
+ String pathFile = new File(dataModel.getExportDirectory(),
+ dataModel.getExportFilename()).getAbsolutePath();
EsriShapeExport shapeExport = new EsriShapeExport(graphicList, tableModel, pathFile);
shapeExport.export();
+ }
- timeLog.log(startTime, "exportGeoPointsMap", "after EsriShapeExport execution");
+ protected void fillDateRecord(Date date, Map<String, Object> record) {
+ record.put("DATE", date);
+ record.put("HHMMSS", timeFormat.format(date));
}
+
+ protected void fillGeoPointRecordAndFlush(GeoPoint geoPoint,
+ Map<String, Object> record,
+ DbfTableModelBuilder builder,
+ EsriGraphicList graphicList) {
+
+ record.put("LAT", geoPoint.getLatitude());
+ record.put("LON", geoPoint.getLongitude());
+ record.put("SPEED", geoPoint.getSpeed());
+ record.put("ALTITUDE", geoPoint.getAltitude());
+
+ builder.addValues(record);
+
+ if (logger.isTraceEnabled()) {
+ logger.trace("Record={}", record);
+ }
+
+ OMGraphic graphic = new OMPoint(geoPoint.getLatitude(),
+ geoPoint.getLongitude());
+ graphicList.add(graphic);
+ }
+
+ protected void fillFlightRecord(Campaign campaign,
+ Region region,
+ Flight flight,
+ Map<String, Object> record) {
+
+ record.put("REGION", region.getCode());
+ record.put("CAMPAIGN", campaign.getCode());
+ record.put("FLIGHT", flight.getFlightNumber());
+ record.put("AIRCRAFT", flight.getImmatriculation());
+ record.put("COMPUTER", flight.getSystemId());
+ }
+
+ protected void fillRouteRecord(Flight flight,
+ Route route,
+ String effortGroup,
+ LegStatus legStatus,
+ Map<String, Object> record) {
+
+ if (logger.isTraceEnabled()) {
+ logger.trace("Create Route record for route {} - {}",
+ new Object[]{route.getBeginTime(),
+ route.getRouteType()}
+ );
+ }
+
+ fillDateRecord(route.getBeginTime(), record);
+ fillRouteTypeRecord(flight, route, effortGroup, record);
+
+ if (legStatus != null) {
+ record.put("STATUS", LegStatus.END);
+ }
+ record.put("COMMENT", route.getComment());
+ record.put("SEA_STATE", route.getSeaState());
+ record.put("SWELL", route.getSwell());
+ record.put("TURBIDITY", route.getTurbidity());
+ record.put("SKY_GLINT", route.getSkyGlint());
+ record.put("GLARE_FROM", route.getGlareFrom());
+ record.put("GLARE_TO", route.getGlareTo());
+ record.put("GLARE_SEVERITY", route.getGlareSeverity());
+ record.put("GLARE_UNDER", route.isGlareUnder());
+ record.put("CLOUD_COVER", route.getCloudCover());
+ record.put("SUBJECTIVE", route.getSubjectiveConditions());
+ record.put("UNEXP_LEFT", route.getUnexpectedLeft());
+ record.put("UNEXP_RIGHT", route.getUnexpectedRight());
+
+ ObserverPosition observerPositionByPosition =
+ route.getObserverPositionByPosition(Position.FRONT_LEFT);
+ if (observerPositionByPosition != null) {
+ record.put("LEFT_REAR", observerPositionByPosition.getObserver().getInitials());
+ }
+ observerPositionByPosition =
+ route.getObserverPositionByPosition(Position.FRONT_RIGHT);
+ if (observerPositionByPosition != null) {
+ record.put("RIGHT_REAR", observerPositionByPosition.getObserver().getInitials());
+ }
+ observerPositionByPosition =
+ route.getObserverPositionByPosition(Position.NAVIGATOR);
+ if (observerPositionByPosition != null) {
+ record.put("CENTER", observerPositionByPosition.getObserver().getInitials());
+ }
+ }
+
+ protected void fillRouteTypeRecord(Flight flight,
+ Route route,
+ String effortGroup,
+ Map<String, Object> record) {
+
+ record.put("ROUTE_TYPE", route.getRouteType().getName());
+ if (Routes.isRouteLeg(route)) {
+ fillLegRouteRecord(route, effortGroup, record);
+ }
+
+ if (Routes.isRouteCircleBack(route)) {
+
+ // compute circle back cause
+ String circleBackCause = computeObservationId(flight, route.getCircleBackCause());
+ record.put("CB_CAUSE", circleBackCause);
+ }
+ }
+
+ protected void fillLegRouteRecord(Route route,
+ String effortGroup,
+ Map<String, Object> record) {
+
+ TransectFlight transectFlight = route.getTransectFlight();
+ Transect transect = transectFlight.getTransect();
+ Strate strate = transect.getStrate();
+
+ String effort = computeEffort(route);
+
+ record.put("SECTOR", strate.getSector().getSectorNumber());
+ record.put("STRATE_TYPE", strate.getStrateType().getCode());
+ record.put("STRATE", strate.getCode());
+ record.put("TRANSECT", transect.getName());
+ record.put("PASSAGE", transectFlight.getCrossingNumber());
+ record.put("EFFORT_GROUP", effortGroup);
+ record.put("EFFORT", effort);
+ }
+
+ protected String computeEffort(Route route) {
+ String result = "L" + route.getEffortNumber() + "-" +
+ route.getFlight().getFlightNumber() + "-" +
+ route.getFlight().getSystemId();
+ return result;
+ }
+
+ protected String computeEffortGroup(Flight flight, Route route) {
+ String result = "G" + route.getEffortNumber() + "-" +
+ flight.getFlightNumber() + "-" +
+ flight.getSystemId();
+ return result;
+ }
+
+ protected String computeObservationId(Flight flight, Observation observation) {
+ return "O" + observation.getObservationNumber() + "-" +
+ flight.getFlightNumber() + "-" +
+ flight.getSystemId();
+ }
}
Modified: trunk/sammoa-application/src/main/java/fr/ulr/sammoa/application/map/LegStatus.java
===================================================================
--- trunk/sammoa-application/src/main/java/fr/ulr/sammoa/application/map/LegStatus.java 2012-08-09 17:26:32 UTC (rev 380)
+++ trunk/sammoa-application/src/main/java/fr/ulr/sammoa/application/map/LegStatus.java 2012-08-09 17:53:27 UTC (rev 381)
@@ -7,7 +7,7 @@
* @since 0.5
*/
public enum LegStatus {
- BEAGIN,
+ BEGIN,
ADD, END;
public String getName() {
Modified: trunk/sammoa-application/src/test/java/fr/ulr/sammoa/application/map/ExportMapServiceTest.java
===================================================================
--- trunk/sammoa-application/src/test/java/fr/ulr/sammoa/application/map/ExportMapServiceTest.java 2012-08-09 17:26:32 UTC (rev 380)
+++ trunk/sammoa-application/src/test/java/fr/ulr/sammoa/application/map/ExportMapServiceTest.java 2012-08-09 17:53:27 UTC (rev 381)
@@ -183,6 +183,7 @@
public Iterable<ImportableColumn<GeoPoint, Object>> getColumnsForImport() {
ModelBuilder builder = new ModelBuilder();
builder.newMandatoryColumn("REGION", "flight.campaign.region.code");
+ builder.newMandatoryColumn("AIRCRAFT", "flight.immatriculation");
builder.newMandatoryColumn("CAMPAIGN", "flight.campaign.code");
builder.newMandatoryColumn("FLIGHT", "flight.flightNumber", new DoubleToIntegerValueParser());
builder.newMandatoryColumn("COMPUTER", "flight.systemId");
Modified: trunk/sammoa-persistence/src/main/java/fr/ulr/sammoa/persistence/Observations.java
===================================================================
--- trunk/sammoa-persistence/src/main/java/fr/ulr/sammoa/persistence/Observations.java 2012-08-09 17:26:32 UTC (rev 380)
+++ trunk/sammoa-persistence/src/main/java/fr/ulr/sammoa/persistence/Observations.java 2012-08-09 17:53:27 UTC (rev 381)
@@ -2,8 +2,8 @@
/*
* #%L
* SAMMOA :: Persistence
- * $Id:$
- * $HeadURL:$
+ * $Id$
+ * $HeadURL$
* %%
* Copyright (C) 2012 UMS 3462, Code Lutin
* %%
@@ -26,9 +26,15 @@
import com.google.common.base.Function;
import com.google.common.base.Preconditions;
import com.google.common.base.Predicate;
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Lists;
+import org.apache.commons.collections.CollectionUtils;
import org.nuiton.util.DateUtil;
+import org.nuiton.util.PeriodDates;
import java.util.Date;
+import java.util.Iterator;
+import java.util.List;
/**
* Created: 16/07/12
@@ -36,15 +42,19 @@
* @author fdesbois <desbois(a)codelutin.com>
*/
public final class Observations {
-
+
private Observations() {
// static class do not have instanciation
}
+ public static Iterable<Date> toDates(Iterable<Observation> observations) {
+ return Iterables.transform(observations, toDate());
+ }
+
public static Function<Observation, Date> toDate() {
return TO_DATE_FUNCTION;
}
-
+
public static boolean inRoute(Observation observation, Route route, Route nextRoute) {
Date begin = route.getBeginTime();
@@ -59,6 +69,21 @@
return new ObservationInRoutePredicate(route, nextRoute);
}
+ public static void removeOtherSpecies(List<Observation> observations,
+ List<Species> species) {
+ if (CollectionUtils.isNotEmpty(species)) {
+
+ // filter by species
+ Iterator<Observation> itr = observations.iterator();
+ while (itr.hasNext()) {
+ Observation observation = itr.next();
+ if (!species.contains(observation.getSpecies())) {
+ itr.remove();
+ }
+ }
+ }
+ }
+
protected static Function<Observation, Date> TO_DATE_FUNCTION = new Function<Observation, Date>() {
@Override
@@ -66,11 +91,27 @@
return input.getObservationTime();
}
};
-
+
+ public static List<Observation> getObservations(List<Observation> observations,
+ Date beginTime,
+ Date endTime) {
+
+ PeriodDates periodDate = new PeriodDates(beginTime, endTime);
+
+ List<Observation> result = Lists.newArrayList();
+ for (Observation observation : observations) {
+ Date observationTime = observation.getObservationTime();
+ if (periodDate.between(observationTime)) {
+ result.add(observation);
+ }
+ }
+ return result;
+ }
+
protected static class ObservationInRoutePredicate implements Predicate<Observation> {
-
+
protected Route route;
-
+
protected Route nextRoute;
public ObservationInRoutePredicate(Route route, Route nextRoute) {
@@ -84,5 +125,5 @@
return Observations.inRoute(input, route, nextRoute);
}
}
-
+
}
Modified: trunk/sammoa-persistence/src/main/java/fr/ulr/sammoa/persistence/Routes.java
===================================================================
--- trunk/sammoa-persistence/src/main/java/fr/ulr/sammoa/persistence/Routes.java 2012-08-09 17:26:32 UTC (rev 380)
+++ trunk/sammoa-persistence/src/main/java/fr/ulr/sammoa/persistence/Routes.java 2012-08-09 17:53:27 UTC (rev 381)
@@ -2,8 +2,8 @@
/*
* #%L
* SAMMOA :: Persistence
- * $Id:$
- * $HeadURL:$
+ * $Id$
+ * $HeadURL$
* %%
* Copyright (C) 2012 UMS 3462, Code Lutin
* %%
@@ -23,8 +23,14 @@
* #L%
*/
+import com.google.common.base.Function;
import com.google.common.base.Objects;
+import com.google.common.collect.Iterables;
+import org.apache.commons.collections.CollectionUtils;
+import java.util.Date;
+import java.util.List;
+
/**
* Created: 16/07/12
*
@@ -36,6 +42,50 @@
// static class do not have instanciation
}
+ public static boolean isRouteLeg(Route route) {
+ return route != null && RouteType.LEG == route.getRouteType();
+ }
+
+ public static boolean isRouteCircleBack(Route route) {
+ return route != null && RouteType.CIRCLE_BACK == route.getRouteType();
+ }
+
+ public static Iterable<Date> toDates(Iterable<Route> routes) {
+ return Iterables.transform(routes, toDate());
+ }
+
+ public static boolean isRouteAccepted(Route route,
+ List<RouteType> routeTypes,
+ List<Strate> strates) {
+ boolean result = false;
+
+ if (CollectionUtils.isEmpty(routeTypes) ||
+ routeTypes.contains(route.getRouteType())) {
+
+ TransectFlight transectFlight = route.getTransectFlight();
+
+ if (CollectionUtils.isEmpty(strates) ||
+ transectFlight == null ||
+ strates.contains(transectFlight.getTransect().getStrate())) {
+ result = true;
+ }
+ }
+
+ return result;
+ }
+
+ public static Function<Route, Date> toDate() {
+ return TO_DATE_FUNCTION;
+ }
+
+ protected static Function<Route, Date> TO_DATE_FUNCTION = new Function<Route, Date>() {
+
+ @Override
+ public Date apply(Route input) {
+ return input.getBeginTime();
+ }
+ };
+
public static boolean equal(Route o1, Route o2) {
boolean result = Objects.equal(o1.getRouteType(), o2.getRouteType());
Modified: trunk/src/site/rst/import-export.rst
===================================================================
--- trunk/src/site/rst/import-export.rst 2012-08-09 17:26:32 UTC (rev 380)
+++ trunk/src/site/rst/import-export.rst 2012-08-09 17:53:27 UTC (rev 381)
@@ -172,6 +172,8 @@
geoPoint.flight.flightNumber
- COMPUTER : Identifiant du système
geoPoint.flight.systemId
+- AIRCRAFT : Immatriculation de l'avion
+ geoPoint.flight.planeImmatriculation
- DATE : Date d'enregistrement du poin
geoPoint.recordTime
- HHMMSS : Heure d'enregistrement du point
@@ -487,7 +489,7 @@
* observation.calves
-- PHOTO : Des photos ont été prises
+- PHOTO : Des photos ont été prises (L)
* observation.photo
1
0