package io.sloeber.core.api;
import java.io.File;
import java.io.FileReader;
import java.io.Reader;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import java.util.TreeSet;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.MultiStatus;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.Status;
import com.google.gson.Gson;
import io.sloeber.core.Activator;
import io.sloeber.core.common.Common;
import io.sloeber.core.common.InstancePreferences;
import io.sloeber.core.managers.Library;
import io.sloeber.core.managers.LibraryIndex;
import io.sloeber.core.managers.Manager;
import io.sloeber.core.managers.Messages;
import io.sloeber.core.tools.Version;
public class LibraryManager {
static private List<LibraryIndex> libraryIndices;
static public List<LibraryIndex> getLibraryIndices() {
if (libraryIndices == null) {
Manager.getPackageIndices();
}
return libraryIndices;
}
public static LibraryTree getLibraryTree() {
return new LibraryTree();
}
public static class LibraryTree {
private TreeMap<String, Category> categories = new TreeMap<>();
public class Category implements Comparable<Category>, Node {
private String name;
protected TreeMap<String, Library> libraries = new TreeMap<>();
public Category(String name) {
this.name = name;
}
@Override
public String getName() {
return this.name;
}
public Collection<Library> getLibraries() {
return this.libraries.values();
}
@Override
public int compareTo(Category other) {
return this.name.compareTo(other.name);
}
@Override
public boolean hasChildren() {
return !this.libraries.isEmpty();
}
@Override
public Object[] getChildren() {
return this.libraries.values().toArray();
}
@Override
public Object getParent() {
return LibraryTree.this;
}
}
public class Library implements Comparable<Library>, Node {
private String name;
private String indexName;
private Category category;
protected TreeSet<VersionNumber> versions = new TreeSet<>();
protected String version;
private String tooltip;
public Library(Category category, String name, String indexName, String tooltip) {
this.category = category;
this.name = name;
this.tooltip = tooltip;
this.indexName = indexName;
}
public Collection<VersionNumber> getVersions() {
return this.versions;
}
@Override
public String getName() {
return this.name;
}
public String getTooltip() {
return this.tooltip;
}
public String getLatest() {
return this.versions.last().toString();
}
public String getVersion() {
return this.version;
}
public String getIndexName() {
return this.indexName;
}
public void setVersion(String version) {
this.version = version;
}
@Override
public int compareTo(Library other) {
return this.name.compareTo(other.name);
}
@Override
public boolean hasChildren() {
return false;
}
@Override
public Object[] getChildren() {
return null;
}
@Override
public Object getParent() {
return this.category;
}
}
public LibraryTree() {
for (LibraryIndex libraryIndex : getLibraryIndices()) {
for (String categoryName : libraryIndex.getCategories()) {
Category category = this.categories.get(categoryName);
if (category == null) {
category = new Category(categoryName);
this.categories.put(category.getName(), category);
}
for (io.sloeber.core.managers.Library library : libraryIndex.getLibraries(categoryName)) {
Library lib = category.libraries.get(library.getName() + " (" + libraryIndex.getName() + ")"); //$NON-NLS-1$ //$NON-NLS-2$
if (lib == null) {
StringBuilder builder = new StringBuilder("Architectures:") //$NON-NLS-1$
.append(library.getArchitectures().toString()).append("\n\n") //$NON-NLS-1$
.append(library.getSentence());
lib = new Library(category, library.getName(), libraryIndex.getName(), builder.toString());
category.libraries.put(library.getName() + " (" + libraryIndex.getName() + ")", lib); //$NON-NLS-1$//$NON-NLS-2$
}
lib.versions.add(new VersionNumber(library.getVersion()));
if (library.isInstalled()) {
lib.version = library.getVersion();
}
}
}
}
}
public Collection<Category> getCategories() {
return this.categories.values();
}
public Collection<Library> getAllLibraries() {
Set<Library> all = new TreeSet<>();
for (Category category : this.categories.values()) {
all.addAll(category.getLibraries());
}
return all;
}
private static LibraryIndex findLibraryIndex(String name) {
for (LibraryIndex libraryIndex : getLibraryIndices()) {
if (libraryIndex.getName().equals(name))
return libraryIndex;
}
return null;
}
public void reset() {
for (Library library : this.getAllLibraries()) {
LibraryIndex libraryIndex = findLibraryIndex(library.getIndexName());
if (libraryIndex != null) {
io.sloeber.core.managers.Library installed = libraryIndex.getInstalledLibrary(library.getName());
library.setVersion(installed != null ? installed.getVersion() : null);
}
}
}
}
public static IStatus setLibraryTree(LibraryTree libs, IProgressMonitor monitor, MultiStatus status) {
for (LibraryTree.Library lib : libs.getAllLibraries()) {
LibraryIndex libraryIndex = getLibraryIndex(lib.getIndexName());
if (libraryIndex != null) {
io.sloeber.core.managers.Library toRemove = libraryIndex.getInstalledLibrary(lib.getName());
if (toRemove != null && !toRemove.getVersion().equals(lib.getVersion())) {
status.add(toRemove.remove(monitor));
}
io.sloeber.core.managers.Library toInstall = libraryIndex.getLibrary(lib.getName(), lib.getVersion());
if (toInstall != null && !toInstall.isInstalled()) {
status.add(toInstall.install(monitor));
}
}
if (monitor.isCanceled())
return Status.CANCEL_STATUS;
}
return status;
}
public static String getPrivateLibraryPathsString() {
return InstancePreferences.getPrivateLibraryPathsString();
}
/**
* get all the categories for all libraries (installed or not)
*
* @return a list of all the categories that exist in any library json file
* known by sloeber
*/
public static Set<String> getAllCategories() {
Set<String> ret = new TreeSet<>();
for (LibraryIndex libraryIndex : getLibraryIndices()) {
for (String categoryName : libraryIndex.getCategories()) {
ret.add(categoryName);
}
}
return ret;
}
public static void InstallDefaultLibraries(IProgressMonitor monitor) {
LibraryIndex libindex = getLibraryIndex(Defaults.DEFAULT);
if (libindex == null)
return;
for (String library : Defaults.INSTALLED_LIBRARIES) {
Library toInstalLib = libindex.getLatestLibrary(library);
if (toInstalLib != null) {
toInstalLib.install(monitor);
}
}
}
static private LibraryIndex getLibraryIndex(String name) {
for (LibraryIndex index : getLibraryIndices()) {
if (index.getName().equals(name)) {
return index;
}
}
return null;
}
static public void loadJson(File jsonFile) {
try (Reader reader = new FileReader(jsonFile)) {
LibraryIndex index = new Gson().fromJson(reader, LibraryIndex.class);
index.resolve();
index.setJsonFile(jsonFile);
libraryIndices.add(index);
} catch (Exception e) {
Common.log(new Status(IStatus.ERROR, Activator.getId(),
Messages.Manager_Failed_to_parse.replace("${FILE}", jsonFile.getAbsolutePath()), e)); //$NON-NLS-1$
jsonFile.delete();// Delete the file so it stops damaging
}
}
/**
* Install the latest version of all the libraries belonging to this
* category If a earlier version is installed this version will be removed
* before installation of the newer version
*
* @param category
*/
public static void installAllLatestLibraries() {
List<LibraryIndex> libraryIndices1 = getLibraryIndices();
Map<String, Library> latestLibs = new HashMap<>();
for (LibraryIndex libraryIndex : libraryIndices1) {
Map<String, Library> libraries = libraryIndex.getLatestLibraries();
for (Map.Entry<String, Library> entry : libraries.entrySet()) {
String curLibName = entry.getKey();
Library curLibrary = entry.getValue();
Library current = latestLibs.get(curLibName);
if (current != null) {
if (Version.compare(curLibrary.getVersion(), current.getVersion()) > 0) {
latestLibs.put(curLibName, curLibrary);
}
} else {
latestLibs.put(curLibName, curLibrary);
}
}
}
for (Map.Entry<String, Library> entry : latestLibs.entrySet()) {
String curLibName = entry.getKey();
Library curLibrary = entry.getValue();
for (LibraryIndex libraryIndex : libraryIndices1) {
Library previousVersion = libraryIndex.getInstalledLibrary(curLibName);
if ((previousVersion != null) && (previousVersion != curLibrary)) {
previousVersion.remove(new NullProgressMonitor());
}
}
if (!curLibrary.isInstalled()) {
curLibrary.install(new NullProgressMonitor());
}
}
}
public static void flushIndices() {
libraryIndices = new ArrayList<>();
}
}