@DefaultHandler
  public Resolution view() throws JSONException, IOException {
    application = findApplication(name, version);

    if (application == null) {
      getContext()
          .getValidationErrors()
          .addGlobalError(
              new LocalizableError("app.notfound", name + (version != null ? " v" + version : "")));
      return new ForwardResolution("/WEB-INF/jsp/error.jsp");
    }

    RedirectResolution login =
        new RedirectResolution(LoginActionBean.class)
            .addParameter("name", name) // binded parameters not included ?
            .addParameter("version", version)
            .addParameter("debug", debug)
            .includeRequestParameters(true);

    loginUrl = login.getUrl(context.getLocale());

    String username = context.getRequest().getRemoteUser();
    if (application.isAuthenticatedRequired() && username == null) {
      return login;
    }

    if (username != null) {
      user = new JSONObject();
      user.put("name", username);
      JSONObject roles = new JSONObject();
      user.put("roles", roles);
      for (String role : Authorizations.getRoles(context.getRequest())) {
        roles.put(role, Boolean.TRUE);
      }
    }

    buildComponentSourceHTML();

    appConfigJSON = application.toJSON(context.getRequest(), false, false);
    this.viewerType = retrieveViewerType();

    // make hashmap for jsonobject.
    this.globalLayout = new HashMap<String, Object>();
    JSONObject layout = application.getGlobalLayout();
    Iterator<String> keys = layout.keys();
    while (keys.hasNext()) {
      String key = keys.next();
      this.globalLayout.put(key, layout.get(key));
    }
    return new ForwardResolution("/WEB-INF/jsp/app.jsp");
  }
  public Resolution save() throws JSONException {
    // Only remove details which are editable and re-added layer if not empty,
    // retain other details possibly used in other parts than this page
    // See JSP for which keys are edited
    applicationLayer
        .getDetails()
        .keySet()
        .removeAll(
            Arrays.asList(
                "titleAlias",
                "legendImageUrl",
                "transparency",
                "influenceradius",
                "summary.title",
                "summary.image",
                "summary.description",
                "summary.link",
                "editfunction.title",
                "style",
                "summary.noHtmlEncode",
                "summary.nl2br"));
    for (Map.Entry<String, String> e : details.entrySet()) {
      if (e.getValue() != null) { // Don't insert null value ClobElement
        applicationLayer.getDetails().put(e.getKey(), new ClobElement(e.getValue()));
      }
    }

    applicationLayer.getReaders().clear();
    for (String groupName : groupsRead) {
      applicationLayer.getReaders().add(groupName);
    }

    applicationLayer.getWriters().clear();
    for (String groupName : groupsWrite) {
      applicationLayer.getWriters().add(groupName);
    }

    if (applicationLayer.getAttributes() != null && applicationLayer.getAttributes().size() > 0) {
      List<ConfiguredAttribute> appAttributes = applicationLayer.getAttributes();
      int i = 0;

      for (Iterator it = appAttributes.iterator(); it.hasNext(); ) {
        ConfiguredAttribute appAttribute = (ConfiguredAttribute) it.next();
        // save visible
        if (selectedAttributes.contains(appAttribute.getFullName())) {
          appAttribute.setVisible(true);
        } else {
          appAttribute.setVisible(false);
        }

        // save editable
        if (attributesJSON.length() > i) {
          JSONObject attribute = attributesJSON.getJSONObject(i);

          if (attribute.has("editable")) {
            appAttribute.setEditable(new Boolean(attribute.get("editable").toString()));
          }
          if (attribute.has("editalias")) {
            appAttribute.setEditAlias(attribute.get("editalias").toString());
          }
          if (attribute.has("editvalues")) {
            appAttribute.setEditValues(attribute.get("editvalues").toString());
          }
          if (attribute.has("editHeight")) {
            appAttribute.setEditHeight(attribute.get("editHeight").toString());
          }

          // save selectable
          if (attribute.has("selectable")) {
            appAttribute.setSelectable(new Boolean(attribute.get("selectable").toString()));
          }
          if (attribute.has("filterable")) {
            appAttribute.setFilterable(new Boolean(attribute.get("filterable").toString()));
          }

          if (attribute.has("defaultValue")) {
            appAttribute.setDefaultValue(attribute.get("defaultValue").toString());
          }
        }
        i++;
      }
    }

    Stripersist.getEntityManager().persist(applicationLayer);
    application.authorizationsModified();

    displayName = applicationLayer.getDisplayName();

    Stripersist.getEntityManager().getTransaction().commit();

    getContext().getMessages().add(new SimpleMessage("De kaartlaag is opgeslagen"));
    return edit();
  }