package net.osmand.plus.render;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import net.osmand.LogUtil;
import net.osmand.render.OsmandRenderingRulesParser;
import org.apache.commons.logging.Log;
import org.xml.sax.SAXException;
public class RendererRegistry {
private final static RendererRegistry registry = new RendererRegistry();
private final static Log log = LogUtil.getLog(RendererRegistry.class);
public final static String DEFAULT_RENDER = "default"; //$NON-NLS-1$
public final static String CAR_RENDER = "car"; //$NON-NLS-1$
public final static String BICYCLE_RENDER = "bicycle"; //$NON-NLS-1$
public final static String PEDESTRIAN_RENDER = "pedestrian"; //$NON-NLS-1$
public final static String NIGHT_SUFFIX = "-night"; //$NON-NLS-1$
public final static String DEFAULT_NIGHT_RENDER = DEFAULT_RENDER + NIGHT_SUFFIX;
public final static String CAR_NIGHT_RENDER = CAR_RENDER + NIGHT_SUFFIX;
public static RendererRegistry getRegistry() {
return registry;
}
public RendererRegistry(){
internalRenderers.put(DEFAULT_RENDER, "default.render.xml"); //$NON-NLS-1$
internalRenderers.put(DEFAULT_NIGHT_RENDER, "default-night.render.xml"); //$NON-NLS-1$
internalRenderers.put(CAR_RENDER, "car.render.xml"); //$NON-NLS-1$
internalRenderers.put(CAR_NIGHT_RENDER, "car-night.render.xml"); //$NON-NLS-1$
internalRenderers.put(BICYCLE_RENDER, "bicycle.render.xml"); //$NON-NLS-1$
}
private BaseOsmandRender defaultRender = null;
private BaseOsmandRender currentSelectedRender = null;
private Map<String, File> externalRenderers = new LinkedHashMap<String, File>();
private Map<String, String> internalRenderers = new LinkedHashMap<String, String>();
private Map<String, BaseOsmandRender> renderers = new LinkedHashMap<String, BaseOsmandRender>();
public BaseOsmandRender defaultRender() {
if(defaultRender == null){
defaultRender = getRenderer(DEFAULT_RENDER);
if (defaultRender == null) {
try {
defaultRender = new BaseOsmandRender();
defaultRender.init(OsmandRenderingRulesParser.class.getResourceAsStream("default.render.xml")); //$NON-NLS-1$
} catch (IOException e) {
log.error("Exception initialize renderer", e); //$NON-NLS-1$
} catch (SAXException e) {
log.error("Exception initialize renderer", e); //$NON-NLS-1$
}
}
}
return defaultRender;
}
public BaseOsmandRender carRender() {
BaseOsmandRender renderer = getRenderer(CAR_RENDER);
if(renderer == null){
return defaultRender();
}
return renderer;
}
public BaseOsmandRender bicycleRender() {
BaseOsmandRender renderer = getRenderer(BICYCLE_RENDER);
if(renderer == null){
return defaultRender();
}
return renderer;
}
public BaseOsmandRender pedestrianRender() {
BaseOsmandRender renderer = getRenderer(PEDESTRIAN_RENDER);
if(renderer == null){
return defaultRender();
}
return renderer;
}
public BaseOsmandRender getRenderer(String name){
if(renderers.containsKey(name)){
return renderers.get(name);
}
if(!hasRender(name)){
return null;
}
return getRenderer(name, new LinkedHashSet<String>());
}
private boolean hasRender(String name) {
return externalRenderers.containsKey(name) || internalRenderers.containsKey(name);
}
private BaseOsmandRender getRenderer(String name, Set<String> loadedRenderers) {
try {
return loadRenderer(name);
} catch (IOException e) {
log.error("Error loading renderer", e); //$NON-NLS-1$
} catch (SAXException e) {
log.error("Error loading renderer", e); //$NON-NLS-1$
}
return null;
}
public BaseOsmandRender loadRenderer(String name) throws IOException, SAXException {
return loadRenderer(name, new LinkedHashSet<String>());
}
private BaseOsmandRender loadRenderer(String name, Set<String> loadedRenderers) throws IOException, SAXException {
InputStream is = null;
if(externalRenderers.containsKey(name)){
is = new FileInputStream(externalRenderers.get(name));
} else if(internalRenderers.containsKey(name)){
is = OsmandRenderingRulesParser.class.getResourceAsStream(internalRenderers.get(name));
} else {
throw new IllegalArgumentException("Not found " + name); //$NON-NLS-1$
}
BaseOsmandRender b = new BaseOsmandRender();
b.init(is);
loadedRenderers.add(name);
List<BaseOsmandRender> dependencies = new ArrayList<BaseOsmandRender>();
for (String s : b.getDepends()) {
if (loadedRenderers.contains(s)) {
log.warn("Circular dependencies found " + name); //$NON-NLS-1$
} else {
BaseOsmandRender dep = getRenderer(s, loadedRenderers);
if (dep == null) {
log.warn("Dependent renderer not found : " + name); //$NON-NLS-1$
} else{
dependencies.add(dep);
}
}
}
b.setDependRenderers(dependencies);
renderers.put(name, b);
return b;
}
public void setExternalRenderers(Map<String, File> externalRenderers) {
this.externalRenderers = externalRenderers;
}
public Collection<String> getRendererNames(){
LinkedHashSet<String> names = new LinkedHashSet<String>();
names.add(DEFAULT_RENDER);
names.addAll(internalRenderers.keySet());
names.addAll(externalRenderers.keySet());
return names;
}
public BaseOsmandRender getCurrentSelectedRenderer() {
if(currentSelectedRender == null){
return defaultRender();
}
return currentSelectedRender;
}
public void setCurrentSelectedRender(BaseOsmandRender currentSelectedRender) {
this.currentSelectedRender = currentSelectedRender;
}
/**
* @return opposite renderer if exists otherwise return input
*/
public BaseOsmandRender getOppositeRendererForDayNight(BaseOsmandRender base) {
String oppositeName;
if (base.isDayRender()) {
oppositeName = base.name + NIGHT_SUFFIX;
} else {
oppositeName = base.name.substring(0, base.name.length() - NIGHT_SUFFIX.length());
}
BaseOsmandRender opposite = getRenderer(oppositeName);
return opposite != null ? opposite : base;
}
}