Merge branch 'master' of github.com:jamesagnew/hapi-fhir

This commit is contained in:
James Agnew 2015-06-17 14:32:42 -04:00
commit a27acb9b79
15 changed files with 516 additions and 38 deletions

View File

@ -180,13 +180,28 @@
<id>SITE</id>
<reporting>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-checkstyle-plugin</artifactId>
<reportSets>
<reportSet>
<reports>
<report>checkstyle</report>
</reports>
</reportSet>
</reportSets>
<configuration>
</configuration>
</plugin>
<!--<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>findbugs-maven-plugin</artifactId>
<version>3.0.0</version>
<configuration>
</configuration>
</plugin>
</plugin>-->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jxr-plugin</artifactId>

View File

@ -107,12 +107,25 @@ public abstract class BaseRuntimeDeclaredChildDefinition extends BaseRuntimeChil
}
final Method accessor = BeanUtils.findAccessor(declaringClass, targetReturnType, elementName);
if (accessor == null) {
throw new ConfigurationException("Could not find bean accessor/getter for property " + elementName + " on class " + declaringClass.getCanonicalName());
StringBuilder b = new StringBuilder();
b.append("Could not find bean accessor/getter for property ");
b.append(elementName);
b.append(" on class ");
b.append(declaringClass.getCanonicalName());
throw new ConfigurationException(b.toString());
}
final Method mutator = findMutator(declaringClass, targetReturnType, elementName);
if (mutator == null) {
throw new ConfigurationException("Could not find bean mutator/setter for property " + elementName + " on class " + declaringClass.getCanonicalName() + " (expected return type " + targetReturnType.getCanonicalName() + ")");
StringBuilder b = new StringBuilder();
b.append("Could not find bean mutator/setter for property ");
b.append(elementName);
b.append(" on class ");
b.append(declaringClass.getCanonicalName());
b.append(" (expected return type ");
b.append(targetReturnType.getCanonicalName());
b.append(")");
throw new ConfigurationException(b.toString());
}
if (List.class.isAssignableFrom(targetReturnType)) {
@ -134,6 +147,7 @@ public abstract class BaseRuntimeDeclaredChildDefinition extends BaseRuntimeChil
return myAccessor;
}
@Override
public String getElementName() {
return myElementName;
}

View File

@ -130,7 +130,11 @@ public class FhirContext {
throw new IllegalStateException(getLocalizer().getMessage(FhirContext.class, "noStructures"));
}
ourLog.info("Creating new FHIR context for FHIR version [{}]", myVersion.getVersion().name());
if (theVersion == null) {
ourLog.info("Creating new FhirContext with auto-detected version [{}]. It is recommended to explicitly select a version for future compatibility by invoking FhirContext.forDstuX()", myVersion.getVersion().name());
} else {
ourLog.info("Creating new FHIR context for FHIR version [{}]", myVersion.getVersion().name());
}
scanResourceTypes(toElementList(theResourceTypes));
}

View File

