All Downloads are FREE. Search and download functionalities are using the official Maven repository.

step.core.collections.filesystem.FilesystemCollection Maven / Gradle / Ivy

There is a newer version: 2.1.0
Show newest version
/*******************************************************************************
 * Copyright (C) 2020, exense GmbH
 *  
 * This file is part of STEP
 *  
 * STEP is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *  
 * STEP 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 Affero General Public License for more details.
 *  
 * You should have received a copy of the GNU Affero General Public License
 * along with STEP.  If not, see .
 ******************************************************************************/
package step.core.collections.filesystem;

import java.io.File;
import java.io.IOException;
import java.util.*;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;

import org.bson.types.ObjectId;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.dataformat.yaml.YAMLFactory;
import com.fasterxml.jackson.dataformat.yaml.YAMLGenerator;

import step.core.accessors.DefaultJacksonMapperProvider;
import step.core.collections.*;
import step.core.collections.Collection;
import step.core.collections.PojoFilters.PojoFilterFactory;

public class FilesystemCollection extends AbstractCollection implements Collection {

	private static final String FILE_EXTENSION = ".entity";
	private final ObjectMapper mapper;
	private final File repository;
	private final Class entityClass;

	public FilesystemCollection(File repository, Class entityClass) {
		super();
		this.repository = repository;
		this.entityClass = entityClass;
		YAMLFactory factory = new YAMLFactory();
		// Disable native type id to enable conversion to generic Documents
		factory.disable(YAMLGenerator.Feature.USE_NATIVE_TYPE_ID);
		this.mapper = DefaultJacksonMapperProvider.getObjectMapper(factory);
		if (!repository.exists()) {
			repository.mkdirs();
		}
	}

	@Override
	public List distinct(String columnName, Filter filter) {
		// TODO Auto-generated method stub
		return null;
	}
	
	private static class FileAndEntity {
		
		private final File file;
		private final T entity;
		
		public FileAndEntity(File file, T entity) {
			super();
			this.file = file;
			this.entity = entity;
		}

		public File getFile() {
			return file;
		}

		public T getEntity() {
			return entity;
		}
	}
	
	private Stream> entityStream() {
		return Arrays.asList(repository.listFiles(f -> f.getName().endsWith(FILE_EXTENSION))).stream().map(f->new FileAndEntity<>(f, readFile(f)));
	}

	@Override
	public long count(Filter filter, Integer limit) {
		Stream stream = find(filter, null, null, null, 0);
		if(limit != null) {
			stream = stream.limit(limit);
		}
		return stream.count();
	}

	@Override
	public long estimatedCount() {
		return repository.list().length;
	}
	
	@Override
	public Stream find(Filter filter, SearchOrder order, Integer skip, Integer limit, int maxTime) {
		Stream stream = filteredStream(filter).map(FileAndEntity::getEntity).sorted(new Comparator() {
			@Override
			public int compare(T o1, T o2) {
				return getId(o1).compareTo(getId(o2));
			}
		});
		if(order != null) {
			@SuppressWarnings("unchecked")
			Comparator comparing = (Comparator) PojoUtils.comparator(order.getAttributeName());
			if(order.getOrder()<0) {
				comparing = comparing.reversed();
			}
			stream = stream.sorted(comparing);
		}
		if(skip != null) {
			stream = stream.skip(skip);
		}
		if(limit != null) {
			stream = stream.limit(limit);
		}
		return stream;
	}

	@Override
	public Stream findReduced(Filter filter, SearchOrder order, Integer skip, Integer limit, int maxTime, List reduceFields) {
		return find(filter, order, skip, limit, maxTime);
	}

	private Stream> filteredStream(Filter filter) {
		PojoFilter pojoFilter = new PojoFilterFactory().buildFilter(filter);
		Iterator> it = entityStream().iterator();
		Spliterator> spliterator = Spliterators.spliteratorUnknownSize(it, 0);
		Stream> filter2 = StreamSupport.stream(spliterator, false).filter(f-> {
			return pojoFilter.test(f.entity);
		});
		return filter2;
	}

	@Override
	public void remove(Filter filter) {
		filteredStream(filter).forEach(f->{
			f.getFile().delete();
		});
	}

	@Override
	public T save(T entity) {
		if (getId(entity) == null) {
			setId(entity, new ObjectId());
		}
		File file = getFile(entity);
		writeEntity(entity, file);
		return entity;
	}

	@Override
	public void save(Iterable entities) {
		if (entities != null) {
			entities.forEach(e -> save(e));
		}
	}
	
	private T readFile(File file) {
		try {
			return mapper.readValue(file, entityClass);
		} catch (IOException e) {
			throw new FilesystemCollectionException("The file '" + file.getAbsolutePath() + " could not be read", e);
		}
	}
	
	private void writeEntity(T entity, File file) {
		try {
			mapper.writeValue(file, entity);
		} catch (IOException e) {
			throw new FilesystemCollectionException(e);
		}
	}

	private File getFile(T entity) {
		ObjectId id = getId(entity);
		File file = getFileById(id);
		return file;
	}

	private File getFileById(ObjectId id) {
		String filename = id.toString() + FILE_EXTENSION;
		File file = new File(repository.getAbsolutePath() + "/" + filename);
		return file;
	}

	@Override
	public void createOrUpdateIndex(String field) {
		// not supported
	}

	@Override
	public void createOrUpdateIndex(String field, int order) {
		// not supported
	}

	@Override
	public void createOrUpdateCompoundIndex(String... fields) {
		// not supported
	}

	@Override
	public void createOrUpdateCompoundIndex(Map fields) {
		// not supported
	}

	@Override
	public void rename(String newName) {
		// TODO Auto-generated method stub
	}

	@Override
	public void drop() {
		// TODO Auto-generated method stub
		
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy