package io.github.ibuildthecloud.gdapi.url;
import io.github.ibuildthecloud.gdapi.context.ApiContext;
import io.github.ibuildthecloud.gdapi.factory.SchemaFactory;
import io.github.ibuildthecloud.gdapi.id.IdFormatter;
import io.github.ibuildthecloud.gdapi.model.Collection;
import io.github.ibuildthecloud.gdapi.model.Resource;
import io.github.ibuildthecloud.gdapi.model.Schema;
import io.github.ibuildthecloud.gdapi.model.Sort.SortOrder;
import io.github.ibuildthecloud.gdapi.request.ApiRequest;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.regex.Pattern;
public final class DefaultUrlBuilder implements UrlBuilder {
private static final String REMOVE_PARAM_REGEXP = "&?%s=[^&]*";
ApiRequest apiRequest;
SchemaFactory schemaFactory;
String subContext = "";
public DefaultUrlBuilder(ApiRequest apiRequest, SchemaFactory schemaFactory) {
this.apiRequest = apiRequest;
this.schemaFactory = schemaFactory;
}
@Override
public URL resourceReferenceLink(Resource resource) {
return constructBasicUrl(getPluralName(resource), resource.getId());
}
@Override
public URL resourceReferenceLink(Class<?> type, String id) {
IdFormatter formatter = ApiContext.getContext().getIdFormatter();
Schema schema = schemaFactory.getSchema(type);
return schema == null ? null : constructBasicUrl(schema.getPluralName(), formatter.formatId(schema.getId(), id).toString());
}
@Override
public URL resourceReferenceLink(String type, String id) {
IdFormatter formatter = ApiContext.getContext().getIdFormatter();
Schema schema = schemaFactory.getSchema(type);
if (schema == null) {
return constructBasicUrl(false, type, formatter.formatId(type, id).toString());
} else {
return constructBasicUrl(schema.getPluralName(), formatter.formatId(schema.getId(), id).toString());
}
}
protected String getPluralName(Resource resource) {
return getPluralName(resource.getType());
}
protected String getPluralName(String type) {
return schemaFactory.getPluralName(type);
}
protected URL constructBasicUrl(boolean lowercase, String... parts) {
StringBuilder builder = new StringBuilder().append(apiRequest.getResponseUrlBase()).append("/").append(apiRequest.getVersion()).append(subContext);
for (String part : parts) {
if (part == null)
return null;
builder.append("/").append(part);
}
if (lowercase) {
return toURL(builder.toString().toLowerCase());
} else {
return toURL(builder.toString());
}
}
protected URL constructBasicUrl(String... parts) {
return constructBasicUrl(true, parts);
}
@Override
public URL resourceCollection(Class<?> type) {
Schema schema = schemaFactory.getSchema(type);
return schema == null ? null : constructBasicUrl(schema.getPluralName());
}
@Override
public URL resourceCollection(String type) {
String plural = getPluralName(type);
return plural == null ? null : constructBasicUrl(getPluralName(type));
}
@Override
public URL resourceLink(Class<?> type, String id, String name) {
if (name == null)
return null;
IdFormatter formatter = ApiContext.getContext().getIdFormatter();
String typeName = schemaFactory.getSchemaName(type);
String pluralName = schemaFactory.getPluralName(typeName);
return constructBasicUrl(pluralName, id == null ? null : formatter.formatId(typeName, id).toString(), name.toLowerCase());
}
@Override
public URL resourceLink(Resource resource, String name) {
if (name == null)
return null;
return constructBasicUrl(getPluralName(resource), resource.getId(), name.toLowerCase());
}
@Override
public URL reverseSort(SortOrder currentOrder) {
StringBuilder buffer = fullUrlToAppendQueryString(Collection.ORDER, Collection.MARKER);
buffer.append(Collection.ORDER).append("=").append(currentOrder.getReverseExternalForm());
return toURL(buffer.toString());
}
@Override
public URL actionLink(Resource resource, String name) {
return constructBasicUrl(getPluralName(resource), resource.getId(), "?" + Resource.ACTION + "=" + name);
}
@Override
public URL sort(String field) {
StringBuilder buffer = fullUrlToAppendQueryString(Collection.SORT, Collection.ORDER);
buffer.append(Collection.SORT).append("=").append(field);
return toURL(buffer.toString());
}
@Override
public URL next(String id) {
IdFormatter formatter = ApiContext.getContext().getIdFormatter();
StringBuilder buffer = fullUrlToAppendQueryString(Collection.MARKER);
Object formatted = id;
if (id != null && id.length() > 0 && id.charAt(0) != 'm') {
formatted = formatter.formatId(Collection.MARKER, id);
}
buffer.append(Collection.MARKER).append("=").append(formatted);
return toURL(buffer.toString());
}
protected StringBuilder fullUrlToAppendQueryString(String... removes) {
StringBuilder buffer = new StringBuilder(apiRequest.getRequestUrl());
buffer.append("?");
String queryString = removeParameter(apiRequest.getQueryString(), removes);
buffer.append(queryString);
if (queryString.length() > 0) {
buffer.append("&");
}
return buffer;
}
protected URL toURL(String url) {
try {
return new URL(url);
} catch (MalformedURLException e) {
throw new IllegalArgumentException("Failed to create URL for [" + url + "]", e);
}
}
protected String removeParameter(String queryString, String... names) {
if (queryString == null)
return "";
for (String name : names) {
String pattern = String.format(REMOVE_PARAM_REGEXP, Pattern.quote(name));
queryString = queryString.replaceAll(pattern, "");
}
return queryString;
}
@Override
public URL version(String version) {
StringBuilder builder = new StringBuilder().append(apiRequest.getResponseUrlBase()).append("/").append(version);
return toURL(builder.toString());
}
@Override
public URL current() {
return toURL(apiRequest.getRequestUrl());
}
@Override
public URL staticResource(String... parts) {
StringBuilder builder = new StringBuilder().append(apiRequest.getResponseUrlBase()).append("/").append(apiRequest.getStaticResourceBase());
for (String part : parts) {
if (part == null)
return null;
builder.append("/").append(part);
}
return toURL(builder.toString().toLowerCase());
}
public String getSubContext() {
return subContext;
}
public void setSubContext(String subContext) {
this.subContext = subContext;
}
}