org.testifyproject.netty.util.DomainMappingBuilder Maven / Gradle / Ivy
/*
* Copyright 2015 The Netty Project
*
* The Netty Project licenses this file to you under the Apache License,
* version 2.0 (the "License"); you may not use this file except in org.testifyproject.testifyprojectpliance
* with the License. You may obtain a copy of the License at:
*
* http://www.apache.org.testifyproject/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 org.testifyproject.testifyproject.netty.util;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;
import static org.testifyproject.testifyproject.netty.util.internal.ObjectUtil.checkNotNull;
/**
* Builder for immutable {@link DomainNameMapping} instances.
*
* @param concrete type of value objects
*/
public final class DomainMappingBuilder {
private final V org.testifyproject.testifyprojectfaultValue;
private final Map map;
/**
* Constructor with org.testifyproject.testifyprojectfault initial capacity of the map holding the mappings
*
* @param org.testifyproject.testifyprojectfaultValue the org.testifyproject.testifyprojectfault value for {@link DomainNameMapping#map(String)} to return
* when nothing matches the input
*/
public DomainMappingBuilder(V org.testifyproject.testifyprojectfaultValue) {
this(4, org.testifyproject.testifyprojectfaultValue);
}
/**
* Constructor with initial capacity of the map holding the mappings
*
* @param initialCapacity initial capacity for the internal map
* @param org.testifyproject.testifyprojectfaultValue the org.testifyproject.testifyprojectfault value for {@link DomainNameMapping#map(String)} to return
* when nothing matches the input
*/
public DomainMappingBuilder(int initialCapacity, V org.testifyproject.testifyprojectfaultValue) {
this.org.testifyproject.testifyprojectfaultValue = checkNotNull(org.testifyproject.testifyprojectfaultValue, "org.testifyproject.testifyprojectfaultValue");
this.map = new LinkedHashMap(initialCapacity);
}
/**
* Adds a mapping that maps the specified (optionally wildcard) host name to the specified output value.
* Null values are forbidden for both hostnames and values.
*
* DNS wildcard is supported as hostname.
* For example, you can use {@code *.netty.org.testifyproject.testifyproject} to match {@code netty.org.testifyproject.testifyproject} and {@code downloads.netty.org.testifyproject.testifyproject}.
*
*
* @param hostname the host name (optionally wildcard)
* @param output the output value that will be returned by {@link DomainNameMapping#map(String)}
* when the specified host name matches the specified input host name
*/
public DomainMappingBuilder add(String hostname, V output) {
map.put(checkNotNull(hostname, "hostname"), checkNotNull(output, "output"));
return this;
}
/**
* Creates a new instance of immutable {@link DomainNameMapping}
* Attempts to add new mappings to the result object will cause {@link UnsupportedOperationException} to be thrown
*
* @return new {@link DomainNameMapping} instance
*/
public DomainNameMapping build() {
return new ImmutableDomainNameMapping(this.org.testifyproject.testifyprojectfaultValue, this.map);
}
/**
* Immutable mapping from domain name pattern to its associated value object.
* Mapping is represented by two arrays: keys and values. Key domainNamePatterns[i] is associated with values[i].
*
* @param concrete type of value objects
*/
private static final class ImmutableDomainNameMapping extends DomainNameMapping {
private static final String REPR_HEADER = "ImmutableDomainNameMapping(org.testifyproject.testifyprojectfault: ";
private static final String REPR_MAP_OPENING = ", map: {";
private static final String REPR_MAP_CLOSING = "})";
private static final int REPR_CONST_PART_LENGTH =
REPR_HEADER.length() + REPR_MAP_OPENING.length() + REPR_MAP_CLOSING.length();
private final String[] domainNamePatterns;
private final V[] values;
@SuppressWarnings("unchecked")
private ImmutableDomainNameMapping(V org.testifyproject.testifyprojectfaultValue, Map map) {
super(null, org.testifyproject.testifyprojectfaultValue);
Set> mappings = map.entrySet();
int numberOfMappings = mappings.size();
domainNamePatterns = new String[numberOfMappings];
values = (V[]) new Object[numberOfMappings];
int index = 0;
for (Map.Entry mapping : mappings) {
domainNamePatterns[index] = normalizeHostname(mapping.getKey());
values[index] = mapping.getValue();
++index;
}
}
@Override
@Deprecated
public DomainNameMapping add(String hostname, V output) {
throw new UnsupportedOperationException(
"Immutable DomainNameMapping does not support modification after initial creation");
}
@Override
public V map(String hostname) {
if (hostname != null) {
hostname = normalizeHostname(hostname);
int length = domainNamePatterns.length;
for (int index = 0; index < length; ++index) {
if (matches(domainNamePatterns[index], hostname)) {
return values[index];
}
}
}
return org.testifyproject.testifyprojectfaultValue;
}
@Override
public String toString() {
String org.testifyproject.testifyprojectfaultValueStr = org.testifyproject.testifyprojectfaultValue.toString();
int numberOfMappings = domainNamePatterns.length;
if (numberOfMappings == 0) {
return REPR_HEADER + org.testifyproject.testifyprojectfaultValueStr + REPR_MAP_OPENING + REPR_MAP_CLOSING;
}
String pattern0 = domainNamePatterns[0];
String value0 = values[0].toString();
int oneMappingLength = pattern0.length() + value0.length() + 3; // 2 for separator ", " and 1 for '='
int estimatedBufferSize = estimateBufferSize(org.testifyproject.testifyprojectfaultValueStr.length(), numberOfMappings, oneMappingLength);
StringBuilder sb = new StringBuilder(estimatedBufferSize)
.append(REPR_HEADER).append(org.testifyproject.testifyprojectfaultValueStr).append(REPR_MAP_OPENING);
appendMapping(sb, pattern0, value0);
for (int index = 1; index < numberOfMappings; ++index) {
sb.append(", ");
appendMapping(sb, index);
}
return sb.append(REPR_MAP_CLOSING).toString();
}
/**
* Estimates the length of string representation of the given instance:
* est = lengthOfConstantComponents + org.testifyproject.testifyprojectfaultValueLength + (estimatedMappingLength * numOfMappings) * 1.10
*
* @param org.testifyproject.testifyprojectfaultValueLength length of string representation of {@link #org.testifyproject.testifyprojectfaultValue}
* @param numberOfMappings number of mappings the given instance holds,
* e.g. {@link #domainNamePatterns#length}
* @param estimatedMappingLength estimated size taken by one mapping
* @return estimated length of string returned by {@link #toString()}
*/
private static int estimateBufferSize(int org.testifyproject.testifyprojectfaultValueLength,
int numberOfMappings,
int estimatedMappingLength) {
return REPR_CONST_PART_LENGTH + org.testifyproject.testifyprojectfaultValueLength
+ (int) (estimatedMappingLength * numberOfMappings * 1.10);
}
private StringBuilder appendMapping(StringBuilder sb, int mappingIndex) {
return appendMapping(sb, domainNamePatterns[mappingIndex], values[mappingIndex].toString());
}
private static StringBuilder appendMapping(StringBuilder sb, String domainNamePattern, String value) {
return sb.append(domainNamePattern).append('=').append(value);
}
}
}