![JAR search and dependency download from the Maven repository](/logo.png)
net.officefloor.web.HttpInputPathImpl Maven / Gradle / Ivy
/*
* OfficeFloor - http://www.officefloor.net
* Copyright (C) 2005-2018 Daniel Sagenschneider
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the 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.
*
* This program 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see .
*/
package net.officefloor.web;
import java.util.ArrayList;
import java.util.List;
import net.officefloor.server.http.HttpException;
import net.officefloor.server.http.HttpStatus;
import net.officefloor.web.HttpInputPathSegment.HttpInputPathSegmentEnum;
import net.officefloor.web.HttpPathFactoryImpl.ParameterSegment;
import net.officefloor.web.HttpPathFactoryImpl.Segment;
import net.officefloor.web.HttpPathFactoryImpl.StaticSegment;
import net.officefloor.web.build.HttpPathFactory;
import net.officefloor.web.value.retrieve.ValueRetriever;
import net.officefloor.web.value.retrieve.ValueRetrieverSource;
/**
* {@link HttpInputPath} implementation.
*
* @author Daniel Sagenschneider
*/
public class HttpInputPathImpl implements HttpInputPath {
/**
* Route path.
*/
private final String routePath;
/**
* Head {@link HttpInputPathSegment} of linked list of
* {@link HttpInputPathSegment} instances.
*/
private final HttpInputPathSegment segmentHead;
/**
* Number of path parameters for sorting routes.
*/
private final int parameterCount;
/**
* Instantiate.
*
* @param routePath Route path.
* @param segmentHead Head {@link HttpInputPathSegment} of linked list of
* {@link HttpInputPathSegment} instances.
* @param parameterCount Number of path parameters for sorting routes.
*/
public HttpInputPathImpl(String routePath, HttpInputPathSegment segmentHead, int parameterCount) {
this.routePath = routePath;
this.segmentHead = segmentHead;
this.parameterCount = parameterCount;
}
/**
* ================ HttpInputPath =======================
*/
@Override
public boolean isPathParameters() {
return this.parameterCount > 0;
}
@Override
public boolean isMatchPath(String path, int endingPathParameterTerminatingCharacter) {
// Determine if match path
HttpInputPathSegment segment = this.segmentHead;
int pathIndex = 0;
while (segment != null) {
switch (segment.type) {
case STATIC:
// Ensure matches static path
int staticLength = segment.value.length();
if (!(path.regionMatches(pathIndex, segment.value, 0, staticLength))) {
return false;
}
pathIndex += staticLength;
break;
case PARAMETER:
// Obtain the terminating character for parameter
int terminator;
if (segment.next != null) {
// Ensure is followed by static path
if (segment.next.type != HttpInputPathSegmentEnum.STATIC) {
throw new HttpException(HttpStatus.INTERNAL_SERVER_ERROR, null,
"Path parameter must only be followed by static path content, but was "
+ segment.next.type.name());
}
// First static character terminates parameter
terminator = segment.next.value.charAt(0);
} else {
// Parameter is last, so use ending path terminator
terminator = endingPathParameterTerminatingCharacter;
}
// Loop until reach terminator (or end of path)
FOUND_TERMINATOR: while (pathIndex < path.length()) {
if (path.charAt(pathIndex) == terminator) {
break FOUND_TERMINATOR;
}
pathIndex++;
}
break;
default:
throw new IllegalStateException("Route should not have segment of type " + segment.type);
}
// Next segment
segment = segment.next;
}
// Ensure match full path
if (pathIndex != path.length()) {
return false; // did not match full path
}
// As here, matches
return true;
}
@Override
@SuppressWarnings("unchecked")
public HttpPathFactory createHttpPathFactory(Class valuesType) throws HttpException {
// Ensure have type
if (valuesType == null) {
valuesType = (Class) Void.TYPE;
}
// Create the value retriever
ValueRetrieverSource source = new ValueRetrieverSource(true);
ValueRetriever valueRetriever = source.sourceValueRetriever(valuesType);
// Create the segments
List> segments = new ArrayList<>();
HttpInputPathSegment segment = this.segmentHead;
while (segment != null) {
switch (segment.type) {
case STATIC:
// Add the static part of path
segments.add(new StaticSegment(segment.value));
break;
case PARAMETER:
// Ensure parameter value is available
if (valueRetriever.getValueType(segment.value) == null) {
throw new HttpException(HttpStatus.INTERNAL_SERVER_ERROR, null, "For path '" + this.routePath
+ "', no property '" + segment.value + "' on object " + valuesType.getName());
}
// Add the parameter
segments.add(new ParameterSegment(segment.value, valueRetriever));
break;
default:
throw new IllegalStateException("Route should not have segment of type " + segment.type);
}
segment = segment.next;
}
// Create the HTTP path factory
return new HttpPathFactoryImpl(valuesType, segments.toArray(new Segment[segments.size()]));
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy