/*******************************************************************************
* Copyright (c) 2012 The PDT Extension Group (https://github.com/pdt-eg)
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
******************************************************************************/
package org.pdtextensions.repos;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.pdtextensions.repos.api.IDependency;
import org.pdtextensions.repos.api.IDownloadFileCallback;
import org.pdtextensions.repos.api.IDownloadStreamCallback;
import org.pdtextensions.repos.api.IModuleVersion;
/**
* Default implementation for module versions that already know their files.
*
* @author mepeisen
*/
public class ModuleVersion implements IModuleVersion {
private String moduleName;
private String vendorName;
private String name;
private boolean isRelease;
private Map<String, IFileDownload> files = new HashMap<String, IFileDownload>();
private String primaryFile;
private List<IDependency> dependencies;
private List<IDependency> deepDependencies;
private IDependencyLoader dependencyLoader;
/**
* Constructor for implementations that are knowing their files
* @param vendor
* @param module
* @param name
* @param isRelease
* @param files
* @param primaryFileName may be null if there are no files
* @param depLoader helper to load the dependencies; maybe null if no dependencies are available
*/
public ModuleVersion(String vendor, String module, String name, boolean isRelease, Map<String, IFile> files, String primaryFileName, IDependencyLoader depLoader) {
this.moduleName = module;
this.vendorName = vendor;
this.name = name;
this.isRelease = isRelease;
this.files = new HashMap<String, IFileDownload>();
for (final Map.Entry<String, IFile> entry : files.entrySet()) {
this.files.put(entry.getKey(), new FileWrapper(entry.getValue()));
}
this.primaryFile = primaryFileName;
this.dependencyLoader = depLoader;
}
/**
* Constructor for implementations that are knowing their files
* @param vendor
* @param module
* @param name
* @param isRelease
* @param primaryFileName may be null if there are no files
* @param primaryFile may be null if there are no files
* @param depLoader helper to load the dependencies; maybe null if no dependencies are available
*/
public ModuleVersion(String vendor, String module, String name, boolean isRelease, String primaryFileName, IFile primaryFile, IDependencyLoader depLoader) {
this.moduleName = module;
this.vendorName = vendor;
this.isRelease = isRelease;
this.files = new HashMap<String, IFileDownload>();
if (primaryFileName != null) {
this.files.put(primaryFileName, new FileWrapper(primaryFile));
}
this.primaryFile = primaryFileName;
this.dependencyLoader = depLoader;
}
/**
* Constructor for implementations that are aware or loading the files on demand
* @param vendor
* @param module
* @param name
* @param isRelease
* @param depLoader helper to load the dependencies; maybe null if no dependencies are available
*/
protected ModuleVersion(String vendor, String module, String name, boolean isRelease, IDependencyLoader depLoader) {
this.moduleName = module;
this.vendorName = vendor;
this.name = name;
this.isRelease = isRelease;
this.dependencyLoader = depLoader;
}
/**
* Method to load the files; must be overwritten by implementations that are aware of loading the files on demand
* @return files map; must not be null
* @throws CoreException thrown on errors.
*/
protected Map<String, IFileDownload> loadFiles() throws CoreException {
return null;
}
/**
* Init the modules
* @throws CoreException thrown on errors.
*/
private void init() throws CoreException {
if (this.files == null) {
this.files = new HashMap<String, IFileDownload>();
this.files = this.loadFiles();
this.primaryFile = this.loadPrimaryFile();
}
}
/**
* Calculates the name of the primary file
* @return primary file name or {@code null} if there is no primary file
* @throws CoreException thrown on errors
*/
protected String loadPrimaryFile() throws CoreException {
return null;
}
@Override
public String getModuleName() {
return this.moduleName;
}
@Override
public String getVendorName() {
return this.vendorName;
}
@Override
public String getName() {
return this.name;
}
@Override
public boolean isRelease() {
return this.isRelease;
}
@Override
public boolean isDevelopment() {
return !this.isRelease;
}
@Override
public Iterable<String> getFiles(IProgressMonitor monitor) throws CoreException {
this.init();
return new ArrayList<String>(this.files.keySet());
}
@Override
public String getPrimaryFile(IProgressMonitor monitor) throws CoreException {
this.init();
return this.primaryFile;
}
@Override
public IFile download(String name, boolean useCache,
IProgressMonitor monitor) throws CoreException {
this.init();
final IFileDownload download = this.files.get(name);
if (download != null) {
return download.download(useCache, monitor);
}
return null;
}
@Override
public InputStream openStream(String name, boolean useCache,
IProgressMonitor monitor) throws CoreException {
this.init();
final IFileDownload download = this.files.get(name);
if (download != null) {
return download.openStream(useCache, monitor);
}
return null;
}
public interface IFileDownload {
IFile download(boolean useCache, IProgressMonitor monitor) throws CoreException;
InputStream openStream(boolean useCache, IProgressMonitor monitor) throws CoreException;
}
public static final class FileWrapper implements IFileDownload {
private IFile file;
public FileWrapper(IFile file) {
this.file = file;
}
@Override
public IFile download(boolean useCache, IProgressMonitor monitor) throws CoreException {
return file;
}
@Override
public InputStream openStream(boolean useCache, IProgressMonitor monitor)
throws CoreException {
return file.getContents();
}
}
/**
* Dependency loader.
*/
public interface IDependencyLoader {
/**
* Loads direct dependencies
* @param monitor progress monitor
* @return result; should be null if the monitor was canceled.
* @throws CoreException
*/
List<IDependency> loadDependencies(IProgressMonitor monitor) throws CoreException;
/**
* Loads deep dependencies
* @param monitor progress monitor
* @return result; should be null if the monitor was canceled.
* @throws CoreException
*/
List<IDependency> loadDeepDependencies(IProgressMonitor monitor) throws CoreException;
}
@SuppressWarnings("unchecked")
@Override
public Iterable<IDependency> getDependencies(boolean deep,
IProgressMonitor monitor) throws CoreException {
if (deep) {
if (this.deepDependencies == null) {
if (this.dependencyLoader == null) {
return Collections.EMPTY_LIST;
}
this.deepDependencies = this.dependencyLoader.loadDeepDependencies(monitor);
}
return Collections.unmodifiableList(this.deepDependencies);
}
if (this.dependencies == null) {
if (this.dependencyLoader == null) {
return Collections.EMPTY_LIST;
}
this.dependencies = this.dependencyLoader.loadDependencies(monitor);
}
return Collections.unmodifiableList(this.dependencies);
}
@Override
public void downloadDependencies(boolean deep, boolean useCache,
IProgressMonitor monitor, IDownloadFileCallback callback)
throws CoreException {
for (final IDependency dep : this.getDependencies(deep, monitor)) {
if (monitor.isCanceled()) {
return;
}
callback.onDependency(dep.download(useCache, monitor), this, dep, monitor);
}
}
@Override
public void openDependenciesStream(boolean deep, boolean useCache,
IProgressMonitor monitor, IDownloadStreamCallback callback)
throws CoreException {
for (final IDependency dep : this.getDependencies(deep, monitor)) {
if (monitor.isCanceled()) {
return;
}
callback.onDependency(dep.openStream(useCache, monitor), this, dep, monitor);
}
}
}