001/** 002 * Copyright 2014 Tampere University of Technology, Pori Department 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016package service.tut.pori.contentstorage; 017 018import java.util.ArrayList; 019import java.util.Collection; 020import java.util.LinkedList; 021import java.util.List; 022import java.util.Map; 023import java.util.Map.Entry; 024 025import org.apache.log4j.Logger; 026 027import service.tut.pori.contentstorage.TwitterPhotoStorage.TwitterEntry; 028import core.tut.pori.dao.clause.AndClause; 029import core.tut.pori.dao.clause.SQLClause.SQLType; 030import core.tut.pori.dao.SQLDAO; 031import core.tut.pori.dao.SQLDeleteBuilder; 032import core.tut.pori.dao.SQLSelectBuilder; 033import core.tut.pori.users.UserIdentity; 034 035/** 036 * DAO for saving and retrieving Twitter content entries. 037 * 038 */ 039public class TwitterDAO extends SQLDAO { 040 private static final Logger LOGGER = Logger.getLogger(TwitterDAO.class); 041 /* tables */ 042 private static final String TABLE_ENTRIES = DATABASE+".ca_twitter_entries"; 043 /* columns */ 044 private static final String COLUMN_ENTITY_ID = "entity_id"; 045 private static final String COLUMN_ENTITY_URL = "entity_url"; 046 private static final String COLUMN_SCREEN_NAME = "screen_name"; 047 /* sql scripts */ 048 private static final String SQL_CREATE_ENTRY = "INSERT INTO "+TABLE_ENTRIES+" ("+COLUMN_GUID+", "+COLUMN_ENTITY_ID+", "+COLUMN_ENTITY_URL+", "+COLUMN_SCREEN_NAME+", "+COLUMN_USER_ID+", "+COLUMN_ROW_CREATED+") VALUES (?,?,?,?,?,NOW())"; 049 private static final int[] SQL_CREATE_ENTRY_SQL_TYPES = new int[]{SQLType.STRING.toInt(), SQLType.STRING.toInt(), SQLType.STRING.toInt(), SQLType.STRING.toInt(), SQLType.LONG.toInt()}; 050 051 private static final String[] SQL_SELECT_COLUMNS = {COLUMN_GUID, COLUMN_USER_ID, COLUMN_ENTITY_ID, COLUMN_ENTITY_URL, COLUMN_SCREEN_NAME}; 052 053 private static final String SQL_GET_URL = "SELECT "+COLUMN_COUNT+", "+COLUMN_ENTITY_URL+" FROM "+TABLE_ENTRIES+" WHERE "+COLUMN_GUID+"=?"; // add count to force result 054 private static final int[] SQL_GET_URL_SQL_TYPES = {SQLType.STRING.toInt()}; 055 056 /** 057 * 058 * @param entityIds optional list of entity ids used as a filter 059 * @param userId 060 * @return list of entries or null if none was found 061 */ 062 public List<TwitterEntry> getEntriesByEntityId(List<String> entityIds, UserIdentity userId) { 063 if(!UserIdentity.isValid(userId)){ 064 LOGGER.warn("Invalid userId."); 065 return null; 066 } 067 068 SQLSelectBuilder sql = new SQLSelectBuilder(TABLE_ENTRIES); 069 sql.addSelectColumns(SQL_SELECT_COLUMNS); 070 sql.addWhereClause(new AndClause(COLUMN_USER_ID, userId.getUserId(), SQLType.LONG)); 071 if(entityIds != null && !entityIds.isEmpty()){ 072 sql.addWhereClause(new AndClause(COLUMN_ENTITY_ID, entityIds, SQLType.STRING)); 073 } 074 List<Map<String, Object>> rows = getJdbcTemplate().queryForList(sql.toSQLString(), sql.getValues(), sql.getValueTypes()); 075 076 if(rows.isEmpty()){ 077 LOGGER.debug("No results."); 078 return null; 079 } 080 081 List<TwitterEntry> entries = new LinkedList<>(); 082 for(Map<String, Object> row : rows){ 083 entries.add(extractEntry(row)); 084 } 085 086 return entries; 087 } 088 089 /** 090 * 091 * @param row 092 * @return the entry extracted from the given row map 093 */ 094 private TwitterEntry extractEntry(Map<String, Object> row) { 095 TwitterEntry te = new TwitterEntry(); 096 for(Entry<String, Object> e : row.entrySet()){ 097 String column = e.getKey(); 098 switch(column){ 099 case COLUMN_GUID: 100 te.setGUID((String) e.getValue()); 101 break; 102 case COLUMN_USER_ID: 103 te.setUserId(new UserIdentity((Long) e.getValue())); 104 break; 105 case COLUMN_ENTITY_ID: 106 te.setEntityId((String)e.getValue()); 107 break; 108 case COLUMN_ENTITY_URL: 109 te.setEntityUrl((String) e.getValue()); 110 break; 111 case COLUMN_SCREEN_NAME: 112 te.setScreenName((String) e.getValue()); 113 break; 114 default: 115 LOGGER.warn("Ignored unknown column: "+column); 116 break; 117 } 118 } 119 return te; 120 } 121 122 /** 123 * 124 * @param screenNames optional screen name filter, if null or empty, the filter is ignored 125 * @param userId 126 * @return list of entries or null if none was found 127 */ 128 public List<TwitterEntry> getEntriesByScreenName(Collection<String> screenNames, UserIdentity userId) { 129 if(!UserIdentity.isValid(userId)){ 130 LOGGER.warn("Invalid userId."); 131 return null; 132 } 133 134 SQLSelectBuilder sql = new SQLSelectBuilder(TABLE_ENTRIES); 135 sql.addSelectColumns(SQL_SELECT_COLUMNS); 136 sql.addWhereClause(new AndClause(COLUMN_USER_ID, userId.getUserId(), SQLType.LONG)); 137 if(screenNames != null && !screenNames.isEmpty()){ 138 LOGGER.debug("Adding screen name filter..."); 139 sql.addWhereClause(new AndClause(COLUMN_SCREEN_NAME, screenNames, SQLType.STRING)); 140 } 141 142 List<Map<String, Object>> rows = getJdbcTemplate().queryForList(sql.toSQLString(), sql.getValues(), sql.getValueTypes()); 143 if(rows.isEmpty()){ 144 LOGGER.debug("No results."); 145 return null; 146 } 147 148 List<TwitterEntry> entries = new ArrayList<>(rows.size()); 149 for(Map<String, Object> row : rows){ 150 entries.add(extractEntry(row)); 151 } 152 return entries; 153 } 154 155 /** 156 * 157 * @param guid 158 * @return static URL for the given GUID or null if not found 159 */ 160 public String getUrl(String guid) { 161 Map<String, Object> rows = getJdbcTemplate().queryForMap(SQL_GET_URL, new Object[]{guid}, SQL_GET_URL_SQL_TYPES); 162 return (String) rows.get(COLUMN_ENTITY_URL); 163 } 164 165 /** 166 * 167 * @param guids 168 */ 169 public void removeEntries(Collection<String> guids) { 170 if(guids != null && !guids.isEmpty()){ 171 SQLDeleteBuilder sql = new SQLDeleteBuilder(TABLE_ENTRIES); 172 sql.addWhereClause(new AndClause(COLUMN_GUID, guids, SQLType.STRING)); 173 LOGGER.debug("Removed entries count: "+getJdbcTemplate().update(sql.toSQLString(), sql.getValues(), sql.getValueTypes())); 174 }else{ 175 LOGGER.debug("Empty GUID list."); 176 } 177 } 178 179 /** 180 * 181 * @param entries 182 */ 183 public void createEntries(Collection<TwitterEntry> entries) { 184 if(entries == null || entries.isEmpty()){ 185 LOGGER.debug("Ignored empty entry list."); 186 return; 187 } 188 Object[] ob = new Object[5]; 189 for(TwitterEntry e : entries){ 190 ob[0] = e.getGUID(); 191 ob[1] = e.getEntityId(); 192 ob[2] = e.getEntityUrl(); 193 ob[3] = e.getScreenName(); 194 ob[4] = e.getUserId().getUserId(); 195 getJdbcTemplate().update(SQL_CREATE_ENTRY, ob, SQL_CREATE_ENTRY_SQL_TYPES); 196 } 197 } 198}