@ -32,18 +32,22 @@ public class Constants {
public static final Charset CHARSET_UTF8;
public static final String CHARSETNAME_UTF_8 = "UTF-8";
public static final String CT_ATOM_XML = "application/atom+xml";
public static final String CT_FHIR_JSON = "application/json+fhir";
public static final String CTSUFFIX_CHARSET_UTF8 = "; charset=" + CHARSETNAME_UTF_8;
public static final String CT_FHIR_XML = "application/xml+fhir";
public static final String CT_HTML = "text/html";
public static final String CT_HTML_WITH_UTF8 = "text/html; charset=UTF-8";
public static final String CT_HTML_WITH_UTF8 = "text/html" + CTSUFFIX_CHARSET_UTF8;
public static final String CT_JSON = "application/json";
public static final String CT_OCTET_STREAM = "application/octet-stream";
public static final String CT_TEXT = "text/plain";
public static final String CT_TEXT_WITH_UTF8 = CT_TEXT + "; charset=UTF-8";
public static final String CT_TEXT_WITH_UTF8 = CT_TEXT + CTSUFFIX_CHARSET_UTF8;
public static final String CT_XML = "application/xml";
public static final String ENCODING_GZIP = "gzip";
public static final String EXTOP_VALIDATE = "$validate";
public static final String EXTOP_VALIDATE_MODE = "mode";
public static final String EXTOP_VALIDATE_PROFILE = "profile";
public static final String EXTOP_VALIDATE_RESOURCE = "resource";
public static final String FORMAT_JSON = "json";
public static final Set<String> FORMAT_VAL_JSON;
public static final Map<String, EncodingEnum> FORMAT_VAL_TO_ENCODING;
@ -128,9 +132,6 @@ public class Constants {
public static final int STATUS_HTTP_501_NOT_IMPLEMENTED = 501;
public static final String URL_TOKEN_HISTORY = "_history";
public static final String URL_TOKEN_METADATA = "metadata";
public static final String EXTOP_VALIDATE_MODE = "mode";
public static final String EXTOP_VALIDATE_PROFILE = "profile";
public static final String EXTOP_VALIDATE_RESOURCE = "resource";
static {
Map<String, EncodingEnum> valToEncoding = new HashMap<String, EncodingEnum>();

View File

@ -600,7 +600,6 @@ public class RestfulServer extends HttpServlet {
operation = Constants.PARAM_HISTORY;
}
} else if (partIsOperation(nextString)) {
// FIXME: this would be untrue for _meta/_delete
if (operation != null) {
throw new InvalidRequestException("URL Path contains two operations: " + requestPath);
}
@ -635,8 +634,6 @@ public class RestfulServer extends HttpServlet {
requestDetails.setSecondaryOperation(secondaryOperation);
requestDetails.setCompartmentName(compartment);
// TODO: look for more tokens for version, compartments, etc...
String acceptEncoding = theRequest.getHeader(Constants.HEADER_ACCEPT_ENCODING);
boolean respondGzip = false;
if (acceptEncoding != null) {
@ -819,7 +816,6 @@ public class RestfulServer extends HttpServlet {
* (which extends {@link ServletException}), as this is a flag to the servlet container that the servlet
* is not usable.
*/
@SuppressWarnings("unused")
protected void initialize() throws ServletException {
// nothing by default
}

View File

@ -32,6 +32,8 @@ import java.util.Enumeration;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.zip.GZIPOutputStream;
import javax.servlet.ServletOutputStream;
@ -59,6 +61,8 @@ import ca.uhn.fhir.rest.method.RequestDetails;
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
public class RestfulServerUtils {
static final Pattern ACCEPT_HEADER_PATTERN = Pattern.compile("\\s*([a-zA-Z0-9+.*/-]+)\\s*(;\\s*([a-zA-Z]+)\\s*=\\s*([a-zA-Z0-9.]+)\\s*)?(,?)");
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(RestfulServerUtils.class);
public static void addProfileToBundleEntry(FhirContext theContext, IBaseResource theResource, String theServerBase) {
@ -188,27 +192,51 @@ public class RestfulServerUtils {
}
}
/*
* The Accept header is kind of ridiculous, e.g.
*/
// text/xml, application/xml, application/xhtml+xml, text/html;q=0.9, text/plain;q=0.8, image/png, */*;q=0.5
Enumeration<String> acceptValues = theReq.getHeaders(Constants.HEADER_ACCEPT);
if (acceptValues != null) {
float bestQ = -1f;
EncodingEnum retVal = null;
while (acceptValues.hasMoreElements()) {
String nextAcceptHeaderValue = acceptValues.nextElement();
if (nextAcceptHeaderValue != null && isNotBlank(nextAcceptHeaderValue)) {
for (String nextPart : nextAcceptHeaderValue.split(",")) {
int scIdx = nextPart.indexOf(';');
if (scIdx == 0) {
continue;
}
if (scIdx != -1) {
nextPart = nextPart.substring(0, scIdx);
}
nextPart = nextPart.trim();
EncodingEnum retVal = Constants.FORMAT_VAL_TO_ENCODING.get(nextPart);
if (retVal != null) {
return retVal;
Matcher m = ACCEPT_HEADER_PATTERN.matcher(nextAcceptHeaderValue);
float q = 1.0f;
while (m.find()) {
String contentTypeGroup = m.group(1);
EncodingEnum encoding = Constants.FORMAT_VAL_TO_ENCODING.get(contentTypeGroup);
if (encoding != null) {
String name = m.group(3);
String value = m.group(4);
if (name != null && value != null) {
if ("q".equals(name)) {
try {
q = Float.parseFloat(value);
q = Math.max(q, 0.0f);
} catch (NumberFormatException e) {
ourLog.debug("Invalid Accept header q value: {}", value);
}
}
}
}
if (q > bestQ) {
retVal = encoding;
bestQ = q;
}
if (!",".equals(m.group(5))) {
break;
}
}
}
return retVal;
}
return null;
}

View File

@ -129,3 +129,4 @@ local.properties
/target/
/target/
/target/

View File

@ -0,0 +1,17 @@
package ca.uhn.fhir;
import static org.junit.Assert.*;
import org.junit.Test;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.context.FhirVersionEnum;
public class Dstu1EnvTest {
@Test
public void testCorrectDefault() {
FhirContext ctx = new FhirContext();
assertEquals("new FhirContext() is creating a context with the wrong FHIR versions. Something is probably wrong with the classpath.", FhirVersionEnum.DSTU1, ctx.getVersion().getVersion());
}
}

View File

@ -0,0 +1,135 @@
package ca.uhn.fhir.rest.server;
import static org.hamcrest.Matchers.*;
import static org.junit.Assert.*;
import java.net.URLEncoder;
import java.util.concurrent.TimeUnit;
import org.apache.commons.io.IOUtils;
import org.apache.http.Header;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.servlet.ServletHandler;
import org.eclipse.jetty.servlet.ServletHolder;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.model.api.IResource;
import ca.uhn.fhir.model.dstu.composite.IdentifierDt;
import ca.uhn.fhir.model.dstu.resource.Organization;
import ca.uhn.fhir.model.dstu.resource.Patient;
import ca.uhn.fhir.model.primitive.IdDt;
import ca.uhn.fhir.rest.annotation.IdParam;
import ca.uhn.fhir.rest.annotation.Read;
import ca.uhn.fhir.util.PortUtil;
/**
* Created by dsotnikov on 2/25/2014.
*/
public class AcceptHeaderTest {
private static CloseableHttpClient ourClient;
private static int ourPort;
private static Server ourServer;
@Test
public void testReadNoHeader() throws Exception {
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/1");
HttpResponse status = ourClient.execute(httpGet);
IOUtils.closeQuietly(status.getEntity().getContent());
assertEquals(Constants.CT_FHIR_XML + Constants.CTSUFFIX_CHARSET_UTF8, status.getFirstHeader(Constants.HEADER_CONTENT_TYPE).getValue());
}
@Test
public void testReadXmlHeaderHigherPriority() throws Exception {
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/1");
httpGet.addHeader(Constants.HEADER_ACCEPT, Constants.CT_FHIR_XML + "; q=1.0, " + Constants.CT_FHIR_JSON + "; q=0.9");
HttpResponse status = ourClient.execute(httpGet);
IOUtils.closeQuietly(status.getEntity().getContent());
assertEquals(Constants.CT_FHIR_XML + Constants.CTSUFFIX_CHARSET_UTF8, status.getFirstHeader(Constants.HEADER_CONTENT_TYPE).getValue());
}
@Test
public void testReadXmlHeaderHigherPriorityWithStar() throws Exception {
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/1");
httpGet.addHeader(Constants.HEADER_ACCEPT, "*/*; q=1.0, " + Constants.CT_FHIR_XML + "; q=1.0, " + Constants.CT_FHIR_JSON + "; q=0.9");
HttpResponse status = ourClient.execute(httpGet);
IOUtils.closeQuietly(status.getEntity().getContent());
assertEquals(Constants.CT_FHIR_XML + Constants.CTSUFFIX_CHARSET_UTF8, status.getFirstHeader(Constants.HEADER_CONTENT_TYPE).getValue());
}
@Test
public void testReadXmlHeaderHigherPriorityBackwards() throws Exception {
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/1");
httpGet.addHeader(Constants.HEADER_ACCEPT, Constants.CT_FHIR_JSON + "; q=0.9, " + Constants.CT_FHIR_XML + "; q=1.0");
HttpResponse status = ourClient.execute(httpGet);
IOUtils.closeQuietly(status.getEntity().getContent());
assertEquals(Constants.CT_FHIR_XML + Constants.CTSUFFIX_CHARSET_UTF8, status.getFirstHeader(Constants.HEADER_CONTENT_TYPE).getValue());
// Now with spaces
httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/1");
httpGet.addHeader(Constants.HEADER_ACCEPT, Constants.CT_FHIR_JSON + "; q = 000000.9 , " + Constants.CT_FHIR_XML + " ; q = 1.0 ,");
status = ourClient.execute(httpGet);
IOUtils.closeQuietly(status.getEntity().getContent());
assertEquals(Constants.CT_FHIR_XML + Constants.CTSUFFIX_CHARSET_UTF8, status.getFirstHeader(Constants.HEADER_CONTENT_TYPE).getValue());
}
@AfterClass
public static void afterClass() throws Exception {
ourServer.stop();
}
@BeforeClass
public static void beforeClass() throws Exception {
ourPort = PortUtil.findFreePort();
ourServer = new Server(ourPort);
ServletHandler proxyHandler = new ServletHandler();
RestfulServer servlet = new RestfulServer();
servlet.setResourceProviders(new PatientProvider());
servlet.setDefaultResponseEncoding(EncodingEnum.XML);
ServletHolder servletHolder = new ServletHolder(servlet);
proxyHandler.addServletWithMapping(servletHolder, "/*");
ourServer.setHandler(proxyHandler);
ourServer.start();
PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(5000, TimeUnit.MILLISECONDS);
HttpClientBuilder builder = HttpClientBuilder.create();
builder.setConnectionManager(connectionManager);
ourClient = builder.build();
}
/**
* Created by dsotnikov on 2/25/2014.
*/
public static class PatientProvider implements IResourceProvider {
@Read(version = true)
public Patient read(@IdParam IdDt theId) {
Patient patient = new Patient();
patient.addIdentifier(theId.getIdPart(), theId.getVersionIdPart());
patient.setId("Patient/1/_history/1");
return patient;
}
@Override
public Class<? extends IResource> getResourceType() {
return Patient.class;
}
}
}

View File

@ -0,0 +1,19 @@
package ca.uhn.fhir.rest.server;
import static org.junit.Assert.*;
import java.util.regex.Matcher;
import org.junit.Test;
public class RestfulServerUtilsTest {
@Test
public void testAcceptPattern() {
Matcher m = RestfulServerUtils.ACCEPT_HEADER_PATTERN.matcher("application/json+fhir");
assertTrue(m.find());
assertEquals("application/json+fhir", m.group(0));
assertEquals("application/json+fhir", m.group(1));
}
}

View File

@ -88,7 +88,7 @@ public class ServerFeaturesTest {
}
@Test
public void testAcceptHeader() throws Exception {
public void testAcceptHeaderXml() throws Exception {
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/1");
httpGet.addHeader("Accept", Constants.CT_FHIR_XML);
HttpResponse status = ourClient.execute(httpGet);
@ -97,18 +97,28 @@ public class ServerFeaturesTest {
assertThat(responseContent, StringContains.containsString("<identifier><use"));
httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/1");
}
@Test
public void testAcceptHeaderAtom() throws Exception {
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/1");
httpGet.addHeader("Accept", Constants.CT_ATOM_XML);
status = ourClient.execute(httpGet);
responseContent = IOUtils.toString(status.getEntity().getContent());
CloseableHttpResponse status = ourClient.execute(httpGet);
String responseContent = IOUtils.toString(status.getEntity().getContent());
IOUtils.closeQuietly(status.getEntity().getContent());
assertThat(responseContent, StringContains.containsString("<identifier><use"));
httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/1");
}
@Test
public void testAcceptHeaderJson() throws Exception {
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/1");
httpGet.addHeader("Accept", Constants.CT_FHIR_JSON);
status = ourClient.execute(httpGet);
responseContent = IOUtils.toString(status.getEntity().getContent());
CloseableHttpResponse status = ourClient.execute(httpGet);
String responseContent = IOUtils.toString(status.getEntity().getContent());
IOUtils.closeQuietly(status.getEntity().getContent());
assertThat(responseContent, StringContains.containsString("\"identifier\":"));
@ -118,7 +128,6 @@ public class ServerFeaturesTest {
@Test
public void testAcceptHeaderWithMultiple() throws Exception {
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/1");

View File

@ -0,0 +1,17 @@
package ca.uhn.fhir;
import static org.junit.Assert.*;
import org.junit.Test;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.context.FhirVersionEnum;
public class Dstu2EnvTest {
@Test
public void testCorrectDefault() {
FhirContext ctx = new FhirContext();
assertEquals("new FhirContext() is creating a context with the wrong FHIR versions. Something is probably wrong with the classpath.", FhirVersionEnum.DSTU2, ctx.getVersion().getVersion());
}
}

20
pom.xml
View File

@ -230,8 +230,8 @@
<configuration>
<source>1.6</source>
<target>1.6</target>
<!-- <compilerId>javac-with-errorprone</compilerId>
<forceJavacCompilerUse>true</forceJavacCompilerUse> -->
<compilerId>javac-with-errorprone</compilerId>
<forceJavacCompilerUse>true</forceJavacCompilerUse>
</configuration>
<dependencies>
<dependency>
@ -258,7 +258,6 @@
<configuration>
<redirectTestOutputToFile>true</redirectTestOutputToFile>
<runOrder>random</runOrder>
<!--<argLine>-Dfile.encoding=ISO-8859-1</argLine> -->
<argLine>-Dfile.encoding=UTF-8</argLine>
</configuration>
</plugin>
@ -426,6 +425,21 @@
</lifecycleMappingMetadata>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-checkstyle-plugin</artifactId>
<version>2.15</version>
<dependencies>
<dependency>
<groupId>com.puppycrawl.tools</groupId>
<artifactId>checkstyle</artifactId>
<version>6.7</version>
</dependency>
</dependencies>
<configuration>
<configLocation>src/checkstyle/checkstyle.xml</configLocation>
</configuration>
</plugin>
</plugins>
</pluginManagement>
<plugins>

View File

@ -98,6 +98,10 @@
in DSTU2 mode. Thanks to Eric from the FHIR Skype Implementers chat for
reporting.
</action>
<action type="add">
Server now supports complete Accept header content negotiation, including
q values specifying order of preference. Previously the q value was ignored.
</action>
</release>
<release version="1.0" date="2015-May-8">
<action type="add">

View File

@ -0,0 +1,204 @@
<?xml version="1.0"?>
<!DOCTYPE module PUBLIC
"-//Puppy Crawl//DTD Check Configuration 1.3//EN"
"http://www.puppycrawl.com/dtds/configuration_1_3.dtd">
<!--
Checkstyle configuration that checks the Google coding conventions from:
- Google Java Style
https://google-styleguide.googlecode.com/svn-history/r130/trunk/javaguide.html
Checkstyle is very configurable. Be sure to read the documentation at
http://checkstyle.sf.net (or in your downloaded distribution).
Most Checks are configurable, be sure to consult the documentation.
To completely disable a check, just comment it out or delete it from the file.
Authors: Max Vetrenko, Ruslan Diachenko, Roman Ivanov.
-->
<module name = "Checker">
<property name="charset" value="UTF-8"/>
<property name="severity" value="warning"/>
<!--<property name="fileExtensions" value="java, properties, xml"/>-->
<module name="TreeWalker">
<property name="tabWidth" value="3"/>
<module name="OuterTypeFilename"/>
<module name="IllegalTokenText">
<property name="tokens" value="STRING_LITERAL, CHAR_LITERAL"/>
<property name="format" value="\\u00(08|09|0(a|A)|0(c|C)|0(d|D)|22|27|5(C|c))|\\(0(10|11|12|14|15|42|47)|134)"/>
<property name="message" value="Avoid using corresponding octal or Unicode escape."/>
</module>
<module name="AvoidEscapedUnicodeCharacters">
<property name="allowEscapesForControlCharacters" value="true"/>
<property name="allowByTailComment" value="true"/>
<property name="allowNonPrintableEscapes" value="true"/>
</module>
<module name="LineLength">
<property name="max" value="200"/>
<property name="ignorePattern" value="^package.*|^import.*|a href|href|http://|https://|ftp://"/>
</module>
<module name="AvoidStarImport"/>
<module name="OneTopLevelClass"/>
<module name="NoLineWrap"/>
<module name="EmptyBlock">
<property name="option" value="TEXT"/>
<property name="tokens" value="LITERAL_TRY, LITERAL_FINALLY, LITERAL_IF, LITERAL_ELSE, LITERAL_SWITCH"/>
</module>
<module name="NeedBraces"/>
<module name="LeftCurly">
<property name="maxLineLength" value="200"/>
</module>
<module name="RightCurly"/>
<module name="RightCurly">
<property name="option" value="alone"/>
<property name="tokens" value="CLASS_DEF, METHOD_DEF, CTOR_DEF, LITERAL_FOR, LITERAL_WHILE, LITERAL_DO, STATIC_INIT, INSTANCE_INIT"/>
</module>
<module name="WhitespaceAround">
<property name="allowEmptyConstructors" value="true"/>
<property name="allowEmptyMethods" value="true"/>
<property name="allowEmptyTypes" value="true"/>
<property name="allowEmptyLoops" value="true"/>
<message key="ws.notFollowed"
value="WhitespaceAround: ''{0}'' is not followed by whitespace. Empty blocks may only be represented as '{}' when not part of a multi-block statement (4.1.3)"/>
<message key="ws.notPreceded"
value="WhitespaceAround: ''{0}'' is not preceded with whitespace."/>
</module>
<module name="OneStatementPerLine"/>
<module name="MultipleVariableDeclarations"/>
<module name="ArrayTypeStyle"/>
<module name="MissingSwitchDefault"/>
<module name="FallThrough"/>
<module name="UpperEll"/>
<module name="ModifierOrder"/>
<module name="EmptyLineSeparator">
<property name="allowNoEmptyLineBetweenFields" value="true"/>
</module>
<module name="SeparatorWrap">
<property name="tokens" value="DOT"/>
<property name="option" value="nl"/>
</module>
<module name="SeparatorWrap">
<property name="tokens" value="COMMA"/>
<property name="option" value="EOL"/>
</module>
<module name="PackageName">
<property name="format" value="^[a-z]+(\.[a-z][a-z0-9]*)*$"/>
<message key="name.invalidPattern"
value="Package name ''{0}'' must match pattern ''{1}''."/>
</module>
<module name="TypeName">
<message key="name.invalidPattern"
value="Type name ''{0}'' must match pattern ''{1}''."/>
</module>
<module name="MemberName">
<property name="format" value="^[a-z][a-z0-9][a-zA-Z0-9]*$"/>
<message key="name.invalidPattern"
value="Member name ''{0}'' must match pattern ''{1}''."/>
</module>
<module name="ParameterName">
<property name="format" value="^[a-z][a-z0-9][a-zA-Z0-9]*$"/>
<message key="name.invalidPattern"
value="Parameter name ''{0}'' must match pattern ''{1}''."/>
</module>
<module name="LocalVariableName">
<property name="tokens" value="VARIABLE_DEF"/>
<property name="format" value="^[a-z][a-z0-9][a-zA-Z0-9]*$"/>
<property name="allowOneCharVarInForLoop" value="true"/>
<message key="name.invalidPattern"
value="Local variable name ''{0}'' must match pattern ''{1}''."/>
</module>
<module name="ClassTypeParameterName">
<property name="format" value="(^[A-Z][0-9]?)$|([A-Z][a-zA-Z0-9]*[T]$)"/>
<message key="name.invalidPattern"
value="Class type name ''{0}'' must match pattern ''{1}''."/>
</module>
<module name="MethodTypeParameterName">
<property name="format" value="(^[A-Z][0-9]?)$|([A-Z][a-zA-Z0-9]*[T]$)"/>
<message key="name.invalidPattern"
value="Method type name ''{0}'' must match pattern ''{1}''."/>
</module>
<module name="NoFinalizer"/>
<module name="GenericWhitespace">
<message key="ws.followed"
value="GenericWhitespace ''{0}'' is followed by whitespace."/>
<message key="ws.preceded"
value="GenericWhitespace ''{0}'' is preceded with whitespace."/>
<message key="ws.illegalFollow"
value="GenericWhitespace ''{0}'' should followed by whitespace."/>
<message key="ws.notPreceded"
value="GenericWhitespace ''{0}'' is not preceded with whitespace."/>
</module>
<module name="UncommentedMain"/>
<module name="Indentation">
<property name="basicOffset" value="3"/>
<property name="braceAdjustment" value="0"/>
<property name="caseIndent" value="3"/>
<property name="throwsIndent" value="6"/>
<property name="lineWrappingIndentation" value="6"/>
<property name="arrayInitIndent" value="3"/>
</module>
<module name="AbbreviationAsWordInName">
<property name="ignoreFinal" value="false"/>
<property name="allowedAbbreviationLength" value="1"/>
</module>
<module name="OverloadMethodsDeclarationOrder"/>
<module name="VariableDeclarationUsageDistance"/>
<!--
<module name="CustomImportOrder">
<property name="specialImportsRegExp" value="com.google"/>
<property name="sortImportsInGroupAlphabetically" value="true"/>
<property name="customImportOrderRules" value="STATIC###SPECIAL_IMPORTS###THIRD_PARTY_PACKAGE###STANDARD_JAVA_PACKAGE"/>
</module>
-->
<module name="MethodParamPad"/>
<module name="OperatorWrap">
<property name="option" value="NL"/>
<property name="tokens" value="BAND, BOR, BSR, BXOR, DIV, EQUAL, GE, GT, LAND, LE, LITERAL_INSTANCEOF, LOR, LT, MINUS, MOD, NOT_EQUAL, PLUS, QUESTION, SL, SR, STAR "/>
</module>
<module name="AnnotationLocation">
<property name="tokens" value="CLASS_DEF, INTERFACE_DEF, ENUM_DEF, METHOD_DEF, CTOR_DEF"/>
</module>
<module name="AnnotationLocation">
<property name="tokens" value="VARIABLE_DEF"/>
<property name="allowSamelineMultipleAnnotations" value="true"/>
</module>
<module name="NonEmptyAtclauseDescription"/>
<module name="JavadocTagContinuationIndentation"/>
<module name="SummaryJavadocCheck">
<property name="forbiddenSummaryFragments" value="^@return the *|^This method returns |^A [{]@code [a-zA-Z0-9]+[}]( is a )"/>
</module>
<module name="JavadocParagraph"/>
<module name="AtclauseOrder">
<property name="tagOrder" value="@param, @return, @throws, @deprecated"/>
<property name="target" value="CLASS_DEF, INTERFACE_DEF, ENUM_DEF, METHOD_DEF, CTOR_DEF, VARIABLE_DEF"/>
</module>
<module name="JavadocMethod">
<property name="scope" value="public"/>
<property name="allowMissingParamTags" value="true"/>
<property name="allowMissingThrowsTags" value="true"/>
<property name="allowMissingReturnTag" value="true"/>
<property name="minLineCount" value="2"/>
<property name="allowedAnnotations" value="Override, Test"/>
<property name="allowThrowsTagsForSubclasses" value="true"/>
</module>
<module name="MethodName">
<property name="format" value="^[a-z][a-z0-9][a-zA-Z0-9_]*$"/>
<message key="name.invalidPattern"
value="Method name ''{0}'' must match pattern ''{1}''."/>
</module>
<module name="SingleLineJavadoc"/>
<!--<property name="ignoreInlineTags" value="false"/>-->
<!--<module name="EmptyCatchBlock">
<property name="exceptionVariableName" value="expected"/>
</module>-->
</module>
</module>