/******************************************************************************* * Copyright 2015 alladin-IT GmbH * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. *******************************************************************************/ package at.alladin.rmbt.mapServer.parameters; import java.util.Collections; import java.util.Map; import java.util.Map.Entry; import java.util.TreeMap; import java.util.regex.Matcher; import java.util.regex.Pattern; import org.restlet.data.Form; import org.restlet.data.Parameter; import at.alladin.rmbt.mapServer.MapServerOptions; import com.google.common.base.Strings; import com.google.common.hash.Funnel; import com.google.common.hash.Funnels; import com.google.common.hash.PrimitiveSink; public abstract class TileParameters implements Funnel<TileParameters> { protected static final Pattern PATH_PATTERN = Pattern.compile("(\\d+)/(\\d+)/(\\d+)"); protected static final int MAX_ZOOM = 21; protected final Path path; protected final int size; protected final String mapOption; protected final float quantile; protected final Map<String,String> filterMap; protected final double transparency; protected final String developerCode; public final static class Path implements Funnel<Path> { protected final int zoom, x, y; public Path(String zoomStr, String xStr, String yStr, String path) { if (zoomStr != null && xStr != null && yStr != null) { zoom = Integer.valueOf(zoomStr); x = Integer.valueOf(xStr); y = Integer.valueOf(yStr); } else { if (path == null) throw new IllegalArgumentException(); final Matcher m = PATH_PATTERN.matcher(path); if (!m.matches()) throw new IllegalArgumentException(); zoom = Integer.valueOf(m.group(1)); x = Integer.valueOf(m.group(2)); y = Integer.valueOf(m.group(3)); } if (zoom < 0 || zoom > MAX_ZOOM) throw new IllegalArgumentException(); if (x < 0 || y < 0) throw new IllegalArgumentException(); int pow = 1 << zoom; if (x >= pow || y >= pow) throw new IllegalArgumentException(); } public Path(int zoom, int x, int y) { this.zoom = zoom; this.x = x; this.y = y; } public int getZoom() { return zoom; } public int getX() { return x; } public int getY() { return y; } @Override public void funnel(Path o, PrimitiveSink into) { into .putInt(o.zoom) .putInt(o.x) .putInt(o.y); } } protected TileParameters(Path path, Form params, double defaultTransparency) { this.path = path; int _size = 0; final String sizeStr = params.getFirstValue("size", true); if (sizeStr != null) { try { _size = Integer.valueOf(sizeStr); } catch (NumberFormatException e) { } } size = _size; mapOption = params.getFirstValue("map_options", true, "mobile/download"); float _quantile = 0.5f; //median is default quantile final String statisticalMethod = params.getFirstValue("statistical_method", true); if (statisticalMethod != null) { try { float __quantile = Float.parseFloat(statisticalMethod); if (__quantile >= 0f && __quantile <= 1f) _quantile = __quantile; } catch (NumberFormatException e) { } } quantile = _quantile; //developer code parameter developerCode = params.getFirstValue("developerCode", true, null); final String transparencyString = params.getFirstValue("transparency"); double _transparency = defaultTransparency; if (transparencyString != null) try { _transparency = Double.parseDouble(transparencyString); } catch (final NumberFormatException e) { } if (_transparency < 0) _transparency = 0; if (_transparency > 1) _transparency = 1; transparency = _transparency; final TreeMap<String, String> _filterMap = new TreeMap<>(); for (final Parameter param : params) { if (MapServerOptions.isValidFilter(param.getName())) _filterMap.put(param.getName(), param.getValue()); } filterMap = Collections.unmodifiableMap(_filterMap); } public Path getPath() { return path; } public int getSize() { return size; } public String getMapOption() { return mapOption; } public float getQuantile() { return quantile; } public Map<String, String> getFilterMap() { return filterMap; } public double getTransparency() { return transparency; } public abstract boolean isNoCache(); protected static final Funnel<Map.Entry<String, String>> FILTER_MAP_FUNNEL_ENTRY = new Funnel<Map.Entry<String,String>>() { @Override public void funnel(Entry<String, String> o, PrimitiveSink into) { into .putUnencodedChars(o.getKey()) .putChar(':') .putUnencodedChars(Strings.nullToEmpty(o.getValue())); } }; protected static final Funnel<Iterable<? extends Entry<String, String>>> FILTER_MAP_FUNNEL = Funnels.sequentialFunnel(FILTER_MAP_FUNNEL_ENTRY); @Override public void funnel(TileParameters o, PrimitiveSink into) { into .putUnencodedChars(o.getClass().getCanonicalName()) .putInt(o.size) .putUnencodedChars(o.mapOption) .putFloat(o.quantile) .putDouble(o.transparency) .putUnencodedChars(Strings.nullToEmpty(o.developerCode)); o.path.funnel(o.path, into); FILTER_MAP_FUNNEL.funnel(o.filterMap.entrySet(), into); } }