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

org.smallmind.bayeux.oumuamua.server.spi.DefaultRoute Maven / Gradle / Ivy

/*
 * Copyright (c) 2007 through 2024 David Berkman
 *
 * This file is part of the SmallMind Code Project.
 *
 * The SmallMind Code Project is free software, you can redistribute
 * it and/or modify it under either, at your discretion...
 *
 * 1) The terms of GNU Affero General Public License as published by the
 * Free Software Foundation, either version 3 of the License, or (at
 * your option) any later version.
 *
 * ...or...
 *
 * 2) The terms of the Apache License, Version 2.0.
 *
 * The SmallMind Code Project is distributed in the hope that it will
 * be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * General Public License or Apache License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * and the Apache License along with the SmallMind Code Project. If not, see
 *  or .
 *
 * Additional permission under the GNU Affero GPL version 3 section 7
 * ------------------------------------------------------------------
 * If you modify this Program, or any covered work, by linking or
 * combining it with other code, such other code is not for that reason
 * alone subject to any of the requirements of the GNU Affero GPL
 * version 3.
 */
package org.smallmind.bayeux.oumuamua.server.spi;

import org.smallmind.bayeux.oumuamua.server.api.InvalidPathException;
import org.smallmind.bayeux.oumuamua.server.api.Route;
import org.smallmind.bayeux.oumuamua.server.api.Segment;
import org.smallmind.nutsnbolts.lang.StaticInitializationError;

public class DefaultRoute implements Route {

  public static final DefaultRoute HANDSHAKE_ROUTE;
  public static final DefaultRoute CONNECT_ROUTE;
  public static final DefaultRoute DISCONNECT_ROUTE;
  public static final DefaultRoute SUBSCRIBE_ROUTE;
  public static final DefaultRoute UNSUBSCRIBE_ROUTE;

  private final String path;
  private final int[] segments;

  static {
    try {
      HANDSHAKE_ROUTE = new DefaultRoute("/meta/handshake");
      CONNECT_ROUTE = new DefaultRoute("/meta/connect");
      DISCONNECT_ROUTE = new DefaultRoute("/meta/disconnect");
      SUBSCRIBE_ROUTE = new DefaultRoute("/meta/subscribe");
      UNSUBSCRIBE_ROUTE = new DefaultRoute("/meta/unsubscribe");
    } catch (InvalidPathException invalidPathException) {
      throw new StaticInitializationError(invalidPathException);
    }
  }

  public DefaultRoute (String path)
    throws InvalidPathException {

    this.path = path;

    segments = PathValidator.validate(path);
  }

  public String getPath () {

    return path;
  }

  public int size () {

    return segments.length + 1;
  }

  public int lastIndex () {

    return segments.length;
  }

  public boolean isWild () {

    return matches(segments.length, "*");
  }

  public boolean isDeepWild () {

    return matches(segments.length, "**");
  }

  public boolean isMeta () {

    return matches(0, "meta");
  }

  public boolean isService () {

    return matches(0, "service");
  }

  @Override
  public boolean matches (String... matchingSegments) {

    if ((matchingSegments == null) || (matchingSegments.length > (segments.length + 1))) {

      return false;
    } else {

      int index = 0;

      for (String matchingSegment : matchingSegments) {
        if ("**".equals(matchingSegment)) {

          return true;
        } else if ((!"*".equals(matchingSegment)) && (!matches(index, matchingSegment))) {

          return false;
        } else {
          index++;
        }
      }

      return true;
    }
  }

  protected boolean matches (int index, CharSequence name) {

    if ((index < 0) || (index > segments.length)) {
      throw new IndexOutOfBoundsException("0 <= index < " + size());
    } else {

      int startPos = (index == 0) ? 1 : segments[index - 1] + 1;

      if ((name == null) || (name.length() != (((index < segments.length) ? segments[index] : getPath().length()) - startPos))) {

        return false;
      } else {
        for (int pos = 0; pos < name.length(); pos++) {
          if (name.charAt(pos) != path.charAt(startPos + pos)) {

            return false;
          }
        }

        return true;
      }
    }
  }

  @Override
  public Segment getSegment (int index) {

    if ((index < 0) || (index > segments.length)) {
      throw new IndexOutOfBoundsException("0 <= index < " + size());
    } else {

      return new RouteSegment(index);
    }
  }

  @Override
  public int hashCode () {

    return path.hashCode();
  }

  @Override
  public boolean equals (Object obj) {

    return (obj instanceof DefaultRoute) && ((DefaultRoute)obj).path.equals(path);
  }

  public class RouteSegment extends Segment {

    private final int index;

    private RouteSegment (int index) {

      this.index = index;
    }

    @Override
    public boolean matches (CharSequence charSequence) {

      return DefaultRoute.this.matches(index, charSequence);
    }

    @Override
    public int length () {

      return ((index < segments.length) ? segments[index] : path.length()) - ((index == 0) ? 1 : segments[index - 1] + 1);
    }

    @Override
    public char charAt (int pos) {

      int startPos = (index == 0) ? 1 : segments[index - 1] + 1;
      int endPos = (index < segments.length) ? segments[index] : path.length();

      if ((pos < 0) || (pos >= (endPos - startPos))) {
        throw new StringIndexOutOfBoundsException("0 <= index < " + (endPos - startPos));
      } else {

        return path.charAt(startPos + pos);
      }
    }

    @Override
    public CharSequence subSequence (int start, int end) {

      int startPos = (index == 0) ? 1 : segments[index - 1] + 1;
      int endPos = (index < segments.length) ? segments[index] : path.length();

      if ((start < 0) || (end >= (endPos - startPos))) {
        throw new StringIndexOutOfBoundsException("0 <= index < " + (endPos - startPos));
      } else {

        return path.substring(startPos + start, startPos + end);
      }
    }

    @Override
    public String toString () {

      return path.substring((index == 0) ? 1 : segments[index - 1] + 1, (index < segments.length) ? segments[index] : path.length());
    }
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy