diff --git a/src/main/java/de/geofroggerfx/dao/UserDAO.java b/src/main/java/de/geofroggerfx/dao/UserDAO.java new file mode 100644 index 0000000..acbcdbe --- /dev/null +++ b/src/main/java/de/geofroggerfx/dao/UserDAO.java @@ -0,0 +1,42 @@ +/* + * Copyright (c) Andreas Billmann + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +package de.geofroggerfx.dao; + +import de.geofroggerfx.model.User; + +import java.util.List; + +/** + * Created by Andreas on 27.03.2015. + */ +public interface UserDAO { + + void save(User user); + void save(List user); + + User getUser(Long id); + +} diff --git a/src/main/java/de/geofroggerfx/dao/jdbc/JdbcCacheDAO.java b/src/main/java/de/geofroggerfx/dao/jdbc/JdbcCacheDAO.java index 53c8218..73234a8 100644 --- a/src/main/java/de/geofroggerfx/dao/jdbc/JdbcCacheDAO.java +++ b/src/main/java/de/geofroggerfx/dao/jdbc/JdbcCacheDAO.java @@ -26,6 +26,7 @@ package de.geofroggerfx.dao.jdbc; import de.geofroggerfx.dao.CacheDAO; +import de.geofroggerfx.dao.UserDAO; import de.geofroggerfx.model.*; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.jdbc.core.JdbcTemplate; @@ -100,6 +101,8 @@ public class JdbcCacheDAO implements CacheDAO { "type", "text"}; + @Autowired + private UserDAO userDAO; private JdbcTemplate jdbcTemplate; @@ -320,9 +323,6 @@ public class JdbcCacheDAO implements CacheDAO { } - - - private Cache getCacheFromResultSet(ResultSet rs) throws SQLException { Cache cache = new Cache(); cache.setId(rs.getLong("id")); @@ -342,7 +342,7 @@ public class JdbcCacheDAO implements CacheDAO { cache.setLongDescriptionHtml(rs.getBoolean("long_description_html")); cache.setContainer(groundspeakStringToContainer(rs.getString("container"))); cache.setType(groundspeakStringToType(rs.getString("type"))); - cache.setOwner(null); + cache.setOwner(userDAO.getUser(rs.getLong("user_id"))); return cache; } @@ -365,7 +365,7 @@ public class JdbcCacheDAO implements CacheDAO { cache.getEncodedHints(), cache.getContainer().toGroundspeakString(), cache.getType().toGroundspeakString(), - cache.getOwner() != null ? cache.getOwner().getId() : null }; + cache.getOwner().getId() }; } private Waypoint getWaypointFromResultSet(ResultSet rs) throws SQLException { @@ -393,6 +393,7 @@ public class JdbcCacheDAO implements CacheDAO { log.setDate(rs.getDate("date")); log.setText(rs.getString("text")); log.setType(LogType.groundspeakStringToType(rs.getString("type"))); + log.setFinder(userDAO.getUser(rs.getLong("user_id"))); return log; } @@ -424,7 +425,7 @@ public class JdbcCacheDAO implements CacheDAO { log.getId(), cache.getId(), log.getDate(), - null, //log.getFinder().getId(), + log.getFinder().getId(), log.getType().toGroundspeakString(), log.getText() }; diff --git a/src/main/java/de/geofroggerfx/dao/jdbc/JdbcUserDAO.java b/src/main/java/de/geofroggerfx/dao/jdbc/JdbcUserDAO.java new file mode 100644 index 0000000..13d51e7 --- /dev/null +++ b/src/main/java/de/geofroggerfx/dao/jdbc/JdbcUserDAO.java @@ -0,0 +1,145 @@ +/* + * Copyright (c) Andreas Billmann + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +package de.geofroggerfx.dao.jdbc; + +import de.geofroggerfx.dao.UserDAO; +import de.geofroggerfx.model.User; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.stereotype.Repository; + +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.List; +import java.util.logging.Level; +import java.util.logging.Logger; +import java.util.stream.Collectors; + +import static de.geofroggerfx.dao.jdbc.JDBCUtils.addCommaToValue; +import static de.geofroggerfx.dao.jdbc.JDBCUtils.generateInsertSQL; +import static de.geofroggerfx.dao.jdbc.JDBCUtils.generateSelectSQL; + +/** + * Created by Andreas on 27.03.2015. + */ +@Repository +public class JdbcUserDAO implements UserDAO { + + private static final Logger LOGGER = Logger.getLogger("JdbcUserDAO"); + private static final String USER_TABLE = "user"; + + private String[] columnListUser = new String[] { + "id", + "name"}; + + private JdbcTemplate jdbcTemplate; + + @Autowired + public void setDataConfig(DataConfig dataConfig) { + this.jdbcTemplate = new JdbcTemplate(dataConfig.dataSource()); + } + + + @Override + public void save(User user) { + + } + + @Override + public void save(List listOfUsers) { + deleteExistingUsers(listOfUsers); + batchInsertUsers(listOfUsers); + } + + @Override + public User getUser(Long id) { + return this.jdbcTemplate.queryForObject( + generateSelectSQL(USER_TABLE, columnListUser) + " WHERE id=?", + new Object[]{id}, + (rs, rowNum) -> { + return getUserFromResultSet(rs); + }); + } + + + + private void deleteExistingUsers(List listOfUsers) { + LOGGER.info("try to delete existing users"); + long startDelete = System.currentTimeMillis(); + StringBuffer sb = new StringBuffer(); + for (int current = 0; current < listOfUsers.size()-1; current++) { + addCommaToValue(sb, Long.toString(listOfUsers.get(current).getId())); + } + sb.append(listOfUsers.get(listOfUsers.size()-1).getId()); + + try { + int result = jdbcTemplate.update("DELETE FROM "+USER_TABLE+" WHERE id IN ("+sb.toString()+")"); + LOGGER.info("deleted "+result+" caches"); + } catch (Throwable e) { + LOGGER.log(Level.SEVERE, e.getMessage(), e); + } + long endDelete = System.currentTimeMillis(); + LOGGER.info("try to delete existing users -> done in " + (endDelete - startDelete) + " ms"); + } + + private void batchInsertUsers(List listOfCaches) { + LOGGER.info("try to save " + listOfCaches.size() + " users"); + long startInsert = System.currentTimeMillis(); + + List batch = listOfCaches.parallelStream().map(this::valuesFromUser).collect(Collectors.toList()); + + try { + String insertSQL = generateInsertSQL(USER_TABLE, columnListUser); + int[] updateCounts = jdbcTemplate.batchUpdate( + insertSQL, + batch); + int updatedRows = 0; + for (int count:updateCounts) { + updatedRows += count; + } + LOGGER.info("batch inserted "+updatedRows+" users"); + } catch (Throwable e) { + LOGGER.log(Level.SEVERE, e.getMessage(), e); + } + + long endInsert = System.currentTimeMillis(); + LOGGER.info("try to save " + listOfCaches.size() + " users -> done in " + (endInsert - startInsert) + " ms"); + } + + private Object[] valuesFromUser(User user) { + return new Object[]{ + user.getId(), + user.getName() }; + } + + private User getUserFromResultSet(ResultSet rs) throws SQLException { + User user = new User(); + user.setId(rs.getLong("id")); + user.setName(rs.getString("name")); + return user; + } + +} diff --git a/src/main/java/de/geofroggerfx/gpx/GroundspeakGPXReader.java b/src/main/java/de/geofroggerfx/gpx/GroundspeakGPXReader.java index ffd8e9f..4498c13 100644 --- a/src/main/java/de/geofroggerfx/gpx/GroundspeakGPXReader.java +++ b/src/main/java/de/geofroggerfx/gpx/GroundspeakGPXReader.java @@ -95,9 +95,6 @@ public class GroundspeakGPXReader implements GPXReader { private final List listeners = new ArrayList<>(); - private final Map userCache = new HashMap<>(); - - @Override public void addListener(ProgressListener listener) { if (!listeners.contains(listener)) { @@ -120,6 +117,7 @@ public class GroundspeakGPXReader implements GPXReader { Waypoint waypoint = null; Cache cache = null; Log log = null; + User user = null; String currentLevel = null; String startTag; StringBuffer tagContent = new StringBuffer(); @@ -167,6 +165,15 @@ public class GroundspeakGPXReader implements GPXReader { case LONG_DESCRIPTION: cache.setLongDescriptionHtml(Boolean.parseBoolean(reader.getAttributeValue(0))); break; + case OWNER: + cache.setOwner(new User()); + cache.getOwner().setId(Long.parseLong(reader.getAttributeValue(0))); + break; + case FINDER: + log.setFinder(new User()); + log.getFinder().setId(Long.parseLong(reader.getAttributeValue(0))); + break; + } break; @@ -219,6 +226,7 @@ public class GroundspeakGPXReader implements GPXReader { cache.setPlacedBy(tagContent.toString()); break; case OWNER: + cache.getOwner().setName(tagContent.toString()); break; case CONTAINER: cache.setContainer(Container.groundspeakStringToContainer(tagContent.toString())); @@ -253,6 +261,9 @@ public class GroundspeakGPXReader implements GPXReader { case TEXT: log.setText(tagContent.toString()); break; + case FINDER: + log.getFinder().setName(tagContent.toString()); + break; } break; diff --git a/src/main/java/de/geofroggerfx/model/User.java b/src/main/java/de/geofroggerfx/model/User.java index 47ed431..62f2f43 100644 --- a/src/main/java/de/geofroggerfx/model/User.java +++ b/src/main/java/de/geofroggerfx/model/User.java @@ -60,4 +60,20 @@ public class User { public void setName(String name) { this.name.set(name); } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + User user = (User) o; + + return id.equals(user.id); + + } + + @Override + public int hashCode() { + return id.hashCode(); + } } diff --git a/src/main/java/de/geofroggerfx/service/CacheServiceImpl.java b/src/main/java/de/geofroggerfx/service/CacheServiceImpl.java index 6111344..5388b7f 100644 --- a/src/main/java/de/geofroggerfx/service/CacheServiceImpl.java +++ b/src/main/java/de/geofroggerfx/service/CacheServiceImpl.java @@ -26,12 +26,18 @@ package de.geofroggerfx.service; import de.geofroggerfx.dao.CacheDAO; +import de.geofroggerfx.dao.UserDAO; import de.geofroggerfx.model.Cache; import de.geofroggerfx.model.CacheListEntry; +import de.geofroggerfx.model.Log; +import de.geofroggerfx.model.User; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; +import java.util.ArrayList; +import java.util.HashMap; import java.util.List; +import java.util.Map; /** * Created by Andreas on 10.03.2015. @@ -42,8 +48,14 @@ public class CacheServiceImpl implements CacheService { @Autowired private CacheDAO cacheDAO; + @Autowired + private UserDAO userDAO; + + @Override public void storeCaches(List cacheList) { + List users = extractUserList(cacheList); + userDAO.save(users); cacheDAO.save(cacheList); } @@ -62,5 +74,24 @@ public class CacheServiceImpl implements CacheService { return cacheDAO.getAllCaches(); } + private List extractUserList(List cacheList) { + + Map users = new HashMap<>(); + + for (Cache cache: cacheList) { + User owner = cache.getOwner(); + if (!users.containsKey(owner.getId())) { + users.put(owner.getId(), owner); + } + for (Log log: cache.getLogs()) { + User finder = log.getFinder(); + if (!users.containsKey(finder.getId())) { + users.put(finder.getId(), finder); + } + } + } + + return new ArrayList(users.values()); + } } diff --git a/src/main/java/de/geofroggerfx/ui/details/DetailsController.java b/src/main/java/de/geofroggerfx/ui/details/DetailsController.java index 2c0c608..faa0dfd 100644 --- a/src/main/java/de/geofroggerfx/ui/details/DetailsController.java +++ b/src/main/java/de/geofroggerfx/ui/details/DetailsController.java @@ -181,7 +181,7 @@ public class DetailsController extends FXMLController { Text icon = GeofroggerGlyphsDude.createIcon(FontAwesomeIcons.CHECK); Label date = new Label(log.getDate().toString()); date.setStyle("-fx-font-weight: bold; -fx-font-size: 1.2em;"); - Label name = new Label("the user's name"); + Label name = new Label(log.getFinder().getName()); name.setStyle("-fx-font-weight: bold; -fx-font-size: 1.2em;"); HBox.setHgrow(icon, Priority.NEVER); diff --git a/src/main/java/de/geofroggerfx/ui/list/ListController.java b/src/main/java/de/geofroggerfx/ui/list/ListController.java index 1b03fb5..5a25d12 100644 --- a/src/main/java/de/geofroggerfx/ui/list/ListController.java +++ b/src/main/java/de/geofroggerfx/ui/list/ListController.java @@ -71,7 +71,7 @@ public class ListController extends FXMLController { setCellFactory(); sessionContext.addListener(CACHE_ENTRY_LIST, () -> Platform.runLater(this::resetCacheList)); cacheListView.getSelectionModel().selectedItemProperty().addListener( - (InvalidationListener) observable -> setSelectedCacheIntoSession() + observable -> setSelectedCacheIntoSession() ); } diff --git a/src/main/resources/de/geofroggerfx/dao/jdbc/updates/4.sql b/src/main/resources/de/geofroggerfx/dao/jdbc/updates/4.sql new file mode 100644 index 0000000..c1f780a --- /dev/null +++ b/src/main/resources/de/geofroggerfx/dao/jdbc/updates/4.sql @@ -0,0 +1,6 @@ +CREATE TABLE user ( + id INT PRIMARY KEY , + name VARCHAR(255) +); + +UPDATE version SET version=4; \ No newline at end of file