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

org.daisy.streamline.api.config.Inventory Maven / Gradle / Ivy

The newest version!
package org.daisy.streamline.api.config;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.nio.file.Files;
import java.nio.file.StandardCopyOption;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.stream.Collectors;

final class Inventory implements Serializable {
	/**
	 * 
	 */
	private static final long serialVersionUID = 1189329230377507983L;
	private static final Logger logger = Logger.getLogger(Inventory.class.getCanonicalName());
	private HashMap configs;
	private Long index;
	
	Inventory() {
		this.configs = new HashMap<>();
		this.index = 0l;
	}

	/**
	 * Gets the inventory identifiers.
	 * @return a set of identifiers
	 */
	Set keys() {
		return Collections.unmodifiableSet(configs.keySet());
	}
	
	/**
	 * Gets the inventory entries.
	 * @return a collection of entries
	 */
	Collection entries() {
		return Collections.unmodifiableCollection(configs.values());
	}
	
	/**
	 * Gets the entry with the specified key.
	 * @param key the key
	 * @return returns the corresponding entry
	 */
	InventoryEntry get(String key) {
		return configs.get(key);
	}

	/**
	 * Adds a new entry to the inventory.
	 * @param entry the entry 
	 */
	void add(InventoryEntry entry) {
		configs.put(entry.getIdentifier(), entry);
	}

	/**
	 * Removes the entry with the specified key.
	 * @param key the key
	 * @return returns the removed entry
	 */
	InventoryEntry remove(String key) {
		InventoryEntry ret = configs.remove(key);
		if (ret!=null) {
			ret.getPath().delete();
		}
		return ret;
	}

	/**
	 * Gets the current index.
	 * @return the current index
	 */
	long getIndex() {
		return index;
	}

	synchronized String nextIdentifier() {
		index++;
		return this.getClass().getCanonicalName()+"_"+index;
	}

	/**
	 * Removes configurations with mismatching identifiers. 
	 * @return a list of configurations with mismatching identifiers
	 */
	List removeMismatching() {
		// List mismatching
		List mismatching = configs.values().stream()
			.filter(v->
				(v.getConfiguration().isPresent()
				&& !v.getIdentifier().equals(v.getConfiguration().get().getDetails().getKey()))
			).collect(Collectors.toList());
		// Remove from inventory
		mismatching.forEach(v->configs.remove(v.getIdentifier()));
		// Return the list of removed configurations 
		return mismatching.stream()
				.map(v->v.getConfiguration().get())
				.collect(Collectors.toList());
	}
	
	/**
	 * Removes entries whose configurations are unreadable from the inventory.
	 * @return the list of entries removed from the inventory
	 */
	List removeUnreadable() {
		// List unreadable
		List unreadable = configs.values()
				.stream()
				.filter(v->!v.getConfiguration().isPresent())
				.collect(Collectors.toList());
		// Remove from inventory
		unreadable.forEach(v->configs.remove(v.getIdentifier()));
		// Return the list of removed files
		return unreadable.stream()
				.map(v->v.getPath())
				.collect(Collectors.toList());
	}

	/**
	 * Creates a new inventory from the specified file. See also {@link #write(File)}.
	 * @param catalog the file containing the inventory
	 * @return a new inventory instance
	 * @throws IOException if the file could not be read
	 */
	static Inventory read(File catalog) throws IOException {
		try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream(catalog))) {
			return (Inventory)ois.readObject();
		} catch (IOException | ClassNotFoundException e) {
			throw new IOException("Failed to read/update file: " + catalog, e);
		}
	}
	
	/**
	 * Writes the inventory to the specified file. See also {@link #read(File)}.
	 * @param prefix the file prefix for a temporary backup file
	 * @param catalog the file to write to
	 * @throws IOException if the file could not be updated
	 */
	void write(String prefix, File catalog) throws IOException {
		File backup = File.createTempFile(prefix, null, catalog.getParentFile());
		if (catalog.exists()) {
			// Create a copy of the current state
			Files.copy(catalog.toPath(), backup.toPath(), StandardCopyOption.REPLACE_EXISTING);
		}

		// Update the file
		try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(catalog))) {
			oos.writeObject(this);
			backup.delete();
		} catch (IOException e) {
			try {
				Files.move(backup.toPath(), catalog.toPath(), StandardCopyOption.ATOMIC_MOVE);
			} catch (IOException e2) {
				logger.log(Level.INFO, "A backup has been saved at: " + backup, e2);
			}
			throw new IOException("Failed to update file: " + catalog, e);
		}
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy