/* * Copyright 2011-16 Fraunhofer ISE * * This file is part of OpenMUC. * For more information visit http://www.openmuc.org * * OpenMUC 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. * * OpenMUC 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 OpenMUC. If not, see <http://www.gnu.org/licenses/>. * */ package org.openmuc.framework.datalogger.slotsdb; import java.io.File; import java.io.IOException; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.List; import java.util.Vector; /** * Class representing a folder in a SlotsDatabase.<br> * <br> * ./rootnode/20110129/ID1/1298734198000.opm <br> * /1298734598000.opm <br> * /ID2/ <br> * /20110130/ID1/ <br> * /ID2/ <br> * <br> * Usually there is only 1 File in a Folder/FileObjectList<br> * But there might be more then 1 file in terms of reconfiguration.<br> * <br> * */ public final class FileObjectList { private List<FileObject> files; // private File folder; private String foldername; private long firstTS; private int size; /** * Creates a FileObjectList<br> * and creates a FileObject for every File * * @param foldername * name of the folder * @throws IOException * if an I/O error occurs. */ public FileObjectList(String foldername) throws IOException { // File folder = new File(foldername); this.foldername = foldername; reLoadFolder(foldername); } /** * Reloads the List * * @param foldername * containing Files * @throws IOException * if an I/O error occurs. */ public void reLoadFolder(String foldername) throws IOException { this.foldername = foldername; reLoadFolder(); } /** * Reloads the List * * @throws IOException * if an I/O error occurs. */ public void reLoadFolder() throws IOException { File folder = new File(foldername); files = new Vector<>(1); if (folder.isDirectory()) { for (File file : folder.listFiles()) { if (file.length() >= 16) { // otherwise is corrupted or empty // file. String[] split = file.getName().split("\\."); if (("." + split[split.length - 1]).equals(SlotsDb.FILE_EXTENSION)) { files.add(new FileObject(file)); } } else { file.delete(); } } if (files.size() > 1) { sortList(files); } } size = files.size(); /* * set first Timestamp for this FileObjectList if there are no files -> first TS = TS@ 00:00:00 o'clock. */ if (size == 0) { SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd"); try { sdf.parse(folder.getParentFile().getName()); } catch (ParseException e) { throw new IOException("Unable to parse Timestamp from folder: " + folder.getParentFile().getName() + ". Expected Folder in yyyyMMdd Format!"); } firstTS = sdf.getCalendar().getTimeInMillis(); } else { firstTS = files.get(0).getStartTimeStamp(); } folder = null; } /* * bubble sort to sort files in directory. usually there is only 1 file, might be 2... will also work for more. but * not very fast. */ private void sortList(List<FileObject> toSort) { int j = 0; FileObject tmp; boolean switched = true; while (switched) { switched = false; j++; for (int i = 0; i < toSort.size() - j; i++) { if (toSort.get(i).getStartTimeStamp() > toSort.get(i + 1).getStartTimeStamp()) { tmp = toSort.get(i); toSort.set(i, toSort.get(i + 1)); toSort.set(i + 1, tmp); switched = true; } } } } /** * Returns the last created FileObject * * @return last created FileObject */ public FileObject getCurrentFileObject() { return get(size - 1); } /** * Returns the File Object at any position in list. * * @param position * position as int * @return FileObject at position */ public FileObject get(int position) { return files.get(position); } /** * Returns the size (Number of Files in this Folder/FileObjectList) * * @return number of FileObjects */ public int size() { return size; } /** * Closes all files in this List. This will also cause DataOutputStreams to be flushed. * * @throws IOException * if an I/O error occurs. */ public void closeAllFiles() throws IOException { for (FileObject f : files) { f.close(); } } /** * Returns a FileObject in this List for a certain Timestamp. If there is no FileObject containing this Value, null * will be returned. * * @param timestamp * the timestamp of the FileObject * @return FileObject of timestamp */ public FileObject getFileObjectForTimestamp(long timestamp) { if (files.size() > 1) { for (FileObject f : files) { if (f.getStartTimeStamp() <= timestamp && f.getTimestampForLatestValue() >= timestamp) { // File // found! return f; } } } else if (files.size() == 1) { if (files.get(0).getStartTimeStamp() <= timestamp && files.get(0).getTimestampForLatestValue() >= timestamp) { // contains // this // TS return files.get(0); } } return null; } /** * Returns All FileObject in this List, which contain Data starting at given timestamp. * * @param timestamp * timestamp of FileObjects * @return list of all FileObjects with timestamp */ public List<FileObject> getFileObjectsStartingAt(long timestamp) { List<FileObject> toReturn = new Vector<>(1); for (int i = 0; i < files.size(); i++) { if (files.get(i).getTimestampForLatestValue() >= timestamp) { toReturn.add(files.get(i)); } } return toReturn; } /** * Returns all FileObjects in this List. * * @return list of all FileObjects */ public List<FileObject> getAllFileObjects() { return files; } /** * Returns all FileObjects which contain Data before ending at given timestamp. * * @param timestamp * time stamp * @return FileObject until timestamp */ public List<FileObject> getFileObjectsUntil(long timestamp) { List<FileObject> toReturn = new Vector<>(1); for (int i = 0; i < files.size(); i++) { if (files.get(i).getStartTimeStamp() <= timestamp) { toReturn.add(files.get(i)); } } return toReturn; } /** * Returns all FileObjects which contain Data from start to end timestamps * * @param start * start time stamp * @param end * end time stamp * @return all FileObject between start and end */ public List<FileObject> getFileObjectsFromTo(long start, long end) { List<FileObject> toReturn = new Vector<>(1); if (files.size() > 1) { for (int i = 0; i < files.size(); i++) { if ((files.get(i).getStartTimeStamp() <= start && files.get(i).getTimestampForLatestValue() >= start) || (files.get(i).getStartTimeStamp() <= end && files.get(i).getTimestampForLatestValue() >= end) || (files.get(i).getStartTimeStamp() >= start && files.get(i).getTimestampForLatestValue() <= end)) { // needed files. toReturn.add(files.get(i)); } } } else if (files.size() == 1) { if (files.get(0).getStartTimeStamp() <= end && files.get(0).getTimestampForLatestValue() >= start) { // contains // this // TS toReturn.add(files.get(0)); } } return toReturn; } /** * Returns first recorded timestamp of oldest FileObject in this list. If List is empty, this timestamp will be set * to 00:00:00 o'clock * * @return first time stamp of oldest FileObject */ public long getFirstTS() { return firstTS; } /** * Flushes all FileObjects in this list. * * @throws IOException * if an I/O error occurs. */ public void flush() throws IOException { for (FileObject f : files) { f.flush(); } } }