io.guise.framework.AbstractDestination Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of guise-framework Show documentation
Show all versions of guise-framework Show documentation
Guise™ Internet application framework.
/*
* Copyright © 2005-2011 GlobalMentor, Inc.
*
* 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 io.guise.framework;
import java.net.URI;
import java.util.*;
import static java.util.Collections.*;
import static java.util.Objects.*;
import java.util.regex.Pattern;
import com.globalmentor.beans.BoundPropertyObject;
import com.globalmentor.java.Objects;
import com.globalmentor.net.*;
import io.urf.model.UrfResourceDescription;
import static com.globalmentor.net.URIs.*;
/**
* Abstract implementation of a navigation point, its properties, and its restrictions. Destinations of identical types with identical paths and path patterns
* are considered equal.
* @author Garret Wilson
*/
public abstract class AbstractDestination extends BoundPropertyObject implements Destination {
/** The map of sub-categories; it is not thread-safe, but any changes will simply create a new list. */
private List categories = unmodifiableList(new ArrayList()); //TODO add a property and fire a change
@Override
public Iterable getCategories() {
return categories;
}
@Override
public void setCategories(final List categories) {
this.categories = unmodifiableList(new ArrayList(categories)); //create a copy of the list and save the list
}
/**
* The application context-relative path within the Guise container context, which does not begin with '/', or null
if there is no path specified
* for this destination.
*/
private final URIPath path;
@Override
public URIPath getPath() {
return path;
}
/**
* The pattern to match an application context-relative path within the Guise container context, which does not begin with '/', or null
if there
* is no path pattern specified for this destination.
*/
private final Pattern pathPattern;
@Override
public Pattern getPathPattern() {
return pathPattern;
}
/**
* Path constructor.
* @param path The application context-relative path within the Guise container context, which does not begin with '/'.
* @throws NullPointerException if the path is null
.
* @throws IllegalArgumentException if the provided path is absolute.
*/
public AbstractDestination(final URIPath path) {
this.path = requireNonNull(path, "Navigation path cannot be null.").checkRelative(); //store the path, making sure it is relative
this.pathPattern = null; //indicate that there is no path pattern
}
/**
* Path pattern constructor.
* @param pathPattern The pattern to match an application context-relative path within the Guise container context, which does not begin with '/'.
* @throws NullPointerException if the path pattern is null
.
*/
public AbstractDestination(final Pattern pathPattern) {
this.pathPattern = requireNonNull(pathPattern, "Navigation path pattern cannot be null.");
this.path = null; //indicate that there is no path
}
@Override
public URIPath getPath(final GuiseSession session, final URIPath path, final Bookmark bookmark, final URI referrerURI) throws ResourceIOException {
if(!exists(session, path, bookmark, referrerURI)) { //if this destination doesn't exist
if(!path.isCollection()) { //if a non-collection path was requested
final URIPath collectionPath = URIPath.of(path.toString() + PATH_SEPARATOR); //create a collection version of the path
if(exists(session, collectionPath, bookmark, referrerURI)) { //if the collection form of the path exists
return collectionPath; //return the collection path
}
}
}
return path; //return the unmodified path by default
}
@Override
public boolean exists(final GuiseSession session, final URIPath navigationPath, final Bookmark bookmark, final URI referrerURI) throws ResourceIOException {
return true; //make it easy for simple resource destinations by assuming the resource exists
}
/**
* {@inheritDoc}
*
* This implementation authorizes all resources.
*
*/
@Override
public boolean isAuthorized(final GuiseSession session, final URIPath navigationPath, final Bookmark bookmark, final URI referrerURI)
throws ResourceIOException {
return true; //by default authorize all resources
}
/**
* {@inheritDoc}
* @implSpec This implementation returns an empty description.
*/
@Override
public Optional getDescription(final GuiseSession session, final URIPath navigationPath, final Bookmark bookmark,
final URI referrerURI) throws ResourceIOException {
return Optional.empty();
}
@Override
public int hashCode() {
return Objects.getHashCode(getPath(), getPathPattern()); //construct a hash code from the path and path pattern
}
/**
* {@inheritDoc}
*
* This implementation considers destinations of identical types with identical paths and path patterns to be equivalent.
*
*/
@Override
public boolean equals(final Object object) {
if(getClass().isInstance(object)) { //if the given object is an instance of this object's class
final Destination destination = (Destination)object; //cast the object to a destination (which it must be, if it's the same type as this instance
return Objects.equals(getPath(), destination.getPath()) && Objects.equals(getPathPattern(), destination.getPathPattern()); //see if the paths and path patterns match
}
return false; //indicate that the objects don't match
}
}