package com.anjlab.eclipse.tapestry5.templates;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Map.Entry;
import org.eclipse.core.resources.IFile;
import org.eclipse.ui.PlatformUI;
import com.anjlab.eclipse.tapestry5.EclipseUtils;
import com.anjlab.eclipse.tapestry5.Openable;
import com.anjlab.eclipse.tapestry5.TapestryProject;
import com.anjlab.eclipse.tapestry5.TapestryService.ServiceDefinition;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonIOException;
import com.google.gson.JsonSyntaxException;
import com.google.gson.stream.JsonReader;
// TODO Add file markers with SEVERITY_INFO in Eclipse views
// for config file if some supported options are missing,
// provide a link to latest template:
// link to GitHub or create unnamed editor and copy default template to it.
public class ProjectSettings implements Openable
{
private static final Gson gson =
new GsonBuilder()
.setPrettyPrinting()
.create();
private IFile source;
private boolean isDefault;
public static class TapestryServiceSettings extends ServiceDefinition
{
// If not empty then other values, like intfClass/implClass,
// may be treated as parameters for this auto-discovery rule.
private String discovery;
public String getDiscovery()
{
return discovery;
}
public TapestryServiceSettings clone()
{
TapestryServiceSettings copy = new TapestryServiceSettings();
copy.copyFrom(this);
copy.discovery = discovery;
return copy;
}
}
public static class TapestryModuleSettings
{
private Map<String, TapestryServiceSettings> services;
public TapestryModuleSettings()
{
services = new HashMap<String, TapestryServiceSettings>();
}
public Map<String, TapestryServiceSettings> getTapestryServices()
{
return services;
}
}
private Map<String, TapestryModuleSettings> tapestryModules;
private Map<String, String> javaScriptModules;
private Map<String, Map<String, String>> symbols;
private Map<String, String> fileNamingConventions;
private static final String CONFIG_NAME = "config";
private static final String CONFIG_EXT = "json";
public static final String CONFIG_FILE_NAME = CONFIG_NAME + "." + CONFIG_EXT;
public ProjectSettings()
{
tapestryModules = new HashMap<String, TapestryModuleSettings>();
javaScriptModules = new HashMap<String, String>();
symbols = new HashMap<String, Map<String, String>>();
fileNamingConventions = new LinkedHashMap<String, String>();
}
public void setSource(IFile source)
{
this.source = source;
}
@Override
public void openInEditor()
{
if (source != null)
{
EclipseUtils.openFile(PlatformUI.getWorkbench().getActiveWorkbenchWindow(), source);
}
}
public String getReferenceLabel()
{
return isDefault
? "default settings"
: source.getFullPath().toPortableString();
}
public Map<String, TapestryModuleSettings> getTapestryModules()
{
// XXX Values are still modifiable
return Collections.unmodifiableMap(tapestryModules);
}
public Map<String, Map<String, String>> getSymbols()
{
// XXX Values are still modifiable
return Collections.unmodifiableMap(symbols);
}
public Map<String, String> getFileNamingConventions()
{
return Collections.unmodifiableMap(fileNamingConventions);
}
public static InputStream getDefaultContents(TapestryProject tapestryProject)
{
return TapestryTemplates.get(tapestryProject)
.openTemplate(null, CONFIG_NAME, CONFIG_EXT);
}
public static ProjectSettings getDefault(TapestryProject tapestryProject)
{
try
{
ProjectSettings settings = parse(getDefaultContents(tapestryProject));
settings.isDefault = true;
return settings;
}
catch (Exception e)
{
throw new IllegalStateException("Error parsing default settings", e);
}
}
public boolean isDefault()
{
return isDefault;
}
public static ProjectSettings parse(InputStream input)
throws JsonIOException, JsonSyntaxException, IOException
{
JsonReader reader = new JsonReader(new InputStreamReader(input, "UTF-8"));
reader.setLenient(true);
try
{
return gson.fromJson(reader, ProjectSettings.class);
}
finally
{
reader.close();
}
}
public ProjectSettings extend(ProjectSettings with)
{
ProjectSettings newSettings = new ProjectSettings();
deepCopyMap(newSettings.symbols, this.symbols);
deepCopyMap(newSettings.symbols, with.symbols);
newSettings.javaScriptModules.putAll(this.javaScriptModules);
newSettings.javaScriptModules.putAll(with.javaScriptModules);
newSettings.tapestryModules.putAll(this.tapestryModules);
newSettings.tapestryModules.putAll(with.tapestryModules);
newSettings.fileNamingConventions.putAll(this.fileNamingConventions);
newSettings.fileNamingConventions.putAll(with.fileNamingConventions);
return newSettings;
}
private <T extends Object> void deepCopyMap(Map<String, Map<String, T>> to, Map<String, Map<String, T>> from)
{
for (Entry<String, Map<String, T>> entry : from.entrySet())
{
Map<String, T> copyOfValueMap = to.get(entry.getKey());
if (copyOfValueMap == null)
{
copyOfValueMap = new HashMap<String, T>();
to.put(entry.getKey(), copyOfValueMap);
}
copyOfValueMap.putAll(entry.getValue());
}
}
}