private boolean hasRightToPublishBaseLayer(final String layerId, final User user) {

    final long id = ConversionHelper.getLong(layerId.substring(PREFIX_BASELAYER.length()), -1);
    if (id == -1) {
      log.warn("Error parsing layerId:", layerId);
      return false;
    }
    List<Long> list = new ArrayList<Long>();
    list.add(id);
    Map<Long, List<Permissions>> map =
        permissionsService.getPermissionsForBaseLayers(list, Permissions.PERMISSION_TYPE_PUBLISH);
    List<Permissions> permissions = map.get(id);

    boolean hasPermission = false;
    hasPermission =
        permissionsService.permissionGrantedForRolesOrUser(
            user, permissions, Permissions.PERMISSION_TYPE_PUBLISH);
    if (!hasPermission) {
      log.warn(
          "User tried to publish layer with no publish permission. LayerID:",
          layerId,
          "- User:",
          user);
    }
    return hasPermission;
  }
  public static JSONObject getConfiguration(final View view) throws ViewException {
    final JSONObject configuration = new JSONObject();
    final List<Bundle> bundles = view.getBundles();
    for (Bundle s : bundles) {
      final String conf = s.getConfig();
      final String state = s.getState();
      final String name = s.getBundleinstance();
      try {
        // setup bundle node in config
        JSONObject bundle = new JSONObject();
        configuration.put(name, bundle);

        // setup conf for bundle
        if (conf != null) {
          bundle.put("conf", new JSONObject(conf));
        } else {
          log.warn("Could not get configuration fragment for bundle '", name, "'");
        }
        // setup state for bundle
        if (state != null) {
          bundle.put("state", new JSONObject(state));
        } else {
          log.warn("Could not get state fragment for bundle '", name, "'");
        }
      } catch (Exception ex) {
        log.error("Malformed JSON in configuration fragment for bundle", name, conf);
      }
    }
    return configuration;
  }
 private boolean hasRightToPublishMyPlaceLayer(
     final String layerId, final String userUuid, final String publisherName) {
   final long categoryId =
       ConversionHelper.getLong(layerId.substring(PREFIX_MYPLACES.length()), -1);
   if (categoryId == -1) {
     log.warn("Error parsing layerId:", layerId);
     return false;
   }
   final List<Long> publishedMyPlaces = new ArrayList<Long>();
   publishedMyPlaces.add(categoryId);
   final List<MyPlaceCategory> myPlacesLayers =
       myPlaceService.getMyPlaceLayersById(publishedMyPlaces);
   for (MyPlaceCategory place : myPlacesLayers) {
     if (place.getUuid().equals(userUuid)) {
       myPlaceService.updatePublisherName(categoryId, userUuid, publisherName); // make it public
       return true;
     }
   }
   log.warn(
       "Found my places layer in selected that isn't users own or isnt published any more! LayerId:",
       layerId,
       "User UUID:",
       userUuid);
   return false;
 }
  public void handleAction(ActionParameters params) throws ActionException {

    final JSONObject root = new JSONObject();

    // Because of analysis layers
    String sid = params.getHttpParam(ID, "n/a");
    final int id = ConversionHelper.getInt(getBaseLayerId(sid), 0);

    final HttpServletResponse response = params.getResponse();
    response.setContentType("application/json");

    if (id == 0) {
      JSONHelper.putValue(root, ERROR, ERROR_NO_ID);
      ResponseHelper.writeResponse(params, root);
      // FIXME: throw ActionParamsException instead and modify client
      // response parsing
      return;
    }

    String json = WFSLayerConfiguration.getCache(id + "");
    if (json == null) {
      WFSLayerConfiguration lc = layerConfigurationService.findConfiguration(id);

      log.warn("id", id);
      log.warn(lc);

      // Extra manage for analysis
      if (sid.indexOf(ANALYSIS_PREFIX) > -1) {
        log.warn("sid", sid);
        // set id to original analysis layer id
        lc.setLayerId(sid);
        // Set analysis layer fields as id based
        lc.setSelectedFeatureParams(getAnalysisFeatureProperties(sid));
      }
      // Extra manage for analysis
      else if (sid.indexOf(MYPLACES_PREFIX) > -1) {
        log.warn("sid", sid);
        // set id to original my places layer id
        lc.setLayerId(sid);
      } else if (sid.indexOf(USERLAYER_PREFIX) > -1) {
        log.warn("sid", sid);
        // set id to original user layer id
        lc.setLayerId(sid);
      }
      if (lc == null) {
        JSONHelper.putValue(root, ERROR, ERROR_NOT_FOUND);
        ResponseHelper.writeResponse(params, root);
        // FIXME: throw ActionParamsException instead and modify client
        // response parsing
        return;
      }
      lc.save();
    }
    JSONHelper.putValue(root, RESULT, RESULT_SUCCESS);
    ResponseHelper.writeResponse(params, root);
  }
 public long addKeyword(final Keyword keyword) {
   // check if keyword is already inserted with matching language and return the id without
   // inserting!
   final Keyword dbKey = findExactKeyword(keyword.getValue(), keyword.getLang());
   if (dbKey != null) {
     log.warn("Keyword already saved:", keyword, "->", dbKey);
     keyword.setId(dbKey.getId());
     return dbKey.getId();
   }
   log.warn("Adding keyword:", keyword);
   final Long id = queryForObject(getNameSpace() + ".add-keyword", keyword);
   keyword.setId(id);
   log.warn("Got keyword id:", id);
   return id;
 }
  public static JSONObject fillTables(JSONObject tables, JSONObject rows) {

    try {

      // Get table id
      Iterator<?> keys = rows.keys();

      while (keys.hasNext()) {
        String key = (String) keys.next(); // should be table1, table2 ,...
        if (key.indexOf("table") > -1) {
          // find key table rows in tables
          if (tables.optJSONObject("content").has(key)) {
            JSONArray tablerows =
                tables.optJSONObject("content").getJSONObject(key).optJSONArray("rows");
            if (tablerows == null) return tables;
            // Append rows
            JSONArray datarows = rows.optJSONArray(key);
            if (datarows == null) return tables;

            for (int n = 0; n < datarows.length(); n++) {
              JSONObject row = datarows.getJSONObject(n);
              tablerows.put(row);
            }
          }
        }
      }
      return tables;

    } catch (Exception ex) {
      log.warn(ex, "Error filling table layout template for printout");
    }
    return null;
  }
 private static void migrateDB() {
   if (PropertyUtil.getOptional("db.flyway", true) == false) {
     log.warn(
         "Skipping flyway migration! Remove 'db.flyway' property or set it to 'true' to enable migration");
     return;
   }
   // upgrade database structure with http://flywaydb.org/
   log.info("Oskari-map checking DB status");
   try {
     FlywaydbMigrator.migrate(DS_HELPER.getDataSource());
     log.info("Oskari core DB migrated successfully");
   } catch (Exception e) {
     log.error(e, "DB migration for Oskari core failed!");
   }
   final String[] additionalPools = PropertyUtil.getCommaSeparatedList(KEY_MODULE_LIST);
   for (String module : additionalPools) {
     final String poolName = DS_HELPER.getOskariDataSourceName(module);
     try {
       FlywaydbMigrator.migrate(DS_HELPER.getDataSource(poolName), module);
       log.info(module + " DB migrated successfully");
     } catch (Exception e) {
       log.error(e, "DB migration for module " + module + " failed!", e);
       e.printStackTrace();
     }
   }
 }
