org.codinjutsu.tools.nosql.redis.view.RedisFragmentedKeyTreeModel.java Source code

Java tutorial

Introduction

Here is the source code for org.codinjutsu.tools.nosql.redis.view.RedisFragmentedKeyTreeModel.java

Source

/*
 * Copyright (c) 2015 David Boissier
 *
 * 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.codinjutsu.tools.nosql.redis.view;

import org.codinjutsu.tools.nosql.commons.utils.StringUtils;
import org.codinjutsu.tools.nosql.commons.view.NoSqlTreeNode;
import org.codinjutsu.tools.nosql.commons.view.nodedescriptor.NodeDescriptor;
import org.codinjutsu.tools.nosql.redis.view.nodedescriptor.FragmentedKeyNodeDescriptor;
import org.codinjutsu.tools.nosql.redis.view.nodedescriptor.RedisKeyValueDescriptor;

import javax.swing.event.TreeModelListener;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.MutableTreeNode;
import java.util.Arrays;
import java.util.Enumeration;

import static org.apache.commons.lang.StringUtils.isEmpty;

public class RedisFragmentedKeyTreeModel extends DefaultTreeModel {

    private String separator;
    private DefaultTreeModel fragmentedKeyModel;

    private boolean needsUpdate = true;

    public RedisFragmentedKeyTreeModel(NoSqlTreeNode root) {
        super(root);
        this.separator = "";
    }

    public void setSeparator(String separator) {
        this.separator = separator;
        needsUpdate = true;
        fireSeparatorChanged();
    }

    public void resetSeparator() {
        this.separator = "";
        needsUpdate = true;
        fireSeparatorChanged();
    }

    @Override
    public DefaultMutableTreeNode getRoot() {
        return (DefaultMutableTreeNode) getFragmentedKeyModel().getRoot();
    }

    @Override
    public void reload() {
        super.reload();
        getFragmentedKeyModel().reload();
        needsUpdate = true;
        fireSeparatorChanged();
    }

    @Override
    public int getChildCount(Object parent) {
        return getFragmentedKeyModel().getChildCount(parent);
    }

    @Override
    public Object getChild(Object parent, int index) {
        return getFragmentedKeyModel().getChild(parent, index);
    }

    @Override
    public int getIndexOfChild(Object parent, Object child) {
        return getFragmentedKeyModel().getIndexOfChild(parent, child);
    }

    @Override
    public void addTreeModelListener(TreeModelListener listener) {
        super.addTreeModelListener(listener);
        getFragmentedKeyModel().addTreeModelListener(listener);
    }

    @Override
    public void removeTreeModelListener(TreeModelListener listener) {
        super.removeTreeModelListener(listener);
        getFragmentedKeyModel().removeTreeModelListener(listener);
    }

    @Override
    public boolean isLeaf(Object node) {
        return getFragmentedKeyModel().isLeaf(node);
    }

    private DefaultTreeModel getFragmentedKeyModel() {
        if (needsUpdate) {
            needsUpdate = false;
            updateFilteredModel();
        }
        return fragmentedKeyModel;
    }

    private void updateFilteredModel() {
        DefaultMutableTreeNode sourceRoot = (DefaultMutableTreeNode) super.getRoot();
        DefaultMutableTreeNode targetRoot = (DefaultMutableTreeNode) sourceRoot.clone();
        wrapNodes(sourceRoot, separator);
        fragmentedKeyModel = new DefaultTreeModel(targetRoot);
        Object[] listeners = listenerList.getListenerList();
        for (int i = listeners.length - 2; i >= 0; i -= 2) {
            if (listeners[i] == TreeModelListener.class) {
                fragmentedKeyModel.addTreeModelListener((TreeModelListener) listeners[i + 1]);
            }
        }
        fireSeparatorChanged();
    }

    private void fireSeparatorChanged() {
        getFragmentedKeyModel().reload();
    }

    public static DefaultMutableTreeNode wrapNodes(DefaultMutableTreeNode source, String separator) {
        if (isEmpty(separator)) {
            return source;
        }
        DefaultMutableTreeNode targetRootNode = (DefaultMutableTreeNode) source.clone();
        for (int i = 0; i < source.getChildCount(); i++) {
            DefaultMutableTreeNode originalChildNode = (DefaultMutableTreeNode) source.getChildAt(i);
            NoSqlTreeNode clonedChildNode = (NoSqlTreeNode) originalChildNode.clone();
            RedisKeyValueDescriptor descriptor = (RedisKeyValueDescriptor) clonedChildNode.getDescriptor();
            String[] explodedKey = StringUtils.explode(descriptor.getKey(), separator);
            if (explodedKey.length == 1) {
                addChildren(clonedChildNode, originalChildNode);
                targetRootNode.add(clonedChildNode);
            } else {
                updateTree(targetRootNode, originalChildNode, explodedKey, descriptor);
            }
        }
        return targetRootNode;
    }

    private static void updateTree(DefaultMutableTreeNode parentTargetNode,
            DefaultMutableTreeNode originalChildNode, String[] explodedKey,
            RedisKeyValueDescriptor sourceDescriptor) {
        if (explodedKey.length == 0) {
            addChildren(parentTargetNode, originalChildNode);
            return;
        }
        String keyFragment = explodedKey[0];
        NoSqlTreeNode node = findNodeByKey(parentTargetNode, keyFragment);
        if (node == null) {
            if (explodedKey.length == 1) {
                node = new NoSqlTreeNode(RedisKeyValueDescriptor.createDescriptor(sourceDescriptor.getKeyType(),
                        keyFragment, sourceDescriptor.getValue()));
            } else {
                node = new NoSqlTreeNode(FragmentedKeyNodeDescriptor.createDescriptor(keyFragment));
            }
        }
        updateTree(node, originalChildNode, Arrays.copyOfRange(explodedKey, 1, explodedKey.length),
                sourceDescriptor);

        parentTargetNode.add(node);
    }

    private static NoSqlTreeNode findNodeByKey(DefaultMutableTreeNode parentTargetNode, String keyFragment) {
        for (int i = 0; i < parentTargetNode.getChildCount(); i++) {
            NoSqlTreeNode currentChild = (NoSqlTreeNode) parentTargetNode.getChildAt(i);
            NodeDescriptor descriptor = currentChild.getDescriptor();
            String nodeKey;
            if (descriptor instanceof FragmentedKeyNodeDescriptor) {
                nodeKey = ((FragmentedKeyNodeDescriptor) descriptor).getKeyFragment();
            } else if (descriptor instanceof RedisKeyValueDescriptor) {
                nodeKey = ((RedisKeyValueDescriptor) descriptor).getKey();
            } else {
                return null;
            }
            if (keyFragment.equals(nodeKey)) {
                return currentChild;
            }
        }
        return null;
    }

    private static void addChildren(DefaultMutableTreeNode parentNode, DefaultMutableTreeNode originalChildNode) {
        Enumeration children = originalChildNode.children();
        while (children.hasMoreElements()) {
            DefaultMutableTreeNode childNode = (DefaultMutableTreeNode) children.nextElement();
            parentNode.add((MutableTreeNode) childNode.clone());
        }
    }
}