/*
* (c) Copyright 2010-2011 AgileBirds
*
* This file is part of OpenFlexo.
*
* OpenFlexo 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.
*
* OpenFlexo 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 OpenFlexo. If not, see <http://www.gnu.org/licenses/>.
*
*/
package org.openflexo.module;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.SwingUtilities;
import org.openflexo.ApplicationContext;
import org.openflexo.foundation.FlexoException;
import org.openflexo.foundation.action.UnexpectedException;
import org.openflexo.foundation.cg.templates.CustomCGTemplateRepository;
import org.openflexo.foundation.rm.CustomTemplatesResource;
import org.openflexo.foundation.rm.FlexoFileResource;
import org.openflexo.foundation.rm.FlexoGeneratedResource;
import org.openflexo.foundation.rm.FlexoImportedResource;
import org.openflexo.foundation.rm.FlexoProject;
import org.openflexo.foundation.rm.FlexoResource;
import org.openflexo.foundation.rm.FlexoResource.DependencyAlgorithmScheme;
import org.openflexo.foundation.rm.FlexoResourceData;
import org.openflexo.foundation.rm.FlexoResourceUpdateHandler;
import org.openflexo.foundation.rm.FlexoStorageResource;
import org.openflexo.foundation.rm.GeneratedResourceData;
import org.openflexo.foundation.rm.ImportedResourceData;
import org.openflexo.foundation.rm.StorageResourceData;
import org.openflexo.foundation.utils.ProjectInitializerException;
import org.openflexo.foundation.utils.ProjectLoadingCancelledException;
import org.openflexo.localization.FlexoLocalization;
import org.openflexo.view.controller.FlexoController;
/**
* Please comment this class
*
* @author sguerin
*
*/
public class InteractiveFlexoResourceUpdateHandler extends FlexoResourceUpdateHandler {
protected static final Logger logger = Logger.getLogger(InteractiveFlexoResourceUpdateHandler.class.getPackage().getName());
private final ApplicationContext applicationContext;
private final FlexoProject project;
public InteractiveFlexoResourceUpdateHandler(ApplicationContext applicationContext, FlexoProject project) {
super();
this.applicationContext = applicationContext;
this.project = project;
}
private ProjectLoader getProjectLoader() {
return applicationContext.getProjectLoader();
}
@Override
protected OptionWhenStorageResourceFoundAsConflicting getOptionWhenStorageResourceFoundAsConflicting(
FlexoStorageResource storageResource) {
String[] options;
if (storageResource == null || !storageResource.implementsResourceMerge()) {
options = new String[3];
} else {
options = new String[4];
}
options[0] = FlexoLocalization.localizedForKey("update_from_disk");
options[1] = FlexoLocalization.localizedForKey("overwrite_disk_change");
options[2] = FlexoLocalization.localizedForKey("ignore");
if (options.length == 4) {
options[3] = FlexoLocalization.localizedForKey("merge_changes");
}
int choice = FlexoController.selectOption(FlexoLocalization.localizedForKey("conflict_detected_on_resource") + " "
+ (storageResource != null ? storageResource : "") + "\n" + FlexoLocalization.localizedForKey("possible_actions_are"),
options, options[2]);
switch (choice) {
case 0:
return OptionWhenStorageResourceFoundAsConflicting.UpdateFromDisk;
case 1:
return OptionWhenStorageResourceFoundAsConflicting.OverwriteDiskChange;
case 2:
return OptionWhenStorageResourceFoundAsConflicting.Ignore;
case 3:
return OptionWhenStorageResourceFoundAsConflicting.MergeChanges;
default:
return null;
}
}
@Override
protected OptionWhenStorageResourceFoundAsModifiedOnDisk getOptionWhenStorageResourceFoundAsModifiedOnDisk(
FlexoStorageResource storageResource) {
String[] options = new String[3];
options[0] = FlexoLocalization.localizedForKey("update_from_disk");
options[1] = FlexoLocalization.localizedForKey("overwrite_disk_change");
options[2] = FlexoLocalization.localizedForKey("ignore");
int choice = FlexoController.selectOption(FlexoLocalization.localizedForKey("disk_change_detected_on_resource") + " "
+ (storageResource != null ? storageResource : "") + "\n" + FlexoLocalization.localizedForKey("possible_actions_are"),
options, options[2]);
switch (choice) {
case 0:
return OptionWhenStorageResourceFoundAsModifiedOnDisk.UpdateFromDisk;
case 1:
return OptionWhenStorageResourceFoundAsModifiedOnDisk.OverwriteDiskChange;
case 2:
return OptionWhenStorageResourceFoundAsModifiedOnDisk.Ignore;
default:
return null;
}
}
@Override
protected OptionWhenImportedResourceFoundAsModifiedOnDisk getOptionWhenImportedResourceFoundAsModifiedOnDisk(
FlexoImportedResource importedResource) {
String[] options = new String[2];
options[0] = FlexoLocalization.localizedForKey("update_from_disk");
options[1] = FlexoLocalization.localizedForKey("ignore");
int choice = FlexoController.selectOption(FlexoLocalization.localizedForKey("disk_change_detected_on_imported_resource") + " "
+ (importedResource != null ? importedResource : "") + "\n" + FlexoLocalization.localizedForKey("possible_actions_are"),
options, options[1]);
switch (choice) {
case 0:
return OptionWhenImportedResourceFoundAsModifiedOnDisk.UpdateFromDisk;
case 1:
return OptionWhenImportedResourceFoundAsModifiedOnDisk.Ignore;
default:
return null;
}
}
@Override
public void handlesResourceUpdate(final FlexoFileResource fileResource) {
if (logger.isLoggable(Level.INFO)) {
logger.info("handlesResourceUpdate() for " + fileResource);
}
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
if (fileResource instanceof FlexoStorageResource) {
FlexoStorageResource storageResource = (FlexoStorageResource) fileResource;
if (storageResource.isModified()) {
if (logger.isLoggable(Level.INFO)) {
logger.info("Conflict detected on resource " + storageResource);
}
OptionWhenStorageResourceFoundAsConflicting choice = getOptionWhenStorageResourceFoundAsConflicting(storageResource);
if (choice == OptionWhenStorageResourceFoundAsConflicting.UpdateFromDisk) {
try {
reloadProject(storageResource);
} catch (FlexoException e) {
handleException("problem_when_trying_to_update_from_disk", e);
} catch (ProjectInitializerException e) {
handleException("problem_when_trying_to_update_from_disk", new UnexpectedException(e));
}
} else if (choice == OptionWhenStorageResourceFoundAsConflicting.OverwriteDiskChange) {
try {
storageResource.saveResourceData();
} catch (FlexoException e) {
handleException("error_during_resource_saving", e);
}
} else if (choice == OptionWhenStorageResourceFoundAsConflicting.Ignore) {
// Does nothing
} else if (choice == OptionWhenStorageResourceFoundAsConflicting.MergeChanges) {
// Not implemented
try {
storageResource.performMerge();
} catch (FlexoException e) {
handleException("error_during_resource_merge", e);
}
}
} else {
if (logger.isLoggable(Level.INFO)) {
logger.info("Update detected on resource " + storageResource);
}
OptionWhenStorageResourceFoundAsModifiedOnDisk choice = getOptionWhenStorageResourceFoundAsModifiedOnDisk(storageResource);
if (choice == OptionWhenStorageResourceFoundAsModifiedOnDisk.UpdateFromDisk) {
try {
storageResource.performDiskUpdate();
} catch (FlexoException e) {
handleException("problem_when_trying_to_update_from_disk", e);
}
} else if (choice == OptionWhenStorageResourceFoundAsModifiedOnDisk.OverwriteDiskChange) {
try {
storageResource.saveResourceData();
} catch (FlexoException e) {
handleException("error_during_resource_saving", e);
}
} else if (choice == OptionWhenStorageResourceFoundAsModifiedOnDisk.Ignore) {
// Does nothing
}
}
}
else if (fileResource instanceof FlexoImportedResource) {
FlexoImportedResource importedResource = (FlexoImportedResource) fileResource;
if (logger.isLoggable(Level.INFO)) {
logger.info("Update detected on resource " + importedResource);
}
OptionWhenImportedResourceFoundAsModifiedOnDisk choice = getOptionWhenImportedResourceFoundAsModifiedOnDisk(importedResource);
if (choice == OptionWhenImportedResourceFoundAsModifiedOnDisk.UpdateFromDisk) {
try {
importedResource.performDiskUpdate();
} catch (FlexoException e) {
handleException("problem_when_trying_to_update_from_disk", e);
}
} else if (choice == OptionWhenImportedResourceFoundAsModifiedOnDisk.Ignore) {
// Does nothing
}
}
else if (fileResource instanceof FlexoGeneratedResource) {
FlexoGeneratedResource generatedResource = (FlexoGeneratedResource) fileResource;
if (logger.isLoggable(Level.INFO)) {
logger.info("Update detected on resource " + generatedResource);
}
generatedResourceModified(generatedResource);
}
else if (fileResource instanceof CustomTemplatesResource) {
logger.info("Updating " + fileResource);
CustomCGTemplateRepository rep = fileResource.getProject().getGeneratedCode().getTemplates()
.getCustomCGTemplateRepository((CustomTemplatesResource) fileResource);
if (rep == null) {
rep = fileResource.getProject().getGeneratedDoc().getTemplates()
.getCustomCGTemplateRepository((CustomTemplatesResource) fileResource);
}
if (rep == null) {
rep = fileResource.getProject().getGeneratedSources().getTemplates()
.getCustomCGTemplateRepository((CustomTemplatesResource) fileResource);
}
rep.update();
}
else {
logger.warning("Dont known what to do with a " + fileResource + " of " + fileResource.getClass().getName());
}
}
});
}
@Override
public void handlesResourcesUpdate(final List<FlexoFileResource<? extends FlexoResourceData>> updatedResources) {
if (!SwingUtilities.isEventDispatchThread()) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
handlesResourcesUpdate(updatedResources);
}
});
return;
}
String[] options = new String[2];
options[0] = FlexoLocalization.localizedForKey("batch_decision");
options[1] = FlexoLocalization.localizedForKey("one_by_one_decidions");
int choice = FlexoController.selectOption(FlexoLocalization.localizedForKey("disk_change_detected_on_resource"), options[0],
options);
switch (choice) {
case 1:
for (FlexoFileResource<? extends FlexoResourceData> fileResource : updatedResources) {
handlesResourceUpdate(fileResource);
}
break;
default:
handlesResourcesUpdateWithBatchDecision(updatedResources);
}
}
private void handlesResourcesUpdateWithBatchDecision(List<FlexoFileResource<? extends FlexoResourceData>> updatedResources) {
List<FlexoStorageResource<? extends StorageResourceData>> updatedStorageResource = new ArrayList<FlexoStorageResource<? extends StorageResourceData>>();
List<FlexoStorageResource<? extends StorageResourceData>> conflictingStorageResource = new ArrayList<FlexoStorageResource<? extends StorageResourceData>>();
List<FlexoImportedResource<? extends ImportedResourceData>> importedResource = new ArrayList<FlexoImportedResource<? extends ImportedResourceData>>();
List<FlexoGeneratedResource<? extends GeneratedResourceData>> generatedResource = new ArrayList<FlexoGeneratedResource<? extends GeneratedResourceData>>();
List<CustomTemplatesResource> templates = new ArrayList<CustomTemplatesResource>();
for (FlexoFileResource<? extends FlexoResourceData> r : updatedResources) {
if (r instanceof FlexoStorageResource<?>) {
if (((FlexoStorageResource<?>) r).isModified()) {
conflictingStorageResource.add((FlexoStorageResource<? extends StorageResourceData>) r);
} else {
updatedStorageResource.add((FlexoStorageResource<? extends StorageResourceData>) r);
}
} else if (r instanceof FlexoImportedResource<?>) {
importedResource.add((FlexoImportedResource<? extends ImportedResourceData>) r);
} else if (r instanceof FlexoGeneratedResource<?>) {
generatedResource.add((FlexoGeneratedResource<? extends GeneratedResourceData>) r);
} else if (r instanceof CustomTemplatesResource) {
templates.add((CustomTemplatesResource) r);
}
}
if (importedResource.size() > 0) {
OptionWhenImportedResourceFoundAsModifiedOnDisk choice = getOptionWhenImportedResourceFoundAsModifiedOnDisk(null);
if (choice == OptionWhenImportedResourceFoundAsModifiedOnDisk.UpdateFromDisk) {
for (FlexoImportedResource<? extends ImportedResourceData> importedResource2 : importedResource) {
try {
importedResource2.performDiskUpdate();
} catch (FlexoException e) {
handleException("problem_when_trying_to_update_from_disk", e);
}
}
} else if (choice == OptionWhenImportedResourceFoundAsModifiedOnDisk.Ignore) {
// Does nothing
}
}
if (generatedResource.size() > 0) {
generatedResourcesModified(generatedResource);
}
if (templates.size() > 0) {
for (CustomTemplatesResource templatesResource : templates) {
CustomCGTemplateRepository rep = templatesResource.getProject().getGeneratedCode().getTemplates()
.getCustomCGTemplateRepository(templatesResource);
if (rep == null) {
rep = templatesResource.getProject().getGeneratedDoc().getTemplates().getCustomCGTemplateRepository(templatesResource);
}
if (rep == null) {
rep = templatesResource.getProject().getGeneratedSources().getTemplates()
.getCustomCGTemplateRepository(templatesResource);
}
if (rep != null) {
rep.update();
} else if (logger.isLoggable(Level.WARNING)) {
logger.warning("Could not find repository for template " + templatesResource);
}
}
}
if (updatedStorageResource.size() > 0) {
OptionWhenStorageResourceFoundAsModifiedOnDisk choice = getOptionWhenStorageResourceFoundAsModifiedOnDisk(null);
if (choice == OptionWhenStorageResourceFoundAsModifiedOnDisk.UpdateFromDisk) {
for (FlexoStorageResource<? extends StorageResourceData> storageResource : updatedStorageResource) {
try {
storageResource.performDiskUpdate();
} catch (FlexoException e) {
handleException("problem_when_trying_to_update_from_disk", e);
}
}
} else if (choice == OptionWhenStorageResourceFoundAsModifiedOnDisk.OverwriteDiskChange) {
DependencyAlgorithmScheme scheme = project.getDependancyScheme();
// Pessimistic dependancy scheme is cheaper and is not intended for this situation
project.setDependancyScheme(DependencyAlgorithmScheme.Pessimistic);
FlexoResource.sortResourcesWithDependancies(updatedStorageResource);
project.setDependancyScheme(scheme);
for (FlexoStorageResource<? extends StorageResourceData> storageResource : updatedStorageResource) {
try {
storageResource.saveResourceData();
} catch (FlexoException e) {
handleException("error_during_resource_saving", e);
}
}
} else if (choice == OptionWhenStorageResourceFoundAsModifiedOnDisk.Ignore) {
// Does nothing
}
}
if (conflictingStorageResource.size() > 0) {
OptionWhenStorageResourceFoundAsConflicting choice = getOptionWhenStorageResourceFoundAsConflicting(null);
if (choice == OptionWhenStorageResourceFoundAsConflicting.UpdateFromDisk) {
try {
reloadProject(conflictingStorageResource);
} catch (ProjectLoadingCancelledException e) {
// TODO handle this
} catch (ModuleLoadingException e) {
// TODO handle this
} catch (ProjectInitializerException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} else if (choice == OptionWhenStorageResourceFoundAsConflicting.OverwriteDiskChange) {
try {
DependencyAlgorithmScheme scheme = project.getDependancyScheme();
// Pessimistic dependancy scheme is cheaper and is not intended for this situation
project.setDependancyScheme(DependencyAlgorithmScheme.Pessimistic);
FlexoResource.sortResourcesWithDependancies(conflictingStorageResource);
project.setDependancyScheme(scheme);
for (FlexoStorageResource<? extends StorageResourceData> flexoStorageResource : conflictingStorageResource) {
flexoStorageResource.saveResourceData();
}
} catch (FlexoException e) {
handleException("error_during_resource_saving", e);
}
} else if (choice == OptionWhenStorageResourceFoundAsConflicting.Ignore) {
// Does nothing
}
}
}
private void reloadProject(List<FlexoStorageResource<? extends StorageResourceData>> updatedStorageResource)
throws ProjectLoadingCancelledException, ModuleLoadingException, ProjectInitializerException {
for (FlexoStorageResource<? extends StorageResourceData> flexoStorageResource : updatedStorageResource) {
flexoStorageResource.getResourceData().clearIsModified(true);
}
getProjectLoader().reloadProject(project);
}
@Override
public void reloadProject(FlexoStorageResource fileResource) throws ProjectLoadingCancelledException, ModuleLoadingException,
ProjectInitializerException {
fileResource.getResourceData().clearIsModified(true);
getProjectLoader().reloadProject(project);
}
@Override
protected void handleException(final String unlocalizedMessage, final FlexoException exception) {
if (!SwingUtilities.isEventDispatchThread()) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
handleException(unlocalizedMessage, exception);
}
});
return;
}
exception.printStackTrace();
FlexoController.showError(FlexoLocalization.localizedForKey(unlocalizedMessage));
}
}