Beispiel #8
0
  /**
   * Overrides values in base data and returns a new object as the merged result.
   *
   * @param baseData
   * @param overrides
   * @return merged result
   */
  public static JSONObject merge(final JSONObject baseData, final JSONObject overrides) {
    if (baseData == null) {
      return merge(new JSONObject(), overrides);
    }
    // copy existing values so we don't leak mutable references
    final JSONObject result = createJSONObject(baseData.toString());
    // TODO: maybe do the same for overrides?

    if (overrides == null || overrides.length() == 0) {
      // JSONObject.getNames() on empty object returns null so early exit here
      return result;
    }
    try {
      for (String key : JSONObject.getNames(overrides)) {
        Object val = overrides.opt(key);
        if (val instanceof JSONObject) {
          val = merge(result.optJSONObject(key), (JSONObject) val);
        }
        result.put(key, val);
      }
    } catch (Exception ex) {
      log.warn(ex, "Error merging objects from:", overrides, "- to:", baseData);
    }
    return result;
  }
Beispiel #9
0
 public static final JSONObject getJSONObject(final JSONObject content, String key) {
   try {
     return content.getJSONObject(key);
   } catch (JSONException e) {
     log.warn("Couldn't get JSONObject from ", content, " with key =", key);
     return null;
   }
 }
Beispiel #10
0
 public static final JSONObject createJSONObject(final String content) {
   try {
     return new JSONObject(content);
   } catch (Exception e) {
     log.warn("Error generating JSONObject from", content);
   }
   return null;
 }
Beispiel #11
0
 public static final boolean putValue(final JSONObject json, final String key, JSONObject value) {
   try {
     json.put(key, value);
     return true;
   } catch (Exception ignore) {
     log.warn("Can't put", key, "value", value, "to json");
   }
   return false;
 }
  /**
   * Sends one feature
   *
   * @param values
   */
  protected void sendWFSFeature(List<Object> values) {
    if (values == null || values.size() == 0) {
      log.warn("Failed to send feature");
      return;
    }
    Map<String, Object> output = new HashMap<String, Object>();
    output.put(OUTPUT_LAYER_ID, this.layerId);
    output.put(OUTPUT_FEATURE, values);

    this.service.addResults(this.session.getClient(), ResultProcessor.CHANNEL_FEATURE, output);
  }
Beispiel #13
0
 /**
  * Compares 2 JSONObjects for equality. Ignores property order and only matches on defined
  * properties and property values.
  *
  * @param jsonObject1
  * @param jsonObject2
  * @return
  */
 public static boolean isEqual(final JSONObject jsonObject1, final JSONObject jsonObject2) {
   if (jsonObject1 == null || JSONObject.getNames(jsonObject1) == null) {
     // if object 1 is null or empty -> object 2 should also be null or empty
     return (jsonObject2 == null || JSONObject.getNames(jsonObject2) == null);
   } else if (jsonObject2 == null || JSONObject.getNames(jsonObject2) == null) {
     return false;
   }
   final List<String> objectProperties1 = Arrays.asList(JSONObject.getNames(jsonObject1));
   Collections.sort(objectProperties1);
   final List<String> objectProperties2 = Arrays.asList(JSONObject.getNames(jsonObject2));
   Collections.sort(objectProperties2);
   // compare sorted propertynames
   if (!objectProperties1.equals(objectProperties2)) {
     log.debug(
         "Object:\n", objectProperties1, "didn't have same properties as:\n", objectProperties2);
     return false;
   }
   try {
     for (String key : objectProperties1) {
       final Object value1 = jsonObject1.get(key);
       final Object value2 = jsonObject2.get(key);
       if (value1 instanceof JSONObject) {
         if (!(value2 instanceof JSONObject)) {
           log.debug(value1, "was a JSONObject unlike", value2);
           return false;
         } else if (!isEqual((JSONObject) value1, (JSONObject) value2)) {
           log.debug("JSONObject recursion was not equal");
           return false;
         }
       } else if (value1 instanceof JSONArray) {
         if (!(value2 instanceof JSONArray)) {
           log.debug(value1, "was a JSONArray unlike", value2);
           return false;
         }
         if (!isEqual((JSONArray) value1, (JSONArray) value2)) {
           log.debug("JSONArrays were not equal");
           return false;
         }
       } else if (value1 == null) {
         if (value2 != null) {
           log.debug("value1 was <null>, but value2 was:" + value2);
           return false;
         }
       } else if (!value1.equals(value2)) {
         log.debug("Values were not equal:", value1, "!=", value2);
         return false;
       }
     }
   } catch (Exception ex) {
     log.warn(ex, "Error comparing JSONObjects");
     return false;
   }
   return true;
 }
Beispiel #14
0
 /**
  * Parses SLD style from a String (XML)
  *
  * @param xml
  * @return sld
  */
 private Style createSLDStyle(String xml) {
   if (xml == null) {
     log.info("Trying to create style from <null> String!");
     return null;
   }
   final Style style = createSLDStyle(new ByteArrayInputStream(xml.getBytes()));
   if (style == null) {
     log.warn("Couldn't create style from XML:", xml);
   }
   return style;
 }
  private String parseProperties(List<String> props, String ns, String geom_prop)
      throws ServiceException {

    try {
      return WFSFilterBuilder.parseProperties(props, ns, geom_prop);

    } catch (Exception e) {
      log.warn(e, "Properties parse failed");
    }

    return null;
  }
  public static String getTableTemplate(final String tableLayout) {

    try {
      final String resource =
          IOHelper.readString(OskariLayoutWorker.class.getResourceAsStream(tableLayout + ".json"));

      return resource;
    } catch (Exception ex) {
      log.warn(ex, "Error loading table layout template for tableLayout:", tableLayout);
    }
    return null;
  }
 private Bundle addBundle(final View view, final String bundleid) {
   Bundle bundle = view.getBundleByName(bundleid);
   if (bundle == null) {
     log.info("Bundle with id:", bundleid, "not found in currentView - adding");
     if (!bundleCache.containsKey(bundleid)) {
       log.warn("Trying to add bundle that isn't loaded:", bundleid, "- Skipping it!");
       return null;
     }
     bundle = bundleCache.get(bundleid).clone();
     view.addBundle(bundle);
   }
   return bundle;
 }
  /**
   * Sends list of feature geometries
   *
   * @param geometries
   * @param channel
   */
  protected void sendWFSFeatureGeometries(List<List<Object>> geometries, String channel) {
    if (geometries == null || geometries.size() == 0) {
      log.warn("Failed to send feature geometries");
      return;
    }
    Map<String, Object> output = new HashMap<String, Object>();
    output.put(OUTPUT_LAYER_ID, this.layerId);
    output.put(OUTPUT_GEOMETRIES, geometries);
    output.put(OUTPUT_KEEP_PREVIOUS, this.session.isKeepPrevious());

    log.debug("Sending", geometries.size(), "geometries");
    this.service.addResults(this.session.getClient(), channel, output);
  }
  /**
   * Fix the geometry property name for WFST transform Geometry property name in WPS method result
   * is not the same as in input featurecollections
   *
   * @param analysisLayer
   */
  private void fixGeometryPropertyName(AnalysisLayer analysisLayer) {

    try {

      AnalysisMethodParams params = analysisLayer.getAnalysisMethodParams();
      if (params.getMethod().equals(AnalysisParser.SPATIAL_JOIN_STATISTICS)) {
        params.setGeom("z_" + ((SpatialJoinStatisticsMethodParams) params).getGeom2());
      }

    } catch (Exception e) {
      log.warn("WPS geometry property name fix failed ", e);
    }
  }
  public void init() {
    // setup service if it hasn't been initialized
    if (viewService == null) {
      setViewService(new ViewServiceIbatisImpl());
    }

    if (myPlaceService == null) {
      setMyPlacesService(new MyPlacesServiceIbatisImpl());
    }

    if (permissionsService == null) {
      setPermissionsService(new PermissionsServiceIbatisImpl());
    }

    if (bundleService == null) {
      setBundleService(new BundleServiceIbatisImpl());
    }
    final String publishTemplateIdProperty = PropertyUtil.getOptional("view.template.publish");
    PUBLISHED_VIEW_TEMPLATE_ID =
        ConversionHelper.getLong(publishTemplateIdProperty, PUBLISHED_VIEW_TEMPLATE_ID);
    if (publishTemplateIdProperty == null) {
      log.warn("Publish template id not configured (property: view.template.publish)!");
    } else {
      log.info("Using publish template id: ", PUBLISHED_VIEW_TEMPLATE_ID);
    }

    // setup roles authorized to enable drawing tools on published map
    drawToolsEnabledRoles = PropertyUtil.getCommaSeparatedList(PROPERTY_DRAW_TOOLS_ENABLED);

    for (String bundleid : CACHED_BUNDLE_IDS) {
      final Bundle bundle = bundleService.getBundleTemplateByName(bundleid);
      if (bundle == null) {
        log.warn("Couldn't get", bundleid, "bundle template from DB!");
        continue;
      }
      bundleCache.put(bundleid, bundle);
    }
  }
