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.fileservice;
017
018
019import java.util.ArrayList;
020import java.util.HashMap;
021import java.util.List;
022import java.util.Map;
023import java.util.Map.Entry;
024
025import org.apache.commons.lang3.ArrayUtils;
026import org.apache.log4j.Logger;
027import org.springframework.jdbc.core.simple.SimpleJdbcInsert;
028
029import core.tut.pori.dao.clause.AndClause;
030import core.tut.pori.dao.clause.SQLClause.SQLType;
031import core.tut.pori.dao.SQLDAO;
032import core.tut.pori.dao.SQLDeleteBuilder;
033import core.tut.pori.dao.SQLSelectBuilder;
034import core.tut.pori.http.parameters.Limits;
035import core.tut.pori.users.UserIdentity;
036
037/**
038 * DAO for saving, retrieving and modifying the details of saved files.
039 */
040public class FileDAO extends SQLDAO {
041  private static final Logger LOGGER = Logger.getLogger(FileDAO.class);
042  /* tables */
043  private static final String TABLE_FILES = DATABASE+".fs_files";
044  /* columns */
045  private static final String COLUMN_FILE_ID = "file_id";
046  private static final String COLUMN_ORIGINAL_NAME = "original_name";
047  private static final String COLUMN_SAVED_NAME = "saved_name";
048  /* sql scripts */
049  private static final String[] COLUMNS_GET_FILES = {COLUMN_FILE_ID, COLUMN_ORIGINAL_NAME, COLUMN_SAVED_NAME, COLUMN_USER_ID};
050  private static final String[] COLUMNS_SAVE_FILE = {COLUMN_ORIGINAL_NAME, COLUMN_SAVED_NAME, COLUMN_USER_ID};
051
052  private static final String SQL_DELETE_FILES_FOR_USER = "DELETE FROM "+TABLE_FILES+" WHERE "+COLUMN_USER_ID+"=?";
053  private static final int[] SQL_DELETE_FILES_FOR_USER_SQL_TYPES = {SQLType.LONG.toInt()};
054  
055  /**
056   * 
057   * @param file
058   */
059  public void save(File file) {
060    SimpleJdbcInsert insert = new SimpleJdbcInsert(getJdbcTemplate());
061    insert.withTableName(TABLE_FILES);
062    insert.withoutTableColumnMetaDataAccess();
063    insert.usingColumns(COLUMNS_SAVE_FILE);
064    insert.setGeneratedKeyName(COLUMN_FILE_ID);
065    
066    Map<String, Object> values = new HashMap<>(COLUMNS_SAVE_FILE.length);
067    values.put(COLUMN_ORIGINAL_NAME, file.getName());
068    values.put(COLUMN_SAVED_NAME, file.getSavedName());
069    values.put(COLUMN_USER_ID, file.getUserId().getUserId());
070    file.setFileId((Long) insert.executeAndReturnKey(values));
071  }
072
073  /**
074   * 
075   * @param authenticatedUser
076   * @param fileIds if null or empty, all files for the given user will be deleted
077   * @return list of deleted files or null if nothing was deleted
078   */
079  public FileList delete(UserIdentity authenticatedUser, long[] fileIds) {
080    FileList files = getFiles(authenticatedUser, fileIds, null);
081    if(FileList.isEmpty(files)){
082      LOGGER.debug("No files found.");
083      return null;
084    }
085    
086    if(ArrayUtils.isEmpty(fileIds)){
087      Object[] ob = new Object[]{authenticatedUser.getUserId()};
088      LOGGER.debug("Removed "+getJdbcTemplate().update(SQL_DELETE_FILES_FOR_USER, ob, SQL_DELETE_FILES_FOR_USER_SQL_TYPES)+" files for user, id: "+ob[0]);
089    }else{
090      List<File> fileList = files.getFiles();
091      List<Long> fileIdList = new ArrayList<>(fileList.size());
092      for(File file : fileList){
093        fileIdList.add(file.getFileId());
094      }
095      SQLDeleteBuilder sql = new SQLDeleteBuilder(TABLE_FILES);
096      sql.addWhereClause(new AndClause(COLUMN_FILE_ID, fileIdList, SQLType.LONG));
097      LOGGER.debug("Removed "+sql.execute(getJdbcTemplate())+" files for user, id: "+authenticatedUser.getUserId());
098    }
099    return files;
100  }
101
102  /**
103   * 
104   * @param authenticatedUser
105   * @param fileIds if null or empty, or users files will be returned
106   * @param limits optional limits parameter, if missing, all files will be returned
107   * @return list of files or null if none found
108   */
109  public FileList getFiles(UserIdentity authenticatedUser, long[] fileIds, Limits limits) {
110    SQLSelectBuilder sql = new SQLSelectBuilder(TABLE_FILES);
111    sql.addSelectColumns(COLUMNS_GET_FILES);
112    sql.addWhereClause(new AndClause(COLUMN_USER_ID, authenticatedUser.getUserId(), SQLType.LONG));
113    if(!ArrayUtils.isEmpty(fileIds)){
114      LOGGER.debug("Adding file id filter.");
115      sql.addWhereClause(new AndClause(COLUMN_FILE_ID, fileIds));
116    }
117    sql.setLimits(limits);
118    List<Map<String, Object>> rows = getJdbcTemplate().queryForList(sql.toSQLString(), sql.getValues(), sql.getValueTypes());
119    if(rows.isEmpty()){
120      LOGGER.debug("No files found.");
121      return null;
122    }
123    
124    List<File> files = new ArrayList<>(rows.size());
125    for(Map<String, Object> row : rows){
126      files.add(extractFile(row));
127    }
128    
129    return FileList.getFileList(files);
130  }
131  
132  /**
133   * 
134   * @param row
135   * @return file extracted from the given row map
136   */
137  private File extractFile(Map<String, Object> row){
138    File file = new File();
139    for(Entry<String, Object> e : row.entrySet()){
140      switch(e.getKey()){
141        case COLUMN_FILE_ID:
142          file.setFileId((Long) e.getValue());
143          break;
144        case COLUMN_ORIGINAL_NAME:
145          file.setName((String) e.getValue());
146          break;
147        case COLUMN_SAVED_NAME:
148          file.setSavedName((String) e.getValue());
149          break;
150        case COLUMN_USER_ID:
151          file.setUserId(new UserIdentity((Long) e.getValue()));
152          break;
153        default:
154          LOGGER.warn("Ignored unknown column: "+e.getKey());
155          break;
156      } // switch
157    }
158    return file;
159  }
160}