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

com.enonic.xp.node.NodePath Maven / Gradle / Ivy

There is a newer version: 7.14.4
Show newest version
package com.enonic.xp.node;


import java.io.Serializable;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

import com.google.common.base.Preconditions;
import com.google.common.base.Splitter;

import com.enonic.xp.annotation.PublicApi;

import static com.google.common.base.Strings.isNullOrEmpty;

@PublicApi
public final class NodePath
    implements Comparable, Serializable
{
    private static final long serialVersionUID = 0;

    private static final String ELEMENT_DIVIDER = "/";

    public static final NodePath ROOT = new NodePath( ELEMENT_DIVIDER, false );

    private final String path;

    private NodePath( final String path, boolean ignore )
    {
        this.path = path;
    }

    public NodePath( final String path )
    {
        if ( path.isEmpty() )
        {
            this.path = "";
        }
        else if ( path.equals( ELEMENT_DIVIDER ) )
        {
            this.path = ELEMENT_DIVIDER;
        }
        else
        {
            this.path = toElements( path ).stream()
                .collect( Collectors.joining( ELEMENT_DIVIDER, isAbsolute( path ) ? ELEMENT_DIVIDER : "",
                                              hasTrailing( path ) ? ELEMENT_DIVIDER : "" ) );
        }
    }

    public NodePath( final NodePath parent, final NodeName name )
    {
        if ( name.isRoot() )
        {
            throw new IllegalArgumentException( "Can't add root name to path" );
        }
        final StringBuilder stringBuilder = new StringBuilder( parent.path );
        if ( !parent.path.endsWith( ELEMENT_DIVIDER ) )
        {
            stringBuilder.append( ELEMENT_DIVIDER );
        }
        stringBuilder.append( name );
        this.path = stringBuilder.toString();
    }

    public boolean isRoot()
    {
        return this.path.equals( ELEMENT_DIVIDER );
    }

    @Deprecated
    public NodePath asRelative()
    {
        if ( !isAbsolute( this.path ) )
        {
            return this;
        }
        return new NodePath( this.path.substring( 1 ) );
    }

    @Deprecated
    public NodePath asAbsolute()
    {
        if ( isAbsolute( this.path ) )
        {
            return this;
        }
        return new NodePath( ELEMENT_DIVIDER + this.path );
    }

    public NodePath getParentPath()
    {
        if ( this.path.isEmpty() || this.path.equals( ELEMENT_DIVIDER ) )
        {
            return this;
        }

        final boolean hasTrailing = hasTrailing( this.path );
        final int endIndex = hasTrailing ? this.path.length() - 1 : this.path.length();
        final String stringNoTrailing = this.path.substring( 0, endIndex );

        final int lastDivider = stringNoTrailing.lastIndexOf( ELEMENT_DIVIDER );

        if ( lastDivider == 0 )
        {
            return NodePath.ROOT;
        }
        else if ( lastDivider == -1 )
        {
            return new NodePath( "", false );
        }
        else
        {
            return new NodePath( stringNoTrailing.substring( 0, hasTrailing ? lastDivider + 1 : lastDivider ), false );
        }
    }

    public List getParentPaths()
    {
        List parentPaths = new ArrayList<>();

        if ( isEmpty() )
        {
            return parentPaths;
        }

        NodePath nodePath = this;
        do
        {
            NodePath parent = nodePath.getParentPath();

            parentPaths.add( parent );
            nodePath = parent;
        }
        while ( !nodePath.isEmpty() );

        return parentPaths;
    }

    public boolean isEmpty()
    {
        return this.path.isEmpty() || this.path.equals( ELEMENT_DIVIDER );
    }

    public boolean isAbsolute()
    {
        return isAbsolute( this.path );
    }

    @Deprecated
    public boolean isRelative()
    {
        return !isAbsolute( this.path );
    }

    @Deprecated
    public boolean hasTrailingDivider()
    {
        return hasTrailing( this.path );
    }

    @Deprecated
    public NodePath trimTrailingDivider()
    {
        if ( path.isEmpty() || path.equals( ELEMENT_DIVIDER ) )
        {
            return this;
        }

        return hasTrailing( this.path ) ? new NodePath( this.path.substring( 0, this.path.length() - 1 ) ) : this;
    }

    @Deprecated
    public int elementCount()
    {
        if ( path.isEmpty() || path.equals( ELEMENT_DIVIDER ) )
        {
            return 0;
        }
        int index = 0;
        int count = 0;
        while ( ( index = this.path.indexOf( ELEMENT_DIVIDER, index ) ) != -1 )
        {
            index += 1;
            count++;
        }
        if ( !isAbsolute( this.path ) )
        {
            count++;
        }

        if ( hasTrailing( this.path ) )
        {
            count--;
        }
        return count;
    }

    @Deprecated
    public Iterator iterator()
    {
        return toElements( this.path ).stream().map( Element::new ).iterator();
    }

    @Deprecated
    public String getElementAsString( final int index )
    {
        int fromIndex = isAbsolute( this.path ) ? 1 : 0;
        for ( int i = 0; i < index; i++ )
        {
            fromIndex = this.path.indexOf( ELEMENT_DIVIDER, fromIndex + 1 ) + 1;
        }

        final int toIndex = this.path.indexOf( ELEMENT_DIVIDER, fromIndex );
        return this.path.substring( fromIndex, toIndex == -1 ? this.path.length() : toIndex );

    }

    @Deprecated
    public Element getLastElement()
    {
        return new Element( getName() );
    }

    public String getName()
    {
        if ( isEmpty() )
        {
            return null;
        }
        else
        {
            final int stringIndex = isAbsolute( this.path ) ? 1 : 0;
            final int endIndex = hasTrailing( this.path ) ? this.path.length() - 1 : this.path.length();
            final String stringNoTrailing = this.path.substring( stringIndex, endIndex );
            final int beginIndex = stringNoTrailing.lastIndexOf( ELEMENT_DIVIDER );
            return stringNoTrailing.substring( beginIndex == -1 ? 0 : beginIndex + 1 );
        }
    }

    @Deprecated
    public Iterable resolvePathElementNames()
    {
        return toElements( this.path );
    }

    @Deprecated
    public NodePath removeFromBeginning( final NodePath path )
    {
        final List elements = toElements( this.path );
        final List pathElements = toElements( path.path );
        Preconditions.checkState( elements.size() >= pathElements.size(),
                                  "No point in trying to remove [" + path + "] from [" + this.toString() + "]" );

        if ( pathElements.isEmpty() )
        {
            return this;
        }

        for ( int i = 0; i < pathElements.size(); i++ )
        {
            if ( !pathElements.get( i ).equalsIgnoreCase( elements.get( i ) ) )
            {
                return this;
            }
        }

        final Builder builder = create( NodePath.ROOT ).absolute( isAbsolute( this.path ) ).trailingDivider( hasTrailing( this.path ) );
        for ( int i = pathElements.size(); i < elements.size(); i++ )
        {
            builder.addElement( elements.get( i ) );
        }

        return builder.build();
    }

    @Override
    public boolean equals( final Object o )
    {
        if ( this == o )
        {
            return true;
        }
        if ( o == null )
        {
            return false;
        }

        if ( !( o instanceof NodePath ) )
        {
            return false;
        }

        final NodePath path = (NodePath) o;
        return this.path.equalsIgnoreCase( path.path );
    }

    @Override
    public int hashCode()
    {
        return path.toLowerCase().hashCode();
    }

    @Override
    public String toString()
    {
        return path;
    }

    public static Builder create()
    {
        return create( NodePath.ROOT );
    }

    @Deprecated
    public static Builder create( final String path )
    {
        return create( NodePath.ROOT ).elements( path );
    }

    public static Builder create( final NodePath source )
    {
        return new Builder( source );
    }

    @Deprecated
    public static Builder create( final NodePath parent, final String path )
    {
        return create( parent ).elements( path ).absolute( true );
    }

    @Deprecated
    public static final class Element
    {
        private final String name;

        public Element( final String name )
        {
            this.name = Objects.requireNonNull( name );
        }

        @Override
        public boolean equals( final Object o )
        {
            if ( this == o )
            {
                return true;
            }
            if ( !( o instanceof Element ) )
            {
                return false;
            }

            final Element element = (Element) o;

            return this.name.equalsIgnoreCase( element.name );
        }

        @Override
        public int hashCode()
        {
            return Objects.hash( this.name.toLowerCase() );
        }

        @Override
        public String toString()
        {
            return name;
        }
    }

    @Override
    public int compareTo( final NodePath o )
    {
        return this.path.compareTo( o.path );
    }

    private static List toElements( final String elements )
    {
        return Splitter.on( ELEMENT_DIVIDER ).omitEmptyStrings().trimResults().splitToList( elements );
    }

    private static boolean isAbsolute( final String path )
    {
        return path.startsWith( ELEMENT_DIVIDER );
    }

    private static boolean hasTrailing( final String path )
    {
        return !path.equals( ELEMENT_DIVIDER ) && path.endsWith( ELEMENT_DIVIDER );
    }

    public static final class Builder
    {
        private boolean absolute;

        private boolean trailingDivider;

        private final ArrayList elementListBuilder;

        public Builder()
        {
            this.absolute = true;
            this.elementListBuilder = new ArrayList<>();
        }

        public Builder( final NodePath source )
        {
            Preconditions.checkNotNull( source, "source to build copy from not given" );
            this.absolute = isAbsolute( source.path );
            this.trailingDivider = hasTrailing( source.path );
            this.elementListBuilder = source.isEmpty() ? new ArrayList<>() : new ArrayList<>( toElements( source.path ) );
        }

        @Deprecated
        public Builder( final String path )
        {
            this.elementListBuilder = new ArrayList<>();
            this.elements( path );
        }

        @Deprecated
        public Builder trailingDivider( final boolean value )
        {
            this.trailingDivider = value;
            return this;
        }

        @Deprecated
        public Builder absolute( final boolean value )
        {
            this.absolute = value;
            return this;
        }

        @Deprecated
        public Builder elements( final String elements )
        {
            if ( elements.isEmpty() )
            {
                this.absolute = false;
                this.trailingDivider = false;
            }
            else
            {
                this.absolute = isAbsolute( elements );
                this.trailingDivider = hasTrailing( elements );
                this.elementListBuilder.addAll( toElements( elements ) );
            }
            return this;
        }

        public Builder addElement( final String value )
        {
            if ( isNullOrEmpty( value ) )
            {
                return this;
            }

            this.elementListBuilder.add( NodeName.from( value ).toString() );
            return this;
        }

        @Deprecated
        public Builder removeLastElement()
        {
            if ( !this.elementListBuilder.isEmpty() )
            {
                this.elementListBuilder.remove( this.elementListBuilder.size() - 1 );
            }
            return this;
        }

        @Deprecated
        public Builder removeFirstElement()
        {
            if ( !this.elementListBuilder.isEmpty() )
            {
                this.elementListBuilder.remove( 0 );
            }
            return this;
        }

        @Deprecated
        public Builder addElement( final Element value )
        {
            addElement( value.name );
            return this;
        }

        public NodePath build()
        {
            return new NodePath( this.elementListBuilder.stream()
                                     .collect( Collectors.joining( ELEMENT_DIVIDER, this.absolute ? ELEMENT_DIVIDER : "",
                                                                   this.trailingDivider && !this.elementListBuilder.isEmpty()
                                                                       ? ELEMENT_DIVIDER
                                                                       : "" ) ), false );
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy