Package de.danielbechler.diff.path

Source Code of de.danielbechler.diff.path.NodePath$AppendableBuilder

/*
* Copyright 2014 Daniel Bechler
*
* 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 de.danielbechler.diff.path;

import de.danielbechler.diff.selector.BeanPropertyElementSelector;
import de.danielbechler.diff.selector.CollectionItemElementSelector;
import de.danielbechler.diff.selector.ElementSelector;
import de.danielbechler.diff.selector.MapKeyElementSelector;
import de.danielbechler.diff.selector.RootElementSelector;
import de.danielbechler.util.Assert;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;

/**
* @author Daniel Bechler
*/
public final class NodePath implements Comparable<NodePath>
{
  private final List<ElementSelector> elementSelectors;

  private NodePath(final List<ElementSelector> elementSelectors)
  {
    this.elementSelectors = Collections.unmodifiableList(elementSelectors);
  }

  public boolean isParentOf(final NodePath nodePath)
  {
    final List<ElementSelector> otherElementSelectors = nodePath.getElementSelectors();
    if (elementSelectors.size() < otherElementSelectors.size())
    {
      return otherElementSelectors.subList(0, elementSelectors.size()).equals(elementSelectors);
    }
    return false;
  }

  public boolean isChildOf(final NodePath nodePath)
  {
    final List<ElementSelector> otherElementSelectors = nodePath.getElementSelectors();
    if (elementSelectors.size() > otherElementSelectors.size())
    {
      return elementSelectors.subList(0, otherElementSelectors.size()).equals(otherElementSelectors);
    }
    return false;
  }

  public ElementSelector getLastElementSelector()
  {
    return elementSelectors.get(elementSelectors.size() - 1);
  }

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

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

    final NodePath that = (NodePath) o;

    if (!elementSelectors.equals(that.elementSelectors))
    {
      return false;
    }

    return true;
  }

  @Override
  public String toString()
  {
    final StringBuilder sb = new StringBuilder();
    final Iterator<ElementSelector> iterator = elementSelectors.iterator();
    ElementSelector previousElementSelector = null;
    while (iterator.hasNext())
    {
      final ElementSelector elementSelector = iterator.next();
      if (elementSelector instanceof RootElementSelector)
      {
        sb.append("/");
      }
      else if (elementSelector instanceof CollectionItemElementSelector || elementSelector instanceof MapKeyElementSelector)
      {
        sb.append(elementSelector);
      }
      else if (previousElementSelector instanceof RootElementSelector)
      {
        sb.append(elementSelector);
      }
      else
      {
        sb.append('/');
        sb.append(elementSelector);
      }
      previousElementSelector = elementSelector;
    }
    return sb.toString();
  }

  public int compareTo(final NodePath that)
  {
    if (this.getElementSelectors().size() <= that.getElementSelectors().size())
    {
      return -1;
    }
    else if (this.matches(that))
    {
      return 0;
    }
    else if (this.getElementSelectors().size() > that.getElementSelectors().size())
    {
      return 1;
    }
    else
    {
      return 1;
    }
  }

  public boolean matches(final NodePath nodePath)
  {
    return nodePath.equals(this);
  }

  public static AppendableBuilder startBuildingFrom(final NodePath nodePath)
  {
    Assert.notNull(nodePath, "propertyPath");
    return new AppendableBuilderImpl(new ArrayList<ElementSelector>(nodePath.getElementSelectors()));
  }

  public List<ElementSelector> getElementSelectors()
  {
    return elementSelectors;
  }

  public static NodePath with(final String propertyName, final String... additionalPropertyNames)
  {
    return startBuilding().propertyName(propertyName, additionalPropertyNames).build();
  }

  public static AppendableBuilder startBuilding()
  {
    final List<ElementSelector> elementSelectors1 = new LinkedList<ElementSelector>();
    elementSelectors1.add(RootElementSelector.getInstance());
    return new AppendableBuilderImpl(elementSelectors1);
  }

  public static NodePath withRoot()
  {
    return startBuilding().build();
  }

  public static interface AppendableBuilder
  {
    AppendableBuilder element(ElementSelector elementSelector);

    AppendableBuilder propertyName(String name, String... names);

    <T> AppendableBuilder collectionItem(T item);

    <K> AppendableBuilder mapKey(K key);

    NodePath build();
  }

  private static final class AppendableBuilderImpl implements AppendableBuilder
  {
    private final List<ElementSelector> elementSelectors;

    public AppendableBuilderImpl(final List<ElementSelector> elementSelectors)
    {
      Assert.notEmpty(elementSelectors, "elementSelectors");
      this.elementSelectors = new LinkedList<ElementSelector>(elementSelectors);
    }

    public AppendableBuilder element(final ElementSelector elementSelector)
    {
      Assert.notNull(elementSelector, "elementSelector");
      elementSelectors.add(elementSelector);
      return this;
    }

    public AppendableBuilder propertyName(final String name, final String... names)
    {
      elementSelectors.add(new BeanPropertyElementSelector(name));
      for (final String s : names)
      {
        elementSelectors.add(new BeanPropertyElementSelector(s));
      }
      return this;
    }

    public <T> AppendableBuilder collectionItem(final T item)
    {
      elementSelectors.add(new CollectionItemElementSelector(item));
      return this;
    }

    public <K> AppendableBuilder mapKey(final K key)
    {
      Assert.notNull(key, "key");
      elementSelectors.add(new MapKeyElementSelector(key));
      return this;
    }

    public NodePath build()
    {
      if (elementSelectors.isEmpty())
      {
        throw new IllegalStateException("A property path cannot be empty");
      }
      else if (!(elementSelectors.get(0) instanceof RootElementSelector))
      {
        throw new IllegalStateException("A property path must start with a root element");
      }
      else if (elementCount(RootElementSelector.class) > 1)
      {
        throw new IllegalStateException("A property path cannot contain multiple root elements");
      }
      return new NodePath(elementSelectors);
    }

    private int elementCount(final Class<? extends ElementSelector> type)
    {
      assert type != null : "Type must not be null";
      int count = 0;
      for (final ElementSelector elementSelector : elementSelectors)
      {
        if (type.isAssignableFrom(elementSelector.getClass()))
        {
          count++;
        }
      }
      return count;
    }
  }
}
TOP

Related Classes of de.danielbechler.diff.path.NodePath$AppendableBuilder

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.