/*
* Copyright (c) 2012 Data Harmonisation Panel
*
* All rights reserved. This program and the accompanying materials are made
* available under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation, either version 3 of the License,
* or (at your option) any later version.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution. If not, see <http://www.gnu.org/licenses/>.
*
* Contributors:
* HUMBOLDT EU Integrated Project #030962
* Data Harmonisation Panel <http://www.dhpanel.eu>
*/
package eu.esdihumboldt.hale.common.core.io.project;
import java.io.File;
import java.io.FileFilter;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import org.eclipse.core.runtime.content.IContentType;
import de.fhg.igd.osgi.util.configuration.AbstractConfigurationService;
import de.fhg.igd.osgi.util.configuration.IConfigurationService;
import eu.esdihumboldt.hale.common.core.io.HaleIO;
import eu.esdihumboldt.hale.common.core.io.Value;
import eu.esdihumboldt.hale.common.core.io.extension.IOProviderDescriptor;
import eu.esdihumboldt.hale.common.core.io.project.extension.ProjectFileExtension;
import eu.esdihumboldt.hale.common.core.io.project.extension.ProjectFileFactory;
import eu.esdihumboldt.hale.common.core.io.project.model.Project;
import eu.esdihumboldt.hale.common.core.io.project.model.ProjectFile;
import eu.esdihumboldt.hale.common.core.io.supplier.FileIOSupplier;
import eu.esdihumboldt.hale.common.core.service.ServiceProvider;
/**
* Common utilities and constants regarding project I/O
*
* @author Simon Templer
*/
public abstract class ProjectIO {
/**
* Configuration service wrapper for a project.
*/
private static class ProjectConfigServiceWrapper extends AbstractConfigurationService implements
ComplexConfigurationService {
private final Project _project;
/**
* Create a configuration service based on the given project.
*
* @param project the project
*/
public ProjectConfigServiceWrapper(Project project) {
_project = project;
}
@Override
protected void setValue(String key, String value) {
_project.getProperties().put(key, Value.of(value));
}
@Override
protected void removeValue(String key) {
_project.getProperties().remove(key);
}
@Override
protected String getValue(String key) {
Value value = _project.getProperties().get(key);
return (value != null) ? (value.as(String.class)) : (null);
}
@Override
public void setProperty(String name, Value value) {
if (value == null || value.getValue() == null) {
_project.getProperties().remove(name);
}
else {
_project.getProperties().put(name, value);
}
}
@Override
public Value getProperty(String name) {
Value value = _project.getProperties().get(name);
return (value != null) ? (value) : (Value.NULL);
}
}
/**
* Project file default type name
*/
public static final String PROJECT_TYPE_NAME = "HALE project";
/**
* Name of the internal project file
*/
public static final String PROJECT_FILE = "project.xml";
/**
* Identifier of the HALE project archive content type
*/
public static final String PROJECT_ARCHIVE_CONTENT_TYPE_ID = "eu.esdihumboldt.hale.io.project.hale25.zip";
/**
* Create a set of default project files for use with {@link ProjectReader}
* and {@link ProjectWriter}
*
* @param serviceProvider the service provider to use for eventual I/O
* advisors created
* @return the default project files
*/
public static Map<String, ProjectFile> createDefaultProjectFiles(ServiceProvider serviceProvider) {
Map<String, ProjectFile> result = new HashMap<String, ProjectFile>();
Collection<ProjectFileFactory> elements = new ProjectFileExtension(serviceProvider)
.getElements();
for (ProjectFileFactory element : elements) {
result.put(element.getId(), element.createProjectFile());
}
return result;
}
/**
* Create an {@link IConfigurationService} from a given project.
*
* @param project the project
* @return the configuration service to access the project's properties
*/
public static ComplexConfigurationService createProjectConfigService(final Project project) {
return new ProjectConfigServiceWrapper(project);
}
/**
* Find the HALE project file in a directory. If there are multiple it will
* only find one.
*
* @param projectDir the project directory
* @return the name of the project file candidate in that directory,
* <code>null</code> if none was found
*/
public static String findProjectFile(File projectDir) {
return findProjectFile(projectDir, null);
}
/**
* Find the HALE project file in a directory. If there are multiple it will
* only find one.
*
* @param projectDir the project directory
* @param supportedExtensions the set of supported extensions, each with a
* leading dot, or <code>null</code> if the supported extensions
* should be determined automatically
* @return the name of the project file candidate in that directory,
* <code>null</code> if none was found
*/
public static String findProjectFile(File projectDir, Set<String> supportedExtensions) {
final Set<String> extensions;
if (supportedExtensions == null) {
extensions = getSupportedExtensions();
}
else {
extensions = supportedExtensions;
}
File[] candidates = projectDir.listFiles(new FileFilter() {
@Override
public boolean accept(File file) {
if (file.isFile() && !file.isHidden()) {
String lowerName = file.getName().toLowerCase();
for (String extension : extensions) {
if (lowerName.endsWith(extension.toLowerCase())) {
return true;
}
}
}
return false;
}
});
if (candidates != null) {
if (candidates.length == 1) {
return candidates[0].getName();
}
// more than one candidate, do a more thorough check
// TODO warn that there are multiple?
for (File candidate : candidates) {
FileIOSupplier supplier = new FileIOSupplier(candidate);
// find content type against stream
IContentType contentType = HaleIO.findContentType(ProjectReader.class, supplier,
null);
if (contentType != null) {
return candidate.getName();
}
}
}
// none found? check in subdirectories
File[] subdirs = projectDir.listFiles(new FileFilter() {
@Override
public boolean accept(File pathname) {
return pathname.isDirectory() && !pathname.isHidden();
}
});
if (subdirs != null) {
for (File subdir : subdirs) {
String name = findProjectFile(subdir, extensions);
if (name != null) {
return subdir.getName() + "/" + name;
}
}
}
return null;
}
/**
* Get the supported file extensions for projects.
*
* @return the set of file extensions (with leading dot)
*/
private static Set<String> getSupportedExtensions() {
Collection<IOProviderDescriptor> providers = HaleIO
.getProviderFactories(ProjectReader.class);
// collect supported content types
Set<String> supportedExtensions = new HashSet<String>();
for (IOProviderDescriptor factory : providers) {
for (IContentType type : factory.getSupportedTypes()) {
String[] extensions = type.getFileSpecs(IContentType.FILE_EXTENSION_SPEC);
if (extensions != null) {
for (String ext : extensions) {
supportedExtensions.add('.' + ext);
}
}
}
}
return supportedExtensions;
}
}