/** * Copyright (c) 2010, 2013 Darmstadt University of Technology. * 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 * * Contributors: * Olav Lenz - initial API and implementation */ package org.eclipse.recommenders.internal.coordinates.rcp; import static com.google.common.base.Optional.*; import static org.eclipse.recommenders.internal.coordinates.rcp.l10n.LogMessages.ERROR_FAILED_TO_READ_MANUAL_MAPPINGS; import java.io.File; import java.io.IOException; import java.lang.reflect.Type; import java.nio.charset.StandardCharsets; import java.util.Map; import javax.annotation.PostConstruct; import javax.annotation.PreDestroy; import javax.inject.Inject; import javax.inject.Named; import org.apache.commons.io.FileUtils; import org.eclipse.recommenders.coordinates.DependencyInfo; import org.eclipse.recommenders.coordinates.IProjectCoordinateAdvisor; import org.eclipse.recommenders.coordinates.ProjectCoordinate; import org.eclipse.recommenders.internal.coordinates.rcp.l10n.LogMessages; import org.eclipse.recommenders.rcp.IRcpService; import org.eclipse.recommenders.utils.Logs; import com.google.common.base.Optional; import com.google.common.collect.Maps; import com.google.common.io.Files; import com.google.common.reflect.TypeToken; import com.google.gson.Gson; import com.google.gson.GsonBuilder; import com.google.gson.JsonParseException; public class ManualProjectCoordinateAdvisor implements IProjectCoordinateAdvisor, IRcpService { private final File persistenceFile; private final Gson gson; private Map<DependencyInfo, ProjectCoordinate> manualMappings = Maps.newHashMap(); @SuppressWarnings("serial") private static final Type MANUAL_MAPPINGS_TYPE_TOKEN = new TypeToken<Map<DependencyInfo, ProjectCoordinate>>() { }.getType(); @Inject public ManualProjectCoordinateAdvisor(@Named(CoordinatesRcpModule.MANUAL_MAPPINGS) File persistenceFile) { this.persistenceFile = persistenceFile; gson = new GsonBuilder() .registerTypeAdapter(File.class, new FileJsonTypeAdapter()) .registerTypeAdapter(ProjectCoordinate.class, new ProjectCoordinateJsonTypeAdapter()) .enableComplexMapKeySerialization().serializeNulls().create(); } @Override public Optional<ProjectCoordinate> suggest(DependencyInfo dependencyInfo) { ProjectCoordinate pc = manualMappings.get(dependencyInfo); if (pc != null) { return of(pc); } else { return absent(); } } public void setManualMapping(DependencyInfo dependencyInfo, ProjectCoordinate pc) { manualMappings.put(dependencyInfo, pc); } public void removeManualMapping(DependencyInfo dependencyInfo) { manualMappings.remove(dependencyInfo); } @PostConstruct public void open() throws IOException { if (!persistenceFile.exists()) { return; } try { String json = Files.toString(persistenceFile, StandardCharsets.UTF_8); Map<DependencyInfo, ProjectCoordinate> deserialized = gson.fromJson(json, MANUAL_MAPPINGS_TYPE_TOKEN); if (deserialized != null) { manualMappings = deserialized; } } catch (IOException | JsonParseException e) { Logs.log(ERROR_FAILED_TO_READ_MANUAL_MAPPINGS, e, persistenceFile); return; } } @PreDestroy public void close() throws IOException { try { String json = gson.toJson(manualMappings, MANUAL_MAPPINGS_TYPE_TOKEN); Files.write(json, persistenceFile, StandardCharsets.UTF_8); } catch (IOException e) { Logs.log(LogMessages.ERROR_FAILED_TO_WRITE_MANUAL_MAPPINGS, e, persistenceFile); // Delete the file (if it exists at all) so not to leave it in a corrupt state. FileUtils.deleteQuietly(persistenceFile); } } }