/*******************************************************************************
* Australian National University Data Commons
* Copyright (C) 2013 The Australian National University
*
* This file is part of Australian National University Data Commons.
*
* Australian National University Data Commons 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.
*
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
******************************************************************************/
package au.edu.anu.dcclient.collection;
import static java.text.MessageFormat.*;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.text.MessageFormat;
import java.util.HashSet;
import java.util.Set;
import javax.ws.rs.core.MultivaluedMap;
import org.apache.commons.io.IOUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.sun.jersey.core.util.MultivaluedMapImpl;
/**
* This class represents a Collection Info file. This class provides methods to read key value pairs from the collection information file.
*/
public class CollectionInfo
{
private static final Logger LOGGER = LoggerFactory.getLogger(CollectionInfo.class);
private static final String NEWLINE = System.getProperty("line.separator");
private final File sourceFile;
private File filesDir = null;
private String pid = null;
private final MultivaluedMap<String, String> createCollMap = new MultivaluedMapImpl();
private final Set<String[]> relationSet = new HashSet<String[]>();
/**
* Constructor that instantiates a CollectionInfo object for a specified Collection Information file.
*
* @param sourceFile
* Collection Info file to read data from
* @throws IOException
* when unable to read the collection information file
*/
public CollectionInfo(File sourceFile) throws IOException
{
if (!sourceFile.isFile())
throw new IOException(format("{0} is not a file.", sourceFile.getAbsolutePath()));
if (!sourceFile.canRead())
throw new IOException(format("Unable to read {0}. Ensure read permission.", sourceFile.getAbsolutePath()));
if (!sourceFile.canWrite())
throw new IOException(format("Unable to write {0}. Ensure write permission.", sourceFile.getAbsolutePath()));
this.sourceFile = sourceFile;
readMap(this.sourceFile);
}
/**
* Gets the pid as specified in the collection file. If not specified in file, null is returned.
*
* @return Pid as String if present in Collection Information file, null otherwise.
*/
public String getPid()
{
return pid;
}
/**
* Sets the pid only if it doesn't already exist in the collection.
*
* @param pid
* Pid as String
* @throws IOException
* when unable to write the Pid in the collection information file.
*/
public void setPid(String pid) throws IOException
{
if (createCollMap.containsKey("pid"))
{
LOGGER.warn("Pid already exists. Leaving Pid unchanged.");
return;
}
this.pid = pid;
createCollMap.add("pid", pid);
// Write pid to collection info file.
FileWriter writer = null;
try
{
writer = new FileWriter(this.sourceFile, true);
writer.write(format("{0}pid={1}{0}", NEWLINE, pid));
}
finally
{
IOUtils.closeQuietly(writer);
}
}
/**
* Gets the location of payload files.
*
* @return Location of payload files as File
*/
public File getFilesDir()
{
return filesDir;
}
/**
* Returns a {@code MultivaluedMap<String, String>} representation of the data in the collection information file.
*
* @return MultivaluedMap object
*/
public MultivaluedMap<String, String> getCreateCollMap()
{
return createCollMap;
}
/**
* Gets the list of relations specified in the collection file as a {@code Set<String[]>}. For each set element, the String[0] contains relationship type
* and String[1] contains the pid of the related record.
*
* @return
*/
public Set<String[]> getRelationSet()
{
return relationSet;
}
/**
* Reads the contents of the collection information file and parses it to extract data as key-value pairs.
*
* @param sourceFile
*
* @throws IOException
*/
private void readMap(File sourceFile) throws IOException
{
FileInputStream fis = null;
BufferedReader reader = null;
try
{
fis = new FileInputStream(sourceFile);
reader = new BufferedReader(new InputStreamReader(fis));
String line;
LOGGER.trace("File contents: ");
for (line = reader.readLine(); line != null; line = reader.readLine())
{
LOGGER.trace(line);
line = line.trim();
if (line.length() == 0)
continue;
// Skip if first character is '#'.
if (line.charAt(0) == '#')
continue;
// If '=' doesn't exist in line at all, skip line.
int equalsIndex = line.indexOf('=');
if (equalsIndex == -1)
continue;
String key = line.substring(0, equalsIndex).trim();
String value = line.substring(equalsIndex + 1).trim().replace("\\r\\n", "<br />");
// Skip line if key or value is ""
if (key.length() == 0 || value.length() == 0)
continue;
if (key.equalsIgnoreCase("files.dir"))
{
this.filesDir = new File(value);
if (!this.filesDir.exists() || !this.filesDir.isDirectory())
throw new IOException(MessageFormat.format("{0} doesn't exist or isn't a directory.", this.filesDir.getAbsolutePath()));
continue;
}
if (key.equalsIgnoreCase("pid"))
{
this.pid = value;
continue;
}
if (key.equalsIgnoreCase("relation"))
{
relationSet.add(value.split(",", 2));
continue;
}
createCollMap.add(key, value);
}
}
finally
{
IOUtils.closeQuietly(reader);
IOUtils.closeQuietly(fis);
}
}
}