/*******************************************************************************
* Copyright 2013 Ivan Shubin http://mindengine.net
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
******************************************************************************/
package net.mindengine.blogix.db;
import java.io.File;
import java.io.FileNotFoundException;
import java.util.LinkedList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import net.mindengine.blogix.db.readers.EntryReader;
import net.mindengine.blogix.db.readers.IdReader;
import net.mindengine.blogix.db.readers.ObjectReader;
import net.mindengine.blogix.db.readers.Reader;
public class FileDb<T1 extends Comparable<T1>> {
public static final String ENTRY_SUFFIX = ".blogix";
private File directory;
private final IdReader idConverter;
private final EntryReader entryConverter;
private final ObjectReader<T1> _objectConverter;
public FileDb(Class<T1> objectType, File directory) {
this.directory = directory;
if (!this.directory.exists() || !this.directory.isDirectory()) {
throw new IllegalArgumentException(directory.getAbsolutePath() + " does not exist or is not a directory");
}
idConverter = new IdReader(ENTRY_SUFFIX);
entryConverter = new EntryReader(directory, ENTRY_SUFFIX);
_objectConverter = new ObjectReader<T1>(objectType, entryConverter);
}
public Entry findEntryById(String id) {
return findByIdAndConvert(id, entryConverter);
}
public T1 findById(String id) {
return findByIdAndConvert(id, _objectConverter);
}
public EntryList<T1> findByFieldContaining(String fieldName, String value) {
List<Entry> entries = findEntriesByFieldContaining(fieldName, value);
return new EntryList<T1>(convertEntriesToObjects(entries));
}
private List<T1> convertEntriesToObjects(List<Entry> entries) {
List<T1> objects = new LinkedList<T1>();
for (Entry entry : entries) {
objects.add(_objectConverter.convert(entry));
}
return objects;
}
private <T> T findByIdAndConvert(String id, Reader<T> converter) {
if (id.endsWith("/")) {
id = trimSlashAtTheEnd(id);
}
String finalId = id + ENTRY_SUFFIX;
List<String> fileNames = allFilesInDirectory(directory);
for (String fileName : fileNames) {
if (fileName.equals(finalId)) {
return converter.convert(fileName);
}
}
return null;
}
private String trimSlashAtTheEnd(String id) {
return id.substring(0, id.length() - 1);
}
/**
* Scans recursively the specified directory and returns paths to all files.
* @param directory
* @param parentPath
* @return
*/
private List<String> allFilesInDirectory(File directory) {
List<String> paths = new LinkedList<String>();
File[] files = directory.listFiles();
for (File file : files) {
if (file.isFile()) {
paths.add(file.getName());
}
}
return paths;
}
public EntryList<String> findAllIds() {
return findAllByPattern(null, idConverter);
}
public EntryList<String> findAllIds(String patternText) {
return findAllByPattern(Pattern.compile(patternText), idConverter);
}
public EntryList<Entry> findAllEntries() {
return findAllByPattern(null, entryConverter);
}
public EntryList<Entry> findAllEntries(String patternText) {
return findAllByPattern(Pattern.compile(patternText), entryConverter);
}
public List<Entry> findEntriesByFieldContaining(String fieldName, String containingText) {
EntryList<Entry> entries = findAllEntries();
List<Entry> fetched = new LinkedList<Entry>();
for (Entry entry : entries) {
String fieldValue = entry.field(fieldName);
if (fieldValue != null && fieldValue.contains(containingText)) {
fetched.add(entry);
}
}
return fetched;
}
public EntryList<String> findAttachments(final String id) {
List<String> entries = new LinkedList<String>();
List<String> fileNames = allFilesInDirectory(directory);
for (String fileName : fileNames) {
if (!fileName.endsWith(ENTRY_SUFFIX)) {
if (fileName.startsWith(id)) {
entries.add(trimEntryIdFromAttachment(id, fileName));
}
}
}
return new EntryList<String>(entries);
}
private String trimEntryIdFromAttachment(String id, String fileName) {
return fileName.substring(id.length() + 1);
}
public EntryList<T1> findAll() {
return findAllByPattern(null, _objectConverter);
}
private <T extends Comparable<T>> EntryList<T> findAllByPattern(Pattern pattern, Reader<T> converter) {
List<T> entries = new LinkedList<T>();
List<String> fileNames = allFilesInDirectory(directory);
boolean checkPass;
for (String fileName : fileNames) {
checkPass = true;
if (fileName.endsWith(ENTRY_SUFFIX)) {
if (pattern != null) {
Matcher matcher = pattern.matcher(fileName);
if (!matcher.matches()) {
checkPass = false;
}
}
if (checkPass) {
T converted = converter.convert(fileName);
if (converted != null) {
entries.add(converted);
}
}
}
}
return new EntryList<T>(entries);
}
public File findAttachmentAsFile(String id, String fileName) throws FileNotFoundException {
String fullAttachmentName = id + "." + fileName;
File file = new File(directory.getAbsolutePath() + File.separator + fullAttachmentName);
if (file.exists()) {
return file;
}
else throw new FileNotFoundException(fullAttachmentName);
}
}