org.hippoecm.frontend.plugins.console.menu.open.OpenDialog.java Source code

Java tutorial

Introduction

Here is the source code for org.hippoecm.frontend.plugins.console.menu.open.OpenDialog.java

Source

/*
 * Copyright 2012-2014 Hippo B.V. (http://www.onehippo.com)
 *
 * 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 org.hippoecm.frontend.plugins.console.menu.open;

import java.util.Collection;
import java.util.Iterator;
import java.util.TreeSet;

import javax.jcr.Node;
import javax.jcr.NodeIterator;
import javax.jcr.PathNotFoundException;
import javax.jcr.RepositoryException;
import javax.jcr.Session;

import org.apache.wicket.extensions.ajax.markup.html.autocomplete.AutoCompleteSettings;
import org.apache.wicket.extensions.ajax.markup.html.autocomplete.AutoCompleteTextField;
import org.apache.wicket.extensions.ajax.markup.html.autocomplete.DefaultCssAutoCompleteTextField;
import org.apache.wicket.markup.head.CssHeaderItem;
import org.apache.wicket.markup.head.IHeaderResponse;
import org.apache.wicket.markup.head.OnDomReadyHeaderItem;
import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.model.IModel;
import org.apache.wicket.model.Model;
import org.apache.wicket.model.PropertyModel;
import org.apache.wicket.request.resource.CssResourceReference;
import org.apache.wicket.util.value.IValueMap;
import org.apache.wicket.util.value.ValueMap;
import org.hippoecm.frontend.dialog.AbstractDialog;
import org.hippoecm.frontend.model.JcrNodeModel;
import org.hippoecm.frontend.plugins.console.NodeModelReference;
import org.hippoecm.frontend.session.UserSession;
import org.hippoecm.repository.api.StringCodecFactory;

public class OpenDialog extends AbstractDialog<Node> {

    private final String WICKET_ELEMENT_ID = "pathOrId";

    private static final long serialVersionUID = 1L;
    private String pathOrId;
    private NodeModelReference modelReference;

    public OpenDialog(final NodeModelReference modelReference) {
        this.modelReference = modelReference;
        IModel<String> labelModel = new Model<>("Path or UUID");
        add(new Label("label", labelModel));
        add(setFocus(makeValueField(getValueCurrentlySelectedJcrNode())));
    }

    private AutoCompleteTextField<String> makeValueField(final PropertyModel<String> value) {
        return new AutoCompleteTextField<String>(WICKET_ELEMENT_ID, value, getAutoCompleteSettings()) {
            private static final long serialVersionUID = 1L;

            @Override
            protected Iterator<String> getChoices(String input) {
                Collection<String> result = new TreeSet<>();
                addMatchingNodes(input, result);
                return result.iterator();
            }

            @Override
            public void renderHead(final IHeaderResponse response) {
                super.renderHead(response);
                String script = "document.getElementById('" + getMarkupId() + "').focus(); "
                        + "document.getElementById('" + getMarkupId() + "').select();";
                response.render(OnDomReadyHeaderItem.forScript(script));
                response.render(CssHeaderItem.forReference(new CssResourceReference(
                        DefaultCssAutoCompleteTextField.class, "DefaultCssAutoCompleteTextField.css")));
            }
        };
    }

    private PropertyModel<String> getValueCurrentlySelectedJcrNode() {
        PropertyModel<String> value = new PropertyModel<>(this, WICKET_ELEMENT_ID);
        final Node node = modelReference.getModel().getObject();
        try {
            value.setObject(node.getPath());
        } catch (RepositoryException e) {
            e.printStackTrace();
        }
        return value;
    }

    private AutoCompleteSettings getAutoCompleteSettings() {
        AutoCompleteSettings settings = new AutoCompleteSettings();
        settings.setAdjustInputWidth(false).setUseSmartPositioning(true).setShowCompleteListOnFocusGain(true)
                .setShowListOnEmptyInput(true);
        return settings;
    }

    private void addMatchingNodes(String path, Collection<String> result) {
        String relPath = path.substring(1);
        try {
            NodeIterator nodes = getNodesFromRelativePath(relPath);
            while (nodes.hasNext()) {
                result.add(nodes.nextNode().getPath());
            }
        } catch (PathNotFoundException e) {
            addNodesMatchingOnSubstring(relPath, result);
        } catch (RepositoryException e) {
            e.printStackTrace();
        }
    }

    private NodeIterator getNodesFromRelativePath(String relPath) throws RepositoryException {
        Node node = UserSession.get().getRootNode();
        if (!relPath.isEmpty()) {
            relPath = removeDoubleSlashes(relPath);
            Node nodeAtPath = getNodeIgnoreException(node, relPath);
            if (nodeAtPath != null) {
                node = nodeAtPath;
            } else {
                // Special characters (such as colon, eg in "/hst:hst") result in false negatives.
                String encRelPath = StringCodecFactory.ISO9075Helper.encodeLocalName(relPath);
                nodeAtPath = getNodeIgnoreException(node, encRelPath);
                if (nodeAtPath != null) {
                    node = nodeAtPath;
                } else {
                    throw new PathNotFoundException("Couldn't find node with relative path: " + relPath);
                }
            }
        }
        return node.getNodes();
    }

    private String removeDoubleSlashes(String path) {
        while (path.contains("//")) {
            path = path.replace("//", "/");
        }
        return path;
    }

    private Node getNodeIgnoreException(Node node, String path) {
        try {
            return node.getNode(path);
        } catch (RepositoryException e) {
            //ignore
        }
        return null;
    }

    private void addNodesMatchingOnSubstring(String relPath, Collection<String> result) {
        String subPath = relPath.substring(0, relPath.lastIndexOf('/') + 1);
        String remainingQuery = relPath.substring(subPath.length());
        try {
            NodeIterator nodes = getNodesFromRelativePath(subPath);
            while (nodes.hasNext()) {
                final Node node = nodes.nextNode();
                if (node.getName().startsWith(remainingQuery)) {
                    result.add(node.getPath());
                }
            }
        } catch (RepositoryException e) {
            e.printStackTrace();
        }
    }

    @Override
    protected void onOk() {
        pathOrId = pathOrId.trim();
        Session jcrSession = UserSession.get().getJcrSession();
        Node selected = null;
        try {
            if (pathOrId.startsWith("/")) {
                if (jcrSession.nodeExists(pathOrId)) {
                    selected = jcrSession.getNode(pathOrId);
                }
            } else {
                final Node parentNode = modelReference.getModel().getObject();
                if (parentNode.hasNode(pathOrId)) {
                    selected = parentNode.getNode(pathOrId);
                } else {
                    selected = jcrSession.getNodeByIdentifier(pathOrId);
                }
            }
        } catch (RepositoryException e) {
            //ignore
        }

        if (selected == null) {
            error("Node was not found, please try again.");
        } else {
            modelReference.setModel(new JcrNodeModel(selected));
        }
    }

    @Override
    public IModel getTitle() {
        return new Model<String>("Open node by path or UUID");
    }

    @Override
    public IValueMap getProperties() {
        return new ValueMap("width=640,height=200").makeImmutable();
    }
}