Beispiel #21
0
 // we only link one theme at the moment so get the first one
 public InspireTheme getInspireTheme() {
   if (inspireThemes == null || inspireThemes.isEmpty()) {
     return null;
   }
   if (inspireThemes.size() > 1) {
     // TODO: remove this when we support more than one theme
     log.warn(
         "More than one inspire theme, this shouldn't happen!! layerId:",
         getId(),
         "- Themes:",
         inspireThemes);
   }
   return inspireThemes.iterator().next();
 }
  /**
   * Get property row order of aggregate result (
   *
   * @param analysejs analysis params
   * @return List of row names
   */
  private List<String> getRowOrder(JSONObject analysejs) {
    List<String> list = new ArrayList<String>();
    try {
      JSONArray fields = analysejs.getJSONArray(JSON_KEY_FIELDS);

      if (fields != null) {
        for (int i = 0; i < fields.length(); i++) {
          list.add(fields.getString(i));
        }
      }
    } catch (Exception e) {
      log.warn("Aggregate row order fetch failed ", e);
    }
    return list;
  }
  private void setupBundle(final View view, final JSONObject publisherData, final String bundleid) {

    final JSONObject bundleData = publisherData.optJSONObject(bundleid);
    if (bundleData != null && bundleData.names().length() > 0) {
      log.info("config found for", bundleid);
      final Bundle bundle = addBundle(view, bundleid);
      mergeBundleConfiguration(bundle, bundleData, null);
    } else {
      log.warn("config not found for", bundleid, "- removing bundle.");
      // We have to remove the bundle...
      // TODO: check if we really want to remove the bundle from view since it could be template
      // view???
      view.removeBundle(bundleid);
    }
  }
  /**
   * Sends image as an URL to IE 8 & 9, base64 data for others
   *
   * @param url
   * @param bufferedImage
   * @param bbox
   * @param isTiled
   */
  protected void sendWFSImage(
      String url,
      BufferedImage bufferedImage,
      Double[] bbox,
      boolean isTiled,
      boolean isboundaryTile) {
    if (bufferedImage == null) {
      log.warn("Failed to send image");
      return;
    }

    Map<String, Object> output = new HashMap<String, Object>();
    output.put(OUTPUT_LAYER_ID, this.layerId);

    Location location = this.session.getLocation();

    Tile tileSize = null;
    if (isTiled) {
      tileSize = this.session.getTileSize();
    } else {
      tileSize = this.session.getMapSize();
    }

    output.put(OUTPUT_IMAGE_SRS, location.getSrs());
    output.put(OUTPUT_IMAGE_BBOX, bbox);
    output.put(OUTPUT_IMAGE_ZOOM, location.getZoom());
    output.put(OUTPUT_IMAGE_TYPE, this.type.toString()); // "normal" | "highlight"
    output.put(OUTPUT_KEEP_PREVIOUS, this.session.isKeepPrevious());
    output.put(OUTPUT_BOUNDARY_TILE, isboundaryTile);
    output.put(OUTPUT_IMAGE_WIDTH, tileSize.getWidth());
    output.put(OUTPUT_IMAGE_HEIGHT, tileSize.getHeight());
    output.put(OUTPUT_IMAGE_URL, url);

    byte[] byteImage = WFSImage.imageToBytes(bufferedImage);
    String base64Image = WFSImage.bytesToBase64(byteImage);
    int base64Size = (base64Image.length() * 2) / 1024;

    // IE6 & IE7 doesn't support base64, max size in base64 for IE8 is 32KB
    if (!(this.session.getBrowser().equals(BROWSER_MSIE) && this.session.getBrowserVersion() < 8
        || this.session.getBrowser().equals(BROWSER_MSIE)
            && this.session.getBrowserVersion() == 8
            && base64Size >= 32)) {
      output.put(OUTPUT_IMAGE_DATA, base64Image);
    }

    this.service.addResults(this.session.getClient(), ResultProcessor.CHANNEL_IMAGE, output);
  }
 /**
  * Get property column order of aggregate result (
  *
  * @param analysejs analysis params
  * @return List of localised method names
  */
 private List<String> getColumnOrder(JSONObject analysejs) {
   List<String> list = new ArrayList<String>();
   try {
     JSONArray locales =
         analysejs.getJSONObject(JSON_KEY_METHODPARAMS).optJSONArray(JSON_KEY_LOCALES);
     JSONArray aggre_funcs =
         analysejs.getJSONObject(JSON_KEY_METHODPARAMS).optJSONArray(JSON_KEY_FUNCTIONS);
     if (locales != null && aggre_funcs.length() == locales.length()) {
       for (int i = 0; i < locales.length(); i++) {
         list.add(locales.getString(i));
       }
     }
   } catch (Exception e) {
     log.warn("Aggregate column order fetch failed ", e);
   }
   return list;
 }
  /**
   * Pure localisation of aggregate result function names
   *
   * @param result
   * @param analysejs
   * @return localised result text
   */
  private String localiseAggregateResult(String result, JSONObject analysejs) {

    try {
      JSONArray locales =
          analysejs.getJSONObject(JSON_KEY_METHODPARAMS).optJSONArray(JSON_KEY_LOCALES);
      JSONArray aggre_funcs =
          analysejs.getJSONObject(JSON_KEY_METHODPARAMS).optJSONArray(JSON_KEY_FUNCTIONS);
      if (locales != null && aggre_funcs.length() == locales.length()) {
        for (int i = 0; i < locales.length(); i++) {
          String funcName = aggre_funcs.getString(i);
          // Plääh WPS funcnames are not equal to result names
          if (funcName.equals(AGGREGATE_STDDEV_WPS_IN)) funcName = AGGREGATE_STDDEV_WPS_OUT;
          result = result.replace(funcName, locales.getString(i));
        }
      }
    } catch (Exception e) {
      log.warn("Aggregate result localisation failed ", e);
    }
    return result;
  }
Beispiel #27
0
 /**
  * Compares 2 JSONArrays for equality.
  *
  * @param jsonArray1
  * @param jsonArray2
  * @return
  */
 public static boolean isEqual(JSONArray jsonArray1, JSONArray jsonArray2) {
   if (jsonArray1.length() != jsonArray2.length()) {
     return false;
   }
   if (jsonArray1.length() == 0) {
     return true;
   }
   for (int i = 0; i < jsonArray1.length(); ++i) {
     try {
       final Object value1 = jsonArray1.get(i);
       final Object value2 = jsonArray2.get(i);
       if (value1 instanceof JSONObject && value2 instanceof JSONObject) {
         if (!isEqual((JSONObject) value1, (JSONObject) value2)) {
           log.debug(
               "Array content was JSONObjects but they were not equal:", value1, "!=", value2);
           return false;
         }
       } else if (value1 instanceof JSONArray && value2 instanceof JSONArray) {
         if (!isEqual((JSONArray) value1, (JSONArray) value2)) {
           log.debug(
               "Array content was JSONArrays but they were not equal:", value1, "!=", value2);
           return false;
         }
       } else if (value1 == null && value2 != null) {
         log.debug("Array1 had <null>, but Array2 had a value:", value2);
         return false;
       } else if (value1 != null && value2 == null) {
         log.debug("Array1 had value", value1, ", but Array2 had <null>");
         return false;
       } else if (value1 != null && value2 != null && !value1.equals(value2)) {
         log.debug("Array values didn't match:", value1, value2);
         return false;
       }
     } catch (Exception ex) {
       log.warn(ex, "Error comparing JSONArrays");
       return false;
     }
   }
   return true;
 }
  /**
   * Sends properties (fields and locales)
   *
   * @param fields
   * @param locales
   */
  protected void sendWFSProperties(List<String> fields, List<String> locales) {
    if (fields == null || fields.size() == 0) {
      log.warn("Failed to send properties");
      return;
    }

    if (!fields.contains("__fid")) fields.add(0, "__fid");
    if (!fields.contains("__centerX")) fields.add("__centerX");
    if (!fields.contains("__centerY")) fields.add("__centerY");

    if (locales != null && !locales.isEmpty()) {
      locales.add(0, "ID");
      locales.add("x");
      locales.add("y");
    } else {
      locales = new ArrayList<String>();
    }
    Map<String, Object> output = new HashMap<String, Object>();
    output.put(OUTPUT_LAYER_ID, this.layerId);
    output.put(OUTPUT_FIELDS, fields);
    output.put(OUTPUT_LOCALES, locales);

    this.service.addResults(this.session.getClient(), ResultProcessor.CHANNEL_PROPERTIES, output);
  }
