All Downloads are FREE. Search and download functionalities are using the official Maven repository.

jlibs.core.graph.Ladder Maven / Gradle / Ivy

There is a newer version: 3.0.1
Show newest version
/**
 * Copyright 2015 Santhosh Kumar Tekuri
 *
 * The JLibs authors license this file to you 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 jlibs.core.graph;

/**
 * @author Santhosh Kumar T
 */
public abstract class Ladder{
    public abstract E parent(E elem);

    public int getHeight(E fromElem, E toElem){
        if(fromElem==null)
            return -1;

        int ht = 0;
        while(fromElem!=toElem){
            fromElem = parent(fromElem);
            ht++;
        }
        return ht;
    }

    public int getHeight(E elem){
        return getHeight(elem, null);
    }

    @SuppressWarnings("unchecked")
    public  A getParent(E elem, Class clazz){
        if(elem==null)
            return null;

        do{
            elem = parent(elem);
        }while(elem!=null && !clazz.isInstance(elem));

        return (A)elem;
    }

    @SuppressWarnings("unchecked")
    public  A getAncestor(E elem, Class clazz){
        if(clazz.isInstance(elem))
            return (A)elem;
        else
            return getParent(elem, clazz);
    }

    public E getRoot(E elem){
        if(elem==null)
            return null;

        E parent = parent(elem);
        while(parent!=null){
            elem = parent;
            parent = parent(elem);
        }
        return elem;
    }

    public E getSharedAncestor(E elem1, E elem2){
        if(elem1==elem2)
            return elem1;
        if(elem1==null || elem2==null)
            return null;

        int ht1 = getHeight(elem1);
        int ht2 = getHeight(elem2);

        int diff;
        if(ht1>ht2)
            diff = ht1 - ht2;
        else{
            diff = ht2 - ht1;
            E temp = elem1;
            elem1 = elem2;
            elem2 = temp;
        }

        // Go up the tree until the nodes are at the same level
        while(diff>0){
            elem1 = parent(elem1);
            diff--;
        }

        // Move up the tree until we find a common ancestor.  Since we know
        // that both nodes are at the same level, we won't cross paths
        // unknowingly (if there is a common ancestor, both nodes hit it in
        // the same iteration).
        do{
            if(elem1.equals(elem2))
                return elem1;
            elem1 = parent(elem1);
            elem2 = parent(elem2);
        }while(elem1 != null); // only need to check one -- they're at the
                               // same level so if one is null, the other is

        return null;
    }

    public boolean isAncestor(E elem, E ancestor){
        if(ancestor==null)
            return false;

        while(elem!=null){
            if(elem==ancestor)
                return true;
            elem = parent(elem);
        }
        return false;
    }

    public boolean isRelated(E elem1, E elem2){
        return !(elem1==null || elem2==null) && getRoot(elem1)==getRoot(elem2);
    }

    public String getPath(E elem, Convertor convertor, String separator){
        StringBuilder buff = new StringBuilder();
        while(elem!=null){
            if(buff.length()>0)
                buff.insert(0, separator);
            buff.insert(0, convertor.convert(elem));
            elem = parent(elem);
        }
        return buff.toString();
    }

    public String getRelativePath(E fromElem, E toElem, Convertor convertor, String separator){
        if(fromElem==toElem)
            return ".";

        E sharedAncestor = getSharedAncestor(fromElem, toElem);
        if(sharedAncestor==null)
            return null;

        StringBuilder buff1 = new StringBuilder();
        while(!fromElem.equals(sharedAncestor)){
            if(buff1.length()>0)
                buff1.append(separator);
            buff1.append("..");
            fromElem = parent(fromElem);
        }

        StringBuilder buff2 = new StringBuilder();
        while(!toElem.equals(sharedAncestor)){
            if(buff2.length()>0)
                buff2.insert(0, separator);

            buff2.insert(0, convertor.convert(toElem));

            toElem = parent(toElem);
        }

        if(buff1.length()>0 && buff2.length()>0)
            return buff1+separator+buff2;
        else
            return buff1.length()>0 ? buff1.toString() : buff2.toString();
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy