Skip to content

v0.2.51..v0.2.52 changeset DbUtils.java

Garret Voltz edited this page Jan 15, 2020 · 1 revision
diff --git a/hoot-services/src/main/java/hoot/services/utils/DbUtils.java b/hoot-services/src/main/java/hoot/services/utils/DbUtils.java
index ea974c4..515ffd9 100644
--- a/hoot-services/src/main/java/hoot/services/utils/DbUtils.java
+++ b/hoot-services/src/main/java/hoot/services/utils/DbUtils.java
@@ -22,7 +22,7 @@
  * This will properly maintain the copyright information. DigitalGlobe
  * copyrights will be updated automatically.
  *
- * @copyright Copyright (C) 2016, 2017, 2018, 2019 DigitalGlobe (http://www.digitalglobe.com/)
+ * @copyright Copyright (C) 2016, 2017, 2018, 2019, 2020 DigitalGlobe (http://www.digitalglobe.com/)
  */
 package hoot.services.utils;
 
@@ -31,6 +31,8 @@ import static hoot.services.models.db.QFolderMapMappings.folderMapMappings;
 import static hoot.services.models.db.QFolders.folders;
 import static hoot.services.models.db.QJobStatus.jobStatus;
 import static hoot.services.models.db.QMaps.maps;
+import static hoot.services.models.db.QReviewBookmarks.reviewBookmarks;
+import static hoot.services.models.db.QUsers.users;
 
 import java.sql.Connection;
 import java.sql.PreparedStatement;
@@ -41,8 +43,10 @@ import java.sql.Timestamp;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
 
 import javax.inject.Provider;
 import javax.sql.DataSource;
@@ -58,6 +62,8 @@ import org.slf4j.LoggerFactory;
 import org.springframework.context.ApplicationContext;
 import org.springframework.transaction.annotation.Transactional;
 
+import com.querydsl.core.Tuple;
+import com.querydsl.core.types.dsl.BooleanExpression;
 import com.querydsl.core.types.dsl.Expressions;
 import com.querydsl.core.types.dsl.NumberPath;
 import com.querydsl.core.types.dsl.StringPath;
@@ -74,8 +80,12 @@ import com.querydsl.sql.types.EnumAsObjectType;
 
 import hoot.services.ApplicationContextUtils;
 import hoot.services.command.CommandResult;
+import hoot.services.models.db.Folders;
 import hoot.services.models.db.JobStatus;
+import hoot.services.models.db.Maps;
+import hoot.services.models.db.QFolders;
 import hoot.services.models.db.QUsers;
+import hoot.services.models.db.Users;
 
 
 /**
@@ -248,6 +258,42 @@ public class DbUtils {
         return sql.fetchFirst();
     }
 
+    public static Set<Long> getFolderIdsForUser(Users user) {
+        Long userId = null;
+        if (user != null) userId = user.getId();
+        return getFolderIdsForUser(userId);
+    }
+
+    public static Set<Long> getFolderIdsForUser(Long userId) {
+        List<Folders> folders = getFoldersForUser(userId);
+        Set<Long> out = new HashSet<Long>(folders.size());
+        for (Folders f : folders) {
+            out.add(f.getId());
+        }
+        return out;
+    }
+
+    public static List<Folders> getFoldersForUser(Users user) {
+        Long userId = null;
+        if (user != null) userId = user.getId();
+        return getFoldersForUser(userId);
+    }
+
+    public static List<Folders> getFoldersForUser(Long userId) {
+        SQLQuery<Folders> sql = createQuery()
+            .select(folders)
+            .from(folders)
+            .where(folders.id.ne(0L));
+        if(userId != null) {
+            sql.where(
+                    folders.userId.eq(userId).or(folders.publicCol.isTrue())
+            );
+        }
+        List<Folders> folderRecordSet = sql.orderBy(folders.displayName.asc()).fetch();
+
+        return folderRecordSet;
+    }
+
     public static List<Long> getChildrenFolders(Long folderId) {
         List<Long> childrenFolders = createQuery()
                 .select(folders.id)
@@ -258,6 +304,44 @@ public class DbUtils {
         return childrenFolders;
     }
 
+/*
+ * --Deletes folders that are empty (no child datasets or folders)
+DELETE
+FROM folders f
+WHERE
+NOT EXISTS
+    (
+    SELECT  NULL
+    FROM    folder_map_mappings fmm
+    WHERE   f.id = fmm.folder_id
+    )
+AND
+NOT EXISTS
+    (
+    SELECT  NULL
+    FROM    folders f2
+    WHERE   f.id = f2.parent_id
+    );
+ */
+    public static void deleteEmptyFolders() {
+        QFolders folders2 = new QFolders("folders2");
+        BooleanExpression isEmpty = new SQLQuery<>().from(folderMapMappings).where(folderMapMappings.folderId.eq(folders.id)).notExists()
+                .and(new SQLQuery<>().from(folders2).where(folders.id.eq(folders2.parentId)).notExists());
+
+        SQLQuery<Folders> hasEmpty = createQuery()
+            .select(folders)
+            .from(folders)
+            .where(isEmpty);
+
+        //keep trying to delete newly empty folders until no more are detected
+        while (hasEmpty.fetchCount() > 0) {
+            createQuery()
+                .delete(folders)
+                .where(isEmpty)
+                .execute();
+        }
+    }
+
     /**
      * Sets the parent directory for the specified folder
      *
@@ -538,6 +622,43 @@ public class DbUtils {
         return count;
     }
 
+/*
+    SELECT id
+    FROM maps
+    WHERE (tags -> 'lastAccessed' IS NULL AND created_at < ts)
+    OR TO_TIMESTAMP(tags -> 'lastAccessed', 'YYYY-MM-DD"T"HH24:MI:SS.MS"Z"') < ts
+
+ */
+
+    private static BooleanExpression getStale(Timestamp ts) {
+        return (Expressions.stringTemplate("tags->'lastAccessed'").isNotNull().and(maps.createdAt.lt(ts)))
+                .or(Expressions.dateTimeTemplate(Timestamp.class, "TO_TIMESTAMP(tags -> 'lastAccessed', 'YYYY-MM-DD\"T\"HH24:MI:SS.MS\"Z\"')").lt(ts));
+    }
+
+    public static List<Maps> getStaleMaps(Timestamp ts) {
+        return createQuery()
+                .select(maps)
+                .from(maps)
+                .where(getStale(ts))
+                .fetch();
+    }
+
+    public static Map<String, Long> getStaleMapsSummary(Timestamp ts) {
+        List<Tuple> result =  createQuery()
+                .select(users.displayName, maps.countDistinct())
+                .from(users, maps)
+                .where(users.id.eq(maps.userId).and(getStale(ts)))
+                .groupBy(users.displayName)
+                .fetch();
+
+        Map<String, Long> response = new HashMap<>();
+
+        result.stream().forEach(tuple -> {
+            response.put(tuple.get(users.displayName), tuple.get(maps.countDistinct()));
+        });
+
+        return response;
+    }
 
     /**
      * Returns table size in bytes
@@ -566,6 +687,20 @@ public class DbUtils {
     }
 
     /**
+     * Checks for the existence of user
+     *
+     * @param userId
+     * @return returns true when exists else false
+     */
+    public static boolean userExists(Long userId) {
+        return createQuery()
+                .select(users)
+                .from(users)
+                .where(users.id.eq(userId))
+                .fetchCount() == 1;
+    }
+
+    /**
      * Returns the record ID associated with the record request input string for
      * the given DAO type. First attempts to parse the request string as a
      * record ID. If that is unsuccessful, it treats the request string as a
@@ -841,4 +976,13 @@ public class DbUtils {
 
         return progress;
     }
+
+    public static void deleteOSMRecordById(Long mapId) {
+        deleteMapRelatedTablesByMapId(mapId);
+        DbUtils.deleteMap(mapId);
+    }
+
+    public static void deleteBookmarksByMapId(Long mapId) {
+        createQuery().delete(reviewBookmarks).where(reviewBookmarks.mapId.eq(mapId)).execute();
+    }
 }
Clone this wiki locally