Beispiel #29
0
  /**
   * Creates a image of the WFS layer's data
   *
   * @param tile
   * @param location
   * @param bounds
   * @param features
   * @return image
   */
  public BufferedImage draw(
      Tile tile,
      Location location,
      List<Double> bounds,
      FeatureCollection<SimpleFeatureType, SimpleFeature> features) {

    this.imageWidth = tile.getWidth();
    this.imageHeight = tile.getHeight();

    if (bounds == null) {
      this.location = location;
    } else {
      this.location = new Location(location.getSrs());
      this.location.setBbox(bounds);

      // enlarge if tile and buffer is defined
      this.isTile = true;
      if (bufferSize != 0.0d) {
        this.bufferedImageWidth = imageWidth + (int) (imageWidth * bufferSize);
        this.bufferedImageHeight = imageHeight + (int) (imageWidth * bufferSize);
      }
    }

    this.features = features;

    if (imageWidth == 0
        || imageHeight == 0
        || this.location == null
        || style == null
        || features == null) {
      log.warn("Not enough information to draw");
      log.warn(imageWidth);
      log.warn(imageHeight);
      log.warn(location);
      log.warn(style);
      log.warn(features.isEmpty());
      return null;
    }

    return this.draw();
  }
  /**
   * Handles action_route CreateAnalysisLayer
   *
   * @param params Ajax request parameters
   *     **********************************************************************
   */
  public void handleAction(ActionParameters params) throws ActionException {

    if (params.getUser().isGuest()) {
      throw new ActionDeniedException("Session expired");
    }

    final String analyse = params.getRequiredParam(PARAM_ANALYSE, ERROR_ANALYSE_PARAMETER_MISSING);
    JSONObject analyseJson = JSONHelper.createJSONObject(analyse);
    if (analyseJson == null) {
      // json corrupted/parsing failed
      throw new ActionParamsException(ERROR_ANALYSE_PARAMETER_MISSING);
    }

    // filter conf data
    final String filter1 = params.getHttpParam(PARAM_FILTER1);
    final String filter2 = params.getHttpParam(PARAM_FILTER2);

    // Get baseProxyUrl
    final String baseUrl = getBaseProxyUrl(params);

    // User
    String uuid = params.getUser().getUuid();
    // note! analysisLayer is replaced in aggregate handling!!
    AnalysisLayer analysisLayer = getAnalysisLayer(analyseJson, filter1, filter2, baseUrl, uuid);
    Analysis analysis = null;

    if (analysisLayer.getMethod().equals(AnalysisParser.LAYER_UNION)) {
      // no WPS for merge analysis
      analysis = analysisDataService.mergeAnalysisData(analysisLayer, analyse, params.getUser());
    } else {
      // Generate WPS XML
      String featureSet = executeWPSprocess(analysisLayer);
      if (analysisLayer.getMethod().equals(AnalysisParser.UNION)
          || analysisLayer.getMethod().equals(AnalysisParser.INTERSECT)
          || analysisLayer.getMethod().equals(AnalysisParser.SPATIAL_JOIN)) {
        // Harmonize namespaces and element names
        featureSet = analysisParser.harmonizeElementNames(featureSet, analysisLayer);
      }

      // Add data to analysis db  - we must create still an union in aggregate case
      if (analysisLayer.getMethod().equals(AnalysisParser.AGGREGATE)) {
        // No store to analysis db for aggregate - set results in to the
        // response
        // Save analysis results - use union of input data
        analysisLayer.setWpsLayerId(-1);
        final String aggregateResult =
            this.localiseAggregateResult(
                analysisParser.parseAggregateResults(featureSet, analysisLayer), analyseJson);
        log.debug("\nAggregate results:\n", aggregateResult, "\n");
        /*
        Aggregate results:
         {"fi_url_1":{"Count":4},"tmp_id":{"Sum":45301,"Median":12232,"Count":4,"Standar
        d deviation":3186.3551571505645,"Maximum":14592,"Average":11325.25,"Minimum":624
        5},"fi_url_3":{"Count":4},"postinumero":{"Count":4},"fi_url_2":{"Count":4},"fi_s
        posti_1":{"Count":4},"kuntakoodi":{"Count":4},"fi_osoite":{"Count":4},"fi_nimi":
        {"Count":4},"kto_tarkennus":{"Count":4}}
                         */
        analysisLayer.setResult(aggregateResult);

        // Get geometry for aggretage features
        try {
          // Just return result as JSON and don't save analysis to DB
          if (!params.getHttpParam(PARAM_SAVE_BLN, true)) {
            // NOTE!! Replacing the analysisLayer!
            // Get response as geojson when no db store
            analysisLayer =
                getAggregateLayer(analyse, filter1, filter2, baseUrl, analysisLayer, JSONFORMAT);
            featureSet = wpsService.requestFeatureSet(analysisLayer);
            // Just return result as JSON and don't save analysis to DB
            // Get geometry as geojson for hilighting features of aggregate result
            JSONObject geojson = JSONHelper.createJSONObject(featureSet);
            JSONObject jsaggregate = JSONHelper.createJSONObject(aggregateResult);
            JSONObject results = new JSONObject();
            JSONHelper.putValue(results, JSON_KEY_GEOJSON, geojson);
            JSONHelper.putValue(results, JSON_KEY_AGGREGATE_RESULT, jsaggregate);
            ResponseHelper.writeResponse(params, results);
            return;
          }
          // NOTE!! Replacing the analysisLayer!  - response is gml
          analysisLayer =
              getAggregateLayer(analyse, filter1, filter2, baseUrl, analysisLayer, null);
          featureSet = wpsService.requestFeatureSet(analysisLayer);
          // Harmonize namespaces and element names
          featureSet = analysisParser.harmonizeElementNames(featureSet, analysisLayer);
          featureSet =
              analysisParser.mergeAggregateResults2FeatureSet(
                  featureSet,
                  analysisLayer,
                  this.getRowOrder(analyseJson),
                  this.getColumnOrder(analyseJson));
          // Redefine column types
          analysisLayer.setFieldtypeMap(
              this.getAggregateFieldTypes(this.getColumnOrder(analyseJson)));
        } catch (ServiceException e) {
          throw new ActionException(ERROR_UNABLE_TO_GET_FEATURES_FOR_UNION, e);
        }
      }
      // Add extra TypeNames (depends on wps method)
      analysisParser.fixTypeNames(analysisLayer);

      // Fix geometry property name for WFST (could be any, depends on Wps method )
      fixGeometryPropertyName(analysisLayer);

      analysis =
          analysisDataService.storeAnalysisData(
              featureSet, analysisLayer, analyse, params.getUser());
    }

    if (analysis == null) {
      this.MyError(ERROR_UNABLE_TO_STORE_ANALYSIS_DATA, params, null);
      return;
    }

    analysisLayer.setWpsLayerId(analysis.getId()); // aka. analysis_id
    // Analysis field mapping
    analysisLayer.setLocaleFields(analysis);
    analysisLayer.setNativeFields(analysis);

    // copy permissions from source layer to new analysis
    final Resource sourceResource =
        getSourcePermission(analysisParser.getSourceLayerId(analyseJson), params.getUser());
    if (sourceResource != null) {
      final Resource analysisResource = new Resource();
      analysisResource.setType(AnalysisLayer.TYPE);
      analysisResource.setMapping("analysis", Long.toString(analysis.getId()));
      for (Permission p : sourceResource.getPermissions()) {
        // check if user has role matching permission?
        if (p.isOfType(Permissions.PERMISSION_TYPE_PUBLISH)
            || p.isOfType(Permissions.PERMISSION_TYPE_VIEW_PUBLISHED)) {
          analysisResource.addPermission(p.clonePermission());
        }
      }
      log.debug(
          "Trying to save permissions for analysis",
          analysisResource,
          analysisResource.getPermissions());
      permissionsService.saveResourcePermissions(analysisResource);
    } else {
      log.warn("Couldn't get source permissions for analysis, result will have none");
    }

    // Get analysisLayer JSON for response to front
    final JSONObject analysisLayerJSON = AnalysisHelper.getlayerJSON(analysis);

    // Additional param for new layer creation when merging layers:
    // - Notify client to remove merged layers since they are removed from backend
    JSONArray mlayers = new JSONArray();
    if (analysisLayer.getMergeAnalysisLayers() != null) {
      for (String lay : analysisLayer.getMergeAnalysisLayers()) {
        mlayers.put(lay);
      }
    }
    JSONHelper.putValue(analysisLayerJSON, "mergeLayers", mlayers);

    Set<String> permissionsList = permissionsService.getPublishPermissions(AnalysisLayer.TYPE);
    Set<String> downloadPermissionsList =
        permissionsService.getDownloadPermissions(AnalysisLayer.TYPE);
    Set<String> editAccessList = null;
    String permissionKey = "analysis+" + analysis.getId();
    JSONObject permissions =
        OskariLayerWorker.getPermissions(
            params.getUser(),
            permissionKey,
            permissionsList,
            downloadPermissionsList,
            editAccessList);
    JSONHelper.putValue(analysisLayerJSON, "permissions", permissions);

    ResponseHelper.writeResponse(params, analysisLayerJSON);
  }