#2612 remove thirdparty google guava module

This commit is contained in:
emeroad
2017-02-14 23:22:08 +09:00
committed by Woonduk Kang
parent 400bc293ae
commit d7643a30bc
490 changed files with 5 additions and 136213 deletions
+1 -2
View File
@@ -7,5 +7,4 @@
- \com\navercorp\pinpoint\common\util\apache
- \com\navercorp\pinpoint\common\util\jsr166
- \com\navercorp\pinpoint\profiler\util\jdk
- \com\navercorp\pinpoint\bootstrap\util\spring
- \com\google
- \com\navercorp\pinpoint\bootstrap\util\spring
-4
View File
@@ -2,8 +2,4 @@
<Match>
<Package name="~com\.navercorp\.pinpoint\.thrift\.dto.*" />
</Match>
<Match>
<!-- google guava -->
<Package name="~com\.google.*" />
</Match>
</FindBugsFilter>
-18
View File
@@ -66,7 +66,6 @@
<module>test</module>
<module>web</module>
<module>hbase</module>
<module>thirdparty</module>
</modules>
<properties>
@@ -119,11 +118,6 @@
<artifactId>pinpoint-commons</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.navercorp.pinpoint</groupId>
<artifactId>pinpoint-google-guava</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.navercorp.pinpoint</groupId>
<artifactId>pinpoint-commons-server</artifactId>
@@ -829,9 +823,6 @@
<exclude>com/navercorp/pinpoint/common/util/apache/**/*.java</exclude>
<exclude>com/navercorp/pinpoint/common/util/jsr166/**/*.java</exclude>
<exclude>com/navercorp/pinpoint/profiler/util/jdk/**/*.java</exclude>
<!--google guava-->
<exclude>com/google/**/*.java</exclude>
</excludes>
</configuration>
</plugin>
@@ -898,9 +889,6 @@
<exclude>com/navercorp/pinpoint/common/util/apache/**/*.java</exclude>
<exclude>com/navercorp/pinpoint/common/util/jsr166/**/*.java</exclude>
<exclude>com/navercorp/pinpoint/profiler/util/jdk/**/*.java</exclude>
<!--google guava-->
<exclude>com/google/**/*.java</exclude>
</excludes>
</configuration>
</plugin>
@@ -990,9 +978,6 @@
<exclude>com/navercorp/pinpoint/common/util/apache/**/*.java</exclude>
<exclude>com/navercorp/pinpoint/common/util/jsr166/**/*.java</exclude>
<exclude>com/navercorp/pinpoint/profiler/util/jdk/**/*.java</exclude>
<!--google guava-->
<exclude>com/google/**/*.java</exclude>
</excludes>
</configuration>
</plugin>
@@ -1010,9 +995,6 @@
<exclude>com/navercorp/pinpoint/common/util/apache/**/*.java</exclude>
<exclude>com/navercorp/pinpoint/common/util/jsr166/**/*.java</exclude>
<exclude>com/navercorp/pinpoint/profiler/util/jdk/**/*.java</exclude>
<!--google guava-->
<exclude>com/google/**/*.java</exclude>
</excludes>
</configuration>
</plugin>
+2 -2
View File
@@ -68,8 +68,8 @@
<artifactId>pinpoint-rpc</artifactId>
</dependency>
<dependency>
<groupId>com.navercorp.pinpoint</groupId>
<artifactId>pinpoint-google-guava</artifactId>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
</dependency>
+2 -2
View File
@@ -57,8 +57,8 @@
<artifactId>pinpoint-rpc</artifactId>
</dependency>
<dependency>
<groupId>com.navercorp.pinpoint</groupId>
<artifactId>pinpoint-google-guava</artifactId>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
</dependency>
<dependency>
<groupId>com.google.inject</groupId>
-5
View File
@@ -1,5 +0,0 @@
/target/
/.settings/
/.classpath
/.project
/*.iml
-2
View File
@@ -1,2 +0,0 @@
# thirdparty lib project
- google-guava
-5
View File
@@ -1,5 +0,0 @@
RMRqrdbgbKFhbaVnDxHUdDQvrOQXxIBklnvcmahheubVC
mh2KM35CLkwUHS4DH7QVhxy52J5hnWbyEm6Cyd3KkF<mV
RmmnSVOqOMnOnMMrmMqwXomoroNrqPNRrPSsWwtUxXuUU
sRONqpnmqmUUnqonmstsmmmmmUUnqonmstsmmmmmUUGfk
mlfkqUUnmmmm
-5
View File
@@ -1,5 +0,0 @@
/.settings/
/*.iml
/target/
/.classpath
/.project
-1
View File
@@ -1 +0,0 @@
Doug Lea
-202
View File
@@ -1,202 +0,0 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
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.
-7
View File
@@ -1,7 +0,0 @@
# pinpoint-google-guava
https://github.com/google/guava
google-guava repackaging
guava version : 19.0
- https://github.com/google/guava/tree/v19.0
- remove jdk logger
- https://github.com/naver/pinpoint/issues/2026
-5
View File
@@ -1,5 +0,0 @@
RMRqrdbgbKFhbaVnDxHUdDQvrOQXxIBklnvcmahheubVC
mh2KM35CLkwUHS4DH7QVhxy52J5hnWbyEm6Cyd3KkF<mV
RmmnSVOqOMnOnMMrmMqwXomoroNrqPNRrPSsWwtUxXuUU
sRONqpnmqmUUnqonmstsmmmmmUUnqonmstsmmmmmUUGfk
mlfkqUUnmmmm
-126
View File
@@ -1,126 +0,0 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.navercorp.pinpoint</groupId>
<artifactId>pinpoint</artifactId>
<relativePath>../..</relativePath>
<version>1.6.1-SNAPSHOT</version>
</parent>
<!--
google-guava version : 19
-->
<artifactId>pinpoint-google-guava</artifactId>
<name>pinpoint-google-guava</name>
<packaging>jar</packaging>
<properties>
<jdk.version>1.6</jdk.version>
<jdk.home>${env.JAVA_7_HOME}</jdk.home>
<sniffer.artifactid>java16</sniffer.artifactid>
</properties>
<!---->
<dependencies>
<dependency>
<groupId>com.google.code.findbugs</groupId>
<artifactId>jsr305</artifactId>
<version>1.3.9</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.google.j2objc</groupId>
<artifactId>j2objc-annotations</artifactId>
<version>1.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.codehaus.mojo</groupId>
<artifactId>animal-sniffer-annotations</artifactId>
<version>1.14</version>
<scope>provided</scope>
</dependency>
<!-- Logging depedencies -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<version>1.10</version>
<executions>
<execution>
<phase>generate-sources</phase>
<goals><goal>add-source</goal></goals>
<configuration>
<sources>
<source>src/main/java-logging</source>
</sources>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>com.google.code.maven-replacer-plugin</groupId>
<artifactId>replacer</artifactId>
<version>1.5.3</version>
<executions>
<execution>
<phase>generate-sources</phase>
<goals>
<goal>replace</goal>
</goals>
</execution>
</executions>
<configuration>
<encoding>${encoding}</encoding>
<basedir>${project.build.sourceDirectory}/</basedir>
<includes>
<include>**/*.java</include>
</includes>
<outputBasedir>
</outputBasedir>
<replacements>
<replacement>
<token>java.util.logging.</token>
<value>com.google.common.logging.</value>
</replacement>
</replacements>
</configuration>
</plugin>
</plugins>
</build>
<profiles>
<!--<profile>-->
<!--<id>jdk7</id>-->
<!--<activation>-->
<!--<jdk>1.7</jdk>-->
<!--</activation>-->
<!--</profile>-->
</profiles>
</project>
@@ -1,51 +0,0 @@
/*
* Copyright 2016 NAVER Corp.
*
* 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 com.google.common.logging;
/**
* compiler trick class
* @author Woonduk Kang(emeroad)
*/
public enum Level {
OFF(Integer.MAX_VALUE),
SEVERE(1000),
WARNING(900),
CONFIG(700),
INFO(800),
FINE(500),
FINER(400),
FINEST(300),
ALL(Integer.MIN_VALUE);
private final int level;
Level(int level) {
this.level = level;
}
public int intValue() {
return level;
}
public String getName() {
return name();
}
}
@@ -1,181 +0,0 @@
/*
* Copyright 2016 NAVER Corp.
*
* 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 com.google.common.logging;
import java.io.PrintStream;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.text.MessageFormat;
/**
* compiler trick class
*
* @author Woonduk Kang(emeroad)
*/
public class Logger {
private static Level DEFAULT_LOG_LEVEL;
private final String name;
private final String messagePattern;
private final Level level;
private final PrintStream out;
private final PrintStream err;
static {
setup();
}
private static void setup() {
// TODO setup log level
DEFAULT_LOG_LEVEL = Level.INFO;
}
public static Logger getLogger(String name) {
return new Logger(name, DEFAULT_LOG_LEVEL);
}
public Logger(String name, Level level) {
this(name, level, System.out, System.err);
}
Logger(String name, Level level, PrintStream out, PrintStream err) {
this.name = name;
this.level = level;
this.messagePattern = "{0,date,yyyy-MM-dd HH:mm:ss} [{1}](" + name + ") {2}{3}";
this.out = out;
this.err = err;
}
public String getName() {
return name;
}
public void log(Level level, String msg) {
if (!isLoggable(level)) {
return;
}
doLog(level, msg, null, null);
}
public void log(Level level, String msg, Throwable throwable) {
if (!isLoggable(level)) {
return;
}
doLog(level, msg, null, throwable);
}
public void log(Level level, String msg, Object params[]) {
if (!isLoggable(level)) {
return;
}
doLog(level, msg, params, null);
}
public void log(Level level, String msg, Object param1) {
if (!isLoggable(level)) {
return;
}
doLog(level, msg, new Object[]{param1}, null);
}
private void doLog(Level level, String msg, Object[] params, Throwable throwable) {
String format = messageFormat(msg, params);
String exceptionMessage = toString(throwable);
String logMessage = logFormat(level, format, exceptionMessage);
PrintStream printStream = getPrintStream(level);
printStream.println(logMessage);
}
private PrintStream getPrintStream(Level level) {
if (level.intValue() >= Level.WARNING.intValue()) {
return this.err;
} else {
return this.out;
}
}
public boolean isLoggable(Level level) {
if (level.intValue() < this.level.intValue()) {
return false;
}
return true;
}
public void info(String msg) {
Level logLevel = Level.INFO;
if (!isLoggable(logLevel)) {
return;
}
doLog(Level.INFO, msg, null, null);
}
public void warning(String msg) {
if (!isLoggable(Level.WARNING)) {
return;
}
doLog(Level.WARNING, msg, null, null);
}
private String messageFormat(String format, Object[] parameter) {
if (parameter == null || parameter.length == 0) {
return format;
}
// emulation java util.logging
if (format.indexOf("{0") >= 0 || format.indexOf("{1") >= 0 || format.indexOf("{2") >= 0 || format.indexOf("{3") >= 0) {
return MessageFormat.format(format, parameter);
}
return format;
}
private String logFormat(Level logLevel, String msg, String exceptionMessage) {
exceptionMessage = defaultString(exceptionMessage, "");
final long date = System.currentTimeMillis();
return MessageFormat.format(messagePattern, date, logLevel.getName(), msg, exceptionMessage);
}
private String toString(Throwable throwable) {
if (throwable == null) {
return "";
}
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
pw.println();
throwable.printStackTrace(pw);
pw.close();
return sw.toString();
}
private String defaultString(String exceptionMessage, String defaultValue) {
if (exceptionMessage == null) {
return defaultValue;
}
return exceptionMessage;
}
}
@@ -1,24 +0,0 @@
/*
* Copyright 2016 NAVER Corp.
*
* 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 com.google.common.logging;/*
/**
* compiler trick package
*/
@@ -1,50 +0,0 @@
/*
* Copyright (C) 2010 The Guava Authors
*
* 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 com.google.common.annotations;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Signifies that a public API (public class, method or field) is subject to
* incompatible changes, or even removal, in a future release. An API bearing
* this annotation is exempt from any compatibility guarantees made by its
* containing library. Note that the presence of this annotation implies nothing
* about the quality or performance of the API in question, only the fact that
* it is not "API-frozen."
*
* <p>It is generally safe for <i>applications</i> to depend on beta APIs, at
* the cost of some extra work during upgrades. However it is generally
* inadvisable for <i>libraries</i> (which get included on users' CLASSPATHs,
* outside the library developers' control) to do so.
*
*
* @author Kevin Bourrillion
*/
@Retention(RetentionPolicy.CLASS)
@Target({
ElementType.ANNOTATION_TYPE,
ElementType.CONSTRUCTOR,
ElementType.FIELD,
ElementType.METHOD,
ElementType.TYPE})
@Documented
@GwtCompatible
public @interface Beta {}
@@ -1,88 +0,0 @@
/*
* Copyright (C) 2009 The Guava Authors
*
* 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 com.google.common.annotations;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* The presence of this annotation on a type indicates that the type may be
* used with the
* <a href="http://code.google.com/webtoolkit/">Google Web Toolkit</a> (GWT).
* When applied to a method, the return type of the method is GWT compatible.
* It's useful to indicate that an instance created by factory methods has a GWT
* serializable type. In the following example,
*
* <pre style="code">
* {@literal @}GwtCompatible
* class Lists {
* ...
* {@literal @}GwtCompatible(serializable = true)
* static &lt;E> List&lt;E> newArrayList(E... elements) {
* ...
* }
* }
* </pre>
* <p>The return value of {@code Lists.newArrayList(E[])} has GWT
* serializable type. It is also useful in specifying contracts of interface
* methods. In the following example,
*
* <pre style="code">
* {@literal @}GwtCompatible
* interface ListFactory {
* ...
* {@literal @}GwtCompatible(serializable = true)
* &lt;E> List&lt;E> newArrayList(E... elements);
* }
* </pre>
* <p>The {@code newArrayList(E[])} method of all implementations of {@code
* ListFactory} is expected to return a value with a GWT serializable type.
*
* <p>Note that a {@code GwtCompatible} type may have some {@link
* GwtIncompatible} methods.
*
* @author Charles Fry
* @author Hayward Chan
*/
@Retention(RetentionPolicy.CLASS)
@Target({ ElementType.TYPE, ElementType.METHOD })
@Documented
@GwtCompatible
public @interface GwtCompatible {
/**
* When {@code true}, the annotated type or the type of the method return
* value is GWT serializable.
*
* @see <a href="http://code.google.com/webtoolkit/doc/latest/DevGuideServerCommunication.html#DevGuideSerializableTypes">
* Documentation about GWT serialization</a>
*/
boolean serializable() default false;
/**
* When {@code true}, the annotated type is emulated in GWT. The emulated
* source (also known as super-source) is different from the implementation
* used by the JVM.
*
* @see <a href="http://code.google.com/webtoolkit/doc/latest/DevGuideOrganizingProjects.html#DevGuideModules">
* Documentation about GWT emulated source</a>
*/
boolean emulated() default false;
}
@@ -1,52 +0,0 @@
/*
* Copyright (C) 2009 The Guava Authors
*
* 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 com.google.common.annotations;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* The presence of this annotation on a method indicates that the method may
* <em>not</em> be used with the
* <a href="http://code.google.com/webtoolkit/">Google Web Toolkit</a> (GWT),
* even though its type is annotated as {@link GwtCompatible} and accessible in
* GWT. They can cause GWT compilation errors or simply unexpected exceptions
* when used in GWT.
*
* <p>Note that this annotation should only be applied to methods, fields, or
* inner classes of types which are annotated as {@link GwtCompatible}.
*
* @author Charles Fry
*/
@Retention(RetentionPolicy.CLASS)
@Target({
ElementType.TYPE, ElementType.METHOD,
ElementType.CONSTRUCTOR, ElementType.FIELD })
@Documented
@GwtCompatible
public @interface GwtIncompatible {
/**
* Describes why the annotated element is incompatible with GWT. Since this is
* generally due to a dependence on a type/method which GWT doesn't support,
* it is sufficient to simply reference the unsupported type/method. E.g.
* "Class.isInstance".
*/
String value();
}
@@ -1,27 +0,0 @@
/*
* Copyright (C) 2006 The Guava Authors
*
* 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 com.google.common.annotations;
/**
* Annotates a program element that exists, or is more widely visible than
* otherwise necessary, only for use in test code.
*
* @author Johannes Henkel
*/
@GwtCompatible
public @interface VisibleForTesting {
}
@@ -1,21 +0,0 @@
/*
* Copyright (C) 2010 The Guava Authors
*
* 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.
*/
/**
* Common annotation types. This package is a part of the open-source
* <a href="http://guava-libraries.googlecode.com">Guava libraries</a>.
*/
package com.google.common.annotations;
@@ -1,106 +0,0 @@
/*
* Copyright (C) 2011 The Guava Authors
*
* 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 com.google.common.base;
import static com.google.common.base.Preconditions.checkNotNull;
import com.google.common.annotations.GwtCompatible;
import java.util.Collections;
import java.util.Set;
import javax.annotation.Nullable;
/**
* Implementation of an {@link Optional} not containing a reference.
*/
@GwtCompatible
final class Absent<T> extends Optional<T> {
static final Absent<Object> INSTANCE = new Absent<Object>();
@SuppressWarnings("unchecked") // implementation is "fully variant"
static <T> Optional<T> withType() {
return (Optional<T>) INSTANCE;
}
private Absent() {}
@Override
public boolean isPresent() {
return false;
}
@Override
public T get() {
throw new IllegalStateException("Optional.get() cannot be called on an absent value");
}
@Override
public T or(T defaultValue) {
return checkNotNull(defaultValue, "use Optional.orNull() instead of Optional.or(null)");
}
@SuppressWarnings("unchecked") // safe covariant cast
@Override
public Optional<T> or(Optional<? extends T> secondChoice) {
return (Optional<T>) checkNotNull(secondChoice);
}
@Override
public T or(Supplier<? extends T> supplier) {
return checkNotNull(
supplier.get(), "use Optional.orNull() instead of a Supplier that returns null");
}
@Override
@Nullable
public T orNull() {
return null;
}
@Override
public Set<T> asSet() {
return Collections.emptySet();
}
@Override
public <V> Optional<V> transform(Function<? super T, V> function) {
checkNotNull(function);
return Optional.absent();
}
@Override
public boolean equals(@Nullable Object object) {
return object == this;
}
@Override
public int hashCode() {
return 0x79a31aac;
}
@Override
public String toString() {
return "Optional.absent()";
}
private Object readResolve() {
return INSTANCE;
}
private static final long serialVersionUID = 0;
}
@@ -1,90 +0,0 @@
/*
* Copyright (C) 2007 The Guava Authors
*
* 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 com.google.common.base;
import static com.google.common.base.Preconditions.checkState;
import com.google.common.annotations.GwtCompatible;
import java.util.Iterator;
import java.util.NoSuchElementException;
/**
* Note this class is a copy of
* {@link com.google.common.collect.AbstractIterator} (for dependency reasons).
*/
@GwtCompatible
abstract class AbstractIterator<T> implements Iterator<T> {
private State state = State.NOT_READY;
protected AbstractIterator() {}
private enum State {
READY,
NOT_READY,
DONE,
FAILED,
}
private T next;
protected abstract T computeNext();
protected final T endOfData() {
state = State.DONE;
return null;
}
@Override
public final boolean hasNext() {
checkState(state != State.FAILED);
switch (state) {
case READY:
return true;
case DONE:
return false;
default:
}
return tryToComputeNext();
}
private boolean tryToComputeNext() {
state = State.FAILED; // temporary pessimism
next = computeNext();
if (state != State.DONE) {
state = State.READY;
return true;
}
return false;
}
@Override
public final T next() {
if (!hasNext()) {
throw new NoSuchElementException();
}
state = State.NOT_READY;
T result = next;
next = null;
return result;
}
@Override
public final void remove() {
throw new UnsupportedOperationException();
}
}
@@ -1,669 +0,0 @@
/*
* Copyright (C) 2010 The Guava Authors
*
* 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 com.google.common.base;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import com.google.common.annotations.Beta;
import com.google.common.annotations.GwtCompatible;
import javax.annotation.CheckReturnValue;
/**
* Static methods pertaining to ASCII characters (those in the range of values
* {@code 0x00} through {@code 0x7F}), and to strings containing such
* characters.
*
* <p>ASCII utilities also exist in other classes of this package:
* <ul>
* <!-- TODO(kevinb): how can we make this not produce a warning when building gwt javadoc? -->
* <li>{@link Charsets#US_ASCII} specifies the {@code Charset} of ASCII characters.
* <li>{@link CharMatcher#ASCII} matches ASCII characters and provides text processing methods
* which operate only on the ASCII characters of a string.
* </ul>
*
* @author Craig Berry
* @author Gregory Kick
* @since 7.0
*/
@CheckReturnValue
@GwtCompatible
public final class Ascii {
private Ascii() {}
/* The ASCII control characters, per RFC 20. */
/**
* Null ('\0'): The all-zeros character which may serve to accomplish
* time fill and media fill. Normally used as a C string terminator.
* <p>Although RFC 20 names this as "Null", note that it is distinct
* from the C/C++ "NULL" pointer.
*
* @since 8.0
*/
public static final byte NUL = 0;
/**
* Start of Heading: A communication control character used at
* the beginning of a sequence of characters which constitute a
* machine-sensible address or routing information. Such a sequence is
* referred to as the "heading." An STX character has the effect of
* terminating a heading.
*
* @since 8.0
*/
public static final byte SOH = 1;
/**
* Start of Text: A communication control character which
* precedes a sequence of characters that is to be treated as an entity
* and entirely transmitted through to the ultimate destination. Such a
* sequence is referred to as "text." STX may be used to terminate a
* sequence of characters started by SOH.
*
* @since 8.0
*/
public static final byte STX = 2;
/**
* End of Text: A communication control character used to
* terminate a sequence of characters started with STX and transmitted
* as an entity.
*
* @since 8.0
*/
public static final byte ETX = 3;
/**
* End of Transmission: A communication control character used
* to indicate the conclusion of a transmission, which may have
* contained one or more texts and any associated headings.
*
* @since 8.0
*/
public static final byte EOT = 4;
/**
* Enquiry: A communication control character used in data
* communication systems as a request for a response from a remote
* station. It may be used as a "Who Are You" (WRU) to obtain
* identification, or may be used to obtain station status, or both.
*
* @since 8.0
*/
public static final byte ENQ = 5;
/**
* Acknowledge: A communication control character transmitted
* by a receiver as an affirmative response to a sender.
*
* @since 8.0
*/
public static final byte ACK = 6;
/**
* Bell ('\a'): A character for use when there is a need to call for
* human attention. It may control alarm or attention devices.
*
* @since 8.0
*/
public static final byte BEL = 7;
/**
* Backspace ('\b'): A format effector which controls the movement of
* the printing position one printing space backward on the same
* printing line. (Applicable also to display devices.)
*
* @since 8.0
*/
public static final byte BS = 8;
/**
* Horizontal Tabulation ('\t'): A format effector which controls the
* movement of the printing position to the next in a series of
* predetermined positions along the printing line. (Applicable also to
* display devices and the skip function on punched cards.)
*
* @since 8.0
*/
public static final byte HT = 9;
/**
* Line Feed ('\n'): A format effector which controls the movement of
* the printing position to the next printing line. (Applicable also to
* display devices.) Where appropriate, this character may have the
* meaning "New Line" (NL), a format effector which controls the
* movement of the printing point to the first printing position on the
* next printing line. Use of this convention requires agreement
* between sender and recipient of data.
*
* @since 8.0
*/
public static final byte LF = 10;
/**
* Alternate name for {@link #LF}. ({@code LF} is preferred.)
*
* @since 8.0
*/
public static final byte NL = 10;
/**
* Vertical Tabulation ('\v'): A format effector which controls the
* movement of the printing position to the next in a series of
* predetermined printing lines. (Applicable also to display devices.)
*
* @since 8.0
*/
public static final byte VT = 11;
/**
* Form Feed ('\f'): A format effector which controls the movement of
* the printing position to the first pre-determined printing line on
* the next form or page. (Applicable also to display devices.)
*
* @since 8.0
*/
public static final byte FF = 12;
/**
* Carriage Return ('\r'): A format effector which controls the
* movement of the printing position to the first printing position on
* the same printing line. (Applicable also to display devices.)
*
* @since 8.0
*/
public static final byte CR = 13;
/**
* Shift Out: A control character indicating that the code
* combinations which follow shall be interpreted as outside of the
* character set of the standard code table until a Shift In character
* is reached.
*
* @since 8.0
*/
public static final byte SO = 14;
/**
* Shift In: A control character indicating that the code
* combinations which follow shall be interpreted according to the
* standard code table.
*
* @since 8.0
*/
public static final byte SI = 15;
/**
* Data Link Escape: A communication control character which
* will change the meaning of a limited number of contiguously following
* characters. It is used exclusively to provide supplementary controls
* in data communication networks.
*
* @since 8.0
*/
public static final byte DLE = 16;
/**
* Device Control 1. Characters for the control
* of ancillary devices associated with data processing or
* telecommunication systems, more especially switching devices "on" or
* "off." (If a single "stop" control is required to interrupt or turn
* off ancillary devices, DC4 is the preferred assignment.)
*
* @since 8.0
*/
public static final byte DC1 = 17; // aka XON
/**
* Transmission On: Although originally defined as DC1, this ASCII
* control character is now better known as the XON code used for software
* flow control in serial communications. The main use is restarting
* the transmission after the communication has been stopped by the XOFF
* control code.
*
* @since 8.0
*/
public static final byte XON = 17; // aka DC1
/**
* Device Control 2. Characters for the control
* of ancillary devices associated with data processing or
* telecommunication systems, more especially switching devices "on" or
* "off." (If a single "stop" control is required to interrupt or turn
* off ancillary devices, DC4 is the preferred assignment.)
*
* @since 8.0
*/
public static final byte DC2 = 18;
/**
* Device Control 3. Characters for the control
* of ancillary devices associated with data processing or
* telecommunication systems, more especially switching devices "on" or
* "off." (If a single "stop" control is required to interrupt or turn
* off ancillary devices, DC4 is the preferred assignment.)
*
* @since 8.0
*/
public static final byte DC3 = 19; // aka XOFF
/**
* Transmission off. See {@link #XON} for explanation.
*
* @since 8.0
*/
public static final byte XOFF = 19; // aka DC3
/**
* Device Control 4. Characters for the control
* of ancillary devices associated with data processing or
* telecommunication systems, more especially switching devices "on" or
* "off." (If a single "stop" control is required to interrupt or turn
* off ancillary devices, DC4 is the preferred assignment.)
*
* @since 8.0
*/
public static final byte DC4 = 20;
/**
* Negative Acknowledge: A communication control character
* transmitted by a receiver as a negative response to the sender.
*
* @since 8.0
*/
public static final byte NAK = 21;
/**
* Synchronous Idle: A communication control character used by
* a synchronous transmission system in the absence of any other
* character to provide a signal from which synchronism may be achieved
* or retained.
*
* @since 8.0
*/
public static final byte SYN = 22;
/**
* End of Transmission Block: A communication control character
* used to indicate the end of a block of data for communication
* purposes. ETB is used for blocking data where the block structure is
* not necessarily related to the processing format.
*
* @since 8.0
*/
public static final byte ETB = 23;
/**
* Cancel: A control character used to indicate that the data
* with which it is sent is in error or is to be disregarded.
*
* @since 8.0
*/
public static final byte CAN = 24;
/**
* End of Medium: A control character associated with the sent
* data which may be used to identify the physical end of the medium, or
* the end of the used, or wanted, portion of information recorded on a
* medium. (The position of this character does not necessarily
* correspond to the physical end of the medium.)
*
* @since 8.0
*/
public static final byte EM = 25;
/**
* Substitute: A character that may be substituted for a
* character which is determined to be invalid or in error.
*
* @since 8.0
*/
public static final byte SUB = 26;
/**
* Escape: A control character intended to provide code
* extension (supplementary characters) in general information
* interchange. The Escape character itself is a prefix affecting the
* interpretation of a limited number of contiguously following
* characters.
*
* @since 8.0
*/
public static final byte ESC = 27;
/**
* File Separator: These four information separators may be
* used within data in optional fashion, except that their hierarchical
* relationship shall be: FS is the most inclusive, then GS, then RS,
* and US is least inclusive. (The content and length of a File, Group,
* Record, or Unit are not specified.)
*
* @since 8.0
*/
public static final byte FS = 28;
/**
* Group Separator: These four information separators may be
* used within data in optional fashion, except that their hierarchical
* relationship shall be: FS is the most inclusive, then GS, then RS,
* and US is least inclusive. (The content and length of a File, Group,
* Record, or Unit are not specified.)
*
* @since 8.0
*/
public static final byte GS = 29;
/**
* Record Separator: These four information separators may be
* used within data in optional fashion, except that their hierarchical
* relationship shall be: FS is the most inclusive, then GS, then RS,
* and US is least inclusive. (The content and length of a File, Group,
* Record, or Unit are not specified.)
*
* @since 8.0
*/
public static final byte RS = 30;
/**
* Unit Separator: These four information separators may be
* used within data in optional fashion, except that their hierarchical
* relationship shall be: FS is the most inclusive, then GS, then RS,
* and US is least inclusive. (The content and length of a File, Group,
* Record, or Unit are not specified.)
*
* @since 8.0
*/
public static final byte US = 31;
/**
* Space: A normally non-printing graphic character used to
* separate words. It is also a format effector which controls the
* movement of the printing position, one printing position forward.
* (Applicable also to display devices.)
*
* @since 8.0
*/
public static final byte SP = 32;
/**
* Alternate name for {@link #SP}.
*
* @since 8.0
*/
public static final byte SPACE = 32;
/**
* Delete: This character is used primarily to "erase" or
* "obliterate" erroneous or unwanted characters in perforated tape.
*
* @since 8.0
*/
public static final byte DEL = 127;
/**
* The minimum value of an ASCII character.
*
* @since 9.0 (was type {@code int} before 12.0)
*/
public static final char MIN = 0;
/**
* The maximum value of an ASCII character.
*
* @since 9.0 (was type {@code int} before 12.0)
*/
public static final char MAX = 127;
/**
* Returns a copy of the input string in which all {@linkplain #isUpperCase(char) uppercase ASCII
* characters} have been converted to lowercase. All other characters are copied without
* modification.
*/
public static String toLowerCase(String string) {
int length = string.length();
for (int i = 0; i < length; i++) {
if (isUpperCase(string.charAt(i))) {
char[] chars = string.toCharArray();
for (; i < length; i++) {
char c = chars[i];
if (isUpperCase(c)) {
chars[i] = (char) (c ^ 0x20);
}
}
return String.valueOf(chars);
}
}
return string;
}
/**
* Returns a copy of the input character sequence in which all {@linkplain #isUpperCase(char)
* uppercase ASCII characters} have been converted to lowercase. All other characters are copied
* without modification.
*
* @since 14.0
*/
public static String toLowerCase(CharSequence chars) {
if (chars instanceof String) {
return toLowerCase((String) chars);
}
int length = chars.length();
StringBuilder builder = new StringBuilder(length);
for (int i = 0; i < length; i++) {
builder.append(toLowerCase(chars.charAt(i)));
}
return builder.toString();
}
/**
* If the argument is an {@linkplain #isUpperCase(char) uppercase ASCII character} returns the
* lowercase equivalent. Otherwise returns the argument.
*/
public static char toLowerCase(char c) {
return isUpperCase(c) ? (char) (c ^ 0x20) : c;
}
/**
* Returns a copy of the input string in which all {@linkplain #isLowerCase(char) lowercase ASCII
* characters} have been converted to uppercase. All other characters are copied without
* modification.
*/
public static String toUpperCase(String string) {
int length = string.length();
for (int i = 0; i < length; i++) {
if (isLowerCase(string.charAt(i))) {
char[] chars = string.toCharArray();
for (; i < length; i++) {
char c = chars[i];
if (isLowerCase(c)) {
chars[i] = (char) (c & 0x5f);
}
}
return String.valueOf(chars);
}
}
return string;
}
/**
* Returns a copy of the input character sequence in which all {@linkplain #isLowerCase(char)
* lowercase ASCII characters} have been converted to uppercase. All other characters are copied
* without modification.
*
* @since 14.0
*/
public static String toUpperCase(CharSequence chars) {
if (chars instanceof String) {
return toUpperCase((String) chars);
}
int length = chars.length();
StringBuilder builder = new StringBuilder(length);
for (int i = 0; i < length; i++) {
builder.append(toUpperCase(chars.charAt(i)));
}
return builder.toString();
}
/**
* If the argument is a {@linkplain #isLowerCase(char) lowercase ASCII character} returns the
* uppercase equivalent. Otherwise returns the argument.
*/
public static char toUpperCase(char c) {
return isLowerCase(c) ? (char) (c & 0x5f) : c;
}
/**
* Indicates whether {@code c} is one of the twenty-six lowercase ASCII alphabetic characters
* between {@code 'a'} and {@code 'z'} inclusive. All others (including non-ASCII characters)
* return {@code false}.
*/
public static boolean isLowerCase(char c) {
// Note: This was benchmarked against the alternate expression "(char)(c - 'a') < 26" (Nov '13)
// and found to perform at least as well, or better.
return (c >= 'a') && (c <= 'z');
}
/**
* Indicates whether {@code c} is one of the twenty-six uppercase ASCII alphabetic characters
* between {@code 'A'} and {@code 'Z'} inclusive. All others (including non-ASCII characters)
* return {@code false}.
*/
public static boolean isUpperCase(char c) {
return (c >= 'A') && (c <= 'Z');
}
/**
* Truncates the given character sequence to the given maximum length. If the length of the
* sequence is greater than {@code maxLength}, the returned string will be exactly
* {@code maxLength} chars in length and will end with the given {@code truncationIndicator}.
* Otherwise, the sequence will be returned as a string with no changes to the content.
*
* <p>Examples:
*
* <pre> {@code
* Ascii.truncate("foobar", 7, "..."); // returns "foobar"
* Ascii.truncate("foobar", 5, "..."); // returns "fo..." }</pre>
*
* <p><b>Note:</b> This method <i>may</i> work with certain non-ASCII text but is not safe for
* use with arbitrary Unicode text. It is mostly intended for use with text that is known to be
* safe for use with it (such as all-ASCII text) and for simple debugging text. When using this
* method, consider the following:
*
* <ul>
* <li>it may split surrogate pairs</li>
* <li>it may split characters and combining characters</li>
* <li>it does not consider word boundaries</li>
* <li>if truncating for display to users, there are other considerations that must be taken
* into account</li>
* <li>the appropriate truncation indicator may be locale-dependent</li>
* <li>it is safe to use non-ASCII characters in the truncation indicator</li>
* </ul>
*
*
* @throws IllegalArgumentException if {@code maxLength} is less than the length of
* {@code truncationIndicator}
* @since 16.0
*/
@Beta
public static String truncate(CharSequence seq, int maxLength, String truncationIndicator) {
checkNotNull(seq);
// length to truncate the sequence to, not including the truncation indicator
int truncationLength = maxLength - truncationIndicator.length();
// in this worst case, this allows a maxLength equal to the length of the truncationIndicator,
// meaning that a string will be truncated to just the truncation indicator itself
checkArgument(
truncationLength >= 0,
"maxLength (%s) must be >= length of the truncation indicator (%s)",
maxLength,
truncationIndicator.length());
if (seq.length() <= maxLength) {
String string = seq.toString();
if (string.length() <= maxLength) {
return string;
}
// if the length of the toString() result was > maxLength for some reason, truncate that
seq = string;
}
return new StringBuilder(maxLength)
.append(seq, 0, truncationLength)
.append(truncationIndicator)
.toString();
}
/**
* Indicates whether the contents of the given character sequences {@code s1} and {@code s2} are
* equal, ignoring the case of any ASCII alphabetic characters between {@code 'a'} and {@code 'z'}
* or {@code 'A'} and {@code 'Z'} inclusive.
*
* <p>This method is significantly faster than {@link String#equalsIgnoreCase} and should be used
* in preference if at least one of the parameters is known to contain only ASCII characters.
*
* <p>Note however that this method does not always behave identically to expressions such as:
* <ul>
* <li>{@code string.toUpperCase().equals("UPPER CASE ASCII")}
* <li>{@code string.toLowerCase().equals("lower case ascii")}
* </ul>
* <p>due to case-folding of some non-ASCII characters (which does not occur in
* {@link String#equalsIgnoreCase}). However in almost all cases that ASCII strings are used,
* the author probably wanted the behavior provided by this method rather than the subtle and
* sometimes surprising behavior of {@code toUpperCase()} and {@code toLowerCase()}.
*
* @since 16.0
*/
@Beta
public static boolean equalsIgnoreCase(CharSequence s1, CharSequence s2) {
// Calling length() is the null pointer check (so do it before we can exit early).
int length = s1.length();
if (s1 == s2) {
return true;
}
if (length != s2.length()) {
return false;
}
for (int i = 0; i < length; i++) {
char c1 = s1.charAt(i);
char c2 = s2.charAt(i);
if (c1 == c2) {
continue;
}
int alphaIndex = getAlphaIndex(c1);
// This was also benchmarked using '&' to avoid branching (but always evaluate the rhs),
// however this showed no obvious improvement.
if (alphaIndex < 26 && alphaIndex == getAlphaIndex(c2)) {
continue;
}
return false;
}
return true;
}
/**
* Returns the non-negative index value of the alpha character {@code c}, regardless of case.
* Ie, 'a'/'A' returns 0 and 'z'/'Z' returns 25. Non-alpha characters return a value of 26 or
* greater.
*/
private static int getAlphaIndex(char c) {
// Fold upper-case ASCII to lower-case and make zero-indexed and unsigned (by casting to char).
return (char) ((c | 0x20) - 'a');
}
}
@@ -1,232 +0,0 @@
/*
* Copyright (C) 2006 The Guava Authors
*
* 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 com.google.common.base;
import static com.google.common.base.Preconditions.checkNotNull;
import com.google.common.annotations.Beta;
import com.google.common.annotations.GwtCompatible;
import java.io.Serializable;
import javax.annotation.CheckReturnValue;
import javax.annotation.Nullable;
/**
* Utility class for converting between various ASCII case formats. Behavior is undefined for
* non-ASCII input.
*
* @author Mike Bostock
* @since 1.0
*/
@CheckReturnValue
@GwtCompatible
public enum CaseFormat {
/**
* Hyphenated variable naming convention, e.g., "lower-hyphen".
*/
LOWER_HYPHEN(CharMatcher.is('-'), "-") {
@Override
String normalizeWord(String word) {
return Ascii.toLowerCase(word);
}
@Override
String convert(CaseFormat format, String s) {
if (format == LOWER_UNDERSCORE) {
return s.replace('-', '_');
}
if (format == UPPER_UNDERSCORE) {
return Ascii.toUpperCase(s.replace('-', '_'));
}
return super.convert(format, s);
}
},
/**
* C++ variable naming convention, e.g., "lower_underscore".
*/
LOWER_UNDERSCORE(CharMatcher.is('_'), "_") {
@Override
String normalizeWord(String word) {
return Ascii.toLowerCase(word);
}
@Override
String convert(CaseFormat format, String s) {
if (format == LOWER_HYPHEN) {
return s.replace('_', '-');
}
if (format == UPPER_UNDERSCORE) {
return Ascii.toUpperCase(s);
}
return super.convert(format, s);
}
},
/**
* Java variable naming convention, e.g., "lowerCamel".
*/
LOWER_CAMEL(CharMatcher.inRange('A', 'Z'), "") {
@Override
String normalizeWord(String word) {
return firstCharOnlyToUpper(word);
}
},
/**
* Java and C++ class naming convention, e.g., "UpperCamel".
*/
UPPER_CAMEL(CharMatcher.inRange('A', 'Z'), "") {
@Override
String normalizeWord(String word) {
return firstCharOnlyToUpper(word);
}
},
/**
* Java and C++ constant naming convention, e.g., "UPPER_UNDERSCORE".
*/
UPPER_UNDERSCORE(CharMatcher.is('_'), "_") {
@Override
String normalizeWord(String word) {
return Ascii.toUpperCase(word);
}
@Override
String convert(CaseFormat format, String s) {
if (format == LOWER_HYPHEN) {
return Ascii.toLowerCase(s.replace('_', '-'));
}
if (format == LOWER_UNDERSCORE) {
return Ascii.toLowerCase(s);
}
return super.convert(format, s);
}
};
private final CharMatcher wordBoundary;
private final String wordSeparator;
CaseFormat(CharMatcher wordBoundary, String wordSeparator) {
this.wordBoundary = wordBoundary;
this.wordSeparator = wordSeparator;
}
/**
* Converts the specified {@code String str} from this format to the specified {@code format}. A
* "best effort" approach is taken; if {@code str} does not conform to the assumed format, then
* the behavior of this method is undefined but we make a reasonable effort at converting anyway.
*/
public final String to(CaseFormat format, String str) {
checkNotNull(format);
checkNotNull(str);
return (format == this) ? str : convert(format, str);
}
/**
* Enum values can override for performance reasons.
*/
String convert(CaseFormat format, String s) {
// deal with camel conversion
StringBuilder out = null;
int i = 0;
int j = -1;
while ((j = wordBoundary.indexIn(s, ++j)) != -1) {
if (i == 0) {
// include some extra space for separators
out = new StringBuilder(s.length() + 4 * wordSeparator.length());
out.append(format.normalizeFirstWord(s.substring(i, j)));
} else {
out.append(format.normalizeWord(s.substring(i, j)));
}
out.append(format.wordSeparator);
i = j + wordSeparator.length();
}
return (i == 0)
? format.normalizeFirstWord(s)
: out.append(format.normalizeWord(s.substring(i))).toString();
}
/**
* Returns a {@code Converter} that converts strings from this format to {@code targetFormat}.
*
* @since 16.0
*/
@Beta
public Converter<String, String> converterTo(CaseFormat targetFormat) {
return new StringConverter(this, targetFormat);
}
private static final class StringConverter extends Converter<String, String>
implements Serializable {
private final CaseFormat sourceFormat;
private final CaseFormat targetFormat;
StringConverter(CaseFormat sourceFormat, CaseFormat targetFormat) {
this.sourceFormat = checkNotNull(sourceFormat);
this.targetFormat = checkNotNull(targetFormat);
}
@Override
protected String doForward(String s) {
return sourceFormat.to(targetFormat, s);
}
@Override
protected String doBackward(String s) {
return targetFormat.to(sourceFormat, s);
}
@Override
public boolean equals(@Nullable Object object) {
if (object instanceof StringConverter) {
StringConverter that = (StringConverter) object;
return sourceFormat.equals(that.sourceFormat) && targetFormat.equals(that.targetFormat);
}
return false;
}
@Override
public int hashCode() {
return sourceFormat.hashCode() ^ targetFormat.hashCode();
}
@Override
public String toString() {
return sourceFormat + ".converterTo(" + targetFormat + ")";
}
private static final long serialVersionUID = 0L;
}
abstract String normalizeWord(String word);
private String normalizeFirstWord(String word) {
return (this == LOWER_CAMEL) ? Ascii.toLowerCase(word) : normalizeWord(word);
}
private static String firstCharOnlyToUpper(String word) {
return (word.isEmpty())
? word
: new StringBuilder(word.length())
.append(Ascii.toUpperCase(word.charAt(0)))
.append(Ascii.toLowerCase(word.substring(1)))
.toString();
}
}
File diff suppressed because it is too large Load Diff
@@ -1,107 +0,0 @@
/*
* Copyright (C) 2007 The Guava Authors
*
* 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 com.google.common.base;
import com.google.common.annotations.GwtCompatible;
import com.google.common.annotations.GwtIncompatible;
import java.nio.charset.Charset;
/**
* Contains constant definitions for the six standard {@link Charset} instances, which are
* guaranteed to be supported by all Java platform implementations.
*
* <p>Assuming you're free to choose, note that <b>{@link #UTF_8} is widely preferred</b>.
*
* <p>See the Guava User Guide article on <a
* href="https://github.com/google/guava/wiki/StringsExplained#charsets">
* {@code Charsets}</a>.
*
* @author Mike Bostock
* @since 1.0
*/
@GwtCompatible(emulated = true)
public final class Charsets {
private Charsets() {}
/**
* US-ASCII: seven-bit ASCII, the Basic Latin block of the Unicode character set (ISO646-US).
*
* <p><b>Note for Java 7 and later:</b> this constant should be treated as deprecated; use
* {@link java.nio.charset.StandardCharsets#US_ASCII} instead.
*
*/
@GwtIncompatible("Non-UTF-8 Charset")
public static final Charset US_ASCII = Charset.forName("US-ASCII");
/**
* ISO-8859-1: ISO Latin Alphabet Number 1 (ISO-LATIN-1).
*
* <p><b>Note for Java 7 and later:</b> this constant should be treated as deprecated; use
* {@link java.nio.charset.StandardCharsets#ISO_8859_1} instead.
*
*/
@GwtIncompatible("Non-UTF-8 Charset")
public static final Charset ISO_8859_1 = Charset.forName("ISO-8859-1");
/**
* UTF-8: eight-bit UCS Transformation Format.
*
* <p><b>Note for Java 7 and later:</b> this constant should be treated as deprecated; use
* {@link java.nio.charset.StandardCharsets#UTF_8} instead.
*
*/
public static final Charset UTF_8 = Charset.forName("UTF-8");
/**
* UTF-16BE: sixteen-bit UCS Transformation Format, big-endian byte order.
*
* <p><b>Note for Java 7 and later:</b> this constant should be treated as deprecated; use
* {@link java.nio.charset.StandardCharsets#UTF_16BE} instead.
*
*/
@GwtIncompatible("Non-UTF-8 Charset")
public static final Charset UTF_16BE = Charset.forName("UTF-16BE");
/**
* UTF-16LE: sixteen-bit UCS Transformation Format, little-endian byte order.
*
* <p><b>Note for Java 7 and later:</b> this constant should be treated as deprecated; use
* {@link java.nio.charset.StandardCharsets#UTF_16LE} instead.
*
*/
@GwtIncompatible("Non-UTF-8 Charset")
public static final Charset UTF_16LE = Charset.forName("UTF-16LE");
/**
* UTF-16: sixteen-bit UCS Transformation Format, byte order identified by an optional byte-order
* mark.
*
* <p><b>Note for Java 7 and later:</b> this constant should be treated as deprecated; use
* {@link java.nio.charset.StandardCharsets#UTF_16} instead.
*
*/
@GwtIncompatible("Non-UTF-8 Charset")
public static final Charset UTF_16 = Charset.forName("UTF-16");
/*
* Please do not add new Charset references to this class, unless those character encodings are
* part of the set required to be supported by all Java platform implementations! Any Charsets
* initialized here may cause unexpected delays when this class is loaded. See the Charset
* Javadocs for the list of built-in character encodings.
*/
}
@@ -1,523 +0,0 @@
/*
* Copyright (C) 2008 The Guava Authors
*
* 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 com.google.common.base;
import static com.google.common.base.Preconditions.checkNotNull;
import com.google.common.annotations.Beta;
import com.google.common.annotations.GwtCompatible;
import java.io.Serializable;
import java.util.Iterator;
import javax.annotation.Nullable;
/**
* A function from {@code A} to {@code B} with an associated <i>reverse</i> function from {@code B}
* to {@code A}; used for converting back and forth between <i>different representations of the same
* information</i>.
*
* <h3>Invertibility</h3>
*
* <p>The reverse operation <b>may</b> be a strict <i>inverse</i> (meaning that {@code
* converter.reverse().convert(converter.convert(a)).equals(a)} is always true). However, it is
* very common (perhaps <i>more</i> common) for round-trip conversion to be <i>lossy</i>. Consider
* an example round-trip using {@link com.google.common.primitives.Doubles#stringConverter}:
*
* <ol>
* <li>{@code stringConverter().convert("1.00")} returns the {@code Double} value {@code 1.0}
* <li>{@code stringConverter().reverse().convert(1.0)} returns the string {@code "1.0"} --
* <i>not</i> the same string ({@code "1.00"}) we started with
* </ol>
*
* <p>Note that it should still be the case that the round-tripped and original objects are
* <i>similar</i>.
*
* <h3>Nullability</h3>
*
* <p>A converter always converts {@code null} to {@code null} and non-null references to non-null
* references. It would not make sense to consider {@code null} and a non-null reference to be
* "different representations of the same information", since one is distinguishable from
* <i>missing</i> information and the other is not. The {@link #convert} method handles this null
* behavior for all converters; implementations of {@link #doForward} and {@link #doBackward} are
* guaranteed to never be passed {@code null}, and must never return {@code null}.
*
* <h3>Common ways to use</h3>
*
* <p>Getting a converter:
*
* <ul>
* <li>Use a provided converter implementation, such as {@link Enums#stringConverter}, {@link
* com.google.common.primitives.Ints#stringConverter Ints.stringConverter} or the {@linkplain
* #reverse reverse} views of these.
* <li>Convert between specific preset values using {@link
* com.google.common.collect.Maps#asConverter Maps.asConverter}. For example, use this to create
* a "fake" converter for a unit test. It is unnecessary (and confusing) to <i>mock</i> the
* {@code Converter} type using a mocking framework.
* <li>Extend this class and implement its {@link #doForward} and {@link #doBackward} methods.
* <li>If using Java 8, you may prefer to pass two lambda expressions or method references to {@link
* #from}.
* </ul>
*
* <p>Using a converter:
*
* <ul>
* <li>Convert one instance in the "forward" direction using {@code converter.convert(a)}.
* <li>Convert multiple instances "forward" using {@code converter.convertAll(as)}.
* <li>Convert in the "backward" direction using {@code converter.reverse().convert(b)} or {@code
* converter.reverse().convertAll(bs)}.
* <li>Use {@code converter} or {@code converter.reverse()} anywhere a {@link Function} is accepted
* <li><b>Do not</b> call {@link #doForward} or {@link #doBackward} directly; these exist only to be
* overridden.
* </ul>
*
* <h3>Example</h3>
*
* <pre> {@code
*
* return new Converter<Integer, String>() {
* @Override
* protected String doForward(Integer i) {
* return Integer.toHexString(i);
* }
*
* @Override
* protected Integer doBackward(String s) {
* return parseUnsignedInt(s, 16);
* }
* };}</pre>
*
* <p>An alternative using Java 8: <pre> {@code
*
* return Converter.from(Integer::toHexString, s -> parseUnsignedInt(s, 16));}</pre>
*
* @author Mike Ward
* @author Kurt Alfred Kluever
* @author Gregory Kick
* @since 16.0
*/
@Beta
@GwtCompatible
public abstract class Converter<A, B> implements Function<A, B> {
private final boolean handleNullAutomatically;
// We lazily cache the reverse view to avoid allocating on every call to reverse().
private transient Converter<B, A> reverse;
/** Constructor for use by subclasses. */
protected Converter() {
this(true);
}
/**
* Constructor used only by {@code LegacyConverter} to suspend automatic null-handling.
*/
Converter(boolean handleNullAutomatically) {
this.handleNullAutomatically = handleNullAutomatically;
}
// SPI methods (what subclasses must implement)
/**
* Returns a representation of {@code a} as an instance of type {@code B}. If {@code a} cannot be
* converted, an unchecked exception (such as {@link IllegalArgumentException}) should be thrown.
*
* @param a the instance to convert; will never be null
* @return the converted instance; <b>must not</b> be null
*/
protected abstract B doForward(A a);
/**
* Returns a representation of {@code b} as an instance of type {@code A}. If {@code b} cannot be
* converted, an unchecked exception (such as {@link IllegalArgumentException}) should be thrown.
*
* @param b the instance to convert; will never be null
* @return the converted instance; <b>must not</b> be null
* @throws UnsupportedOperationException if backward conversion is not implemented; this should be
* very rare. Note that if backward conversion is not only unimplemented but
* unimplement<i>able</i> (for example, consider a {@code Converter<Chicken, ChickenNugget>}),
* then this is not logically a {@code Converter} at all, and should just implement {@link
* Function}.
*/
protected abstract A doBackward(B b);
// API (consumer-side) methods
/**
* Returns a representation of {@code a} as an instance of type {@code B}.
*
* @return the converted value; is null <i>if and only if</i> {@code a} is null
*/
@Nullable
public final B convert(@Nullable A a) {
return correctedDoForward(a);
}
@Nullable
B correctedDoForward(@Nullable A a) {
if (handleNullAutomatically) {
// TODO(kevinb): we shouldn't be checking for a null result at runtime. Assert?
return a == null ? null : checkNotNull(doForward(a));
} else {
return doForward(a);
}
}
@Nullable
A correctedDoBackward(@Nullable B b) {
if (handleNullAutomatically) {
// TODO(kevinb): we shouldn't be checking for a null result at runtime. Assert?
return b == null ? null : checkNotNull(doBackward(b));
} else {
return doBackward(b);
}
}
/**
* Returns an iterable that applies {@code convert} to each element of {@code fromIterable}. The
* conversion is done lazily.
*
* <p>The returned iterable's iterator supports {@code remove()} if the input iterator does. After
* a successful {@code remove()} call, {@code fromIterable} no longer contains the corresponding
* element.
*/
public Iterable<B> convertAll(final Iterable<? extends A> fromIterable) {
checkNotNull(fromIterable, "fromIterable");
return new Iterable<B>() {
@Override
public Iterator<B> iterator() {
return new Iterator<B>() {
private final Iterator<? extends A> fromIterator = fromIterable.iterator();
@Override
public boolean hasNext() {
return fromIterator.hasNext();
}
@Override
public B next() {
return convert(fromIterator.next());
}
@Override
public void remove() {
fromIterator.remove();
}
};
}
};
}
/**
* Returns the reversed view of this converter, which converts {@code this.convert(a)} back to a
* value roughly equivalent to {@code a}.
*
* <p>The returned converter is serializable if {@code this} converter is.
*/
// TODO(kak): Make this method final
public Converter<B, A> reverse() {
Converter<B, A> result = reverse;
return (result == null) ? reverse = new ReverseConverter<A, B>(this) : result;
}
private static final class ReverseConverter<A, B> extends Converter<B, A>
implements Serializable {
final Converter<A, B> original;
ReverseConverter(Converter<A, B> original) {
this.original = original;
}
/*
* These gymnastics are a little confusing. Basically this class has neither legacy nor
* non-legacy behavior; it just needs to let the behavior of the backing converter shine
* through. So, we override the correctedDo* methods, after which the do* methods should never
* be reached.
*/
@Override
protected A doForward(B b) {
throw new AssertionError();
}
@Override
protected B doBackward(A a) {
throw new AssertionError();
}
@Override
@Nullable
A correctedDoForward(@Nullable B b) {
return original.correctedDoBackward(b);
}
@Override
@Nullable
B correctedDoBackward(@Nullable A a) {
return original.correctedDoForward(a);
}
@Override
public Converter<A, B> reverse() {
return original;
}
@Override
public boolean equals(@Nullable Object object) {
if (object instanceof ReverseConverter) {
ReverseConverter<?, ?> that = (ReverseConverter<?, ?>) object;
return this.original.equals(that.original);
}
return false;
}
@Override
public int hashCode() {
return ~original.hashCode();
}
@Override
public String toString() {
return original + ".reverse()";
}
private static final long serialVersionUID = 0L;
}
/**
* Returns a converter whose {@code convert} method applies {@code secondConverter} to the result
* of this converter. Its {@code reverse} method applies the converters in reverse order.
*
* <p>The returned converter is serializable if {@code this} converter and {@code secondConverter}
* are.
*/
public final <C> Converter<A, C> andThen(Converter<B, C> secondConverter) {
return doAndThen(secondConverter);
}
/**
* Package-private non-final implementation of andThen() so only we can override it.
*/
<C> Converter<A, C> doAndThen(Converter<B, C> secondConverter) {
return new ConverterComposition<A, B, C>(this, checkNotNull(secondConverter));
}
private static final class ConverterComposition<A, B, C> extends Converter<A, C>
implements Serializable {
final Converter<A, B> first;
final Converter<B, C> second;
ConverterComposition(Converter<A, B> first, Converter<B, C> second) {
this.first = first;
this.second = second;
}
/*
* These gymnastics are a little confusing. Basically this class has neither legacy nor
* non-legacy behavior; it just needs to let the behaviors of the backing converters shine
* through (which might even differ from each other!). So, we override the correctedDo* methods,
* after which the do* methods should never be reached.
*/
@Override
protected C doForward(A a) {
throw new AssertionError();
}
@Override
protected A doBackward(C c) {
throw new AssertionError();
}
@Override
@Nullable
C correctedDoForward(@Nullable A a) {
return second.correctedDoForward(first.correctedDoForward(a));
}
@Override
@Nullable
A correctedDoBackward(@Nullable C c) {
return first.correctedDoBackward(second.correctedDoBackward(c));
}
@Override
public boolean equals(@Nullable Object object) {
if (object instanceof ConverterComposition) {
ConverterComposition<?, ?, ?> that = (ConverterComposition<?, ?, ?>) object;
return this.first.equals(that.first) && this.second.equals(that.second);
}
return false;
}
@Override
public int hashCode() {
return 31 * first.hashCode() + second.hashCode();
}
@Override
public String toString() {
return first + ".andThen(" + second + ")";
}
private static final long serialVersionUID = 0L;
}
/**
* @deprecated Provided to satisfy the {@code Function} interface; use {@link #convert} instead.
*/
@Deprecated
@Override
@Nullable
public final B apply(@Nullable A a) {
return convert(a);
}
/**
* Indicates whether another object is equal to this converter.
*
* <p>Most implementations will have no reason to override the behavior of {@link Object#equals}.
* However, an implementation may also choose to return {@code true} whenever {@code object} is a
* {@link Converter} that it considers <i>interchangeable</i> with this one. "Interchangeable"
* <i>typically</i> means that {@code Objects.equal(this.convert(a), that.convert(a))} is true for
* all {@code a} of type {@code A} (and similarly for {@code reverse}). Note that a {@code false}
* result from this method does not imply that the converters are known <i>not</i> to be
* interchangeable.
*/
@Override
public boolean equals(@Nullable Object object) {
return super.equals(object);
}
// Static converters
/**
* Returns a converter based on <i>existing</i> forward and backward functions. Note that it is
* unnecessary to create <i>new</i> classes implementing {@code Function} just to pass them in
* here. Instead, simply subclass {@code Converter} and implement its {@link #doForward} and
* {@link #doBackward} methods directly.
*
* <p>These functions will never be passed {@code null} and must not under any circumstances
* return {@code null}. If a value cannot be converted, the function should throw an unchecked
* exception (typically, but not necessarily, {@link IllegalArgumentException}).
*
* <p>The returned converter is serializable if both provided functions are.
*
* @since 17.0
*/
public static <A, B> Converter<A, B> from(
Function<? super A, ? extends B> forwardFunction,
Function<? super B, ? extends A> backwardFunction) {
return new FunctionBasedConverter<A, B>(forwardFunction, backwardFunction);
}
private static final class FunctionBasedConverter<A, B> extends Converter<A, B>
implements Serializable {
private final Function<? super A, ? extends B> forwardFunction;
private final Function<? super B, ? extends A> backwardFunction;
private FunctionBasedConverter(
Function<? super A, ? extends B> forwardFunction,
Function<? super B, ? extends A> backwardFunction) {
this.forwardFunction = checkNotNull(forwardFunction);
this.backwardFunction = checkNotNull(backwardFunction);
}
@Override
protected B doForward(A a) {
return forwardFunction.apply(a);
}
@Override
protected A doBackward(B b) {
return backwardFunction.apply(b);
}
@Override
public boolean equals(@Nullable Object object) {
if (object instanceof FunctionBasedConverter) {
FunctionBasedConverter<?, ?> that = (FunctionBasedConverter<?, ?>) object;
return this.forwardFunction.equals(that.forwardFunction)
&& this.backwardFunction.equals(that.backwardFunction);
}
return false;
}
@Override
public int hashCode() {
return forwardFunction.hashCode() * 31 + backwardFunction.hashCode();
}
@Override
public String toString() {
return "Converter.from(" + forwardFunction + ", " + backwardFunction + ")";
}
}
/**
* Returns a serializable converter that always converts or reverses an object to itself.
*/
@SuppressWarnings("unchecked") // implementation is "fully variant"
public static <T> Converter<T, T> identity() {
return (IdentityConverter<T>) IdentityConverter.INSTANCE;
}
/**
* A converter that always converts or reverses an object to itself. Note that T is now a
* "pass-through type".
*/
private static final class IdentityConverter<T> extends Converter<T, T> implements Serializable {
static final IdentityConverter INSTANCE = new IdentityConverter();
@Override
protected T doForward(T t) {
return t;
}
@Override
protected T doBackward(T t) {
return t;
}
@Override
public IdentityConverter<T> reverse() {
return this;
}
@Override
<S> Converter<T, S> doAndThen(Converter<T, S> otherConverter) {
return checkNotNull(otherConverter, "otherConverter");
}
/*
* We *could* override convertAll() to return its input, but it's a rather pointless
* optimization and opened up a weird type-safety problem.
*/
@Override
public String toString() {
return "Converter.identity()";
}
private Object readResolve() {
return INSTANCE;
}
private static final long serialVersionUID = 0L;
}
}
@@ -1,70 +0,0 @@
/*
* Copyright (C) 2007 The Guava Authors
*
* 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 com.google.common.base;
import static com.google.common.base.Preconditions.checkNotNull;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import javax.annotation.CheckReturnValue;
import javax.annotation.Nullable;
/**
* This class provides default values for all Java types, as defined by the JLS.
*
* @author Ben Yu
* @since 1.0
*/
@CheckReturnValue
public final class Defaults {
private Defaults() {}
private static final Map<Class<?>, Object> DEFAULTS;
static {
// Only add to this map via put(Map, Class<T>, T)
Map<Class<?>, Object> map = new HashMap<Class<?>, Object>();
put(map, boolean.class, false);
put(map, char.class, '\0');
put(map, byte.class, (byte) 0);
put(map, short.class, (short) 0);
put(map, int.class, 0);
put(map, long.class, 0L);
put(map, float.class, 0f);
put(map, double.class, 0d);
DEFAULTS = Collections.unmodifiableMap(map);
}
private static <T> void put(Map<Class<?>, Object> map, Class<T> type, T value) {
map.put(type, value);
}
/**
* Returns the default value of {@code type} as defined by JLS --- {@code 0} for numbers, {@code
* false} for {@code boolean} and {@code '\0'} for {@code char}. For non-primitive types and
* {@code void}, {@code null} is returned.
*/
@Nullable
public static <T> T defaultValue(Class<T> type) {
// Primitives.wrap(type).cast(...) would avoid the warning, but we can't use that from here
@SuppressWarnings("unchecked") // the put method enforces this key-value relationship
T t = (T) DEFAULTS.get(checkNotNull(type));
return t;
}
}
@@ -1,163 +0,0 @@
/*
* Copyright (C) 2011 The Guava Authors
*
* 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 com.google.common.base;
import static com.google.common.base.Preconditions.checkNotNull;
import com.google.common.annotations.Beta;
import com.google.common.annotations.GwtCompatible;
import com.google.common.annotations.GwtIncompatible;
import java.io.Serializable;
import java.lang.ref.WeakReference;
import java.lang.reflect.Field;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.Map;
import java.util.WeakHashMap;
import javax.annotation.CheckReturnValue;
import javax.annotation.Nullable;
/**
* Utility methods for working with {@link Enum} instances.
*
* @author Steve McKay
*
* @since 9.0
*/
@CheckReturnValue
@GwtCompatible(emulated = true)
@Beta
public final class Enums {
private Enums() {}
/**
* Returns the {@link Field} in which {@code enumValue} is defined. For example, to get the
* {@code Description} annotation on the {@code GOLF} constant of enum {@code Sport}, use
* {@code Enums.getField(Sport.GOLF).getAnnotation(Description.class)}.
*
* @since 12.0
*/
@GwtIncompatible("reflection")
public static Field getField(Enum<?> enumValue) {
Class<?> clazz = enumValue.getDeclaringClass();
try {
return clazz.getDeclaredField(enumValue.name());
} catch (NoSuchFieldException impossible) {
throw new AssertionError(impossible);
}
}
/**
* Returns an optional enum constant for the given type, using {@link Enum#valueOf}. If the
* constant does not exist, {@link Optional#absent} is returned. A common use case is for parsing
* user input or falling back to a default enum constant. For example,
* {@code Enums.getIfPresent(Country.class, countryInput).or(Country.DEFAULT);}
*
* @since 12.0
*/
public static <T extends Enum<T>> Optional<T> getIfPresent(Class<T> enumClass, String value) {
checkNotNull(enumClass);
checkNotNull(value);
return Platform.getEnumIfPresent(enumClass, value);
}
@GwtIncompatible("java.lang.ref.WeakReference")
private static final Map<Class<? extends Enum<?>>, Map<String, WeakReference<? extends Enum<?>>>>
enumConstantCache =
new WeakHashMap<
Class<? extends Enum<?>>, Map<String, WeakReference<? extends Enum<?>>>>();
@GwtIncompatible("java.lang.ref.WeakReference")
private static <T extends Enum<T>> Map<String, WeakReference<? extends Enum<?>>> populateCache(
Class<T> enumClass) {
Map<String, WeakReference<? extends Enum<?>>> result =
new HashMap<String, WeakReference<? extends Enum<?>>>();
for (T enumInstance : EnumSet.allOf(enumClass)) {
result.put(enumInstance.name(), new WeakReference<Enum<?>>(enumInstance));
}
enumConstantCache.put(enumClass, result);
return result;
}
@GwtIncompatible("java.lang.ref.WeakReference")
static <T extends Enum<T>> Map<String, WeakReference<? extends Enum<?>>> getEnumConstants(
Class<T> enumClass) {
synchronized (enumConstantCache) {
Map<String, WeakReference<? extends Enum<?>>> constants = enumConstantCache.get(enumClass);
if (constants == null) {
constants = populateCache(enumClass);
}
return constants;
}
}
/**
* Returns a converter that converts between strings and {@code enum} values of type
* {@code enumClass} using {@link Enum#valueOf(Class, String)} and {@link Enum#name()}. The
* converter will throw an {@code IllegalArgumentException} if the argument is not the name of
* any enum constant in the specified enum.
*
* @since 16.0
*/
public static <T extends Enum<T>> Converter<String, T> stringConverter(final Class<T> enumClass) {
return new StringConverter<T>(enumClass);
}
private static final class StringConverter<T extends Enum<T>> extends Converter<String, T>
implements Serializable {
private final Class<T> enumClass;
StringConverter(Class<T> enumClass) {
this.enumClass = checkNotNull(enumClass);
}
@Override
protected T doForward(String value) {
return Enum.valueOf(enumClass, value);
}
@Override
protected String doBackward(T enumValue) {
return enumValue.name();
}
@Override
public boolean equals(@Nullable Object object) {
if (object instanceof StringConverter) {
StringConverter<?> that = (StringConverter<?>) object;
return this.enumClass.equals(that.enumClass);
}
return false;
}
@Override
public int hashCode() {
return enumClass.hashCode();
}
@Override
public String toString() {
return "Enums.stringConverter(" + enumClass.getName() + ".class)";
}
private static final long serialVersionUID = 0L;
}
}
@@ -1,371 +0,0 @@
/*
* Copyright (C) 2010 The Guava Authors
*
* 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 com.google.common.base;
import static com.google.common.base.Preconditions.checkNotNull;
import com.google.common.annotations.Beta;
import com.google.common.annotations.GwtCompatible;
import java.io.Serializable;
import javax.annotation.CheckReturnValue;
import javax.annotation.Nullable;
/**
* A strategy for determining whether two instances are considered equivalent. Examples of
* equivalences are the {@linkplain #identity() identity equivalence} and {@linkplain #equals equals
* equivalence}.
*
* @author Bob Lee
* @author Ben Yu
* @author Gregory Kick
* @since 10.0 (<a href="https://github.com/google/guava/wiki/Compatibility"
* >mostly source-compatible</a> since 4.0)
*/
@CheckReturnValue
@GwtCompatible
public abstract class Equivalence<T> {
/**
* Constructor for use by subclasses.
*/
protected Equivalence() {}
/**
* Returns {@code true} if the given objects are considered equivalent.
*
* <p>The {@code equivalent} method implements an equivalence relation on object references:
*
* <ul>
* <li>It is <i>reflexive</i>: for any reference {@code x}, including null, {@code
* equivalent(x, x)} returns {@code true}.
* <li>It is <i>symmetric</i>: for any references {@code x} and {@code y}, {@code
* equivalent(x, y) == equivalent(y, x)}.
* <li>It is <i>transitive</i>: for any references {@code x}, {@code y}, and {@code z}, if
* {@code equivalent(x, y)} returns {@code true} and {@code equivalent(y, z)} returns {@code
* true}, then {@code equivalent(x, z)} returns {@code true}.
* <li>It is <i>consistent</i>: for any references {@code x} and {@code y}, multiple invocations
* of {@code equivalent(x, y)} consistently return {@code true} or consistently return {@code
* false} (provided that neither {@code x} nor {@code y} is modified).
* </ul>
*/
public final boolean equivalent(@Nullable T a, @Nullable T b) {
if (a == b) {
return true;
}
if (a == null || b == null) {
return false;
}
return doEquivalent(a, b);
}
/**
* Returns {@code true} if {@code a} and {@code b} are considered equivalent.
*
* <p>Called by {@link #equivalent}. {@code a} and {@code b} are not the same
* object and are not nulls.
*
* @since 10.0 (previously, subclasses would override equivalent())
*/
protected abstract boolean doEquivalent(T a, T b);
/**
* Returns a hash code for {@code t}.
*
* <p>The {@code hash} has the following properties:
* <ul>
* <li>It is <i>consistent</i>: for any reference {@code x}, multiple invocations of
* {@code hash(x}} consistently return the same value provided {@code x} remains unchanged
* according to the definition of the equivalence. The hash need not remain consistent from
* one execution of an application to another execution of the same application.
* <li>It is <i>distributable across equivalence</i>: for any references {@code x} and {@code y},
* if {@code equivalent(x, y)}, then {@code hash(x) == hash(y)}. It is <i>not</i> necessary
* that the hash be distributable across <i>inequivalence</i>. If {@code equivalence(x, y)}
* is false, {@code hash(x) == hash(y)} may still be true.
* <li>{@code hash(null)} is {@code 0}.
* </ul>
*/
public final int hash(@Nullable T t) {
if (t == null) {
return 0;
}
return doHash(t);
}
/**
* Returns a hash code for non-null object {@code t}.
*
* <p>Called by {@link #hash}.
*
* @since 10.0 (previously, subclasses would override hash())
*/
protected abstract int doHash(T t);
/**
* Returns a new equivalence relation for {@code F} which evaluates equivalence by first applying
* {@code function} to the argument, then evaluating using {@code this}. That is, for any pair of
* non-null objects {@code x} and {@code y}, {@code
* equivalence.onResultOf(function).equivalent(a, b)} is true if and only if {@code
* equivalence.equivalent(function.apply(a), function.apply(b))} is true.
*
* <p>For example:
*
* <pre> {@code
* Equivalence<Person> SAME_AGE = Equivalence.equals().onResultOf(GET_PERSON_AGE);}</pre>
*
* <p>{@code function} will never be invoked with a null value.
*
* <p>Note that {@code function} must be consistent according to {@code this} equivalence
* relation. That is, invoking {@link Function#apply} multiple times for a given value must return
* equivalent results.
* For example, {@code Equivalence.identity().onResultOf(Functions.toStringFunction())} is broken
* because it's not guaranteed that {@link Object#toString}) always returns the same string
* instance.
*
* @since 10.0
*/
public final <F> Equivalence<F> onResultOf(Function<F, ? extends T> function) {
return new FunctionalEquivalence<F, T>(function, this);
}
/**
* Returns a wrapper of {@code reference} that implements
* {@link Wrapper#equals(Object) Object.equals()} such that
* {@code wrap(a).equals(wrap(b))} if and only if {@code equivalent(a, b)}.
*
* @since 10.0
*/
public final <S extends T> Wrapper<S> wrap(@Nullable S reference) {
return new Wrapper<S>(this, reference);
}
/**
* Wraps an object so that {@link #equals(Object)} and {@link #hashCode()} delegate to an
* {@link Equivalence}.
*
* <p>For example, given an {@link Equivalence} for {@link String strings} named {@code equiv}
* that tests equivalence using their lengths:
*
* <pre> {@code
* equiv.wrap("a").equals(equiv.wrap("b")) // true
* equiv.wrap("a").equals(equiv.wrap("hello")) // false}</pre>
*
* <p>Note in particular that an equivalence wrapper is never equal to the object it wraps.
*
* <pre> {@code
* equiv.wrap(obj).equals(obj) // always false}</pre>
*
* @since 10.0
*/
public static final class Wrapper<T> implements Serializable {
private final Equivalence<? super T> equivalence;
@Nullable private final T reference;
private Wrapper(Equivalence<? super T> equivalence, @Nullable T reference) {
this.equivalence = checkNotNull(equivalence);
this.reference = reference;
}
/** Returns the (possibly null) reference wrapped by this instance. */
@Nullable
public T get() {
return reference;
}
/**
* Returns {@code true} if {@link Equivalence#equivalent(Object, Object)} applied to the wrapped
* references is {@code true} and both wrappers use the {@link Object#equals(Object) same}
* equivalence.
*/
@Override
public boolean equals(@Nullable Object obj) {
if (obj == this) {
return true;
}
if (obj instanceof Wrapper) {
Wrapper<?> that = (Wrapper<?>) obj; // note: not necessarily a Wrapper<T>
if (this.equivalence.equals(that.equivalence)) {
/*
* We'll accept that as sufficient "proof" that either equivalence should be able to
* handle either reference, so it's safe to circumvent compile-time type checking.
*/
@SuppressWarnings("unchecked")
Equivalence<Object> equivalence = (Equivalence<Object>) this.equivalence;
return equivalence.equivalent(this.reference, that.reference);
}
}
return false;
}
/**
* Returns the result of {@link Equivalence#hash(Object)} applied to the wrapped reference.
*/
@Override
public int hashCode() {
return equivalence.hash(reference);
}
/**
* Returns a string representation for this equivalence wrapper. The form of this string
* representation is not specified.
*/
@Override
public String toString() {
return equivalence + ".wrap(" + reference + ")";
}
private static final long serialVersionUID = 0;
}
/**
* Returns an equivalence over iterables based on the equivalence of their elements. More
* specifically, two iterables are considered equivalent if they both contain the same number of
* elements, and each pair of corresponding elements is equivalent according to
* {@code this}. Null iterables are equivalent to one another.
*
* <p>Note that this method performs a similar function for equivalences as {@link
* com.google.common.collect.Ordering#lexicographical} does for orderings.
*
* @since 10.0
*/
@GwtCompatible(serializable = true)
public final <S extends T> Equivalence<Iterable<S>> pairwise() {
// Ideally, the returned equivalence would support Iterable<? extends T>. However,
// the need for this is so rare that it's not worth making callers deal with the ugly wildcard.
return new PairwiseEquivalence<S>(this);
}
/**
* Returns a predicate that evaluates to true if and only if the input is
* equivalent to {@code target} according to this equivalence relation.
*
* @since 10.0
*/
@Beta
public final Predicate<T> equivalentTo(@Nullable T target) {
return new EquivalentToPredicate<T>(this, target);
}
private static final class EquivalentToPredicate<T> implements Predicate<T>, Serializable {
private final Equivalence<T> equivalence;
@Nullable private final T target;
EquivalentToPredicate(Equivalence<T> equivalence, @Nullable T target) {
this.equivalence = checkNotNull(equivalence);
this.target = target;
}
@Override
public boolean apply(@Nullable T input) {
return equivalence.equivalent(input, target);
}
@Override
public boolean equals(@Nullable Object obj) {
if (this == obj) {
return true;
}
if (obj instanceof EquivalentToPredicate) {
EquivalentToPredicate<?> that = (EquivalentToPredicate<?>) obj;
return equivalence.equals(that.equivalence) && Objects.equal(target, that.target);
}
return false;
}
@Override
public int hashCode() {
return Objects.hashCode(equivalence, target);
}
@Override
public String toString() {
return equivalence + ".equivalentTo(" + target + ")";
}
private static final long serialVersionUID = 0;
}
/**
* Returns an equivalence that delegates to {@link Object#equals} and {@link Object#hashCode}.
* {@link Equivalence#equivalent} returns {@code true} if both values are null, or if neither
* value is null and {@link Object#equals} returns {@code true}. {@link Equivalence#hash} returns
* {@code 0} if passed a null value.
*
* @since 13.0
* @since 8.0 (in Equivalences with null-friendly behavior)
* @since 4.0 (in Equivalences)
*/
public static Equivalence<Object> equals() {
return Equals.INSTANCE;
}
/**
* Returns an equivalence that uses {@code ==} to compare values and {@link
* System#identityHashCode(Object)} to compute the hash code. {@link Equivalence#equivalent}
* returns {@code true} if {@code a == b}, including in the case that a and b are both null.
*
* @since 13.0
* @since 4.0 (in Equivalences)
*/
public static Equivalence<Object> identity() {
return Identity.INSTANCE;
}
static final class Equals extends Equivalence<Object> implements Serializable {
static final Equals INSTANCE = new Equals();
@Override
protected boolean doEquivalent(Object a, Object b) {
return a.equals(b);
}
@Override
protected int doHash(Object o) {
return o.hashCode();
}
private Object readResolve() {
return INSTANCE;
}
private static final long serialVersionUID = 1;
}
static final class Identity extends Equivalence<Object> implements Serializable {
static final Identity INSTANCE = new Identity();
@Override
protected boolean doEquivalent(Object a, Object b) {
return false;
}
@Override
protected int doHash(Object o) {
return System.identityHashCode(o);
}
private Object readResolve() {
return INSTANCE;
}
private static final long serialVersionUID = 1;
}
}
@@ -1,44 +0,0 @@
/*
* Copyright (C) 2007 The Guava Authors
*
* 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 com.google.common.base;
import java.lang.ref.PhantomReference;
import java.lang.ref.ReferenceQueue;
/**
* Phantom reference with a {@code finalizeReferent()} method which a background thread invokes
* after the garbage collector reclaims the referent. This is a simpler alternative to using a
* {@link ReferenceQueue}.
*
* <p>Unlike a normal phantom reference, this reference will be cleared automatically.
*
* @author Bob Lee
* @since 2.0
*/
public abstract class FinalizablePhantomReference<T> extends PhantomReference<T>
implements FinalizableReference {
/**
* Constructs a new finalizable phantom reference.
*
* @param referent to phantom reference
* @param queue that should finalize the referent
*/
protected FinalizablePhantomReference(T referent, FinalizableReferenceQueue queue) {
super(referent, queue.queue);
queue.cleanUp();
}
}
@@ -1,33 +0,0 @@
/*
* Copyright (C) 2007 The Guava Authors
*
* 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 com.google.common.base;
/**
* Implemented by references that have code to run after garbage collection of their referents.
*
* @see FinalizableReferenceQueue
* @author Bob Lee
* @since 2.0
*/
public interface FinalizableReference {
/**
* Invoked on a background thread after the referent has been garbage collected unless security
* restrictions prevented starting a background thread, in which case this method is invoked when
* new references are created.
*/
void finalizeReferent();
}
@@ -1,362 +0,0 @@
/*
* Copyright (C) 2007 The Guava Authors
*
* 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 com.google.common.base;
import com.google.common.annotations.VisibleForTesting;
import java.io.Closeable;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.lang.ref.PhantomReference;
import java.lang.ref.Reference;
import java.lang.ref.ReferenceQueue;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLClassLoader;
import com.google.common.logging.Level;
import com.google.common.logging.Logger;
import javax.annotation.Nullable;
/**
* A reference queue with an associated background thread that dequeues references and invokes
* {@link FinalizableReference#finalizeReferent()} on them.
*
* <p>Keep a strong reference to this object until all of the associated referents have been
* finalized. If this object is garbage collected earlier, the backing thread will not invoke {@code
* finalizeReferent()} on the remaining references.
*
* <p>As an example of how this is used, imagine you have a class {@code MyServer} that creates a
* a {@link java.net.ServerSocket ServerSocket}, and you would like to ensure that the
* {@code ServerSocket} is closed even if the {@code MyServer} object is garbage-collected without
* calling its {@code close} method. You <em>could</em> use a finalizer to accomplish this, but
* that has a number of well-known problems. Here is how you might use this class instead:
*
* <pre>
* public class MyServer implements Closeable {
* private static final FinalizableReferenceQueue frq = new FinalizableReferenceQueue();
* // You might also share this between several objects.
*
* private static final Set&lt;Reference&lt;?>> references = Sets.newConcurrentHashSet();
* // This ensures that the FinalizablePhantomReference itself is not garbage-collected.
*
* private final ServerSocket serverSocket;
*
* private MyServer(...) {
* ...
* this.serverSocket = new ServerSocket(...);
* ...
* }
*
* public static MyServer create(...) {
* MyServer myServer = new MyServer(...);
* final ServerSocket serverSocket = myServer.serverSocket;
* Reference&lt;?> reference = new FinalizablePhantomReference&lt;MyServer>(myServer, frq) {
* &#64;Override public void finalizeReferent() {
* references.remove(this):
* if (!serverSocket.isClosed()) {
* ...log a message about how nobody called close()...
* try {
* serverSocket.close();
* } catch (IOException e) {
* ...
* }
* }
* }
* };
* references.add(reference);
* return myServer;
* }
*
* &#64;Override public void close() {
* serverSocket.close();
* }
* }
* </pre>
*
* @author Bob Lee
* @since 2.0
*/
public class FinalizableReferenceQueue implements Closeable {
/*
* The Finalizer thread keeps a phantom reference to this object. When the client (for example, a
* map built by MapMaker) no longer has a strong reference to this object, the garbage collector
* will reclaim it and enqueue the phantom reference. The enqueued reference will trigger the
* Finalizer to stop.
*
* If this library is loaded in the system class loader, FinalizableReferenceQueue can load
* Finalizer directly with no problems.
*
* If this library is loaded in an application class loader, it's important that Finalizer not
* have a strong reference back to the class loader. Otherwise, you could have a graph like this:
*
* Finalizer Thread runs instance of -> Finalizer.class loaded by -> Application class loader
* which loaded -> ReferenceMap.class which has a static -> FinalizableReferenceQueue instance
*
* Even if no other references to classes from the application class loader remain, the Finalizer
* thread keeps an indirect strong reference to the queue in ReferenceMap, which keeps the
* Finalizer running, and as a result, the application class loader can never be reclaimed.
*
* This means that dynamically loaded web applications and OSGi bundles can't be unloaded.
*
* If the library is loaded in an application class loader, we try to break the cycle by loading
* Finalizer in its own independent class loader:
*
* System class loader -> Application class loader -> ReferenceMap -> FinalizableReferenceQueue
* -> etc. -> Decoupled class loader -> Finalizer
*
* Now, Finalizer no longer keeps an indirect strong reference to the static
* FinalizableReferenceQueue field in ReferenceMap. The application class loader can be reclaimed
* at which point the Finalizer thread will stop and its decoupled class loader can also be
* reclaimed.
*
* If any of this fails along the way, we fall back to loading Finalizer directly in the
* application class loader.
*/
private static final Logger logger = Logger.getLogger(FinalizableReferenceQueue.class.getName());
private static final String FINALIZER_CLASS_NAME = "com.google.common.base.internal.Finalizer";
/** Reference to Finalizer.startFinalizer(). */
private static final Method startFinalizer;
static {
Class<?> finalizer =
loadFinalizer(new SystemLoader(), new DecoupledLoader(), new DirectLoader());
startFinalizer = getStartFinalizer(finalizer);
}
/**
* The actual reference queue that our background thread will poll.
*/
final ReferenceQueue<Object> queue;
final PhantomReference<Object> frqRef;
/**
* Whether or not the background thread started successfully.
*/
final boolean threadStarted;
/**
* Constructs a new queue.
*/
public FinalizableReferenceQueue() {
// We could start the finalizer lazily, but I'd rather it blow up early.
queue = new ReferenceQueue<Object>();
frqRef = new PhantomReference<Object>(this, queue);
boolean threadStarted = false;
try {
startFinalizer.invoke(null, FinalizableReference.class, queue, frqRef);
threadStarted = true;
} catch (IllegalAccessException impossible) {
throw new AssertionError(impossible); // startFinalizer() is public
} catch (Throwable t) {
logger.log(
Level.INFO,
"Failed to start reference finalizer thread."
+ " Reference cleanup will only occur when new references are created.",
t);
}
this.threadStarted = threadStarted;
}
@Override
public void close() {
frqRef.enqueue();
cleanUp();
}
/**
* Repeatedly dequeues references from the queue and invokes {@link
* FinalizableReference#finalizeReferent()} on them until the queue is empty. This method is a
* no-op if the background thread was created successfully.
*/
void cleanUp() {
if (threadStarted) {
return;
}
Reference<?> reference;
while ((reference = queue.poll()) != null) {
/*
* This is for the benefit of phantom references. Weak and soft references will have already
* been cleared by this point.
*/
reference.clear();
try {
((FinalizableReference) reference).finalizeReferent();
} catch (Throwable t) {
logger.log(Level.SEVERE, "Error cleaning up after reference.", t);
}
}
}
/**
* Iterates through the given loaders until it finds one that can load Finalizer.
*
* @return Finalizer.class
*/
private static Class<?> loadFinalizer(FinalizerLoader... loaders) {
for (FinalizerLoader loader : loaders) {
Class<?> finalizer = loader.loadFinalizer();
if (finalizer != null) {
return finalizer;
}
}
throw new AssertionError();
}
/**
* Loads Finalizer.class.
*/
interface FinalizerLoader {
/**
* Returns Finalizer.class or null if this loader shouldn't or can't load it.
*
* @throws SecurityException if we don't have the appropriate privileges
*/
@Nullable
Class<?> loadFinalizer();
}
/**
* Tries to load Finalizer from the system class loader. If Finalizer is in the system class path,
* we needn't create a separate loader.
*/
static class SystemLoader implements FinalizerLoader {
// This is used by the ClassLoader-leak test in FinalizableReferenceQueueTest to disable
// finding Finalizer on the system class path even if it is there.
@VisibleForTesting static boolean disabled;
@Override
public Class<?> loadFinalizer() {
if (disabled) {
return null;
}
ClassLoader systemLoader;
try {
systemLoader = ClassLoader.getSystemClassLoader();
} catch (SecurityException e) {
logger.info("Not allowed to access system class loader.");
return null;
}
if (systemLoader != null) {
try {
return systemLoader.loadClass(FINALIZER_CLASS_NAME);
} catch (ClassNotFoundException e) {
// Ignore. Finalizer is simply in a child class loader.
return null;
}
} else {
return null;
}
}
}
/**
* Try to load Finalizer in its own class loader. If Finalizer's thread had a direct reference to
* our class loader (which could be that of a dynamically loaded web application or OSGi bundle),
* it would prevent our class loader from getting garbage collected.
*/
static class DecoupledLoader implements FinalizerLoader {
private static final String LOADING_ERROR =
"Could not load Finalizer in its own class loader. Loading Finalizer in the current class "
+ "loader instead. As a result, you will not be able to garbage collect this class "
+ "loader. To support reclaiming this class loader, either resolve the underlying "
+ "issue, or move Guava to your system class path.";
@Override
public Class<?> loadFinalizer() {
try {
/*
* We use URLClassLoader because it's the only concrete class loader implementation in the
* JDK. If we used our own ClassLoader subclass, Finalizer would indirectly reference this
* class loader:
*
* Finalizer.class -> CustomClassLoader -> CustomClassLoader.class -> This class loader
*
* System class loader will (and must) be the parent.
*/
ClassLoader finalizerLoader = newLoader(getBaseUrl());
return finalizerLoader.loadClass(FINALIZER_CLASS_NAME);
} catch (Exception e) {
logger.log(Level.WARNING, LOADING_ERROR, e);
return null;
}
}
/**
* Gets URL for base of path containing Finalizer.class.
*/
URL getBaseUrl() throws IOException {
// Find URL pointing to Finalizer.class file.
String finalizerPath = FINALIZER_CLASS_NAME.replace('.', '/') + ".class";
URL finalizerUrl = getClass().getClassLoader().getResource(finalizerPath);
if (finalizerUrl == null) {
throw new FileNotFoundException(finalizerPath);
}
// Find URL pointing to base of class path.
String urlString = finalizerUrl.toString();
if (!urlString.endsWith(finalizerPath)) {
throw new IOException("Unsupported path style: " + urlString);
}
urlString = urlString.substring(0, urlString.length() - finalizerPath.length());
return new URL(finalizerUrl, urlString);
}
/** Creates a class loader with the given base URL as its classpath. */
URLClassLoader newLoader(URL base) {
// We use the bootstrap class loader as the parent because Finalizer by design uses
// only standard Java classes. That also means that FinalizableReferenceQueueTest
// doesn't pick up the wrong version of the Finalizer class.
return new URLClassLoader(new URL[] {base}, null);
}
}
/**
* Loads Finalizer directly using the current class loader. We won't be able to garbage collect
* this class loader, but at least the world doesn't end.
*/
static class DirectLoader implements FinalizerLoader {
@Override
public Class<?> loadFinalizer() {
try {
return Class.forName(FINALIZER_CLASS_NAME);
} catch (ClassNotFoundException e) {
throw new AssertionError(e);
}
}
}
/**
* Looks up Finalizer.startFinalizer().
*/
static Method getStartFinalizer(Class<?> finalizer) {
try {
return finalizer.getMethod(
"startFinalizer", Class.class, ReferenceQueue.class, PhantomReference.class);
} catch (NoSuchMethodException e) {
throw new AssertionError(e);
}
}
}
@@ -1,42 +0,0 @@
/*
* Copyright (C) 2007 The Guava Authors
*
* 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 com.google.common.base;
import java.lang.ref.ReferenceQueue;
import java.lang.ref.SoftReference;
/**
* Soft reference with a {@code finalizeReferent()} method which a background thread invokes after
* the garbage collector reclaims the referent. This is a simpler alternative to using a {@link
* ReferenceQueue}.
*
* @author Bob Lee
* @since 2.0
*/
public abstract class FinalizableSoftReference<T> extends SoftReference<T>
implements FinalizableReference {
/**
* Constructs a new finalizable soft reference.
*
* @param referent to softly reference
* @param queue that should finalize the referent
*/
protected FinalizableSoftReference(T referent, FinalizableReferenceQueue queue) {
super(referent, queue.queue);
queue.cleanUp();
}
}
@@ -1,42 +0,0 @@
/*
* Copyright (C) 2007 The Guava Authors
*
* 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 com.google.common.base;
import java.lang.ref.ReferenceQueue;
import java.lang.ref.WeakReference;
/**
* Weak reference with a {@code finalizeReferent()} method which a background thread invokes after
* the garbage collector reclaims the referent. This is a simpler alternative to using a {@link
* ReferenceQueue}.
*
* @author Bob Lee
* @since 2.0
*/
public abstract class FinalizableWeakReference<T> extends WeakReference<T>
implements FinalizableReference {
/**
* Constructs a new finalizable weak reference.
*
* @param referent to weakly reference
* @param queue that should finalize the referent
*/
protected FinalizableWeakReference(T referent, FinalizableReferenceQueue queue) {
super(referent, queue.queue);
queue.cleanUp();
}
}
@@ -1,66 +0,0 @@
/*
* Copyright (C) 2007 The Guava Authors
*
* 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 com.google.common.base;
import com.google.common.annotations.GwtCompatible;
import javax.annotation.Nullable;
/**
* Determines an output value based on an input value.
*
* <p>The {@link Functions} class provides common functions and related utilites.
*
* <p>See the Guava User Guide article on <a href=
* "https://github.com/google/guava/wiki/FunctionalExplained">the use of {@code
* Function}</a>.
*
* @author Kevin Bourrillion
* @since 2.0
*/
@GwtCompatible
public interface Function<F, T> {
/**
* Returns the result of applying this function to {@code input}. This method is <i>generally
* expected</i>, but not absolutely required, to have the following properties:
*
* <ul>
* <li>Its execution does not cause any observable side effects.
* <li>The computation is <i>consistent with equals</i>; that is, {@link Objects#equal
* Objects.equal}{@code (a, b)} implies that {@code Objects.equal(function.apply(a),
* function.apply(b))}.
* </ul>
*
* @throws NullPointerException if {@code input} is null and this function does not accept null
* arguments
*/
@Nullable
T apply(@Nullable F input);
/**
* Indicates whether another object is equal to this function.
*
* <p>Most implementations will have no reason to override the behavior of {@link Object#equals}.
* However, an implementation may also choose to return {@code true} whenever {@code object} is a
* {@link Function} that it considers <i>interchangeable</i> with this one. "Interchangeable"
* <i>typically</i> means that {@code Objects.equal(this.apply(f), that.apply(f))} is true for all
* {@code f} of type {@code F}. Note that a {@code false} result from this method does not imply
* that the functions are known <i>not</i> to be interchangeable.
*/
@Override
boolean equals(@Nullable Object object);
}
@@ -1,79 +0,0 @@
/*
* Copyright (C) 2011 The Guava Authors
*
* 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 com.google.common.base;
import static com.google.common.base.Preconditions.checkNotNull;
import com.google.common.annotations.Beta;
import com.google.common.annotations.GwtCompatible;
import java.io.Serializable;
import javax.annotation.Nullable;
/**
* Equivalence applied on functional result.
*
* @author Bob Lee
* @since 10.0
*/
@Beta
@GwtCompatible
final class FunctionalEquivalence<F, T> extends Equivalence<F> implements Serializable {
private static final long serialVersionUID = 0;
private final Function<F, ? extends T> function;
private final Equivalence<T> resultEquivalence;
FunctionalEquivalence(Function<F, ? extends T> function, Equivalence<T> resultEquivalence) {
this.function = checkNotNull(function);
this.resultEquivalence = checkNotNull(resultEquivalence);
}
@Override
protected boolean doEquivalent(F a, F b) {
return resultEquivalence.equivalent(function.apply(a), function.apply(b));
}
@Override
protected int doHash(F a) {
return resultEquivalence.hash(function.apply(a));
}
@Override
public boolean equals(@Nullable Object obj) {
if (obj == this) {
return true;
}
if (obj instanceof FunctionalEquivalence) {
FunctionalEquivalence<?, ?> that = (FunctionalEquivalence<?, ?>) obj;
return function.equals(that.function) && resultEquivalence.equals(that.resultEquivalence);
}
return false;
}
@Override
public int hashCode() {
return Objects.hashCode(function, resultEquivalence);
}
@Override
public String toString() {
return resultEquivalence + ".onResultOf(" + function + ")";
}
}
@@ -1,388 +0,0 @@
/*
* Copyright (C) 2007 The Guava Authors
*
* 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 com.google.common.base;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import com.google.common.annotations.Beta;
import com.google.common.annotations.GwtCompatible;
import java.io.Serializable;
import java.util.Map;
import javax.annotation.CheckReturnValue;
import javax.annotation.Nullable;
/**
* Static utility methods pertaining to {@code Function} instances.
*
* <p>All methods return serializable functions as long as they're given serializable parameters.
*
* <p>See the Guava User Guide article on <a href=
* "https://github.com/google/guava/wiki/FunctionalExplained">the use of {@code
* Function}</a>.
*
* @author Mike Bostock
* @author Jared Levy
* @since 2.0
*/
@GwtCompatible
@CheckReturnValue
public final class Functions {
private Functions() {}
/**
* Returns a function that calls {@code toString()} on its argument. The function does not accept
* nulls; it will throw a {@link NullPointerException} when applied to {@code null}.
*
* <p><b>Warning:</b> The returned function may not be <i>consistent with equals</i> (as
* documented at {@link Function#apply}). For example, this function yields different results for
* the two equal instances {@code ImmutableSet.of(1, 2)} and {@code ImmutableSet.of(2, 1)}.
*/
public static Function<Object, String> toStringFunction() {
return ToStringFunction.INSTANCE;
}
// enum singleton pattern
private enum ToStringFunction implements Function<Object, String> {
INSTANCE;
@Override
public String apply(Object o) {
checkNotNull(o); // eager for GWT.
return o.toString();
}
@Override
public String toString() {
return "Functions.toStringFunction()";
}
}
/**
* Returns the identity function.
*/
// implementation is "fully variant"; E has become a "pass-through" type
@SuppressWarnings("unchecked")
public static <E> Function<E, E> identity() {
return (Function<E, E>) IdentityFunction.INSTANCE;
}
// enum singleton pattern
private enum IdentityFunction implements Function<Object, Object> {
INSTANCE;
@Override
@Nullable
public Object apply(@Nullable Object o) {
return o;
}
@Override
public String toString() {
return "Functions.identity()";
}
}
/**
* Returns a function which performs a map lookup. The returned function throws an {@link
* IllegalArgumentException} if given a key that does not exist in the map. See also {@link
* #forMap(Map, Object)}, which returns a default value in this case.
*
* <p>Note: if {@code map} is a {@link com.google.common.collect.BiMap BiMap} (or can be one), you
* can use {@link com.google.common.collect.Maps#asConverter Maps.asConverter} instead to get a
* function that also supports reverse conversion.
*/
public static <K, V> Function<K, V> forMap(Map<K, V> map) {
return new FunctionForMapNoDefault<K, V>(map);
}
private static class FunctionForMapNoDefault<K, V> implements Function<K, V>, Serializable {
final Map<K, V> map;
FunctionForMapNoDefault(Map<K, V> map) {
this.map = checkNotNull(map);
}
@Override
public V apply(@Nullable K key) {
V result = map.get(key);
checkArgument(result != null || map.containsKey(key), "Key '%s' not present in map", key);
return result;
}
@Override
public boolean equals(@Nullable Object o) {
if (o instanceof FunctionForMapNoDefault) {
FunctionForMapNoDefault<?, ?> that = (FunctionForMapNoDefault<?, ?>) o;
return map.equals(that.map);
}
return false;
}
@Override
public int hashCode() {
return map.hashCode();
}
@Override
public String toString() {
return "Functions.forMap(" + map + ")";
}
private static final long serialVersionUID = 0;
}
/**
* Returns a function which performs a map lookup with a default value. The function created by
* this method returns {@code defaultValue} for all inputs that do not belong to the map's key
* set. See also {@link #forMap(Map)}, which throws an exception in this case.
*
* @param map source map that determines the function behavior
* @param defaultValue the value to return for inputs that aren't map keys
* @return function that returns {@code map.get(a)} when {@code a} is a key, or {@code
* defaultValue} otherwise
*/
public static <K, V> Function<K, V> forMap(Map<K, ? extends V> map, @Nullable V defaultValue) {
return new ForMapWithDefault<K, V>(map, defaultValue);
}
private static class ForMapWithDefault<K, V> implements Function<K, V>, Serializable {
final Map<K, ? extends V> map;
final V defaultValue;
ForMapWithDefault(Map<K, ? extends V> map, @Nullable V defaultValue) {
this.map = checkNotNull(map);
this.defaultValue = defaultValue;
}
@Override
public V apply(@Nullable K key) {
V result = map.get(key);
return (result != null || map.containsKey(key)) ? result : defaultValue;
}
@Override
public boolean equals(@Nullable Object o) {
if (o instanceof ForMapWithDefault) {
ForMapWithDefault<?, ?> that = (ForMapWithDefault<?, ?>) o;
return map.equals(that.map) && Objects.equal(defaultValue, that.defaultValue);
}
return false;
}
@Override
public int hashCode() {
return Objects.hashCode(map, defaultValue);
}
@Override
public String toString() {
// TODO(cpovirk): maybe remove "defaultValue=" to make this look like the method call does
return "Functions.forMap(" + map + ", defaultValue=" + defaultValue + ")";
}
private static final long serialVersionUID = 0;
}
/**
* Returns the composition of two functions. For {@code f: A->B} and {@code g: B->C}, composition
* is defined as the function h such that {@code h(a) == g(f(a))} for each {@code a}.
*
* @param g the second function to apply
* @param f the first function to apply
* @return the composition of {@code f} and {@code g}
* @see <a href="//en.wikipedia.org/wiki/Function_composition">function composition</a>
*/
public static <A, B, C> Function<A, C> compose(Function<B, C> g, Function<A, ? extends B> f) {
return new FunctionComposition<A, B, C>(g, f);
}
private static class FunctionComposition<A, B, C> implements Function<A, C>, Serializable {
private final Function<B, C> g;
private final Function<A, ? extends B> f;
public FunctionComposition(Function<B, C> g, Function<A, ? extends B> f) {
this.g = checkNotNull(g);
this.f = checkNotNull(f);
}
@Override
public C apply(@Nullable A a) {
return g.apply(f.apply(a));
}
@Override
public boolean equals(@Nullable Object obj) {
if (obj instanceof FunctionComposition) {
FunctionComposition<?, ?, ?> that = (FunctionComposition<?, ?, ?>) obj;
return f.equals(that.f) && g.equals(that.g);
}
return false;
}
@Override
public int hashCode() {
return f.hashCode() ^ g.hashCode();
}
@Override
public String toString() {
// TODO(cpovirk): maybe make this look like the method call does ("Functions.compose(...)")
return g + "(" + f + ")";
}
private static final long serialVersionUID = 0;
}
/**
* Creates a function that returns the same boolean output as the given predicate for all inputs.
*
* <p>The returned function is <i>consistent with equals</i> (as documented at {@link
* Function#apply}) if and only if {@code predicate} is itself consistent with equals.
*/
public static <T> Function<T, Boolean> forPredicate(Predicate<T> predicate) {
return new PredicateFunction<T>(predicate);
}
/** @see Functions#forPredicate */
private static class PredicateFunction<T> implements Function<T, Boolean>, Serializable {
private final Predicate<T> predicate;
private PredicateFunction(Predicate<T> predicate) {
this.predicate = checkNotNull(predicate);
}
@Override
public Boolean apply(@Nullable T t) {
return predicate.apply(t);
}
@Override
public boolean equals(@Nullable Object obj) {
if (obj instanceof PredicateFunction) {
PredicateFunction<?> that = (PredicateFunction<?>) obj;
return predicate.equals(that.predicate);
}
return false;
}
@Override
public int hashCode() {
return predicate.hashCode();
}
@Override
public String toString() {
return "Functions.forPredicate(" + predicate + ")";
}
private static final long serialVersionUID = 0;
}
/**
* Creates a function that returns {@code value} for any input.
*
* @param value the constant value for the function to return
* @return a function that always returns {@code value}
*/
public static <E> Function<Object, E> constant(@Nullable E value) {
return new ConstantFunction<E>(value);
}
private static class ConstantFunction<E> implements Function<Object, E>, Serializable {
private final E value;
public ConstantFunction(@Nullable E value) {
this.value = value;
}
@Override
public E apply(@Nullable Object from) {
return value;
}
@Override
public boolean equals(@Nullable Object obj) {
if (obj instanceof ConstantFunction) {
ConstantFunction<?> that = (ConstantFunction<?>) obj;
return Objects.equal(value, that.value);
}
return false;
}
@Override
public int hashCode() {
return (value == null) ? 0 : value.hashCode();
}
@Override
public String toString() {
return "Functions.constant(" + value + ")";
}
private static final long serialVersionUID = 0;
}
/**
* Returns a function that always returns the result of invoking {@link Supplier#get} on {@code
* supplier}, regardless of its input.
*
* @since 10.0
*/
@Beta
public static <T> Function<Object, T> forSupplier(Supplier<T> supplier) {
return new SupplierFunction<T>(supplier);
}
/** @see Functions#forSupplier*/
private static class SupplierFunction<T> implements Function<Object, T>, Serializable {
private final Supplier<T> supplier;
private SupplierFunction(Supplier<T> supplier) {
this.supplier = checkNotNull(supplier);
}
@Override
public T apply(@Nullable Object input) {
return supplier.get();
}
@Override
public boolean equals(@Nullable Object obj) {
if (obj instanceof SupplierFunction) {
SupplierFunction<?> that = (SupplierFunction<?>) obj;
return this.supplier.equals(that.supplier);
}
return false;
}
@Override
public int hashCode() {
return supplier.hashCode();
}
@Override
public String toString() {
return "Functions.forSupplier(" + supplier + ")";
}
private static final long serialVersionUID = 0;
}
}
@@ -1,473 +0,0 @@
/*
* Copyright (C) 2008 The Guava Authors
*
* 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 com.google.common.base;
import static com.google.common.base.Preconditions.checkNotNull;
import com.google.common.annotations.Beta;
import com.google.common.annotations.GwtCompatible;
import java.io.IOException;
import java.util.AbstractList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import javax.annotation.CheckReturnValue;
import javax.annotation.Nullable;
/**
* An object which joins pieces of text (specified as an array, {@link Iterable}, varargs or even a
* {@link Map}) with a separator. It either appends the results to an {@link Appendable} or returns
* them as a {@link String}. Example: <pre> {@code
*
* Joiner joiner = Joiner.on("; ").skipNulls();
* . . .
* return joiner.join("Harry", null, "Ron", "Hermione");}</pre>
*
* <p>This returns the string {@code "Harry; Ron; Hermione"}. Note that all input elements are
* converted to strings using {@link Object#toString()} before being appended.
*
* <p>If neither {@link #skipNulls()} nor {@link #useForNull(String)} is specified, the joining
* methods will throw {@link NullPointerException} if any given element is null.
*
* <p><b>Warning: joiner instances are always immutable</b>; a configuration method such as {@code
* useForNull} has no effect on the instance it is invoked on! You must store and use the new joiner
* instance returned by the method. This makes joiners thread-safe, and safe to store as {@code
* static final} constants. <pre> {@code
*
* // Bad! Do not do this!
* Joiner joiner = Joiner.on(',');
* joiner.skipNulls(); // does nothing!
* return joiner.join("wrong", null, "wrong");}</pre>
*
* <p>See the Guava User Guide article on <a href=
* "https://github.com/google/guava/wiki/StringsExplained#joiner">{@code Joiner}</a>.
*
* @author Kevin Bourrillion
* @since 2.0
*/
@GwtCompatible
public class Joiner {
/**
* Returns a joiner which automatically places {@code separator} between consecutive elements.
*/
@CheckReturnValue
public static Joiner on(String separator) {
return new Joiner(separator);
}
/**
* Returns a joiner which automatically places {@code separator} between consecutive elements.
*/
@CheckReturnValue
public static Joiner on(char separator) {
return new Joiner(String.valueOf(separator));
}
private final String separator;
private Joiner(String separator) {
this.separator = checkNotNull(separator);
}
private Joiner(Joiner prototype) {
this.separator = prototype.separator;
}
/**
* Appends the string representation of each of {@code parts}, using the previously configured
* separator between each, to {@code appendable}.
*/
public <A extends Appendable> A appendTo(A appendable, Iterable<?> parts) throws IOException {
return appendTo(appendable, parts.iterator());
}
/**
* Appends the string representation of each of {@code parts}, using the previously configured
* separator between each, to {@code appendable}.
*
* @since 11.0
*/
public <A extends Appendable> A appendTo(A appendable, Iterator<?> parts) throws IOException {
checkNotNull(appendable);
if (parts.hasNext()) {
appendable.append(toString(parts.next()));
while (parts.hasNext()) {
appendable.append(separator);
appendable.append(toString(parts.next()));
}
}
return appendable;
}
/**
* Appends the string representation of each of {@code parts}, using the previously configured
* separator between each, to {@code appendable}.
*/
public final <A extends Appendable> A appendTo(A appendable, Object[] parts) throws IOException {
return appendTo(appendable, Arrays.asList(parts));
}
/**
* Appends to {@code appendable} the string representation of each of the remaining arguments.
*/
public final <A extends Appendable> A appendTo(
A appendable, @Nullable Object first, @Nullable Object second, Object... rest)
throws IOException {
return appendTo(appendable, iterable(first, second, rest));
}
/**
* Appends the string representation of each of {@code parts}, using the previously configured
* separator between each, to {@code builder}. Identical to {@link #appendTo(Appendable,
* Iterable)}, except that it does not throw {@link IOException}.
*/
public final StringBuilder appendTo(StringBuilder builder, Iterable<?> parts) {
return appendTo(builder, parts.iterator());
}
/**
* Appends the string representation of each of {@code parts}, using the previously configured
* separator between each, to {@code builder}. Identical to {@link #appendTo(Appendable,
* Iterable)}, except that it does not throw {@link IOException}.
*
* @since 11.0
*/
public final StringBuilder appendTo(StringBuilder builder, Iterator<?> parts) {
try {
appendTo((Appendable) builder, parts);
} catch (IOException impossible) {
throw new AssertionError(impossible);
}
return builder;
}
/**
* Appends the string representation of each of {@code parts}, using the previously configured
* separator between each, to {@code builder}. Identical to {@link #appendTo(Appendable,
* Iterable)}, except that it does not throw {@link IOException}.
*/
public final StringBuilder appendTo(StringBuilder builder, Object[] parts) {
return appendTo(builder, Arrays.asList(parts));
}
/**
* Appends to {@code builder} the string representation of each of the remaining arguments.
* Identical to {@link #appendTo(Appendable, Object, Object, Object...)}, except that it does not
* throw {@link IOException}.
*/
public final StringBuilder appendTo(
StringBuilder builder, @Nullable Object first, @Nullable Object second, Object... rest) {
return appendTo(builder, iterable(first, second, rest));
}
/**
* Returns a string containing the string representation of each of {@code parts}, using the
* previously configured separator between each.
*/
@CheckReturnValue
public final String join(Iterable<?> parts) {
return join(parts.iterator());
}
/**
* Returns a string containing the string representation of each of {@code parts}, using the
* previously configured separator between each.
*
* @since 11.0
*/
@CheckReturnValue
public final String join(Iterator<?> parts) {
return appendTo(new StringBuilder(), parts).toString();
}
/**
* Returns a string containing the string representation of each of {@code parts}, using the
* previously configured separator between each.
*/
@CheckReturnValue
public final String join(Object[] parts) {
return join(Arrays.asList(parts));
}
/**
* Returns a string containing the string representation of each argument, using the previously
* configured separator between each.
*/
@CheckReturnValue
public final String join(@Nullable Object first, @Nullable Object second, Object... rest) {
return join(iterable(first, second, rest));
}
/**
* Returns a joiner with the same behavior as this one, except automatically substituting {@code
* nullText} for any provided null elements.
*/
@CheckReturnValue
public Joiner useForNull(final String nullText) {
checkNotNull(nullText);
return new Joiner(this) {
@Override
CharSequence toString(@Nullable Object part) {
return (part == null) ? nullText : Joiner.this.toString(part);
}
@Override
public Joiner useForNull(String nullText) {
throw new UnsupportedOperationException("already specified useForNull");
}
@Override
public Joiner skipNulls() {
throw new UnsupportedOperationException("already specified useForNull");
}
};
}
/**
* Returns a joiner with the same behavior as this joiner, except automatically skipping over any
* provided null elements.
*/
@CheckReturnValue
public Joiner skipNulls() {
return new Joiner(this) {
@Override
public <A extends Appendable> A appendTo(A appendable, Iterator<?> parts) throws IOException {
checkNotNull(appendable, "appendable");
checkNotNull(parts, "parts");
while (parts.hasNext()) {
Object part = parts.next();
if (part != null) {
appendable.append(Joiner.this.toString(part));
break;
}
}
while (parts.hasNext()) {
Object part = parts.next();
if (part != null) {
appendable.append(separator);
appendable.append(Joiner.this.toString(part));
}
}
return appendable;
}
@Override
public Joiner useForNull(String nullText) {
throw new UnsupportedOperationException("already specified skipNulls");
}
@Override
public MapJoiner withKeyValueSeparator(String kvs) {
throw new UnsupportedOperationException("can't use .skipNulls() with maps");
}
};
}
/**
* Returns a {@code MapJoiner} using the given key-value separator, and the same configuration as
* this {@code Joiner} otherwise.
*/
@CheckReturnValue
public MapJoiner withKeyValueSeparator(String keyValueSeparator) {
return new MapJoiner(this, keyValueSeparator);
}
/**
* An object that joins map entries in the same manner as {@code Joiner} joins iterables and
* arrays. Like {@code Joiner}, it is thread-safe and immutable.
*
* <p>In addition to operating on {@code Map} instances, {@code MapJoiner} can operate on {@code
* Multimap} entries in two distinct modes:
*
* <ul>
* <li>To output a separate entry for each key-value pair, pass {@code multimap.entries()} to a
* {@code MapJoiner} method that accepts entries as input, and receive output of the form
* {@code key1=A&key1=B&key2=C}.
* <li>To output a single entry for each key, pass {@code multimap.asMap()} to a {@code MapJoiner}
* method that accepts a map as input, and receive output of the form {@code
* key1=[A, B]&key2=C}.
* </ul>
*
* @since 2.0
*/
public static final class MapJoiner {
private final Joiner joiner;
private final String keyValueSeparator;
private MapJoiner(Joiner joiner, String keyValueSeparator) {
this.joiner = joiner; // only "this" is ever passed, so don't checkNotNull
this.keyValueSeparator = checkNotNull(keyValueSeparator);
}
/**
* Appends the string representation of each entry of {@code map}, using the previously
* configured separator and key-value separator, to {@code appendable}.
*/
public <A extends Appendable> A appendTo(A appendable, Map<?, ?> map) throws IOException {
return appendTo(appendable, map.entrySet());
}
/**
* Appends the string representation of each entry of {@code map}, using the previously
* configured separator and key-value separator, to {@code builder}. Identical to {@link
* #appendTo(Appendable, Map)}, except that it does not throw {@link IOException}.
*/
public StringBuilder appendTo(StringBuilder builder, Map<?, ?> map) {
return appendTo(builder, map.entrySet());
}
/**
* Returns a string containing the string representation of each entry of {@code map}, using the
* previously configured separator and key-value separator.
*/
@CheckReturnValue
public String join(Map<?, ?> map) {
return join(map.entrySet());
}
/**
* Appends the string representation of each entry in {@code entries}, using the previously
* configured separator and key-value separator, to {@code appendable}.
*
* @since 10.0
*/
@Beta
public <A extends Appendable> A appendTo(A appendable, Iterable<? extends Entry<?, ?>> entries)
throws IOException {
return appendTo(appendable, entries.iterator());
}
/**
* Appends the string representation of each entry in {@code entries}, using the previously
* configured separator and key-value separator, to {@code appendable}.
*
* @since 11.0
*/
@Beta
public <A extends Appendable> A appendTo(A appendable, Iterator<? extends Entry<?, ?>> parts)
throws IOException {
checkNotNull(appendable);
if (parts.hasNext()) {
Entry<?, ?> entry = parts.next();
appendable.append(joiner.toString(entry.getKey()));
appendable.append(keyValueSeparator);
appendable.append(joiner.toString(entry.getValue()));
while (parts.hasNext()) {
appendable.append(joiner.separator);
Entry<?, ?> e = parts.next();
appendable.append(joiner.toString(e.getKey()));
appendable.append(keyValueSeparator);
appendable.append(joiner.toString(e.getValue()));
}
}
return appendable;
}
/**
* Appends the string representation of each entry in {@code entries}, using the previously
* configured separator and key-value separator, to {@code builder}. Identical to {@link
* #appendTo(Appendable, Iterable)}, except that it does not throw {@link IOException}.
*
* @since 10.0
*/
@Beta
public StringBuilder appendTo(StringBuilder builder, Iterable<? extends Entry<?, ?>> entries) {
return appendTo(builder, entries.iterator());
}
/**
* Appends the string representation of each entry in {@code entries}, using the previously
* configured separator and key-value separator, to {@code builder}. Identical to {@link
* #appendTo(Appendable, Iterable)}, except that it does not throw {@link IOException}.
*
* @since 11.0
*/
@Beta
public StringBuilder appendTo(StringBuilder builder, Iterator<? extends Entry<?, ?>> entries) {
try {
appendTo((Appendable) builder, entries);
} catch (IOException impossible) {
throw new AssertionError(impossible);
}
return builder;
}
/**
* Returns a string containing the string representation of each entry in {@code entries}, using
* the previously configured separator and key-value separator.
*
* @since 10.0
*/
@Beta
@CheckReturnValue
public String join(Iterable<? extends Entry<?, ?>> entries) {
return join(entries.iterator());
}
/**
* Returns a string containing the string representation of each entry in {@code entries}, using
* the previously configured separator and key-value separator.
*
* @since 11.0
*/
@Beta
@CheckReturnValue
public String join(Iterator<? extends Entry<?, ?>> entries) {
return appendTo(new StringBuilder(), entries).toString();
}
/**
* Returns a map joiner with the same behavior as this one, except automatically substituting
* {@code nullText} for any provided null keys or values.
*/
@CheckReturnValue
public MapJoiner useForNull(String nullText) {
return new MapJoiner(joiner.useForNull(nullText), keyValueSeparator);
}
}
CharSequence toString(Object part) {
checkNotNull(part); // checkNotNull for GWT (do not optimize).
return (part instanceof CharSequence) ? (CharSequence) part : part.toString();
}
private static Iterable<Object> iterable(
final Object first, final Object second, final Object[] rest) {
checkNotNull(rest);
return new AbstractList<Object>() {
@Override
public int size() {
return rest.length + 2;
}
@Override
public Object get(int index) {
switch (index) {
case 0:
return first;
case 1:
return second;
default:
return rest[index - 2];
}
}
};
}
}
@@ -1,381 +0,0 @@
/*
* Copyright (C) 2014 The Guava Authors
*
* 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 com.google.common.base;
import static com.google.common.base.Preconditions.checkNotNull;
import com.google.common.annotations.GwtCompatible;
import java.util.Arrays;
import javax.annotation.CheckReturnValue;
import javax.annotation.Nullable;
/**
* Helper functions that operate on any {@code Object}, and are not already provided in
* {@link java.util.Objects}.
*
* <p>See the Guava User Guide on <a
* href="https://github.com/google/guava/wiki/CommonObjectUtilitiesExplained">writing
* {@code Object} methods with {@code MoreObjects}</a>.
*
* @author Laurence Gonsalves
* @since 18.0 (since 2.0 as {@code Objects})
*/
@GwtCompatible
public final class MoreObjects {
/**
* Returns the first of two given parameters that is not {@code null}, if either is, or otherwise
* throws a {@link NullPointerException}.
*
* <p><b>Note:</b> if {@code first} is represented as an {@link Optional}, this can be
* accomplished with {@link Optional#or(Object) first.or(second)}. That approach also allows for
* lazy evaluation of the fallback instance, using {@link Optional#or(Supplier)
* first.or(supplier)}.
*
* @return {@code first} if it is non-null; otherwise {@code second} if it is non-null
* @throws NullPointerException if both {@code first} and {@code second} are null
* @since 18.0 (since 3.0 as {@code Objects.firstNonNull()}).
*/
@CheckReturnValue
public static <T> T firstNonNull(@Nullable T first, @Nullable T second) {
return first != null ? first : checkNotNull(second);
}
/**
* Creates an instance of {@link ToStringHelper}.
*
* <p>This is helpful for implementing {@link Object#toString()}.
* Specification by example: <pre> {@code
* // Returns "ClassName{}"
* MoreObjects.toStringHelper(this)
* .toString();
*
* // Returns "ClassName{x=1}"
* MoreObjects.toStringHelper(this)
* .add("x", 1)
* .toString();
*
* // Returns "MyObject{x=1}"
* MoreObjects.toStringHelper("MyObject")
* .add("x", 1)
* .toString();
*
* // Returns "ClassName{x=1, y=foo}"
* MoreObjects.toStringHelper(this)
* .add("x", 1)
* .add("y", "foo")
* .toString();
*
* // Returns "ClassName{x=1}"
* MoreObjects.toStringHelper(this)
* .omitNullValues()
* .add("x", 1)
* .add("y", null)
* .toString();
* }}</pre>
*
* <p>Note that in GWT, class names are often obfuscated.
*
* @param self the object to generate the string for (typically {@code this}), used only for its
* class name
* @since 18.0 (since 2.0 as {@code Objects.toStringHelper()}).
*/
@CheckReturnValue
public static ToStringHelper toStringHelper(Object self) {
return new ToStringHelper(self.getClass().getSimpleName());
}
/**
* Creates an instance of {@link ToStringHelper} in the same manner as {@link
* #toStringHelper(Object)}, but using the simple name of {@code clazz} instead of using an
* instance's {@link Object#getClass()}.
*
* <p>Note that in GWT, class names are often obfuscated.
*
* @param clazz the {@link Class} of the instance
* @since 18.0 (since 7.0 as {@code Objects.toStringHelper()}).
*/
@CheckReturnValue
public static ToStringHelper toStringHelper(Class<?> clazz) {
return new ToStringHelper(clazz.getSimpleName());
}
/**
* Creates an instance of {@link ToStringHelper} in the same manner as {@link
* #toStringHelper(Object)}, but using {@code className} instead of using an instance's {@link
* Object#getClass()}.
*
* @param className the name of the instance type
* @since 18.0 (since 7.0 as {@code Objects.toStringHelper()}).
*/
@CheckReturnValue
public static ToStringHelper toStringHelper(String className) {
return new ToStringHelper(className);
}
/**
* Support class for {@link MoreObjects#toStringHelper}.
*
* @author Jason Lee
* @since 18.0 (since 2.0 as {@code Objects.ToStringHelper}).
*/
public static final class ToStringHelper {
private final String className;
private ValueHolder holderHead = new ValueHolder();
private ValueHolder holderTail = holderHead;
private boolean omitNullValues = false;
/**
* Use {@link MoreObjects#toStringHelper(Object)} to create an instance.
*/
private ToStringHelper(String className) {
this.className = checkNotNull(className);
}
/**
* Configures the {@link ToStringHelper} so {@link #toString()} will ignore
* properties with null value. The order of calling this method, relative
* to the {@code add()}/{@code addValue()} methods, is not significant.
*
* @since 18.0 (since 12.0 as {@code Objects.ToStringHelper.omitNullValues()}).
*/
public ToStringHelper omitNullValues() {
omitNullValues = true;
return this;
}
/**
* Adds a name/value pair to the formatted output in {@code name=value}
* format. If {@code value} is {@code null}, the string {@code "null"}
* is used, unless {@link #omitNullValues()} is called, in which case this
* name/value pair will not be added.
*/
public ToStringHelper add(String name, @Nullable Object value) {
return addHolder(name, value);
}
/**
* Adds a name/value pair to the formatted output in {@code name=value}
* format.
*
* @since 18.0 (since 11.0 as {@code Objects.ToStringHelper.add()}).
*/
public ToStringHelper add(String name, boolean value) {
return addHolder(name, String.valueOf(value));
}
/**
* Adds a name/value pair to the formatted output in {@code name=value}
* format.
*
* @since 18.0 (since 11.0 as {@code Objects.ToStringHelper.add()}).
*/
public ToStringHelper add(String name, char value) {
return addHolder(name, String.valueOf(value));
}
/**
* Adds a name/value pair to the formatted output in {@code name=value}
* format.
*
* @since 18.0 (since 11.0 as {@code Objects.ToStringHelper.add()}).
*/
public ToStringHelper add(String name, double value) {
return addHolder(name, String.valueOf(value));
}
/**
* Adds a name/value pair to the formatted output in {@code name=value}
* format.
*
* @since 18.0 (since 11.0 as {@code Objects.ToStringHelper.add()}).
*/
public ToStringHelper add(String name, float value) {
return addHolder(name, String.valueOf(value));
}
/**
* Adds a name/value pair to the formatted output in {@code name=value}
* format.
*
* @since 18.0 (since 11.0 as {@code Objects.ToStringHelper.add()}).
*/
public ToStringHelper add(String name, int value) {
return addHolder(name, String.valueOf(value));
}
/**
* Adds a name/value pair to the formatted output in {@code name=value}
* format.
*
* @since 18.0 (since 11.0 as {@code Objects.ToStringHelper.add()}).
*/
public ToStringHelper add(String name, long value) {
return addHolder(name, String.valueOf(value));
}
/**
* Adds an unnamed value to the formatted output.
*
* <p>It is strongly encouraged to use {@link #add(String, Object)} instead
* and give value a readable name.
*/
public ToStringHelper addValue(@Nullable Object value) {
return addHolder(value);
}
/**
* Adds an unnamed value to the formatted output.
*
* <p>It is strongly encouraged to use {@link #add(String, boolean)} instead
* and give value a readable name.
*
* @since 18.0 (since 11.0 as {@code Objects.ToStringHelper.addValue()}).
*/
public ToStringHelper addValue(boolean value) {
return addHolder(String.valueOf(value));
}
/**
* Adds an unnamed value to the formatted output.
*
* <p>It is strongly encouraged to use {@link #add(String, char)} instead
* and give value a readable name.
*
* @since 18.0 (since 11.0 as {@code Objects.ToStringHelper.addValue()}).
*/
public ToStringHelper addValue(char value) {
return addHolder(String.valueOf(value));
}
/**
* Adds an unnamed value to the formatted output.
*
* <p>It is strongly encouraged to use {@link #add(String, double)} instead
* and give value a readable name.
*
* @since 18.0 (since 11.0 as {@code Objects.ToStringHelper.addValue()}).
*/
public ToStringHelper addValue(double value) {
return addHolder(String.valueOf(value));
}
/**
* Adds an unnamed value to the formatted output.
*
* <p>It is strongly encouraged to use {@link #add(String, float)} instead
* and give value a readable name.
*
* @since 18.0 (since 11.0 as {@code Objects.ToStringHelper.addValue()}).
*/
public ToStringHelper addValue(float value) {
return addHolder(String.valueOf(value));
}
/**
* Adds an unnamed value to the formatted output.
*
* <p>It is strongly encouraged to use {@link #add(String, int)} instead
* and give value a readable name.
*
* @since 18.0 (since 11.0 as {@code Objects.ToStringHelper.addValue()}).
*/
public ToStringHelper addValue(int value) {
return addHolder(String.valueOf(value));
}
/**
* Adds an unnamed value to the formatted output.
*
* <p>It is strongly encouraged to use {@link #add(String, long)} instead
* and give value a readable name.
*
* @since 18.0 (since 11.0 as {@code Objects.ToStringHelper.addValue()}).
*/
public ToStringHelper addValue(long value) {
return addHolder(String.valueOf(value));
}
/**
* Returns a string in the format specified by
* {@link MoreObjects#toStringHelper(Object)}.
*
* <p>After calling this method, you can keep adding more properties to later
* call toString() again and get a more complete representation of the
* same object; but properties cannot be removed, so this only allows
* limited reuse of the helper instance. The helper allows duplication of
* properties (multiple name/value pairs with the same name can be added).
*/
@CheckReturnValue
@Override
public String toString() {
// create a copy to keep it consistent in case value changes
boolean omitNullValuesSnapshot = omitNullValues;
String nextSeparator = "";
StringBuilder builder = new StringBuilder(32).append(className).append('{');
for (ValueHolder valueHolder = holderHead.next;
valueHolder != null;
valueHolder = valueHolder.next) {
Object value = valueHolder.value;
if (!omitNullValuesSnapshot || value != null) {
builder.append(nextSeparator);
nextSeparator = ", ";
if (valueHolder.name != null) {
builder.append(valueHolder.name).append('=');
}
if (value != null && value.getClass().isArray()) {
Object[] objectArray = {value};
String arrayString = Arrays.deepToString(objectArray);
builder.append(arrayString.substring(1, arrayString.length() - 1));
} else {
builder.append(value);
}
}
}
return builder.append('}').toString();
}
private ValueHolder addHolder() {
ValueHolder valueHolder = new ValueHolder();
holderTail = holderTail.next = valueHolder;
return valueHolder;
}
private ToStringHelper addHolder(@Nullable Object value) {
ValueHolder valueHolder = addHolder();
valueHolder.value = value;
return this;
}
private ToStringHelper addHolder(String name, @Nullable Object value) {
ValueHolder valueHolder = addHolder();
valueHolder.value = value;
valueHolder.name = checkNotNull(name);
return this;
}
private static final class ValueHolder {
String name;
Object value;
ValueHolder next;
}
}
private MoreObjects() {}
}
@@ -1,437 +0,0 @@
/*
* Copyright (C) 2007 The Guava Authors
*
* 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 com.google.common.base;
import static com.google.common.base.Preconditions.checkNotNull;
import com.google.common.annotations.GwtCompatible;
import java.util.Arrays;
import javax.annotation.CheckReturnValue;
import javax.annotation.Nullable;
/**
* Helper functions that can operate on any {@code Object}.
*
* <p>See the Guava User Guide on <a
* href="https://github.com/google/guava/wiki/CommonObjectUtilitiesExplained">writing
* {@code Object} methods with {@code Objects}</a>.
*
* @author Laurence Gonsalves
* @since 2.0
*/
@GwtCompatible
public final class Objects {
private Objects() {}
/**
* Determines whether two possibly-null objects are equal. Returns:
*
* <ul>
* <li>{@code true} if {@code a} and {@code b} are both null.
* <li>{@code true} if {@code a} and {@code b} are both non-null and they are
* equal according to {@link Object#equals(Object)}.
* <li>{@code false} in all other situations.
* </ul>
*
* <p>This assumes that any non-null objects passed to this function conform
* to the {@code equals()} contract.
*
* <p><b>Note for Java 7 and later:</b> This method should be treated as
* deprecated; use {@link java.util.Objects#equals} instead.
*/
@CheckReturnValue
public static boolean equal(@Nullable Object a, @Nullable Object b) {
return a == b || (a != null && a.equals(b));
}
/**
* Generates a hash code for multiple values. The hash code is generated by
* calling {@link Arrays#hashCode(Object[])}. Note that array arguments to
* this method, with the exception of a single Object array, do not get any
* special handling; their hash codes are based on identity and not contents.
*
* <p>This is useful for implementing {@link Object#hashCode()}. For example,
* in an object that has three properties, {@code x}, {@code y}, and
* {@code z}, one could write:
* <pre> {@code
* public int hashCode() {
* return Objects.hashCode(getX(), getY(), getZ());
* }}</pre>
*
* <p><b>Warning:</b> When a single object is supplied, the returned hash code
* does not equal the hash code of that object.
*
* <p><b>Note for Java 7 and later:</b> This method should be treated as
* deprecated; use {@link java.util.Objects#hash} instead.
*/
@CheckReturnValue
public static int hashCode(@Nullable Object... objects) {
return Arrays.hashCode(objects);
}
/**
* Creates an instance of {@link ToStringHelper}.
*
* <p>This is helpful for implementing {@link Object#toString()}.
* Specification by example: <pre> {@code
* // Returns "ClassName{}"
* Objects.toStringHelper(this)
* .toString();
*
* // Returns "ClassName{x=1}"
* Objects.toStringHelper(this)
* .add("x", 1)
* .toString();
*
* // Returns "MyObject{x=1}"
* Objects.toStringHelper("MyObject")
* .add("x", 1)
* .toString();
*
* // Returns "ClassName{x=1, y=foo}"
* Objects.toStringHelper(this)
* .add("x", 1)
* .add("y", "foo")
* .toString();
*
* // Returns "ClassName{x=1}"
* Objects.toStringHelper(this)
* .omitNullValues()
* .add("x", 1)
* .add("y", null)
* .toString();
* }}</pre>
*
* <p>Note that in GWT, class names are often obfuscated.
*
* @param self the object to generate the string for (typically {@code this}),
* used only for its class name
* @since 2.0
* @deprecated Use {@link MoreObjects#toStringHelper(Object)} instead. This
* method is scheduled for removal in June 2016.
*/
@CheckReturnValue
@Deprecated
public static ToStringHelper toStringHelper(Object self) {
return new ToStringHelper(self.getClass().getSimpleName());
}
/**
* Creates an instance of {@link ToStringHelper} in the same manner as
* {@link Objects#toStringHelper(Object)}, but using the name of {@code clazz}
* instead of using an instance's {@link Object#getClass()}.
*
* <p>Note that in GWT, class names are often obfuscated.
*
* @param clazz the {@link Class} of the instance
* @since 7.0 (source-compatible since 2.0)
* @deprecated Use {@link MoreObjects#toStringHelper(Class)} instead. This
* method is scheduled for removal in June 2016.
*/
@CheckReturnValue
@Deprecated
public static ToStringHelper toStringHelper(Class<?> clazz) {
return new ToStringHelper(clazz.getSimpleName());
}
/**
* Creates an instance of {@link ToStringHelper} in the same manner as
* {@link Objects#toStringHelper(Object)}, but using {@code className} instead
* of using an instance's {@link Object#getClass()}.
*
* @param className the name of the instance type
* @since 7.0 (source-compatible since 2.0)
* @deprecated Use {@link MoreObjects#toStringHelper(String)} instead. This
* method is scheduled for removal in June 2016.
*/
@CheckReturnValue
@Deprecated
public static ToStringHelper toStringHelper(String className) {
return new ToStringHelper(className);
}
/**
* Returns the first of two given parameters that is not {@code null}, if
* either is, or otherwise throws a {@link NullPointerException}.
*
* <p><b>Note:</b> if {@code first} is represented as an {@link Optional},
* this can be accomplished with
* {@linkplain Optional#or(Object) first.or(second)}.
* That approach also allows for lazy evaluation of the fallback instance,
* using {@linkplain Optional#or(Supplier) first.or(Supplier)}.
*
* @return {@code first} if {@code first} is not {@code null}, or
* {@code second} if {@code first} is {@code null} and {@code second} is
* not {@code null}
* @throws NullPointerException if both {@code first} and {@code second} were
* {@code null}
* @since 3.0
* @deprecated Use {@link MoreObjects#firstNonNull} instead. This method is
* scheduled for removal in June 2016.
*/
@CheckReturnValue
@Deprecated
public static <T> T firstNonNull(@Nullable T first, @Nullable T second) {
return MoreObjects.firstNonNull(first, second);
}
/**
* Support class for {@link Objects#toStringHelper}.
*
* @author Jason Lee
* @since 2.0
* @deprecated Use {@link MoreObjects.ToStringHelper} instead. This class is
* scheduled for removal in June 2016.
*/
@Deprecated
public static final class ToStringHelper {
private final String className;
private ValueHolder holderHead = new ValueHolder();
private ValueHolder holderTail = holderHead;
private boolean omitNullValues = false;
/**
* Use {@link Objects#toStringHelper(Object)} to create an instance.
*/
private ToStringHelper(String className) {
this.className = checkNotNull(className);
}
/**
* Configures the {@link ToStringHelper} so {@link #toString()} will ignore
* properties with null value. The order of calling this method, relative
* to the {@code add()}/{@code addValue()} methods, is not significant.
*
* @since 12.0
*/
public ToStringHelper omitNullValues() {
omitNullValues = true;
return this;
}
/**
* Adds a name/value pair to the formatted output in {@code name=value}
* format. If {@code value} is {@code null}, the string {@code "null"}
* is used, unless {@link #omitNullValues()} is called, in which case this
* name/value pair will not be added.
*/
public ToStringHelper add(String name, @Nullable Object value) {
return addHolder(name, value);
}
/**
* Adds a name/value pair to the formatted output in {@code name=value}
* format.
*
* @since 11.0 (source-compatible since 2.0)
*/
public ToStringHelper add(String name, boolean value) {
return addHolder(name, String.valueOf(value));
}
/**
* Adds a name/value pair to the formatted output in {@code name=value}
* format.
*
* @since 11.0 (source-compatible since 2.0)
*/
public ToStringHelper add(String name, char value) {
return addHolder(name, String.valueOf(value));
}
/**
* Adds a name/value pair to the formatted output in {@code name=value}
* format.
*
* @since 11.0 (source-compatible since 2.0)
*/
public ToStringHelper add(String name, double value) {
return addHolder(name, String.valueOf(value));
}
/**
* Adds a name/value pair to the formatted output in {@code name=value}
* format.
*
* @since 11.0 (source-compatible since 2.0)
*/
public ToStringHelper add(String name, float value) {
return addHolder(name, String.valueOf(value));
}
/**
* Adds a name/value pair to the formatted output in {@code name=value}
* format.
*
* @since 11.0 (source-compatible since 2.0)
*/
public ToStringHelper add(String name, int value) {
return addHolder(name, String.valueOf(value));
}
/**
* Adds a name/value pair to the formatted output in {@code name=value}
* format.
*
* @since 11.0 (source-compatible since 2.0)
*/
public ToStringHelper add(String name, long value) {
return addHolder(name, String.valueOf(value));
}
/**
* Adds an unnamed value to the formatted output.
*
* <p>It is strongly encouraged to use {@link #add(String, Object)} instead
* and give value a readable name.
*/
public ToStringHelper addValue(@Nullable Object value) {
return addHolder(value);
}
/**
* Adds an unnamed value to the formatted output.
*
* <p>It is strongly encouraged to use {@link #add(String, boolean)} instead
* and give value a readable name.
*
* @since 11.0 (source-compatible since 2.0)
*/
public ToStringHelper addValue(boolean value) {
return addHolder(String.valueOf(value));
}
/**
* Adds an unnamed value to the formatted output.
*
* <p>It is strongly encouraged to use {@link #add(String, char)} instead
* and give value a readable name.
*
* @since 11.0 (source-compatible since 2.0)
*/
public ToStringHelper addValue(char value) {
return addHolder(String.valueOf(value));
}
/**
* Adds an unnamed value to the formatted output.
*
* <p>It is strongly encouraged to use {@link #add(String, double)} instead
* and give value a readable name.
*
* @since 11.0 (source-compatible since 2.0)
*/
public ToStringHelper addValue(double value) {
return addHolder(String.valueOf(value));
}
/**
* Adds an unnamed value to the formatted output.
*
* <p>It is strongly encouraged to use {@link #add(String, float)} instead
* and give value a readable name.
*
* @since 11.0 (source-compatible since 2.0)
*/
public ToStringHelper addValue(float value) {
return addHolder(String.valueOf(value));
}
/**
* Adds an unnamed value to the formatted output.
*
* <p>It is strongly encouraged to use {@link #add(String, int)} instead
* and give value a readable name.
*
* @since 11.0 (source-compatible since 2.0)
*/
public ToStringHelper addValue(int value) {
return addHolder(String.valueOf(value));
}
/**
* Adds an unnamed value to the formatted output.
*
* <p>It is strongly encouraged to use {@link #add(String, long)} instead
* and give value a readable name.
*
* @since 11.0 (source-compatible since 2.0)
*/
public ToStringHelper addValue(long value) {
return addHolder(String.valueOf(value));
}
/**
* Returns a string in the format specified by {@link
* Objects#toStringHelper(Object)}.
*
* <p>After calling this method, you can keep adding more properties to later
* call toString() again and get a more complete representation of the
* same object; but properties cannot be removed, so this only allows
* limited reuse of the helper instance. The helper allows duplication of
* properties (multiple name/value pairs with the same name can be added).
*/
@Override
public String toString() {
// create a copy to keep it consistent in case value changes
boolean omitNullValuesSnapshot = omitNullValues;
String nextSeparator = "";
StringBuilder builder = new StringBuilder(32).append(className).append('{');
for (ValueHolder valueHolder = holderHead.next;
valueHolder != null;
valueHolder = valueHolder.next) {
if (!omitNullValuesSnapshot || valueHolder.value != null) {
builder.append(nextSeparator);
nextSeparator = ", ";
if (valueHolder.name != null) {
builder.append(valueHolder.name).append('=');
}
builder.append(valueHolder.value);
}
}
return builder.append('}').toString();
}
private ValueHolder addHolder() {
ValueHolder valueHolder = new ValueHolder();
holderTail = holderTail.next = valueHolder;
return valueHolder;
}
private ToStringHelper addHolder(@Nullable Object value) {
ValueHolder valueHolder = addHolder();
valueHolder.value = value;
return this;
}
private ToStringHelper addHolder(String name, @Nullable Object value) {
ValueHolder valueHolder = addHolder();
valueHolder.value = value;
valueHolder.name = checkNotNull(name);
return this;
}
private static final class ValueHolder {
String name;
Object value;
ValueHolder next;
}
}
}
@@ -1,320 +0,0 @@
/*
* Copyright (C) 2011 The Guava Authors
*
* 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 com.google.common.base;
import static com.google.common.base.Preconditions.checkNotNull;
import com.google.common.annotations.Beta;
import com.google.common.annotations.GwtCompatible;
import java.io.Serializable;
import java.util.Iterator;
import java.util.Set;
import javax.annotation.CheckReturnValue;
import javax.annotation.Nullable;
/**
* An immutable object that may contain a non-null reference to another object. Each
* instance of this type either contains a non-null reference, or contains nothing (in
* which case we say that the reference is "absent"); it is never said to "contain {@code
* null}".
*
* <p>A non-null {@code Optional<T>} reference can be used as a replacement for a nullable
* {@code T} reference. It allows you to represent "a {@code T} that must be present" and
* a "a {@code T} that might be absent" as two distinct types in your program, which can
* aid clarity.
*
* <p>Some uses of this class include
*
* <ul>
* <li>As a method return type, as an alternative to returning {@code null} to indicate
* that no value was available
* <li>To distinguish between "unknown" (for example, not present in a map) and "known to
* have no value" (present in the map, with value {@code Optional.absent()})
* <li>To wrap nullable references for storage in a collection that does not support
* {@code null} (though there are
* <a href="https://github.com/google/guava/wiki/LivingWithNullHostileCollections">
* several other approaches to this</a> that should be considered first)
* </ul>
*
* <p>A common alternative to using this class is to find or create a suitable
* <a href="http://en.wikipedia.org/wiki/Null_Object_pattern">null object</a> for the
* type in question.
*
* <p>This class is not intended as a direct analogue of any existing "option" or "maybe"
* construct from other programming environments, though it may bear some similarities.
*
* <p><b>Comparison to {@code java.util.Optional} (JDK 8 and higher):</b> A new {@code Optional}
* class was added for Java 8. The two classes are extremely similar, but incompatible (they cannot
* share a common supertype). <i>All</i> known differences are listed either here or with the
* relevant methods below.
*
* <ul>
* <li>This class is serializable; {@code java.util.Optional} is not.
* <li>{@code java.util.Optional} has the additional methods {@code ifPresent}, {@code filter},
* {@code flatMap}, and {@code orElseThrow}.
* <li>{@code java.util} offers the primitive-specialized versions {@code OptionalInt}, {@code
* OptionalLong} and {@code OptionalDouble}, the use of which is recommended; Guava does not
* have these.
* </ul>
*
* <p><b>There are no plans to deprecate this class in the foreseeable future.</b> However, we do
* gently recommend that you prefer the new, standard Java class whenever possible.
*
* <p>See the Guava User Guide article on <a
* href="https://github.com/google/guava/wiki/UsingAndAvoidingNullExplained#optional">
* using {@code Optional}</a>.
*
* @param <T> the type of instance that can be contained. {@code Optional} is naturally
* covariant on this type, so it is safe to cast an {@code Optional<T>} to {@code
* Optional<S>} for any supertype {@code S} of {@code T}.
* @author Kurt Alfred Kluever
* @author Kevin Bourrillion
* @since 10.0
*/
@CheckReturnValue
@GwtCompatible(serializable = true)
public abstract class Optional<T> implements Serializable {
/**
* Returns an {@code Optional} instance with no contained reference.
*
* <p><b>Comparison to {@code java.util.Optional}:</b> this method is equivalent to Java 8's
* {@code Optional.empty}.
*/
public static <T> Optional<T> absent() {
return Absent.withType();
}
/**
* Returns an {@code Optional} instance containing the given non-null reference. To have {@code
* null} treated as {@link #absent}, use {@link #fromNullable} instead.
*
* <p><b>Comparison to {@code java.util.Optional}:</b> no differences.
*
* @throws NullPointerException if {@code reference} is null
*/
public static <T> Optional<T> of(T reference) {
return new Present<T>(checkNotNull(reference));
}
/**
* If {@code nullableReference} is non-null, returns an {@code Optional} instance containing that
* reference; otherwise returns {@link Optional#absent}.
*
* <p><b>Comparison to {@code java.util.Optional}:</b> this method is equivalent to Java 8's
* {@code Optional.ofNullable}.
*/
public static <T> Optional<T> fromNullable(@Nullable T nullableReference) {
return (nullableReference == null)
? Optional.<T>absent()
: new Present<T>(nullableReference);
}
Optional() {}
/**
* Returns {@code true} if this holder contains a (non-null) instance.
*
* <p><b>Comparison to {@code java.util.Optional}:</b> no differences.
*/
public abstract boolean isPresent();
/**
* Returns the contained instance, which must be present. If the instance might be
* absent, use {@link #or(Object)} or {@link #orNull} instead.
*
* <p><b>Comparison to {@code java.util.Optional}:</b> when the value is absent, this method
* throws {@link IllegalStateException}, whereas the Java 8 counterpart throws {@link
* NoSuchElementException}.
*
* @throws IllegalStateException if the instance is absent ({@link #isPresent} returns
* {@code false}); depending on this <i>specific</i> exception type (over the more general
* {@link RuntimeException}) is discouraged
*/
public abstract T get();
/**
* Returns the contained instance if it is present; {@code defaultValue} otherwise. If
* no default value should be required because the instance is known to be present, use
* {@link #get()} instead. For a default value of {@code null}, use {@link #orNull}.
*
* <p>Note about generics: The signature {@code public T or(T defaultValue)} is overly
* restrictive. However, the ideal signature, {@code public <S super T> S or(S)}, is not legal
* Java. As a result, some sensible operations involving subtypes are compile errors:
* <pre> {@code
*
* Optional<Integer> optionalInt = getSomeOptionalInt();
* Number value = optionalInt.or(0.5); // error
*
* FluentIterable<? extends Number> numbers = getSomeNumbers();
* Optional<? extends Number> first = numbers.first();
* Number value = first.or(0.5); // error}</pre>
*
* <p>As a workaround, it is always safe to cast an {@code Optional<? extends T>} to {@code
* Optional<T>}. Casting either of the above example {@code Optional} instances to {@code
* Optional<Number>} (where {@code Number} is the desired output type) solves the problem:
* <pre> {@code
*
* Optional<Number> optionalInt = (Optional) getSomeOptionalInt();
* Number value = optionalInt.or(0.5); // fine
*
* FluentIterable<? extends Number> numbers = getSomeNumbers();
* Optional<Number> first = (Optional) numbers.first();
* Number value = first.or(0.5); // fine}</pre>
*
* <p><b>Comparison to {@code java.util.Optional}:</b> this method is similar to Java 8's
* {@code Optional.orElse}, but will not accept {@code null} as a {@code defaultValue} ({@link
* #orNull} must be used instead). As a result, the value returned by this method is guaranteed
* non-null, which is not the case for the {@code java.util} equivalent.
*/
public abstract T or(T defaultValue);
/**
* Returns this {@code Optional} if it has a value present; {@code secondChoice}
* otherwise.
*
* <p><b>Comparison to {@code java.util.Optional}:</b> this method has no equivalent in Java 8's
* {@code Optional} class; write {@code thisOptional.isPresent() ? thisOptional : secondChoice}
* instead.
*/
public abstract Optional<T> or(Optional<? extends T> secondChoice);
/**
* Returns the contained instance if it is present; {@code supplier.get()} otherwise.
*
* <p><b>Comparison to {@code java.util.Optional}:</b> this method is similar to Java 8's
* {@code Optional.orElseGet}, except when {@code supplier} returns {@code null}. In this case
* this method throws an exception, whereas the Java 8 method returns the {@code null} to the
* caller.
*
* @throws NullPointerException if this optional's value is absent and the supplier returns
* {@code null}
*/
@Beta
public abstract T or(Supplier<? extends T> supplier);
/**
* Returns the contained instance if it is present; {@code null} otherwise. If the
* instance is known to be present, use {@link #get()} instead.
*
* <p><b>Comparison to {@code java.util.Optional}:</b> this method is equivalent to Java 8's
* {@code Optional.orElse(null)}.
*/
@Nullable
public abstract T orNull();
/**
* Returns an immutable singleton {@link Set} whose only element is the contained instance
* if it is present; an empty immutable {@link Set} otherwise.
*
* <p><b>Comparison to {@code java.util.Optional}:</b> this method has no equivalent in Java 8's
* {@code Optional} class. However, this common usage: <pre> {@code
*
* for (Foo foo : possibleFoo.asSet()) {
* doSomethingWith(foo);
* }}</pre>
*
* ... can be replaced with: <pre> {@code
*
* possibleFoo.ifPresent(foo -> doSomethingWith(foo));}</pre>
*
* @since 11.0
*/
public abstract Set<T> asSet();
/**
* If the instance is present, it is transformed with the given {@link Function}; otherwise,
* {@link Optional#absent} is returned.
*
* <p><b>Comparison to {@code java.util.Optional}:</b> this method is similar to Java 8's
* {@code Optional.map}, except when {@code function} returns {@code null}. In this case this
* method throws an exception, whereas the Java 8 method returns {@code Optional.absent()}.
*
* @throws NullPointerException if the function returns {@code null}
* @since 12.0
*/
public abstract <V> Optional<V> transform(Function<? super T, V> function);
/**
* Returns {@code true} if {@code object} is an {@code Optional} instance, and either
* the contained references are {@linkplain Object#equals equal} to each other or both
* are absent. Note that {@code Optional} instances of differing parameterized types can
* be equal.
*
* <p><b>Comparison to {@code java.util.Optional}:</b> no differences.
*/
@Override
public abstract boolean equals(@Nullable Object object);
/**
* Returns a hash code for this instance.
*
* <p><b>Comparison to {@code java.util.Optional}:</b> this class leaves the specific choice of
* hash code unspecified, unlike the Java 8 equivalent.
*/
@Override
public abstract int hashCode();
/**
* Returns a string representation for this instance.
*
* <p><b>Comparison to {@code java.util.Optional}:</b> this class leaves the specific string
* representation unspecified, unlike the Java 8 equivalent.
*/
@Override
public abstract String toString();
/**
* Returns the value of each present instance from the supplied {@code optionals}, in order,
* skipping over occurrences of {@link Optional#absent}. Iterators are unmodifiable and are
* evaluated lazily.
*
* <p><b>Comparison to {@code java.util.Optional}:</b> this method has no equivalent in Java 8's
* {@code Optional} class; use
* {@code optionals.stream().filter(Optional::isPresent).map(Optional::get)} instead.
*
* @since 11.0 (generics widened in 13.0)
*/
@Beta
public static <T> Iterable<T> presentInstances(
final Iterable<? extends Optional<? extends T>> optionals) {
checkNotNull(optionals);
return new Iterable<T>() {
@Override
public Iterator<T> iterator() {
return new AbstractIterator<T>() {
private final Iterator<? extends Optional<? extends T>> iterator =
checkNotNull(optionals.iterator());
@Override
protected T computeNext() {
while (iterator.hasNext()) {
Optional<? extends T> optional = iterator.next();
if (optional.isPresent()) {
return optional.get();
}
}
return endOfData();
}
};
}
};
}
private static final long serialVersionUID = 0;
}
@@ -1,79 +0,0 @@
/*
* Copyright (C) 2011 The Guava Authors
*
* 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 com.google.common.base;
import com.google.common.annotations.GwtCompatible;
import java.io.Serializable;
import java.util.Iterator;
import javax.annotation.Nullable;
@GwtCompatible(serializable = true)
final class PairwiseEquivalence<T> extends Equivalence<Iterable<T>> implements Serializable {
final Equivalence<? super T> elementEquivalence;
PairwiseEquivalence(Equivalence<? super T> elementEquivalence) {
this.elementEquivalence = Preconditions.checkNotNull(elementEquivalence);
}
@Override
protected boolean doEquivalent(Iterable<T> iterableA, Iterable<T> iterableB) {
Iterator<T> iteratorA = iterableA.iterator();
Iterator<T> iteratorB = iterableB.iterator();
while (iteratorA.hasNext() && iteratorB.hasNext()) {
if (!elementEquivalence.equivalent(iteratorA.next(), iteratorB.next())) {
return false;
}
}
return !iteratorA.hasNext() && !iteratorB.hasNext();
}
@Override
protected int doHash(Iterable<T> iterable) {
int hash = 78721;
for (T element : iterable) {
hash = hash * 24943 + elementEquivalence.hash(element);
}
return hash;
}
@Override
public boolean equals(@Nullable Object object) {
if (object instanceof PairwiseEquivalence) {
PairwiseEquivalence<?> that = (PairwiseEquivalence<?>) object;
return this.elementEquivalence.equals(that.elementEquivalence);
}
return false;
}
@Override
public int hashCode() {
return elementEquivalence.hashCode() ^ 0x46a3eb07;
}
@Override
public String toString() {
return elementEquivalence + ".pairwise()";
}
private static final long serialVersionUID = 1;
}
@@ -1,47 +0,0 @@
/*
* Copyright (C) 2009 The Guava Authors
*
* 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 com.google.common.base;
import com.google.common.annotations.GwtCompatible;
import java.lang.ref.WeakReference;
/**
* Methods factored out so that they can be emulated differently in GWT.
*
* @author Jesse Wilson
*/
@GwtCompatible(emulated = true)
final class Platform {
private Platform() {}
/** Calls {@link System#nanoTime()}. */
static long systemNanoTime() {
return System.nanoTime();
}
static CharMatcher precomputeCharMatcher(CharMatcher matcher) {
return matcher.precomputedInternal();
}
static <T extends Enum<T>> Optional<T> getEnumIfPresent(Class<T> enumClass, String value) {
WeakReference<? extends Enum<?>> ref = Enums.getEnumConstants(enumClass).get(value);
return ref == null
? Optional.<T>absent()
: Optional.of(enumClass.cast(ref.get()));
}
}
@@ -1,440 +0,0 @@
/*
* Copyright (C) 2007 The Guava Authors
*
* 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 com.google.common.base;
import com.google.common.annotations.GwtCompatible;
import javax.annotation.Nullable;
/**
* Static convenience methods that help a method or constructor check whether it was invoked
* correctly (whether its <i>preconditions</i> have been met). These methods generally accept a
* {@code boolean} expression which is expected to be {@code true} (or in the case of {@code
* checkNotNull}, an object reference which is expected to be non-null). When {@code false} (or
* {@code null}) is passed instead, the {@code Preconditions} method throws an unchecked exception,
* which helps the calling method communicate to <i>its</i> caller that <i>that</i> caller has made
* a mistake. Example: <pre> {@code
*
* /**
* * Returns the positive square root of the given value.
* *
* * @throws IllegalArgumentException if the value is negative
* *}{@code /
* public static double sqrt(double value) {
* Preconditions.checkArgument(value >= 0.0, "negative value: %s", value);
* // calculate the square root
* }
*
* void exampleBadCaller() {
* double d = sqrt(-1.0);
* }}</pre>
*
* In this example, {@code checkArgument} throws an {@code IllegalArgumentException} to indicate
* that {@code exampleBadCaller} made an error in <i>its</i> call to {@code sqrt}.
*
* <h3>Warning about performance</h3>
*
* <p>The goal of this class is to improve readability of code, but in some circumstances this may
* come at a significant performance cost. Remember that parameter values for message construction
* must all be computed eagerly, and autoboxing and varargs array creation may happen as well, even
* when the precondition check then succeeds (as it should almost always do in production). In some
* circumstances these wasted CPU cycles and allocations can add up to a real problem.
* Performance-sensitive precondition checks can always be converted to the customary form:
* <pre> {@code
*
* if (value < 0.0) {
* throw new IllegalArgumentException("negative value: " + value);
* }}</pre>
*
* <h3>Other types of preconditions</h3>
*
* <p>Not every type of precondition failure is supported by these methods. Continue to throw
* standard JDK exceptions such as {@link java.util.NoSuchElementException} or {@link
* UnsupportedOperationException} in the situations they are intended for.
*
* <h3>Non-preconditions</h3>
*
* <p>It is of course possible to use the methods of this class to check for invalid conditions
* which are <i>not the caller's fault</i>. Doing so is <b>not recommended</b> because it is
* misleading to future readers of the code and of stack traces. See
* <a href="https://github.com/google/guava/wiki/ConditionalFailuresExplained">Conditional
* failures explained</a> in the Guava User Guide for more advice.
*
* <h3>{@code java.util.Objects.requireNonNull()}</h3>
*
* <p>Projects which use {@code com.google.common} should generally avoid the use of {@link
* java.util.Objects#requireNonNull(Object)}. Instead, use whichever of {@link
* #checkNotNull(Object)} or {@link Verify#verifyNotNull(Object)} is appropriate to the situation.
* (The same goes for the message-accepting overloads.)
*
* <h3>Only {@code %s} is supported</h3>
*
* <p>In {@code Preconditions} error message template strings, only the {@code "%s"} specifier is
* supported, not the full range of {@link java.util.Formatter} specifiers.
*
* <h3>More information</h3>
*
* <p>See the Guava User Guide on
* <a href="https://github.com/google/guava/wiki/PreconditionsExplained">using {@code
* Preconditions}</a>.
*
* @author Kevin Bourrillion
* @since 2.0
*/
@GwtCompatible
public final class Preconditions {
private Preconditions() {}
/**
* Ensures the truth of an expression involving one or more parameters to the calling method.
*
* @param expression a boolean expression
* @throws IllegalArgumentException if {@code expression} is false
*/
public static void checkArgument(boolean expression) {
if (!expression) {
throw new IllegalArgumentException();
}
}
/**
* Ensures the truth of an expression involving one or more parameters to the calling method.
*
* @param expression a boolean expression
* @param errorMessage the exception message to use if the check fails; will be converted to a
* string using {@link String#valueOf(Object)}
* @throws IllegalArgumentException if {@code expression} is false
*/
public static void checkArgument(boolean expression, @Nullable Object errorMessage) {
if (!expression) {
throw new IllegalArgumentException(String.valueOf(errorMessage));
}
}
/**
* Ensures the truth of an expression involving one or more parameters to the calling method.
*
* @param expression a boolean expression
* @param errorMessageTemplate a template for the exception message should the check fail. The
* message is formed by replacing each {@code %s} placeholder in the template with an
* argument. These are matched by position - the first {@code %s} gets {@code
* errorMessageArgs[0]}, etc. Unmatched arguments will be appended to the formatted message
* in square braces. Unmatched placeholders will be left as-is.
* @param errorMessageArgs the arguments to be substituted into the message template. Arguments
* are converted to strings using {@link String#valueOf(Object)}.
* @throws IllegalArgumentException if {@code expression} is false
* @throws NullPointerException if the check fails and either {@code errorMessageTemplate} or
* {@code errorMessageArgs} is null (don't let this happen)
*/
public static void checkArgument(
boolean expression,
@Nullable String errorMessageTemplate,
@Nullable Object... errorMessageArgs) {
if (!expression) {
throw new IllegalArgumentException(format(errorMessageTemplate, errorMessageArgs));
}
}
/**
* Ensures the truth of an expression involving the state of the calling instance, but not
* involving any parameters to the calling method.
*
* @param expression a boolean expression
* @throws IllegalStateException if {@code expression} is false
*/
public static void checkState(boolean expression) {
if (!expression) {
throw new IllegalStateException();
}
}
/**
* Ensures the truth of an expression involving the state of the calling instance, but not
* involving any parameters to the calling method.
*
* @param expression a boolean expression
* @param errorMessage the exception message to use if the check fails; will be converted to a
* string using {@link String#valueOf(Object)}
* @throws IllegalStateException if {@code expression} is false
*/
public static void checkState(boolean expression, @Nullable Object errorMessage) {
if (!expression) {
throw new IllegalStateException(String.valueOf(errorMessage));
}
}
/**
* Ensures the truth of an expression involving the state of the calling instance, but not
* involving any parameters to the calling method.
*
* @param expression a boolean expression
* @param errorMessageTemplate a template for the exception message should the check fail. The
* message is formed by replacing each {@code %s} placeholder in the template with an
* argument. These are matched by position - the first {@code %s} gets {@code
* errorMessageArgs[0]}, etc. Unmatched arguments will be appended to the formatted message
* in square braces. Unmatched placeholders will be left as-is.
* @param errorMessageArgs the arguments to be substituted into the message template. Arguments
* are converted to strings using {@link String#valueOf(Object)}.
* @throws IllegalStateException if {@code expression} is false
* @throws NullPointerException if the check fails and either {@code errorMessageTemplate} or
* {@code errorMessageArgs} is null (don't let this happen)
*/
public static void checkState(
boolean expression,
@Nullable String errorMessageTemplate,
@Nullable Object... errorMessageArgs) {
if (!expression) {
throw new IllegalStateException(format(errorMessageTemplate, errorMessageArgs));
}
}
/**
* Ensures that an object reference passed as a parameter to the calling method is not null.
*
* @param reference an object reference
* @return the non-null reference that was validated
* @throws NullPointerException if {@code reference} is null
*/
public static <T> T checkNotNull(T reference) {
if (reference == null) {
throw new NullPointerException();
}
return reference;
}
/**
* Ensures that an object reference passed as a parameter to the calling method is not null.
*
* @param reference an object reference
* @param errorMessage the exception message to use if the check fails; will be converted to a
* string using {@link String#valueOf(Object)}
* @return the non-null reference that was validated
* @throws NullPointerException if {@code reference} is null
*/
public static <T> T checkNotNull(T reference, @Nullable Object errorMessage) {
if (reference == null) {
throw new NullPointerException(String.valueOf(errorMessage));
}
return reference;
}
/**
* Ensures that an object reference passed as a parameter to the calling method is not null.
*
* @param reference an object reference
* @param errorMessageTemplate a template for the exception message should the check fail. The
* message is formed by replacing each {@code %s} placeholder in the template with an
* argument. These are matched by position - the first {@code %s} gets {@code
* errorMessageArgs[0]}, etc. Unmatched arguments will be appended to the formatted message
* in square braces. Unmatched placeholders will be left as-is.
* @param errorMessageArgs the arguments to be substituted into the message template. Arguments
* are converted to strings using {@link String#valueOf(Object)}.
* @return the non-null reference that was validated
* @throws NullPointerException if {@code reference} is null
*/
public static <T> T checkNotNull(
T reference, @Nullable String errorMessageTemplate, @Nullable Object... errorMessageArgs) {
if (reference == null) {
// If either of these parameters is null, the right thing happens anyway
throw new NullPointerException(format(errorMessageTemplate, errorMessageArgs));
}
return reference;
}
/*
* All recent hotspots (as of 2009) *really* like to have the natural code
*
* if (guardExpression) {
* throw new BadException(messageExpression);
* }
*
* refactored so that messageExpression is moved to a separate String-returning method.
*
* if (guardExpression) {
* throw new BadException(badMsg(...));
* }
*
* The alternative natural refactorings into void or Exception-returning methods are much slower.
* This is a big deal - we're talking factors of 2-8 in microbenchmarks, not just 10-20%. (This
* is a hotspot optimizer bug, which should be fixed, but that's a separate, big project).
*
* The coding pattern above is heavily used in java.util, e.g. in ArrayList. There is a
* RangeCheckMicroBenchmark in the JDK that was used to test this.
*
* But the methods in this class want to throw different exceptions, depending on the args, so it
* appears that this pattern is not directly applicable. But we can use the ridiculous, devious
* trick of throwing an exception in the middle of the construction of another exception. Hotspot
* is fine with that.
*/
/**
* Ensures that {@code index} specifies a valid <i>element</i> in an array, list or string of size
* {@code size}. An element index may range from zero, inclusive, to {@code size}, exclusive.
*
* @param index a user-supplied index identifying an element of an array, list or string
* @param size the size of that array, list or string
* @return the value of {@code index}
* @throws IndexOutOfBoundsException if {@code index} is negative or is not less than {@code size}
* @throws IllegalArgumentException if {@code size} is negative
*/
public static int checkElementIndex(int index, int size) {
return checkElementIndex(index, size, "index");
}
/**
* Ensures that {@code index} specifies a valid <i>element</i> in an array, list or string of size
* {@code size}. An element index may range from zero, inclusive, to {@code size}, exclusive.
*
* @param index a user-supplied index identifying an element of an array, list or string
* @param size the size of that array, list or string
* @param desc the text to use to describe this index in an error message
* @return the value of {@code index}
* @throws IndexOutOfBoundsException if {@code index} is negative or is not less than {@code size}
* @throws IllegalArgumentException if {@code size} is negative
*/
public static int checkElementIndex(int index, int size, @Nullable String desc) {
// Carefully optimized for execution by hotspot (explanatory comment above)
if (index < 0 || index >= size) {
throw new IndexOutOfBoundsException(badElementIndex(index, size, desc));
}
return index;
}
private static String badElementIndex(int index, int size, String desc) {
if (index < 0) {
return format("%s (%s) must not be negative", desc, index);
} else if (size < 0) {
throw new IllegalArgumentException("negative size: " + size);
} else { // index >= size
return format("%s (%s) must be less than size (%s)", desc, index, size);
}
}
/**
* Ensures that {@code index} specifies a valid <i>position</i> in an array, list or string of
* size {@code size}. A position index may range from zero to {@code size}, inclusive.
*
* @param index a user-supplied index identifying a position in an array, list or string
* @param size the size of that array, list or string
* @return the value of {@code index}
* @throws IndexOutOfBoundsException if {@code index} is negative or is greater than {@code size}
* @throws IllegalArgumentException if {@code size} is negative
*/
public static int checkPositionIndex(int index, int size) {
return checkPositionIndex(index, size, "index");
}
/**
* Ensures that {@code index} specifies a valid <i>position</i> in an array, list or string of
* size {@code size}. A position index may range from zero to {@code size}, inclusive.
*
* @param index a user-supplied index identifying a position in an array, list or string
* @param size the size of that array, list or string
* @param desc the text to use to describe this index in an error message
* @return the value of {@code index}
* @throws IndexOutOfBoundsException if {@code index} is negative or is greater than {@code size}
* @throws IllegalArgumentException if {@code size} is negative
*/
public static int checkPositionIndex(int index, int size, @Nullable String desc) {
// Carefully optimized for execution by hotspot (explanatory comment above)
if (index < 0 || index > size) {
throw new IndexOutOfBoundsException(badPositionIndex(index, size, desc));
}
return index;
}
private static String badPositionIndex(int index, int size, String desc) {
if (index < 0) {
return format("%s (%s) must not be negative", desc, index);
} else if (size < 0) {
throw new IllegalArgumentException("negative size: " + size);
} else { // index > size
return format("%s (%s) must not be greater than size (%s)", desc, index, size);
}
}
/**
* Ensures that {@code start} and {@code end} specify a valid <i>positions</i> in an array, list
* or string of size {@code size}, and are in order. A position index may range from zero to
* {@code size}, inclusive.
*
* @param start a user-supplied index identifying a starting position in an array, list or string
* @param end a user-supplied index identifying a ending position in an array, list or string
* @param size the size of that array, list or string
* @throws IndexOutOfBoundsException if either index is negative or is greater than {@code size},
* or if {@code end} is less than {@code start}
* @throws IllegalArgumentException if {@code size} is negative
*/
public static void checkPositionIndexes(int start, int end, int size) {
// Carefully optimized for execution by hotspot (explanatory comment above)
if (start < 0 || end < start || end > size) {
throw new IndexOutOfBoundsException(badPositionIndexes(start, end, size));
}
}
private static String badPositionIndexes(int start, int end, int size) {
if (start < 0 || start > size) {
return badPositionIndex(start, size, "start index");
}
if (end < 0 || end > size) {
return badPositionIndex(end, size, "end index");
}
// end < start
return format("end index (%s) must not be less than start index (%s)", end, start);
}
/**
* Substitutes each {@code %s} in {@code template} with an argument. These are matched by
* position: the first {@code %s} gets {@code args[0]}, etc. If there are more arguments than
* placeholders, the unmatched arguments will be appended to the end of the formatted message in
* square braces.
*
* @param template a non-null string containing 0 or more {@code %s} placeholders.
* @param args the arguments to be substituted into the message template. Arguments are converted
* to strings using {@link String#valueOf(Object)}. Arguments can be null.
*/
// Note that this is somewhat-improperly used from Verify.java as well.
static String format(String template, @Nullable Object... args) {
template = String.valueOf(template); // null -> "null"
// start substituting the arguments into the '%s' placeholders
StringBuilder builder = new StringBuilder(template.length() + 16 * args.length);
int templateStart = 0;
int i = 0;
while (i < args.length) {
int placeholderStart = template.indexOf("%s", templateStart);
if (placeholderStart == -1) {
break;
}
builder.append(template.substring(templateStart, placeholderStart));
builder.append(args[i++]);
templateStart = placeholderStart + 2;
}
builder.append(template.substring(templateStart));
// if we run out of placeholders, append the extra args in square braces
if (i < args.length) {
builder.append(" [");
builder.append(args[i++]);
while (i < args.length) {
builder.append(", ");
builder.append(args[i++]);
}
builder.append(']');
}
return builder.toString();
}
}
@@ -1,65 +0,0 @@
/*
* Copyright (C) 2007 The Guava Authors
*
* 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 com.google.common.base;
import com.google.common.annotations.GwtCompatible;
import javax.annotation.Nullable;
/**
* Determines a true or false value for a given input.
*
* <p>The {@link Predicates} class provides common predicates and related utilities.
*
* <p>See the Guava User Guide article on <a href=
* "https://github.com/google/guava/wiki/FunctionalExplained">the use of {@code
* Predicate}</a>.
*
* @author Kevin Bourrillion
* @since 2.0
*/
@GwtCompatible
public interface Predicate<T> {
/**
* Returns the result of applying this predicate to {@code input}. This method is <i>generally
* expected</i>, but not absolutely required, to have the following properties:
*
* <ul>
* <li>Its execution does not cause any observable side effects.
* <li>The computation is <i>consistent with equals</i>; that is, {@link Objects#equal
* Objects.equal}{@code (a, b)} implies that {@code predicate.apply(a) ==
* predicate.apply(b))}.
* </ul>
*
* @throws NullPointerException if {@code input} is null and this predicate does not accept null
* arguments
*/
boolean apply(@Nullable T input);
/**
* Indicates whether another object is equal to this predicate.
*
* <p>Most implementations will have no reason to override the behavior of {@link Object#equals}.
* However, an implementation may also choose to return {@code true} whenever {@code object} is a
* {@link Predicate} that it considers <i>interchangeable</i> with this one. "Interchangeable"
* <i>typically</i> means that {@code this.apply(t) == that.apply(t)} for all {@code t} of type
* {@code T}). Note that a {@code false} result from this method does not imply that the
* predicates are known <i>not</i> to be interchangeable.
*/
@Override
boolean equals(@Nullable Object object);
}
@@ -1,712 +0,0 @@
/*
* Copyright (C) 2007 The Guava Authors
*
* 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 com.google.common.base;
import static com.google.common.base.Preconditions.checkNotNull;
import com.google.common.annotations.Beta;
import com.google.common.annotations.GwtCompatible;
import com.google.common.annotations.GwtIncompatible;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.regex.Pattern;
import javax.annotation.CheckReturnValue;
import javax.annotation.Nullable;
/**
* Static utility methods pertaining to {@code Predicate} instances.
*
* <p>All methods returns serializable predicates as long as they're given
* serializable parameters.
*
* <p>See the Guava User Guide article on <a href=
* "https://github.com/google/guava/wiki/FunctionalExplained">the
* use of {@code Predicate}</a>.
*
* @author Kevin Bourrillion
* @since 2.0
*/
@CheckReturnValue
@GwtCompatible(emulated = true)
public final class Predicates {
private Predicates() {}
// TODO(kevinb): considering having these implement a VisitablePredicate
// interface which specifies an accept(PredicateVisitor) method.
/**
* Returns a predicate that always evaluates to {@code true}.
*/
@GwtCompatible(serializable = true)
public static <T> Predicate<T> alwaysTrue() {
return ObjectPredicate.ALWAYS_TRUE.withNarrowedType();
}
/**
* Returns a predicate that always evaluates to {@code false}.
*/
@GwtCompatible(serializable = true)
public static <T> Predicate<T> alwaysFalse() {
return ObjectPredicate.ALWAYS_FALSE.withNarrowedType();
}
/**
* Returns a predicate that evaluates to {@code true} if the object reference
* being tested is null.
*/
@GwtCompatible(serializable = true)
public static <T> Predicate<T> isNull() {
return ObjectPredicate.IS_NULL.withNarrowedType();
}
/**
* Returns a predicate that evaluates to {@code true} if the object reference
* being tested is not null.
*/
@GwtCompatible(serializable = true)
public static <T> Predicate<T> notNull() {
return ObjectPredicate.NOT_NULL.withNarrowedType();
}
/**
* Returns a predicate that evaluates to {@code true} if the given predicate
* evaluates to {@code false}.
*/
public static <T> Predicate<T> not(Predicate<T> predicate) {
return new NotPredicate<T>(predicate);
}
/**
* Returns a predicate that evaluates to {@code true} if each of its
* components evaluates to {@code true}. The components are evaluated in
* order, and evaluation will be "short-circuited" as soon as a false
* predicate is found. It defensively copies the iterable passed in, so future
* changes to it won't alter the behavior of this predicate. If {@code
* components} is empty, the returned predicate will always evaluate to {@code
* true}.
*/
public static <T> Predicate<T> and(Iterable<? extends Predicate<? super T>> components) {
return new AndPredicate<T>(defensiveCopy(components));
}
/**
* Returns a predicate that evaluates to {@code true} if each of its
* components evaluates to {@code true}. The components are evaluated in
* order, and evaluation will be "short-circuited" as soon as a false
* predicate is found. It defensively copies the array passed in, so future
* changes to it won't alter the behavior of this predicate. If {@code
* components} is empty, the returned predicate will always evaluate to {@code
* true}.
*/
public static <T> Predicate<T> and(Predicate<? super T>... components) {
return new AndPredicate<T>(defensiveCopy(components));
}
/**
* Returns a predicate that evaluates to {@code true} if both of its
* components evaluate to {@code true}. The components are evaluated in
* order, and evaluation will be "short-circuited" as soon as a false
* predicate is found.
*/
public static <T> Predicate<T> and(Predicate<? super T> first, Predicate<? super T> second) {
return new AndPredicate<T>(Predicates.<T>asList(checkNotNull(first), checkNotNull(second)));
}
/**
* Returns a predicate that evaluates to {@code true} if any one of its
* components evaluates to {@code true}. The components are evaluated in
* order, and evaluation will be "short-circuited" as soon as a
* true predicate is found. It defensively copies the iterable passed in, so
* future changes to it won't alter the behavior of this predicate. If {@code
* components} is empty, the returned predicate will always evaluate to {@code
* false}.
*/
public static <T> Predicate<T> or(Iterable<? extends Predicate<? super T>> components) {
return new OrPredicate<T>(defensiveCopy(components));
}
/**
* Returns a predicate that evaluates to {@code true} if any one of its
* components evaluates to {@code true}. The components are evaluated in
* order, and evaluation will be "short-circuited" as soon as a
* true predicate is found. It defensively copies the array passed in, so
* future changes to it won't alter the behavior of this predicate. If {@code
* components} is empty, the returned predicate will always evaluate to {@code
* false}.
*/
public static <T> Predicate<T> or(Predicate<? super T>... components) {
return new OrPredicate<T>(defensiveCopy(components));
}
/**
* Returns a predicate that evaluates to {@code true} if either of its
* components evaluates to {@code true}. The components are evaluated in
* order, and evaluation will be "short-circuited" as soon as a
* true predicate is found.
*/
public static <T> Predicate<T> or(Predicate<? super T> first, Predicate<? super T> second) {
return new OrPredicate<T>(Predicates.<T>asList(checkNotNull(first), checkNotNull(second)));
}
/**
* Returns a predicate that evaluates to {@code true} if the object being
* tested {@code equals()} the given target or both are null.
*/
public static <T> Predicate<T> equalTo(@Nullable T target) {
return (target == null) ? Predicates.<T>isNull() : new IsEqualToPredicate<T>(target);
}
/**
* Returns a predicate that evaluates to {@code true} if the object being
* tested is an instance of the given class. If the object being tested
* is {@code null} this predicate evaluates to {@code false}.
*
* <p>If you want to filter an {@code Iterable} to narrow its type, consider
* using {@link com.google.common.collect.Iterables#filter(Iterable, Class)}
* in preference.
*
* <p><b>Warning:</b> contrary to the typical assumptions about predicates (as
* documented at {@link Predicate#apply}), the returned predicate may not be
* <i>consistent with equals</i>. For example, {@code
* instanceOf(ArrayList.class)} will yield different results for the two equal
* instances {@code Lists.newArrayList(1)} and {@code Arrays.asList(1)}.
*/
@GwtIncompatible("Class.isInstance")
public static Predicate<Object> instanceOf(Class<?> clazz) {
return new InstanceOfPredicate(clazz);
}
/**
* Returns a predicate that evaluates to {@code true} if the class being
* tested is assignable from the given class. The returned predicate
* does not allow null inputs.
*
* @since 10.0
*/
@GwtIncompatible("Class.isAssignableFrom")
@Beta
public static Predicate<Class<?>> assignableFrom(Class<?> clazz) {
return new AssignableFromPredicate(clazz);
}
/**
* Returns a predicate that evaluates to {@code true} if the object reference
* being tested is a member of the given collection. It does not defensively
* copy the collection passed in, so future changes to it will alter the
* behavior of the predicate.
*
* <p>This method can technically accept any {@code Collection<?>}, but using
* a typed collection helps prevent bugs. This approach doesn't block any
* potential users since it is always possible to use {@code
* Predicates.<Object>in()}.
*
* @param target the collection that may contain the function input
*/
public static <T> Predicate<T> in(Collection<? extends T> target) {
return new InPredicate<T>(target);
}
/**
* Returns the composition of a function and a predicate. For every {@code x},
* the generated predicate returns {@code predicate(function(x))}.
*
* @return the composition of the provided function and predicate
*/
public static <A, B> Predicate<A> compose(
Predicate<B> predicate, Function<A, ? extends B> function) {
return new CompositionPredicate<A, B>(predicate, function);
}
/**
* Returns a predicate that evaluates to {@code true} if the
* {@code CharSequence} being tested contains any match for the given
* regular expression pattern. The test used is equivalent to
* {@code Pattern.compile(pattern).matcher(arg).find()}
*
* @throws java.util.regex.PatternSyntaxException if the pattern is invalid
* @since 3.0
*/
@GwtIncompatible(value = "java.util.regex.Pattern")
public static Predicate<CharSequence> containsPattern(String pattern) {
return new ContainsPatternFromStringPredicate(pattern);
}
/**
* Returns a predicate that evaluates to {@code true} if the
* {@code CharSequence} being tested contains any match for the given
* regular expression pattern. The test used is equivalent to
* {@code pattern.matcher(arg).find()}
*
* @since 3.0
*/
@GwtIncompatible(value = "java.util.regex.Pattern")
public static Predicate<CharSequence> contains(Pattern pattern) {
return new ContainsPatternPredicate(pattern);
}
// End public API, begin private implementation classes.
// Package private for GWT serialization.
enum ObjectPredicate implements Predicate<Object> {
/** @see Predicates#alwaysTrue() */
ALWAYS_TRUE {
@Override
public boolean apply(@Nullable Object o) {
return true;
}
@Override
public String toString() {
return "Predicates.alwaysTrue()";
}
},
/** @see Predicates#alwaysFalse() */
ALWAYS_FALSE {
@Override
public boolean apply(@Nullable Object o) {
return false;
}
@Override
public String toString() {
return "Predicates.alwaysFalse()";
}
},
/** @see Predicates#isNull() */
IS_NULL {
@Override
public boolean apply(@Nullable Object o) {
return o == null;
}
@Override
public String toString() {
return "Predicates.isNull()";
}
},
/** @see Predicates#notNull() */
NOT_NULL {
@Override
public boolean apply(@Nullable Object o) {
return o != null;
}
@Override
public String toString() {
return "Predicates.notNull()";
}
};
@SuppressWarnings("unchecked") // safe contravariant cast
<T> Predicate<T> withNarrowedType() {
return (Predicate<T>) this;
}
}
/** @see Predicates#not(Predicate) */
private static class NotPredicate<T> implements Predicate<T>, Serializable {
final Predicate<T> predicate;
NotPredicate(Predicate<T> predicate) {
this.predicate = checkNotNull(predicate);
}
@Override
public boolean apply(@Nullable T t) {
return !predicate.apply(t);
}
@Override
public int hashCode() {
return ~predicate.hashCode();
}
@Override
public boolean equals(@Nullable Object obj) {
if (obj instanceof NotPredicate) {
NotPredicate<?> that = (NotPredicate<?>) obj;
return predicate.equals(that.predicate);
}
return false;
}
@Override
public String toString() {
return "Predicates.not(" + predicate + ")";
}
private static final long serialVersionUID = 0;
}
private static final Joiner COMMA_JOINER = Joiner.on(',');
/** @see Predicates#and(Iterable) */
private static class AndPredicate<T> implements Predicate<T>, Serializable {
private final List<? extends Predicate<? super T>> components;
private AndPredicate(List<? extends Predicate<? super T>> components) {
this.components = components;
}
@Override
public boolean apply(@Nullable T t) {
// Avoid using the Iterator to avoid generating garbage (issue 820).
for (int i = 0; i < components.size(); i++) {
if (!components.get(i).apply(t)) {
return false;
}
}
return true;
}
@Override
public int hashCode() {
// add a random number to avoid collisions with OrPredicate
return components.hashCode() + 0x12472c2c;
}
@Override
public boolean equals(@Nullable Object obj) {
if (obj instanceof AndPredicate) {
AndPredicate<?> that = (AndPredicate<?>) obj;
return components.equals(that.components);
}
return false;
}
@Override
public String toString() {
return "Predicates.and(" + COMMA_JOINER.join(components) + ")";
}
private static final long serialVersionUID = 0;
}
/** @see Predicates#or(Iterable) */
private static class OrPredicate<T> implements Predicate<T>, Serializable {
private final List<? extends Predicate<? super T>> components;
private OrPredicate(List<? extends Predicate<? super T>> components) {
this.components = components;
}
@Override
public boolean apply(@Nullable T t) {
// Avoid using the Iterator to avoid generating garbage (issue 820).
for (int i = 0; i < components.size(); i++) {
if (components.get(i).apply(t)) {
return true;
}
}
return false;
}
@Override
public int hashCode() {
// add a random number to avoid collisions with AndPredicate
return components.hashCode() + 0x053c91cf;
}
@Override
public boolean equals(@Nullable Object obj) {
if (obj instanceof OrPredicate) {
OrPredicate<?> that = (OrPredicate<?>) obj;
return components.equals(that.components);
}
return false;
}
@Override
public String toString() {
return "Predicates.or(" + COMMA_JOINER.join(components) + ")";
}
private static final long serialVersionUID = 0;
}
/** @see Predicates#equalTo(Object) */
private static class IsEqualToPredicate<T> implements Predicate<T>, Serializable {
private final T target;
private IsEqualToPredicate(T target) {
this.target = target;
}
@Override
public boolean apply(T t) {
return target.equals(t);
}
@Override
public int hashCode() {
return target.hashCode();
}
@Override
public boolean equals(@Nullable Object obj) {
if (obj instanceof IsEqualToPredicate) {
IsEqualToPredicate<?> that = (IsEqualToPredicate<?>) obj;
return target.equals(that.target);
}
return false;
}
@Override
public String toString() {
return "Predicates.equalTo(" + target + ")";
}
private static final long serialVersionUID = 0;
}
/** @see Predicates#instanceOf(Class) */
@GwtIncompatible("Class.isInstance")
private static class InstanceOfPredicate implements Predicate<Object>, Serializable {
private final Class<?> clazz;
private InstanceOfPredicate(Class<?> clazz) {
this.clazz = checkNotNull(clazz);
}
@Override
public boolean apply(@Nullable Object o) {
return clazz.isInstance(o);
}
@Override
public int hashCode() {
return clazz.hashCode();
}
@Override
public boolean equals(@Nullable Object obj) {
if (obj instanceof InstanceOfPredicate) {
InstanceOfPredicate that = (InstanceOfPredicate) obj;
return clazz == that.clazz;
}
return false;
}
@Override
public String toString() {
return "Predicates.instanceOf(" + clazz.getName() + ")";
}
private static final long serialVersionUID = 0;
}
/** @see Predicates#assignableFrom(Class) */
@GwtIncompatible("Class.isAssignableFrom")
private static class AssignableFromPredicate implements Predicate<Class<?>>, Serializable {
private final Class<?> clazz;
private AssignableFromPredicate(Class<?> clazz) {
this.clazz = checkNotNull(clazz);
}
@Override
public boolean apply(Class<?> input) {
return clazz.isAssignableFrom(input);
}
@Override
public int hashCode() {
return clazz.hashCode();
}
@Override
public boolean equals(@Nullable Object obj) {
if (obj instanceof AssignableFromPredicate) {
AssignableFromPredicate that = (AssignableFromPredicate) obj;
return clazz == that.clazz;
}
return false;
}
@Override
public String toString() {
return "Predicates.assignableFrom(" + clazz.getName() + ")";
}
private static final long serialVersionUID = 0;
}
/** @see Predicates#in(Collection) */
private static class InPredicate<T> implements Predicate<T>, Serializable {
private final Collection<?> target;
private InPredicate(Collection<?> target) {
this.target = checkNotNull(target);
}
@Override
public boolean apply(@Nullable T t) {
try {
return target.contains(t);
} catch (NullPointerException e) {
return false;
} catch (ClassCastException e) {
return false;
}
}
@Override
public boolean equals(@Nullable Object obj) {
if (obj instanceof InPredicate) {
InPredicate<?> that = (InPredicate<?>) obj;
return target.equals(that.target);
}
return false;
}
@Override
public int hashCode() {
return target.hashCode();
}
@Override
public String toString() {
return "Predicates.in(" + target + ")";
}
private static final long serialVersionUID = 0;
}
/** @see Predicates#compose(Predicate, Function) */
private static class CompositionPredicate<A, B> implements Predicate<A>, Serializable {
final Predicate<B> p;
final Function<A, ? extends B> f;
private CompositionPredicate(Predicate<B> p, Function<A, ? extends B> f) {
this.p = checkNotNull(p);
this.f = checkNotNull(f);
}
@Override
public boolean apply(@Nullable A a) {
return p.apply(f.apply(a));
}
@Override
public boolean equals(@Nullable Object obj) {
if (obj instanceof CompositionPredicate) {
CompositionPredicate<?, ?> that = (CompositionPredicate<?, ?>) obj;
return f.equals(that.f) && p.equals(that.p);
}
return false;
}
@Override
public int hashCode() {
return f.hashCode() ^ p.hashCode();
}
@Override
public String toString() {
// TODO(cpovirk): maybe make this look like the method call does ("Predicates.compose(...)")
return p + "(" + f + ")";
}
private static final long serialVersionUID = 0;
}
/** @see Predicates#contains(Pattern) */
@GwtIncompatible("Only used by other GWT-incompatible code.")
private static class ContainsPatternPredicate implements Predicate<CharSequence>, Serializable {
final Pattern pattern;
ContainsPatternPredicate(Pattern pattern) {
this.pattern = checkNotNull(pattern);
}
@Override
public boolean apply(CharSequence t) {
return pattern.matcher(t).find();
}
@Override
public int hashCode() {
// Pattern uses Object.hashCode, so we have to reach
// inside to build a hashCode consistent with equals.
return Objects.hashCode(pattern.pattern(), pattern.flags());
}
@Override
public boolean equals(@Nullable Object obj) {
if (obj instanceof ContainsPatternPredicate) {
ContainsPatternPredicate that = (ContainsPatternPredicate) obj;
// Pattern uses Object (identity) equality, so we have to reach
// inside to compare individual fields.
return Objects.equal(pattern.pattern(), that.pattern.pattern())
&& Objects.equal(pattern.flags(), that.pattern.flags());
}
return false;
}
@Override
public String toString() {
String patternString = Objects.toStringHelper(pattern)
.add("pattern", pattern.pattern())
.add("pattern.flags", pattern.flags())
.toString();
return "Predicates.contains(" + patternString + ")";
}
private static final long serialVersionUID = 0;
}
/** @see Predicates#containsPattern(String) */
@GwtIncompatible("Only used by other GWT-incompatible code.")
private static class ContainsPatternFromStringPredicate extends ContainsPatternPredicate {
ContainsPatternFromStringPredicate(String string) {
super(Pattern.compile(string));
}
@Override
public String toString() {
return "Predicates.containsPattern(" + pattern.pattern() + ")";
}
private static final long serialVersionUID = 0;
}
private static <T> List<Predicate<? super T>> asList(
Predicate<? super T> first, Predicate<? super T> second) {
// TODO(kevinb): understand why we still get a warning despite @SafeVarargs!
return Arrays.<Predicate<? super T>>asList(first, second);
}
private static <T> List<T> defensiveCopy(T... array) {
return defensiveCopy(Arrays.asList(array));
}
static <T> List<T> defensiveCopy(Iterable<T> iterable) {
ArrayList<T> list = new ArrayList<T>();
for (T element : iterable) {
list.add(checkNotNull(element));
}
return list;
}
}
@@ -1,105 +0,0 @@
/*
* Copyright (C) 2011 The Guava Authors
*
* 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 com.google.common.base;
import static com.google.common.base.Preconditions.checkNotNull;
import com.google.common.annotations.GwtCompatible;
import java.util.Collections;
import java.util.Set;
import javax.annotation.Nullable;
/**
* Implementation of an {@link Optional} containing a reference.
*/
@GwtCompatible
final class Present<T> extends Optional<T> {
private final T reference;
Present(T reference) {
this.reference = reference;
}
@Override
public boolean isPresent() {
return true;
}
@Override
public T get() {
return reference;
}
@Override
public T or(T defaultValue) {
checkNotNull(defaultValue, "use Optional.orNull() instead of Optional.or(null)");
return reference;
}
@Override
public Optional<T> or(Optional<? extends T> secondChoice) {
checkNotNull(secondChoice);
return this;
}
@Override
public T or(Supplier<? extends T> supplier) {
checkNotNull(supplier);
return reference;
}
@Override
public T orNull() {
return reference;
}
@Override
public Set<T> asSet() {
return Collections.singleton(reference);
}
@Override
public <V> Optional<V> transform(Function<? super T, V> function) {
return new Present<V>(
checkNotNull(
function.apply(reference),
"the Function passed to Optional.transform() must not return null."));
}
@Override
public boolean equals(@Nullable Object object) {
if (object instanceof Present) {
Present<?> other = (Present<?>) object;
return reference.equals(other.reference);
}
return false;
}
@Override
public int hashCode() {
return 0x598df91c + reference.hashCode();
}
@Override
public String toString() {
return "Optional.of(" + reference + ")";
}
private static final long serialVersionUID = 0;
}
@@ -1,153 +0,0 @@
/*
* Copyright (C) 2012 The Guava Authors
*
* 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 com.google.common.base;
import com.google.common.annotations.GwtIncompatible;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.CharMatcher.NamedFastMatcher;
import java.util.BitSet;
/**
* An immutable version of CharMatcher for smallish sets of characters that uses a hash table
* with linear probing to check for matches.
*
* @author Christopher Swenson
*/
@GwtIncompatible("no precomputation is done in GWT")
final class SmallCharMatcher extends NamedFastMatcher {
static final int MAX_SIZE = 1023;
private final char[] table;
private final boolean containsZero;
private final long filter;
private SmallCharMatcher(char[] table, long filter, boolean containsZero, String description) {
super(description);
this.table = table;
this.filter = filter;
this.containsZero = containsZero;
}
private static final int C1 = 0xcc9e2d51;
private static final int C2 = 0x1b873593;
/*
* This method was rewritten in Java from an intermediate step of the Murmur hash function in
* http://code.google.com/p/smhasher/source/browse/trunk/MurmurHash3.cpp, which contained the
* following header:
*
* MurmurHash3 was written by Austin Appleby, and is placed in the public domain. The author
* hereby disclaims copyright to this source code.
*/
static int smear(int hashCode) {
return C2 * Integer.rotateLeft(hashCode * C1, 15);
}
private boolean checkFilter(int c) {
return 1 == (1 & (filter >> c));
}
// This is all essentially copied from ImmutableSet, but we have to duplicate because
// of dependencies.
// Represents how tightly we can pack things, as a maximum.
private static final double DESIRED_LOAD_FACTOR = 0.5;
/**
* Returns an array size suitable for the backing array of a hash table that
* uses open addressing with linear probing in its implementation. The
* returned size is the smallest power of two that can hold setSize elements
* with the desired load factor.
*/
@VisibleForTesting
static int chooseTableSize(int setSize) {
if (setSize == 1) {
return 2;
}
// Correct the size for open addressing to match desired load factor.
// Round up to the next highest power of 2.
int tableSize = Integer.highestOneBit(setSize - 1) << 1;
while (tableSize * DESIRED_LOAD_FACTOR < setSize) {
tableSize <<= 1;
}
return tableSize;
}
static CharMatcher from(BitSet chars, String description) {
// Compute the filter.
long filter = 0;
int size = chars.cardinality();
boolean containsZero = chars.get(0);
// Compute the hash table.
char[] table = new char[chooseTableSize(size)];
int mask = table.length - 1;
for (int c = chars.nextSetBit(0); c != -1; c = chars.nextSetBit(c + 1)) {
// Compute the filter at the same time.
filter |= 1L << c;
int index = smear(c) & mask;
while (true) {
// Check for empty.
if (table[index] == 0) {
table[index] = (char) c;
break;
}
// Linear probing.
index = (index + 1) & mask;
}
}
return new SmallCharMatcher(table, filter, containsZero, description);
}
@Override
public boolean matches(char c) {
if (c == 0) {
return containsZero;
}
if (!checkFilter(c)) {
return false;
}
int mask = table.length - 1;
int startingIndex = smear(c) & mask;
int index = startingIndex;
do {
// Check for empty.
if (table[index] == 0) {
return false;
// Check for match.
} else if (table[index] == c) {
return true;
} else {
// Linear probing.
index = (index + 1) & mask;
}
// Check to see if we wrapped around the whole table.
} while (index != startingIndex);
return false;
}
@Override
void setBits(BitSet table) {
if (containsZero) {
table.set(0);
}
for (char c : this.table) {
if (c != 0) {
table.set(c);
}
}
}
}
@@ -1,643 +0,0 @@
/*
* Copyright (C) 2009 The Guava Authors
*
* 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 com.google.common.base;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import com.google.common.annotations.Beta;
import com.google.common.annotations.GwtCompatible;
import com.google.common.annotations.GwtIncompatible;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.annotation.CheckReturnValue;
/**
* Extracts non-overlapping substrings from an input string, typically by
* recognizing appearances of a <i>separator</i> sequence. This separator can be
* specified as a single {@linkplain #on(char) character}, fixed {@linkplain
* #on(String) string}, {@linkplain #onPattern regular expression} or {@link
* #on(CharMatcher) CharMatcher} instance. Or, instead of using a separator at
* all, a splitter can extract adjacent substrings of a given {@linkplain
* #fixedLength fixed length}.
*
* <p>For example, this expression: <pre> {@code
*
* Splitter.on(',').split("foo,bar,qux")}</pre>
*
* ... produces an {@code Iterable} containing {@code "foo"}, {@code "bar"} and
* {@code "qux"}, in that order.
*
* <p>By default, {@code Splitter}'s behavior is simplistic and unassuming. The
* following expression: <pre> {@code
*
* Splitter.on(',').split(" foo,,, bar ,")}</pre>
*
* ... yields the substrings {@code [" foo", "", "", " bar ", ""]}. If this
* is not the desired behavior, use configuration methods to obtain a <i>new</i>
* splitter instance with modified behavior: <pre> {@code
*
* private static final Splitter MY_SPLITTER = Splitter.on(',')
* .trimResults()
* .omitEmptyStrings();}</pre>
*
* <p>Now {@code MY_SPLITTER.split("foo,,, bar ,")} returns just {@code ["foo",
* "bar"]}. Note that the order in which these configuration methods are called
* is never significant.
*
* <p><b>Warning:</b> Splitter instances are immutable. Invoking a configuration
* method has no effect on the receiving instance; you must store and use the
* new splitter instance it returns instead. <pre> {@code
*
* // Do NOT do this
* Splitter splitter = Splitter.on('/');
* splitter.trimResults(); // does nothing!
* return splitter.split("wrong / wrong / wrong");}</pre>
*
* <p>For separator-based splitters that do not use {@code omitEmptyStrings}, an
* input string containing {@code n} occurrences of the separator naturally
* yields an iterable of size {@code n + 1}. So if the separator does not occur
* anywhere in the input, a single substring is returned containing the entire
* input. Consequently, all splitters split the empty string to {@code [""]}
* (note: even fixed-length splitters).
*
* <p>Splitter instances are thread-safe immutable, and are therefore safe to
* store as {@code static final} constants.
*
* <p>The {@link Joiner} class provides the inverse operation to splitting, but
* note that a round-trip between the two should be assumed to be lossy.
*
* <p>See the Guava User Guide article on <a href=
* "https://github.com/google/guava/wiki/StringsExplained#splitter">
* {@code Splitter}</a>.
*
* @author Julien Silland
* @author Jesse Wilson
* @author Kevin Bourrillion
* @author Louis Wasserman
* @since 1.0
*/
@GwtCompatible(emulated = true)
public final class Splitter {
private final CharMatcher trimmer;
private final boolean omitEmptyStrings;
private final Strategy strategy;
private final int limit;
private Splitter(Strategy strategy) {
this(strategy, false, CharMatcher.NONE, Integer.MAX_VALUE);
}
private Splitter(Strategy strategy, boolean omitEmptyStrings, CharMatcher trimmer, int limit) {
this.strategy = strategy;
this.omitEmptyStrings = omitEmptyStrings;
this.trimmer = trimmer;
this.limit = limit;
}
/**
* Returns a splitter that uses the given single-character separator. For
* example, {@code Splitter.on(',').split("foo,,bar")} returns an iterable
* containing {@code ["foo", "", "bar"]}.
*
* @param separator the character to recognize as a separator
* @return a splitter, with default settings, that recognizes that separator
*/
@CheckReturnValue
public static Splitter on(char separator) {
return on(CharMatcher.is(separator));
}
/**
* Returns a splitter that considers any single character matched by the
* given {@code CharMatcher} to be a separator. For example, {@code
* Splitter.on(CharMatcher.anyOf(";,")).split("foo,;bar,quux")} returns an
* iterable containing {@code ["foo", "", "bar", "quux"]}.
*
* @param separatorMatcher a {@link CharMatcher} that determines whether a
* character is a separator
* @return a splitter, with default settings, that uses this matcher
*/
@CheckReturnValue
public static Splitter on(final CharMatcher separatorMatcher) {
checkNotNull(separatorMatcher);
return new Splitter(
new Strategy() {
@Override
public SplittingIterator iterator(Splitter splitter, final CharSequence toSplit) {
return new SplittingIterator(splitter, toSplit) {
@Override
int separatorStart(int start) {
return separatorMatcher.indexIn(toSplit, start);
}
@Override
int separatorEnd(int separatorPosition) {
return separatorPosition + 1;
}
};
}
});
}
/**
* Returns a splitter that uses the given fixed string as a separator. For
* example, {@code Splitter.on(", ").split("foo, bar,baz")} returns an
* iterable containing {@code ["foo", "bar,baz"]}.
*
* @param separator the literal, nonempty string to recognize as a separator
* @return a splitter, with default settings, that recognizes that separator
*/
@CheckReturnValue
public static Splitter on(final String separator) {
checkArgument(separator.length() != 0, "The separator may not be the empty string.");
if (separator.length() == 1) {
return Splitter.on(separator.charAt(0));
}
return new Splitter(
new Strategy() {
@Override
public SplittingIterator iterator(Splitter splitter, CharSequence toSplit) {
return new SplittingIterator(splitter, toSplit) {
@Override
public int separatorStart(int start) {
int separatorLength = separator.length();
positions:
for (int p = start, last = toSplit.length() - separatorLength; p <= last; p++) {
for (int i = 0; i < separatorLength; i++) {
if (toSplit.charAt(i + p) != separator.charAt(i)) {
continue positions;
}
}
return p;
}
return -1;
}
@Override
public int separatorEnd(int separatorPosition) {
return separatorPosition + separator.length();
}
};
}
});
}
/**
* Returns a splitter that considers any subsequence matching {@code
* pattern} to be a separator. For example, {@code
* Splitter.on(Pattern.compile("\r?\n")).split(entireFile)} splits a string
* into lines whether it uses DOS-style or UNIX-style line terminators.
*
* @param separatorPattern the pattern that determines whether a subsequence
* is a separator. This pattern may not match the empty string.
* @return a splitter, with default settings, that uses this pattern
* @throws IllegalArgumentException if {@code separatorPattern} matches the
* empty string
*/
@CheckReturnValue
@GwtIncompatible("java.util.regex")
public static Splitter on(final Pattern separatorPattern) {
checkNotNull(separatorPattern);
checkArgument(
!separatorPattern.matcher("").matches(),
"The pattern may not match the empty string: %s",
separatorPattern);
return new Splitter(
new Strategy() {
@Override
public SplittingIterator iterator(final Splitter splitter, CharSequence toSplit) {
final Matcher matcher = separatorPattern.matcher(toSplit);
return new SplittingIterator(splitter, toSplit) {
@Override
public int separatorStart(int start) {
return matcher.find(start) ? matcher.start() : -1;
}
@Override
public int separatorEnd(int separatorPosition) {
return matcher.end();
}
};
}
});
}
/**
* Returns a splitter that considers any subsequence matching a given
* pattern (regular expression) to be a separator. For example, {@code
* Splitter.onPattern("\r?\n").split(entireFile)} splits a string into lines
* whether it uses DOS-style or UNIX-style line terminators. This is
* equivalent to {@code Splitter.on(Pattern.compile(pattern))}.
*
* @param separatorPattern the pattern that determines whether a subsequence
* is a separator. This pattern may not match the empty string.
* @return a splitter, with default settings, that uses this pattern
* @throws java.util.regex.PatternSyntaxException if {@code separatorPattern}
* is a malformed expression
* @throws IllegalArgumentException if {@code separatorPattern} matches the
* empty string
*/
@CheckReturnValue
@GwtIncompatible("java.util.regex")
public static Splitter onPattern(String separatorPattern) {
return on(Pattern.compile(separatorPattern));
}
/**
* Returns a splitter that divides strings into pieces of the given length.
* For example, {@code Splitter.fixedLength(2).split("abcde")} returns an
* iterable containing {@code ["ab", "cd", "e"]}. The last piece can be
* smaller than {@code length} but will never be empty.
*
* <p><b>Exception:</b> for consistency with separator-based splitters, {@code
* split("")} does not yield an empty iterable, but an iterable containing
* {@code ""}. This is the only case in which {@code
* Iterables.size(split(input))} does not equal {@code
* IntMath.divide(input.length(), length, CEILING)}. To avoid this behavior,
* use {@code omitEmptyStrings}.
*
* @param length the desired length of pieces after splitting, a positive
* integer
* @return a splitter, with default settings, that can split into fixed sized
* pieces
* @throws IllegalArgumentException if {@code length} is zero or negative
*/
@CheckReturnValue
public static Splitter fixedLength(final int length) {
checkArgument(length > 0, "The length may not be less than 1");
return new Splitter(
new Strategy() {
@Override
public SplittingIterator iterator(final Splitter splitter, CharSequence toSplit) {
return new SplittingIterator(splitter, toSplit) {
@Override
public int separatorStart(int start) {
int nextChunkStart = start + length;
return (nextChunkStart < toSplit.length() ? nextChunkStart : -1);
}
@Override
public int separatorEnd(int separatorPosition) {
return separatorPosition;
}
};
}
});
}
/**
* Returns a splitter that behaves equivalently to {@code this} splitter, but
* automatically omits empty strings from the results. For example, {@code
* Splitter.on(',').omitEmptyStrings().split(",a,,,b,c,,")} returns an
* iterable containing only {@code ["a", "b", "c"]}.
*
* <p>If either {@code trimResults} option is also specified when creating a
* splitter, that splitter always trims results first before checking for
* emptiness. So, for example, {@code
* Splitter.on(':').omitEmptyStrings().trimResults().split(": : : ")} returns
* an empty iterable.
*
* <p>Note that it is ordinarily not possible for {@link #split(CharSequence)}
* to return an empty iterable, but when using this option, it can (if the
* input sequence consists of nothing but separators).
*
* @return a splitter with the desired configuration
*/
@CheckReturnValue
public Splitter omitEmptyStrings() {
return new Splitter(strategy, true, trimmer, limit);
}
/**
* Returns a splitter that behaves equivalently to {@code this} splitter but
* stops splitting after it reaches the limit.
* The limit defines the maximum number of items returned by the iterator, or
* the maximum size of the list returned by {@link #splitToList}.
*
* <p>For example,
* {@code Splitter.on(',').limit(3).split("a,b,c,d")} returns an iterable
* containing {@code ["a", "b", "c,d"]}. When omitting empty strings, the
* omitted strings do no count. Hence,
* {@code Splitter.on(',').limit(3).omitEmptyStrings().split("a,,,b,,,c,d")}
* returns an iterable containing {@code ["a", "b", "c,d"}.
* When trim is requested, all entries, including the last are trimmed. Hence
* {@code Splitter.on(',').limit(3).trimResults().split(" a , b , c , d ")}
* results in {@code ["a", "b", "c , d"]}.
*
* @param limit the maximum number of items returned
* @return a splitter with the desired configuration
* @since 9.0
*/
@CheckReturnValue
public Splitter limit(int limit) {
checkArgument(limit > 0, "must be greater than zero: %s", limit);
return new Splitter(strategy, omitEmptyStrings, trimmer, limit);
}
/**
* Returns a splitter that behaves equivalently to {@code this} splitter, but
* automatically removes leading and trailing {@linkplain
* CharMatcher#WHITESPACE whitespace} from each returned substring; equivalent
* to {@code trimResults(CharMatcher.WHITESPACE)}. For example, {@code
* Splitter.on(',').trimResults().split(" a, b ,c ")} returns an iterable
* containing {@code ["a", "b", "c"]}.
*
* @return a splitter with the desired configuration
*/
@CheckReturnValue
public Splitter trimResults() {
return trimResults(CharMatcher.WHITESPACE);
}
/**
* Returns a splitter that behaves equivalently to {@code this} splitter, but
* removes all leading or trailing characters matching the given {@code
* CharMatcher} from each returned substring. For example, {@code
* Splitter.on(',').trimResults(CharMatcher.is('_')).split("_a ,_b_ ,c__")}
* returns an iterable containing {@code ["a ", "b_ ", "c"]}.
*
* @param trimmer a {@link CharMatcher} that determines whether a character
* should be removed from the beginning/end of a subsequence
* @return a splitter with the desired configuration
*/
// TODO(kevinb): throw if a trimmer was already specified!
@CheckReturnValue
public Splitter trimResults(CharMatcher trimmer) {
checkNotNull(trimmer);
return new Splitter(strategy, omitEmptyStrings, trimmer, limit);
}
/**
* Splits {@code sequence} into string components and makes them available
* through an {@link Iterator}, which may be lazily evaluated. If you want
* an eagerly computed {@link List}, use {@link #splitToList(CharSequence)}.
*
* @param sequence the sequence of characters to split
* @return an iteration over the segments split from the parameter.
*/
@CheckReturnValue
public Iterable<String> split(final CharSequence sequence) {
checkNotNull(sequence);
return new Iterable<String>() {
@Override
public Iterator<String> iterator() {
return splittingIterator(sequence);
}
@Override
public String toString() {
return Joiner.on(", ")
.appendTo(new StringBuilder().append('['), this)
.append(']')
.toString();
}
};
}
private Iterator<String> splittingIterator(CharSequence sequence) {
return strategy.iterator(this, sequence);
}
/**
* Splits {@code sequence} into string components and returns them as
* an immutable list. If you want an {@link Iterable} which may be lazily
* evaluated, use {@link #split(CharSequence)}.
*
* @param sequence the sequence of characters to split
* @return an immutable list of the segments split from the parameter
* @since 15.0
*/
@CheckReturnValue
@Beta
public List<String> splitToList(CharSequence sequence) {
checkNotNull(sequence);
Iterator<String> iterator = splittingIterator(sequence);
List<String> result = new ArrayList<String>();
while (iterator.hasNext()) {
result.add(iterator.next());
}
return Collections.unmodifiableList(result);
}
/**
* Returns a {@code MapSplitter} which splits entries based on this splitter,
* and splits entries into keys and values using the specified separator.
*
* @since 10.0
*/
@CheckReturnValue
@Beta
public MapSplitter withKeyValueSeparator(String separator) {
return withKeyValueSeparator(on(separator));
}
/**
* Returns a {@code MapSplitter} which splits entries based on this splitter,
* and splits entries into keys and values using the specified separator.
*
* @since 14.0
*/
@CheckReturnValue
@Beta
public MapSplitter withKeyValueSeparator(char separator) {
return withKeyValueSeparator(on(separator));
}
/**
* Returns a {@code MapSplitter} which splits entries based on this splitter,
* and splits entries into keys and values using the specified key-value
* splitter.
*
* @since 10.0
*/
@CheckReturnValue
@Beta
public MapSplitter withKeyValueSeparator(Splitter keyValueSplitter) {
return new MapSplitter(this, keyValueSplitter);
}
/**
* An object that splits strings into maps as {@code Splitter} splits
* iterables and lists. Like {@code Splitter}, it is thread-safe and
* immutable.
*
* @since 10.0
*/
@Beta
public static final class MapSplitter {
private static final String INVALID_ENTRY_MESSAGE = "Chunk [%s] is not a valid entry";
private final Splitter outerSplitter;
private final Splitter entrySplitter;
private MapSplitter(Splitter outerSplitter, Splitter entrySplitter) {
this.outerSplitter = outerSplitter; // only "this" is passed
this.entrySplitter = checkNotNull(entrySplitter);
}
/**
* Splits {@code sequence} into substrings, splits each substring into
* an entry, and returns an unmodifiable map with each of the entries. For
* example, <code>
* Splitter.on(';').trimResults().withKeyValueSeparator("=>")
* .split("a=>b ; c=>b")
* </code> will return a mapping from {@code "a"} to {@code "b"} and
* {@code "c"} to {@code b}.
*
* <p>The returned map preserves the order of the entries from
* {@code sequence}.
*
* @throws IllegalArgumentException if the specified sequence does not split
* into valid map entries, or if there are duplicate keys
*/
@CheckReturnValue
public Map<String, String> split(CharSequence sequence) {
Map<String, String> map = new LinkedHashMap<String, String>();
for (String entry : outerSplitter.split(sequence)) {
Iterator<String> entryFields = entrySplitter.splittingIterator(entry);
checkArgument(entryFields.hasNext(), INVALID_ENTRY_MESSAGE, entry);
String key = entryFields.next();
checkArgument(!map.containsKey(key), "Duplicate key [%s] found.", key);
checkArgument(entryFields.hasNext(), INVALID_ENTRY_MESSAGE, entry);
String value = entryFields.next();
map.put(key, value);
checkArgument(!entryFields.hasNext(), INVALID_ENTRY_MESSAGE, entry);
}
return Collections.unmodifiableMap(map);
}
}
private interface Strategy {
Iterator<String> iterator(Splitter splitter, CharSequence toSplit);
}
private abstract static class SplittingIterator extends AbstractIterator<String> {
final CharSequence toSplit;
final CharMatcher trimmer;
final boolean omitEmptyStrings;
/**
* Returns the first index in {@code toSplit} at or after {@code start}
* that contains the separator.
*/
abstract int separatorStart(int start);
/**
* Returns the first index in {@code toSplit} after {@code
* separatorPosition} that does not contain a separator. This method is only
* invoked after a call to {@code separatorStart}.
*/
abstract int separatorEnd(int separatorPosition);
int offset = 0;
int limit;
protected SplittingIterator(Splitter splitter, CharSequence toSplit) {
this.trimmer = splitter.trimmer;
this.omitEmptyStrings = splitter.omitEmptyStrings;
this.limit = splitter.limit;
this.toSplit = toSplit;
}
@Override
protected String computeNext() {
/*
* The returned string will be from the end of the last match to the
* beginning of the next one. nextStart is the start position of the
* returned substring, while offset is the place to start looking for a
* separator.
*/
int nextStart = offset;
while (offset != -1) {
int start = nextStart;
int end;
int separatorPosition = separatorStart(offset);
if (separatorPosition == -1) {
end = toSplit.length();
offset = -1;
} else {
end = separatorPosition;
offset = separatorEnd(separatorPosition);
}
if (offset == nextStart) {
/*
* This occurs when some pattern has an empty match, even if it
* doesn't match the empty string -- for example, if it requires
* lookahead or the like. The offset must be increased to look for
* separators beyond this point, without changing the start position
* of the next returned substring -- so nextStart stays the same.
*/
offset++;
if (offset >= toSplit.length()) {
offset = -1;
}
continue;
}
while (start < end && trimmer.matches(toSplit.charAt(start))) {
start++;
}
while (end > start && trimmer.matches(toSplit.charAt(end - 1))) {
end--;
}
if (omitEmptyStrings && start == end) {
// Don't include the (unused) separator in next split string.
nextStart = offset;
continue;
}
if (limit == 1) {
// The limit has been reached, return the rest of the string as the
// final item. This is tested after empty string removal so that
// empty strings do not count towards the limit.
end = toSplit.length();
offset = -1;
// Since we may have changed the end, we need to trim it again.
while (end > start && trimmer.matches(toSplit.charAt(end - 1))) {
end--;
}
} else {
limit--;
}
return toSplit.subSequence(start, end).toString();
}
return endOfData();
}
}
}
@@ -1,149 +0,0 @@
/*
* Copyright (C) 2012 The Guava Authors
*
* 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 com.google.common.base;
import com.google.common.annotations.Beta;
import com.google.common.annotations.GwtIncompatible;
import javax.annotation.CheckReturnValue;
import javax.annotation.Nullable;
/**
* Represents a {@linkplain System#getProperties() standard system property}.
*
* @author Kurt Alfred Kluever
* @since 15.0
*/
@Beta
@GwtIncompatible("java.lang.System#getProperty")
@CheckReturnValue
public enum StandardSystemProperty {
/** Java Runtime Environment version. */
JAVA_VERSION("java.version"),
/** Java Runtime Environment vendor. */
JAVA_VENDOR("java.vendor"),
/** Java vendor URL. */
JAVA_VENDOR_URL("java.vendor.url"),
/** Java installation directory. */
JAVA_HOME("java.home"),
/** Java Virtual Machine specification version. */
JAVA_VM_SPECIFICATION_VERSION("java.vm.specification.version"),
/** Java Virtual Machine specification vendor. */
JAVA_VM_SPECIFICATION_VENDOR("java.vm.specification.vendor"),
/** Java Virtual Machine specification name. */
JAVA_VM_SPECIFICATION_NAME("java.vm.specification.name"),
/** Java Virtual Machine implementation version. */
JAVA_VM_VERSION("java.vm.version"),
/** Java Virtual Machine implementation vendor. */
JAVA_VM_VENDOR("java.vm.vendor"),
/** Java Virtual Machine implementation name. */
JAVA_VM_NAME("java.vm.name"),
/** Java Runtime Environment specification version. */
JAVA_SPECIFICATION_VERSION("java.specification.version"),
/** Java Runtime Environment specification vendor. */
JAVA_SPECIFICATION_VENDOR("java.specification.vendor"),
/** Java Runtime Environment specification name. */
JAVA_SPECIFICATION_NAME("java.specification.name"),
/** Java class format version number. */
JAVA_CLASS_VERSION("java.class.version"),
/** Java class path. */
JAVA_CLASS_PATH("java.class.path"),
/** List of paths to search when loading libraries. */
JAVA_LIBRARY_PATH("java.library.path"),
/** Default temp file path. */
JAVA_IO_TMPDIR("java.io.tmpdir"),
/** Name of JIT compiler to use. */
JAVA_COMPILER("java.compiler"),
/** Path of extension directory or directories. */
JAVA_EXT_DIRS("java.ext.dirs"),
/** Operating system name. */
OS_NAME("os.name"),
/** Operating system architecture. */
OS_ARCH("os.arch"),
/** Operating system version. */
OS_VERSION("os.version"),
/** File separator ("/" on UNIX). */
FILE_SEPARATOR("file.separator"),
/** Path separator (":" on UNIX). */
PATH_SEPARATOR("path.separator"),
/** Line separator ("\n" on UNIX). */
LINE_SEPARATOR("line.separator"),
/** User's account name. */
USER_NAME("user.name"),
/** User's home directory. */
USER_HOME("user.home"),
/** User's current working directory. */
USER_DIR("user.dir");
private final String key;
private StandardSystemProperty(String key) {
this.key = key;
}
/**
* Returns the key used to lookup this system property.
*/
public String key() {
return key;
}
/**
* Returns the current value for this system property by delegating to
* {@link System#getProperty(String)}.
*/
@Nullable
public String value() {
return System.getProperty(key);
}
/**
* Returns a string representation of this system property.
*/
@Override
public String toString() {
return key() + "=" + value();
}
}
@@ -1,261 +0,0 @@
/*
* Copyright (C) 2008 The Guava Authors
*
* 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 com.google.common.base;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState;
import static java.util.concurrent.TimeUnit.DAYS;
import static java.util.concurrent.TimeUnit.HOURS;
import static java.util.concurrent.TimeUnit.MICROSECONDS;
import static java.util.concurrent.TimeUnit.MILLISECONDS;
import static java.util.concurrent.TimeUnit.MINUTES;
import static java.util.concurrent.TimeUnit.NANOSECONDS;
import static java.util.concurrent.TimeUnit.SECONDS;
import com.google.common.annotations.GwtCompatible;
import com.google.common.annotations.GwtIncompatible;
import java.util.Locale;
import java.util.concurrent.TimeUnit;
import javax.annotation.CheckReturnValue;
/**
* An object that measures elapsed time in nanoseconds. It is useful to measure
* elapsed time using this class instead of direct calls to {@link
* System#nanoTime} for a few reasons:
*
* <ul>
* <li>An alternate time source can be substituted, for testing or performance
* reasons.
* <li>As documented by {@code nanoTime}, the value returned has no absolute
* meaning, and can only be interpreted as relative to another timestamp
* returned by {@code nanoTime} at a different time. {@code Stopwatch} is a
* more effective abstraction because it exposes only these relative values,
* not the absolute ones.
* </ul>
*
* <p>Basic usage:
* <pre>
* Stopwatch stopwatch = Stopwatch.{@link #createStarted createStarted}();
* doSomething();
* stopwatch.{@link #stop stop}(); // optional
*
* long millis = stopwatch.elapsed(MILLISECONDS);
*
* log.info("time: " + stopwatch); // formatted string like "12.3 ms"</pre>
*
* <p>Stopwatch methods are not idempotent; it is an error to start or stop a
* stopwatch that is already in the desired state.
*
* <p>When testing code that uses this class, use
* {@link #createUnstarted(Ticker)} or {@link #createStarted(Ticker)} to
* supply a fake or mock ticker.
* <!-- TODO(kevinb): restore the "such as" --> This allows you to
* simulate any valid behavior of the stopwatch.
*
* <p><b>Note:</b> This class is not thread-safe.
*
* @author Kevin Bourrillion
* @since 10.0
*/
@GwtCompatible(emulated = true)
public final class Stopwatch {
private final Ticker ticker;
private boolean isRunning;
private long elapsedNanos;
private long startTick;
/**
* Creates (but does not start) a new stopwatch using {@link System#nanoTime}
* as its time source.
*
* @since 15.0
*/
@CheckReturnValue
public static Stopwatch createUnstarted() {
return new Stopwatch();
}
/**
* Creates (but does not start) a new stopwatch, using the specified time
* source.
*
* @since 15.0
*/
@CheckReturnValue
public static Stopwatch createUnstarted(Ticker ticker) {
return new Stopwatch(ticker);
}
/**
* Creates (and starts) a new stopwatch using {@link System#nanoTime}
* as its time source.
*
* @since 15.0
*/
@CheckReturnValue
public static Stopwatch createStarted() {
return new Stopwatch().start();
}
/**
* Creates (and starts) a new stopwatch, using the specified time
* source.
*
* @since 15.0
*/
@CheckReturnValue
public static Stopwatch createStarted(Ticker ticker) {
return new Stopwatch(ticker).start();
}
Stopwatch() {
this.ticker = Ticker.systemTicker();
}
Stopwatch(Ticker ticker) {
this.ticker = checkNotNull(ticker, "ticker");
}
/**
* Returns {@code true} if {@link #start()} has been called on this stopwatch,
* and {@link #stop()} has not been called since the last call to {@code
* start()}.
*/
@CheckReturnValue
public boolean isRunning() {
return isRunning;
}
/**
* Starts the stopwatch.
*
* @return this {@code Stopwatch} instance
* @throws IllegalStateException if the stopwatch is already running.
*/
public Stopwatch start() {
checkState(!isRunning, "This stopwatch is already running.");
isRunning = true;
startTick = ticker.read();
return this;
}
/**
* Stops the stopwatch. Future reads will return the fixed duration that had
* elapsed up to this point.
*
* @return this {@code Stopwatch} instance
* @throws IllegalStateException if the stopwatch is already stopped.
*/
public Stopwatch stop() {
long tick = ticker.read();
checkState(isRunning, "This stopwatch is already stopped.");
isRunning = false;
elapsedNanos += tick - startTick;
return this;
}
/**
* Sets the elapsed time for this stopwatch to zero,
* and places it in a stopped state.
*
* @return this {@code Stopwatch} instance
*/
public Stopwatch reset() {
elapsedNanos = 0;
isRunning = false;
return this;
}
private long elapsedNanos() {
return isRunning ? ticker.read() - startTick + elapsedNanos : elapsedNanos;
}
/**
* Returns the current elapsed time shown on this stopwatch, expressed
* in the desired time unit, with any fraction rounded down.
*
* <p>Note that the overhead of measurement can be more than a microsecond, so
* it is generally not useful to specify {@link TimeUnit#NANOSECONDS}
* precision here.
*
* @since 14.0 (since 10.0 as {@code elapsedTime()})
*/
@CheckReturnValue
public long elapsed(TimeUnit desiredUnit) {
return desiredUnit.convert(elapsedNanos(), NANOSECONDS);
}
/**
* Returns a string representation of the current elapsed time.
*/
@GwtIncompatible("String.format()")
@Override
public String toString() {
long nanos = elapsedNanos();
TimeUnit unit = chooseUnit(nanos);
double value = (double) nanos / NANOSECONDS.convert(1, unit);
// Too bad this functionality is not exposed as a regular method call
return String.format(Locale.ROOT, "%.4g %s", value, abbreviate(unit));
}
private static TimeUnit chooseUnit(long nanos) {
if (DAYS.convert(nanos, NANOSECONDS) > 0) {
return DAYS;
}
if (HOURS.convert(nanos, NANOSECONDS) > 0) {
return HOURS;
}
if (MINUTES.convert(nanos, NANOSECONDS) > 0) {
return MINUTES;
}
if (SECONDS.convert(nanos, NANOSECONDS) > 0) {
return SECONDS;
}
if (MILLISECONDS.convert(nanos, NANOSECONDS) > 0) {
return MILLISECONDS;
}
if (MICROSECONDS.convert(nanos, NANOSECONDS) > 0) {
return MICROSECONDS;
}
return NANOSECONDS;
}
private static String abbreviate(TimeUnit unit) {
switch (unit) {
case NANOSECONDS:
return "ns";
case MICROSECONDS:
return "\u03bcs"; // μs
case MILLISECONDS:
return "ms";
case SECONDS:
return "s";
case MINUTES:
return "min";
case HOURS:
return "h";
case DAYS:
return "d";
default:
throw new AssertionError();
}
}
}
@@ -1,240 +0,0 @@
/*
* Copyright (C) 2010 The Guava Authors
*
* 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 com.google.common.base;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import com.google.common.annotations.GwtCompatible;
import com.google.common.annotations.VisibleForTesting;
import java.util.Formatter;
import javax.annotation.CheckReturnValue;
import javax.annotation.Nullable;
/**
* Static utility methods pertaining to {@code String} or {@code CharSequence}
* instances.
*
* @author Kevin Bourrillion
* @since 3.0
*/
@CheckReturnValue
@GwtCompatible
public final class Strings {
private Strings() {}
/**
* Returns the given string if it is non-null; the empty string otherwise.
*
* @param string the string to test and possibly return
* @return {@code string} itself if it is non-null; {@code ""} if it is null
*/
public static String nullToEmpty(@Nullable String string) {
return (string == null) ? "" : string;
}
/**
* Returns the given string if it is nonempty; {@code null} otherwise.
*
* @param string the string to test and possibly return
* @return {@code string} itself if it is nonempty; {@code null} if it is
* empty or null
*/
@Nullable
public static String emptyToNull(@Nullable String string) {
return isNullOrEmpty(string) ? null : string;
}
/**
* Returns {@code true} if the given string is null or is the empty string.
*
* <p>Consider normalizing your string references with {@link #nullToEmpty}.
* If you do, you can use {@link String#isEmpty()} instead of this
* method, and you won't need special null-safe forms of methods like {@link
* String#toUpperCase} either. Or, if you'd like to normalize "in the other
* direction," converting empty strings to {@code null}, you can use {@link
* #emptyToNull}.
*
* @param string a string reference to check
* @return {@code true} if the string is null or is the empty string
*/
public static boolean isNullOrEmpty(@Nullable String string) {
return string == null || string.length() == 0; // string.isEmpty() in Java 6
}
/**
* Returns a string, of length at least {@code minLength}, consisting of
* {@code string} prepended with as many copies of {@code padChar} as are
* necessary to reach that length. For example,
*
* <ul>
* <li>{@code padStart("7", 3, '0')} returns {@code "007"}
* <li>{@code padStart("2010", 3, '0')} returns {@code "2010"}
* </ul>
*
* <p>See {@link Formatter} for a richer set of formatting capabilities.
*
* @param string the string which should appear at the end of the result
* @param minLength the minimum length the resulting string must have. Can be
* zero or negative, in which case the input string is always returned.
* @param padChar the character to insert at the beginning of the result until
* the minimum length is reached
* @return the padded string
*/
public static String padStart(String string, int minLength, char padChar) {
checkNotNull(string); // eager for GWT.
if (string.length() >= minLength) {
return string;
}
StringBuilder sb = new StringBuilder(minLength);
for (int i = string.length(); i < minLength; i++) {
sb.append(padChar);
}
sb.append(string);
return sb.toString();
}
/**
* Returns a string, of length at least {@code minLength}, consisting of
* {@code string} appended with as many copies of {@code padChar} as are
* necessary to reach that length. For example,
*
* <ul>
* <li>{@code padEnd("4.", 5, '0')} returns {@code "4.000"}
* <li>{@code padEnd("2010", 3, '!')} returns {@code "2010"}
* </ul>
*
* <p>See {@link Formatter} for a richer set of formatting capabilities.
*
* @param string the string which should appear at the beginning of the result
* @param minLength the minimum length the resulting string must have. Can be
* zero or negative, in which case the input string is always returned.
* @param padChar the character to append to the end of the result until the
* minimum length is reached
* @return the padded string
*/
public static String padEnd(String string, int minLength, char padChar) {
checkNotNull(string); // eager for GWT.
if (string.length() >= minLength) {
return string;
}
StringBuilder sb = new StringBuilder(minLength);
sb.append(string);
for (int i = string.length(); i < minLength; i++) {
sb.append(padChar);
}
return sb.toString();
}
/**
* Returns a string consisting of a specific number of concatenated copies of
* an input string. For example, {@code repeat("hey", 3)} returns the string
* {@code "heyheyhey"}.
*
* @param string any non-null string
* @param count the number of times to repeat it; a nonnegative integer
* @return a string containing {@code string} repeated {@code count} times
* (the empty string if {@code count} is zero)
* @throws IllegalArgumentException if {@code count} is negative
*/
public static String repeat(String string, int count) {
checkNotNull(string); // eager for GWT.
if (count <= 1) {
checkArgument(count >= 0, "invalid count: %s", count);
return (count == 0) ? "" : string;
}
// IF YOU MODIFY THE CODE HERE, you must update StringsRepeatBenchmark
final int len = string.length();
final long longSize = (long) len * (long) count;
final int size = (int) longSize;
if (size != longSize) {
throw new ArrayIndexOutOfBoundsException("Required array size too large: " + longSize);
}
final char[] array = new char[size];
string.getChars(0, len, array, 0);
int n;
for (n = len; n < size - n; n <<= 1) {
System.arraycopy(array, 0, array, n, n);
}
System.arraycopy(array, 0, array, n, size - n);
return new String(array);
}
/**
* Returns the longest string {@code prefix} such that
* {@code a.toString().startsWith(prefix) && b.toString().startsWith(prefix)},
* taking care not to split surrogate pairs. If {@code a} and {@code b} have
* no common prefix, returns the empty string.
*
* @since 11.0
*/
public static String commonPrefix(CharSequence a, CharSequence b) {
checkNotNull(a);
checkNotNull(b);
int maxPrefixLength = Math.min(a.length(), b.length());
int p = 0;
while (p < maxPrefixLength && a.charAt(p) == b.charAt(p)) {
p++;
}
if (validSurrogatePairAt(a, p - 1) || validSurrogatePairAt(b, p - 1)) {
p--;
}
return a.subSequence(0, p).toString();
}
/**
* Returns the longest string {@code suffix} such that
* {@code a.toString().endsWith(suffix) && b.toString().endsWith(suffix)},
* taking care not to split surrogate pairs. If {@code a} and {@code b} have
* no common suffix, returns the empty string.
*
* @since 11.0
*/
public static String commonSuffix(CharSequence a, CharSequence b) {
checkNotNull(a);
checkNotNull(b);
int maxSuffixLength = Math.min(a.length(), b.length());
int s = 0;
while (s < maxSuffixLength && a.charAt(a.length() - s - 1) == b.charAt(b.length() - s - 1)) {
s++;
}
if (validSurrogatePairAt(a, a.length() - s - 1)
|| validSurrogatePairAt(b, b.length() - s - 1)) {
s--;
}
return a.subSequence(a.length() - s, a.length()).toString();
}
/**
* True when a valid surrogate pair starts at the given {@code index} in the
* given {@code string}. Out-of-range indexes return false.
*/
@VisibleForTesting
static boolean validSurrogatePairAt(CharSequence string, int index) {
return index >= 0
&& index <= (string.length() - 2)
&& Character.isHighSurrogate(string.charAt(index))
&& Character.isLowSurrogate(string.charAt(index + 1));
}
}
@@ -1,38 +0,0 @@
/*
* Copyright (C) 2007 The Guava Authors
*
* 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 com.google.common.base;
import com.google.common.annotations.GwtCompatible;
/**
* A class that can supply objects of a single type. Semantically, this could
* be a factory, generator, builder, closure, or something else entirely. No
* guarantees are implied by this interface.
*
* @author Harry Heymann
* @since 2.0
*/
@GwtCompatible
public interface Supplier<T> {
/**
* Retrieves an instance of the appropriate type. The returned object may or
* may not be a new instance, depending on the implementation.
*
* @return an instance of the appropriate type
*/
T get();
}
@@ -1,322 +0,0 @@
/*
* Copyright (C) 2007 The Guava Authors
*
* 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 com.google.common.base;
import com.google.common.annotations.Beta;
import com.google.common.annotations.GwtCompatible;
import com.google.common.annotations.VisibleForTesting;
import java.io.Serializable;
import java.util.concurrent.TimeUnit;
import javax.annotation.CheckReturnValue;
import javax.annotation.Nullable;
/**
* Useful suppliers.
*
* <p>All methods return serializable suppliers as long as they're given
* serializable parameters.
*
* @author Laurence Gonsalves
* @author Harry Heymann
* @since 2.0
*/
@CheckReturnValue
@GwtCompatible
public final class Suppliers {
private Suppliers() {}
/**
* Returns a new supplier which is the composition of the provided function
* and supplier. In other words, the new supplier's value will be computed by
* retrieving the value from {@code supplier}, and then applying
* {@code function} to that value. Note that the resulting supplier will not
* call {@code supplier} or invoke {@code function} until it is called.
*/
public static <F, T> Supplier<T> compose(Function<? super F, T> function, Supplier<F> supplier) {
Preconditions.checkNotNull(function);
Preconditions.checkNotNull(supplier);
return new SupplierComposition<F, T>(function, supplier);
}
private static class SupplierComposition<F, T> implements Supplier<T>, Serializable {
final Function<? super F, T> function;
final Supplier<F> supplier;
SupplierComposition(Function<? super F, T> function, Supplier<F> supplier) {
this.function = function;
this.supplier = supplier;
}
@Override
public T get() {
return function.apply(supplier.get());
}
@Override
public boolean equals(@Nullable Object obj) {
if (obj instanceof SupplierComposition) {
SupplierComposition<?, ?> that = (SupplierComposition<?, ?>) obj;
return function.equals(that.function) && supplier.equals(that.supplier);
}
return false;
}
@Override
public int hashCode() {
return Objects.hashCode(function, supplier);
}
@Override
public String toString() {
return "Suppliers.compose(" + function + ", " + supplier + ")";
}
private static final long serialVersionUID = 0;
}
/**
* Returns a supplier which caches the instance retrieved during the first
* call to {@code get()} and returns that value on subsequent calls to
* {@code get()}. See:
* <a href="http://en.wikipedia.org/wiki/Memoization">memoization</a>
*
* <p>The returned supplier is thread-safe. The delegate's {@code get()}
* method will be invoked at most once. The supplier's serialized form does
* not contain the cached value, which will be recalculated when {@code get()}
* is called on the reserialized instance.
*
* <p>If {@code delegate} is an instance created by an earlier call to {@code
* memoize}, it is returned directly.
*/
public static <T> Supplier<T> memoize(Supplier<T> delegate) {
return (delegate instanceof MemoizingSupplier)
? delegate
: new MemoizingSupplier<T>(Preconditions.checkNotNull(delegate));
}
@VisibleForTesting
static class MemoizingSupplier<T> implements Supplier<T>, Serializable {
final Supplier<T> delegate;
transient volatile boolean initialized;
// "value" does not need to be volatile; visibility piggy-backs
// on volatile read of "initialized".
transient T value;
MemoizingSupplier(Supplier<T> delegate) {
this.delegate = delegate;
}
@Override
public T get() {
// A 2-field variant of Double Checked Locking.
if (!initialized) {
synchronized (this) {
if (!initialized) {
T t = delegate.get();
value = t;
initialized = true;
return t;
}
}
}
return value;
}
@Override
public String toString() {
return "Suppliers.memoize(" + delegate + ")";
}
private static final long serialVersionUID = 0;
}
/**
* Returns a supplier that caches the instance supplied by the delegate and
* removes the cached value after the specified time has passed. Subsequent
* calls to {@code get()} return the cached value if the expiration time has
* not passed. After the expiration time, a new value is retrieved, cached,
* and returned. See:
* <a href="http://en.wikipedia.org/wiki/Memoization">memoization</a>
*
* <p>The returned supplier is thread-safe. The supplier's serialized form
* does not contain the cached value, which will be recalculated when {@code
* get()} is called on the reserialized instance.
*
* @param duration the length of time after a value is created that it
* should stop being returned by subsequent {@code get()} calls
* @param unit the unit that {@code duration} is expressed in
* @throws IllegalArgumentException if {@code duration} is not positive
* @since 2.0
*/
public static <T> Supplier<T> memoizeWithExpiration(
Supplier<T> delegate, long duration, TimeUnit unit) {
return new ExpiringMemoizingSupplier<T>(delegate, duration, unit);
}
@VisibleForTesting
static class ExpiringMemoizingSupplier<T> implements Supplier<T>, Serializable {
final Supplier<T> delegate;
final long durationNanos;
transient volatile T value;
// The special value 0 means "not yet initialized".
transient volatile long expirationNanos;
ExpiringMemoizingSupplier(Supplier<T> delegate, long duration, TimeUnit unit) {
this.delegate = Preconditions.checkNotNull(delegate);
this.durationNanos = unit.toNanos(duration);
Preconditions.checkArgument(duration > 0);
}
@Override
public T get() {
// Another variant of Double Checked Locking.
//
// We use two volatile reads. We could reduce this to one by
// putting our fields into a holder class, but (at least on x86)
// the extra memory consumption and indirection are more
// expensive than the extra volatile reads.
long nanos = expirationNanos;
long now = Platform.systemNanoTime();
if (nanos == 0 || now - nanos >= 0) {
synchronized (this) {
if (nanos == expirationNanos) { // recheck for lost race
T t = delegate.get();
value = t;
nanos = now + durationNanos;
// In the very unlikely event that nanos is 0, set it to 1;
// no one will notice 1 ns of tardiness.
expirationNanos = (nanos == 0) ? 1 : nanos;
return t;
}
}
}
return value;
}
@Override
public String toString() {
// This is a little strange if the unit the user provided was not NANOS,
// but we don't want to store the unit just for toString
return "Suppliers.memoizeWithExpiration(" + delegate + ", " + durationNanos + ", NANOS)";
}
private static final long serialVersionUID = 0;
}
/**
* Returns a supplier that always supplies {@code instance}.
*/
public static <T> Supplier<T> ofInstance(@Nullable T instance) {
return new SupplierOfInstance<T>(instance);
}
private static class SupplierOfInstance<T> implements Supplier<T>, Serializable {
final T instance;
SupplierOfInstance(@Nullable T instance) {
this.instance = instance;
}
@Override
public T get() {
return instance;
}
@Override
public boolean equals(@Nullable Object obj) {
if (obj instanceof SupplierOfInstance) {
SupplierOfInstance<?> that = (SupplierOfInstance<?>) obj;
return Objects.equal(instance, that.instance);
}
return false;
}
@Override
public int hashCode() {
return Objects.hashCode(instance);
}
@Override
public String toString() {
return "Suppliers.ofInstance(" + instance + ")";
}
private static final long serialVersionUID = 0;
}
/**
* Returns a supplier whose {@code get()} method synchronizes on
* {@code delegate} before calling it, making it thread-safe.
*/
public static <T> Supplier<T> synchronizedSupplier(Supplier<T> delegate) {
return new ThreadSafeSupplier<T>(Preconditions.checkNotNull(delegate));
}
private static class ThreadSafeSupplier<T> implements Supplier<T>, Serializable {
final Supplier<T> delegate;
ThreadSafeSupplier(Supplier<T> delegate) {
this.delegate = delegate;
}
@Override
public T get() {
synchronized (delegate) {
return delegate.get();
}
}
@Override
public String toString() {
return "Suppliers.synchronizedSupplier(" + delegate + ")";
}
private static final long serialVersionUID = 0;
}
/**
* Returns a function that accepts a supplier and returns the result of
* invoking {@link Supplier#get} on that supplier.
*
* @since 8.0
*/
@Beta
public static <T> Function<Supplier<T>, T> supplierFunction() {
@SuppressWarnings("unchecked") // implementation is "fully variant"
SupplierFunction<T> sf = (SupplierFunction<T>) SupplierFunctionImpl.INSTANCE;
return sf;
}
private interface SupplierFunction<T> extends Function<Supplier<T>, T> {}
private enum SupplierFunctionImpl implements SupplierFunction<Object> {
INSTANCE;
// Note: This makes T a "pass-through type"
@Override
public Object apply(Supplier<Object> input) {
return input.get();
}
@Override
public String toString() {
return "Suppliers.supplierFunction()";
}
}
}
@@ -1,380 +0,0 @@
/*
* Copyright (C) 2007 The Guava Authors
*
* 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 com.google.common.base;
import static com.google.common.base.Preconditions.checkNotNull;
import static java.util.Arrays.asList;
import static java.util.Collections.unmodifiableList;
import com.google.common.annotations.Beta;
import com.google.common.annotations.VisibleForTesting;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.AbstractList;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import javax.annotation.CheckReturnValue;
import javax.annotation.Nullable;
/**
* Static utility methods pertaining to instances of {@link Throwable}.
*
* <p>See the Guava User Guide entry on <a href=
* "https://github.com/google/guava/wiki/ThrowablesExplained">Throwables</a>.
*
* @author Kevin Bourrillion
* @author Ben Yu
* @since 1.0
*/
public final class Throwables {
private Throwables() {}
/**
* Propagates {@code throwable} exactly as-is, if and only if it is an instance of {@code
* declaredType}. Example usage:
* <pre>
* try {
* someMethodThatCouldThrowAnything();
* } catch (IKnowWhatToDoWithThisException e) {
* handle(e);
* } catch (Throwable t) {
* Throwables.propagateIfInstanceOf(t, IOException.class);
* Throwables.propagateIfInstanceOf(t, SQLException.class);
* throw Throwables.propagate(t);
* }
* </pre>
*/
public static <X extends Throwable> void propagateIfInstanceOf(
@Nullable Throwable throwable, Class<X> declaredType) throws X {
// Check for null is needed to avoid frequent JNI calls to isInstance().
if (throwable != null && declaredType.isInstance(throwable)) {
throw declaredType.cast(throwable);
}
}
/**
* Propagates {@code throwable} exactly as-is, if and only if it is an instance of {@link
* RuntimeException} or {@link Error}. Example usage:
* <pre>
* try {
* someMethodThatCouldThrowAnything();
* } catch (IKnowWhatToDoWithThisException e) {
* handle(e);
* } catch (Throwable t) {
* Throwables.propagateIfPossible(t);
* throw new RuntimeException("unexpected", t);
* }
* </pre>
*/
public static void propagateIfPossible(@Nullable Throwable throwable) {
propagateIfInstanceOf(throwable, Error.class);
propagateIfInstanceOf(throwable, RuntimeException.class);
}
/**
* Propagates {@code throwable} exactly as-is, if and only if it is an instance of {@link
* RuntimeException}, {@link Error}, or {@code declaredType}. Example usage:
* <pre>
* try {
* someMethodThatCouldThrowAnything();
* } catch (IKnowWhatToDoWithThisException e) {
* handle(e);
* } catch (Throwable t) {
* Throwables.propagateIfPossible(t, OtherException.class);
* throw new RuntimeException("unexpected", t);
* }
* </pre>
*
* @param throwable the Throwable to possibly propagate
* @param declaredType the single checked exception type declared by the calling method
*/
public static <X extends Throwable> void propagateIfPossible(
@Nullable Throwable throwable, Class<X> declaredType) throws X {
propagateIfInstanceOf(throwable, declaredType);
propagateIfPossible(throwable);
}
/**
* Propagates {@code throwable} exactly as-is, if and only if it is an instance of {@link
* RuntimeException}, {@link Error}, {@code declaredType1}, or {@code declaredType2}. In the
* unlikely case that you have three or more declared checked exception types, you can handle them
* all by invoking these methods repeatedly. See usage example in {@link
* #propagateIfPossible(Throwable, Class)}.
*
* @param throwable the Throwable to possibly propagate
* @param declaredType1 any checked exception type declared by the calling method
* @param declaredType2 any other checked exception type declared by the calling method
*/
public static <X1 extends Throwable, X2 extends Throwable> void propagateIfPossible(
@Nullable Throwable throwable, Class<X1> declaredType1, Class<X2> declaredType2)
throws X1, X2 {
checkNotNull(declaredType2);
propagateIfInstanceOf(throwable, declaredType1);
propagateIfPossible(throwable, declaredType2);
}
/**
* Propagates {@code throwable} as-is if it is an instance of {@link RuntimeException} or {@link
* Error}, or else as a last resort, wraps it in a {@code RuntimeException} and then propagates.
* <p>
* This method always throws an exception. The {@code RuntimeException} return type is only for
* client code to make Java type system happy in case a return value is required by the enclosing
* method. Example usage:
* <pre>
* T doSomething() {
* try {
* return someMethodThatCouldThrowAnything();
* } catch (IKnowWhatToDoWithThisException e) {
* return handle(e);
* } catch (Throwable t) {
* throw Throwables.propagate(t);
* }
* }
* </pre>
*
* @param throwable the Throwable to propagate
* @return nothing will ever be returned; this return type is only for your convenience, as
* illustrated in the example above
*/
public static RuntimeException propagate(Throwable throwable) {
propagateIfPossible(checkNotNull(throwable));
throw new RuntimeException(throwable);
}
/**
* Returns the innermost cause of {@code throwable}. The first throwable in a
* chain provides context from when the error or exception was initially
* detected. Example usage:
* <pre>
* assertEquals("Unable to assign a customer id", Throwables.getRootCause(e).getMessage());
* </pre>
*/
@CheckReturnValue
public static Throwable getRootCause(Throwable throwable) {
Throwable cause;
while ((cause = throwable.getCause()) != null) {
throwable = cause;
}
return throwable;
}
/**
* Gets a {@code Throwable} cause chain as a list. The first entry in the list will be {@code
* throwable} followed by its cause hierarchy. Note that this is a snapshot of the cause chain
* and will not reflect any subsequent changes to the cause chain.
*
* <p>Here's an example of how it can be used to find specific types of exceptions in the cause
* chain:
*
* <pre>
* Iterables.filter(Throwables.getCausalChain(e), IOException.class));
* </pre>
*
* @param throwable the non-null {@code Throwable} to extract causes from
* @return an unmodifiable list containing the cause chain starting with {@code throwable}
*/
@Beta // TODO(kevinb): decide best return type
@CheckReturnValue
public static List<Throwable> getCausalChain(Throwable throwable) {
checkNotNull(throwable);
List<Throwable> causes = new ArrayList<Throwable>(4);
while (throwable != null) {
causes.add(throwable);
throwable = throwable.getCause();
}
return Collections.unmodifiableList(causes);
}
/**
* Returns a string containing the result of {@link Throwable#toString() toString()}, followed by
* the full, recursive stack trace of {@code throwable}. Note that you probably should not be
* parsing the resulting string; if you need programmatic access to the stack frames, you can call
* {@link Throwable#getStackTrace()}.
*/
@CheckReturnValue
public static String getStackTraceAsString(Throwable throwable) {
StringWriter stringWriter = new StringWriter();
throwable.printStackTrace(new PrintWriter(stringWriter));
return stringWriter.toString();
}
/**
* Returns the stack trace of {@code throwable}, possibly providing slower iteration over the full
* trace but faster iteration over parts of the trace. Here, "slower" and "faster" are defined in
* comparison to the normal way to access the stack trace, {@link Throwable#getStackTrace()
* throwable.getStackTrace()}. Note, however, that this method's special implementation is not
* available for all platforms and configurations. If that implementation is unavailable, this
* method falls back to {@code getStackTrace}. Callers that require the special implementation can
* check its availability with {@link #lazyStackTraceIsLazy()}.
*
* <p>The expected (but not guaranteed) performance of the special implementation differs from
* {@code getStackTrace} in one main way: The {@code lazyStackTrace} call itself returns quickly
* by delaying the per-stack-frame work until each element is accessed. Roughly speaking:
*
* <ul>
* <li>{@code getStackTrace} takes {@code stackSize} time to return but then negligible time to
* retrieve each element of the returned list.
* <li>{@code lazyStackTrace} takes negligible time to return but then {@code 1/stackSize} time to
* retrieve each element of the returned list (probably slightly more than {@code 1/stackSize}).
* </ul>
*
* <p>Note: The special implementation does not respect calls to {@link Throwable#setStackTrace
* throwable.setStackTrace}. Instead, it always reflects the original stack trace from the
* exception's creation.
*
* @since 19.0
*/
// TODO(cpovirk): Say something about the possibility that List access could fail at runtime?
@Beta
@CheckReturnValue
public static List<StackTraceElement> lazyStackTrace(Throwable throwable) {
return lazyStackTraceIsLazy()
? jlaStackTrace(throwable)
: unmodifiableList(asList(throwable.getStackTrace()));
}
/**
* Returns whether {@link #lazyStackTrace} will use the special implementation described in its
* documentation.
*
* @since 19.0
*/
@Beta
@CheckReturnValue
public static boolean lazyStackTraceIsLazy() {
return getStackTraceElementMethod != null & getStackTraceDepthMethod != null;
}
private static List<StackTraceElement> jlaStackTrace(final Throwable t) {
checkNotNull(t);
/*
* TODO(cpovirk): Consider optimizing iterator() to catch IOOBE instead of doing bounds checks.
*
* TODO(cpovirk): Consider the UnsignedBytes pattern if it performs faster and doesn't cause
* AOSP grief.
*/
return new AbstractList<StackTraceElement>() {
@Override
public StackTraceElement get(int n) {
return (StackTraceElement)
invokeAccessibleNonThrowingMethod(getStackTraceElementMethod, jla, t, n);
}
@Override
public int size() {
return (Integer) invokeAccessibleNonThrowingMethod(getStackTraceDepthMethod, jla, t);
}
};
}
private static Object invokeAccessibleNonThrowingMethod(
Method method, Object receiver, Object... params) {
try {
return method.invoke(receiver, params);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
} catch (InvocationTargetException e) {
throw propagate(e.getCause());
}
}
/** JavaLangAccess class name to load using reflection */
private static final String JAVA_LANG_ACCESS_CLASSNAME = "sun.misc.JavaLangAccess";
/** SharedSecrets class name to load using reflection */
@VisibleForTesting static final String SHARED_SECRETS_CLASSNAME = "sun.misc.SharedSecrets";
/** Access to some fancy internal JVM internals. */
@Nullable private static final Object jla = getJLA();
/**
* The "getStackTraceElementMethod" method, only available on some JDKs so we use reflection to
* find it when available. When this is null, use the slow way.
*/
@Nullable
private static final Method getStackTraceElementMethod = (jla == null) ? null : getGetMethod();
/**
* The "getStackTraceDepth" method, only available on some JDKs so we use reflection to find it
* when available. When this is null, use the slow way.
*/
@Nullable
private static final Method getStackTraceDepthMethod = (jla == null) ? null : getSizeMethod();
/**
* Returns the JavaLangAccess class that is present in all Sun JDKs. It is not whitelisted for
* AppEngine, and not present in non-Sun JDKs.
*/
@Nullable
private static Object getJLA() {
try {
/*
* We load sun.misc.* classes using reflection since Android doesn't support these classes and
* would result in compilation failure if we directly refer to these classes.
*/
Class<?> sharedSecrets = Class.forName(SHARED_SECRETS_CLASSNAME, false, null);
Method langAccess = sharedSecrets.getMethod("getJavaLangAccess");
return langAccess.invoke(null);
} catch (ThreadDeath death) {
throw death;
} catch (Throwable t) {
/*
* This is not one of AppEngine's whitelisted classes, so even in Sun JDKs, this can fail with
* a NoClassDefFoundError. Other apps might deny access to sun.misc packages.
*/
return null;
}
}
/**
* Returns the Method that can be used to resolve an individual StackTraceElement, or null if that
* method cannot be found (it is only to be found in fairly recent JDKs).
*/
@Nullable
private static Method getGetMethod() {
return getJlaMethod("getStackTraceElement", Throwable.class, int.class);
}
/**
* Returns the Method that can be used to return the size of a stack, or null if that method
* cannot be found (it is only to be found in fairly recent JDKs).
*/
@Nullable
private static Method getSizeMethod() {
return getJlaMethod("getStackTraceDepth", Throwable.class);
}
@Nullable
private static Method getJlaMethod(String name, Class<?>... parameterTypes) throws ThreadDeath {
try {
return Class.forName(JAVA_LANG_ACCESS_CLASSNAME, false, null).getMethod(name, parameterTypes);
} catch (ThreadDeath death) {
throw death;
} catch (Throwable t) {
/*
* Either the JavaLangAccess class itself is not found, or the method is not supported on the
* JVM.
*/
return null;
}
}
}
@@ -1,67 +0,0 @@
/*
* Copyright (C) 2011 The Guava Authors
*
* 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 com.google.common.base;
import com.google.common.annotations.Beta;
import com.google.common.annotations.GwtCompatible;
import javax.annotation.CheckReturnValue;
/**
* A time source; returns a time value representing the number of nanoseconds elapsed since some
* fixed but arbitrary point in time. Note that most users should use {@link Stopwatch} instead of
* interacting with this class directly.
*
* <p><b>Warning:</b> this interface can only be used to measure elapsed time, not wall time.
*
* @author Kevin Bourrillion
* @since 10.0
* (<a href="https://github.com/google/guava/wiki/Compatibility"
* >mostly source-compatible</a> since 9.0)
*/
@Beta
@GwtCompatible
public abstract class Ticker {
/**
* Constructor for use by subclasses.
*/
protected Ticker() {}
/**
* Returns the number of nanoseconds elapsed since this ticker's fixed
* point of reference.
*/
public abstract long read();
/**
* A ticker that reads the current time using {@link System#nanoTime}.
*
* @since 10.0
*/
@CheckReturnValue
public static Ticker systemTicker() {
return SYSTEM_TICKER;
}
private static final Ticker SYSTEM_TICKER =
new Ticker() {
@Override
public long read() {
return Platform.systemNanoTime();
}
};
}
@@ -1,206 +0,0 @@
/*
* Copyright (C) 2013 The Guava Authors
*
* 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 com.google.common.base;
import static com.google.common.base.Preconditions.checkPositionIndexes;
import static java.lang.Character.MAX_SURROGATE;
import static java.lang.Character.MIN_SURROGATE;
import com.google.common.annotations.Beta;
import com.google.common.annotations.GwtCompatible;
import javax.annotation.CheckReturnValue;
/**
* Low-level, high-performance utility methods related to the {@linkplain Charsets#UTF_8 UTF-8}
* character encoding. UTF-8 is defined in section D92 of
* <a href="http://www.unicode.org/versions/Unicode6.2.0/ch03.pdf">The Unicode Standard Core
* Specification, Chapter 3</a>.
*
* <p>The variant of UTF-8 implemented by this class is the restricted definition of UTF-8
* introduced in Unicode 3.1. One implication of this is that it rejects
* <a href="http://www.unicode.org/versions/corrigendum1.html">"non-shortest form"</a> byte
* sequences, even though the JDK decoder may accept them.
*
* @author Martin Buchholz
* @author Clément Roux
* @since 16.0
*/
@Beta
@GwtCompatible
public final class Utf8 {
/**
* Returns the number of bytes in the UTF-8-encoded form of {@code sequence}. For a string,
* this method is equivalent to {@code string.getBytes(UTF_8).length}, but is more efficient in
* both time and space.
*
* @throws IllegalArgumentException if {@code sequence} contains ill-formed UTF-16 (unpaired
* surrogates)
*/
@CheckReturnValue
public static int encodedLength(CharSequence sequence) {
// Warning to maintainers: this implementation is highly optimized.
int utf16Length = sequence.length();
int utf8Length = utf16Length;
int i = 0;
// This loop optimizes for pure ASCII.
while (i < utf16Length && sequence.charAt(i) < 0x80) {
i++;
}
// This loop optimizes for chars less than 0x800.
for (; i < utf16Length; i++) {
char c = sequence.charAt(i);
if (c < 0x800) {
utf8Length += ((0x7f - c) >>> 31); // branch free!
} else {
utf8Length += encodedLengthGeneral(sequence, i);
break;
}
}
if (utf8Length < utf16Length) {
// Necessary and sufficient condition for overflow because of maximum 3x expansion
throw new IllegalArgumentException(
"UTF-8 length does not fit in int: " + (utf8Length + (1L << 32)));
}
return utf8Length;
}
private static int encodedLengthGeneral(CharSequence sequence, int start) {
int utf16Length = sequence.length();
int utf8Length = 0;
for (int i = start; i < utf16Length; i++) {
char c = sequence.charAt(i);
if (c < 0x800) {
utf8Length += (0x7f - c) >>> 31; // branch free!
} else {
utf8Length += 2;
// jdk7+: if (Character.isSurrogate(c)) {
if (MIN_SURROGATE <= c && c <= MAX_SURROGATE) {
// Check that we have a well-formed surrogate pair.
if (Character.codePointAt(sequence, i) == c) {
throw new IllegalArgumentException(unpairedSurrogateMsg(i));
}
i++;
}
}
}
return utf8Length;
}
/**
* Returns {@code true} if {@code bytes} is a <i>well-formed</i> UTF-8 byte sequence according to
* Unicode 6.0. Note that this is a stronger criterion than simply whether the bytes can be
* decoded. For example, some versions of the JDK decoder will accept "non-shortest form" byte
* sequences, but encoding never reproduces these. Such byte sequences are <i>not</i> considered
* well-formed.
*
* <p>This method returns {@code true} if and only if {@code Arrays.equals(bytes, new
* String(bytes, UTF_8).getBytes(UTF_8))} does, but is more efficient in both time and space.
*/
@CheckReturnValue
public static boolean isWellFormed(byte[] bytes) {
return isWellFormed(bytes, 0, bytes.length);
}
/**
* Returns whether the given byte array slice is a well-formed UTF-8 byte sequence, as defined by
* {@link #isWellFormed(byte[])}. Note that this can be false even when {@code
* isWellFormed(bytes)} is true.
*
* @param bytes the input buffer
* @param off the offset in the buffer of the first byte to read
* @param len the number of bytes to read from the buffer
*/
@CheckReturnValue
public static boolean isWellFormed(byte[] bytes, int off, int len) {
int end = off + len;
checkPositionIndexes(off, end, bytes.length);
// Look for the first non-ASCII character.
for (int i = off; i < end; i++) {
if (bytes[i] < 0) {
return isWellFormedSlowPath(bytes, i, end);
}
}
return true;
}
private static boolean isWellFormedSlowPath(byte[] bytes, int off, int end) {
int index = off;
while (true) {
int byte1;
// Optimize for interior runs of ASCII bytes.
do {
if (index >= end) {
return true;
}
} while ((byte1 = bytes[index++]) >= 0);
if (byte1 < (byte) 0xE0) {
// Two-byte form.
if (index == end) {
return false;
}
// Simultaneously check for illegal trailing-byte in leading position
// and overlong 2-byte form.
if (byte1 < (byte) 0xC2 || bytes[index++] > (byte) 0xBF) {
return false;
}
} else if (byte1 < (byte) 0xF0) {
// Three-byte form.
if (index + 1 >= end) {
return false;
}
int byte2 = bytes[index++];
if (byte2 > (byte) 0xBF
// Overlong? 5 most significant bits must not all be zero.
|| (byte1 == (byte) 0xE0 && byte2 < (byte) 0xA0)
// Check for illegal surrogate codepoints.
|| (byte1 == (byte) 0xED && (byte) 0xA0 <= byte2)
// Third byte trailing-byte test.
|| bytes[index++] > (byte) 0xBF) {
return false;
}
} else {
// Four-byte form.
if (index + 2 >= end) {
return false;
}
int byte2 = bytes[index++];
if (byte2 > (byte) 0xBF
// Check that 1 <= plane <= 16. Tricky optimized form of:
// if (byte1 > (byte) 0xF4
// || byte1 == (byte) 0xF0 && byte2 < (byte) 0x90
// || byte1 == (byte) 0xF4 && byte2 > (byte) 0x8F)
|| (((byte1 << 28) + (byte2 - (byte) 0x90)) >> 30) != 0
// Third byte trailing-byte test
|| bytes[index++] > (byte) 0xBF
// Fourth byte trailing-byte test
|| bytes[index++] > (byte) 0xBF) {
return false;
}
}
}
}
private static String unpairedSurrogateMsg(int i) {
return "Unpaired surrogate at index " + i;
}
private Utf8() {}
}
@@ -1,168 +0,0 @@
/*
* Copyright (C) 2013 The Guava Authors
*
* 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 com.google.common.base;
import static com.google.common.base.Preconditions.format;
import com.google.common.annotations.Beta;
import com.google.common.annotations.GwtCompatible;
import javax.annotation.Nullable;
/**
* Static convenience methods that serve the same purpose as Java language
* <a href="http://docs.oracle.com/javase/7/docs/technotes/guides/language/assert.html">
* assertions</a>, except that they are always enabled. These methods should be used instead of Java
* assertions whenever there is a chance the check may fail "in real life". Example: <pre> {@code
*
* Bill bill = remoteService.getLastUnpaidBill();
*
* // In case bug 12345 happens again we'd rather just die
* Verify.verify(bill.status() == Status.UNPAID,
* "Unexpected bill status: %s", bill.status());}</pre>
*
* <h3>Comparison to alternatives</h3>
*
* <p><b>Note:</b> In some cases the differences explained below can be subtle. When it's unclear
* which approach to use, <b>don't worry</b> too much about it; just pick something that seems
* reasonable and it will be fine.
*
* <ul>
* <li>If checking whether the <i>caller</i> has violated your method or constructor's contract
* (such as by passing an invalid argument), use the utilities of the {@link Preconditions}
* class instead.
*
* <li>If checking an <i>impossible</i> condition (which <i>cannot</i> happen unless your own class
* or its <i>trusted</i> dependencies is badly broken), this is what ordinary Java assertions
* are for. Note that assertions are not enabled by default; they are essentially considered
* "compiled comments."
*
* <li>An explicit {@code if/throw} (as illustrated below) is always acceptable; we still recommend
* using our {@link VerifyException} exception type. Throwing a plain {@link RuntimeException}
* is frowned upon.
*
* <li>Use of {@link java.util.Objects#requireNonNull(Object)} is generally discouraged, since
* {@link #verifyNotNull(Object)} and {@link Preconditions#checkNotNull(Object)} perform the
* same function with more clarity.
* </ul>
*
* <h3>Warning about performance</h3>
*
* <p>Remember that parameter values for message construction must all be computed eagerly, and
* autoboxing and varargs array creation may happen as well, even when the verification succeeds and
* the message ends up unneeded. Performance-sensitive verification checks should continue to use
* usual form: <pre> {@code
*
* Bill bill = remoteService.getLastUnpaidBill();
* if (bill.status() != Status.UNPAID) {
* throw new VerifyException("Unexpected bill status: " + bill.status());
* }}</pre>
*
* <h3>Only {@code %s} is supported</h3>
*
* <p>As with {@link Preconditions} error message template strings, only the {@code "%s"} specifier
* is supported, not the full range of {@link java.util.Formatter} specifiers. However, note that
* if the number of arguments does not match the number of occurrences of {@code "%s"} in the
* format string, {@code Verify} will still behave as expected, and will still include all argument
* values in the error message; the message will simply not be formatted exactly as intended.
*
* <h3>More information</h3>
*
* See
* <a href="https://github.com/google/guava/wiki/ConditionalFailuresExplained">Conditional
* failures explained</a> in the Guava User Guide for advice on when this class should be used.
*
* @since 17.0
*/
@Beta
@GwtCompatible
public final class Verify {
/**
* Ensures that {@code expression} is {@code true}, throwing a {@code VerifyException} with no
* message otherwise.
*
* @throws VerifyException if {@code expression} is {@code false}
*/
public static void verify(boolean expression) {
if (!expression) {
throw new VerifyException();
}
}
/**
* Ensures that {@code expression} is {@code true}, throwing a {@code VerifyException} with a
* custom message otherwise.
*
* @param expression a boolean expression
* @param errorMessageTemplate a template for the exception message should the
* check fail. The message is formed by replacing each {@code %s}
* placeholder in the template with an argument. These are matched by
* position - the first {@code %s} gets {@code errorMessageArgs[0]}, etc.
* Unmatched arguments will be appended to the formatted message in square
* braces. Unmatched placeholders will be left as-is.
* @param errorMessageArgs the arguments to be substituted into the message
* template. Arguments are converted to strings using
* {@link String#valueOf(Object)}.
* @throws VerifyException if {@code expression} is {@code false}
*/
public static void verify(
boolean expression,
@Nullable String errorMessageTemplate,
@Nullable Object... errorMessageArgs) {
if (!expression) {
throw new VerifyException(format(errorMessageTemplate, errorMessageArgs));
}
}
/**
* Ensures that {@code reference} is non-null, throwing a {@code VerifyException} with a default
* message otherwise.
*
* @return {@code reference}, guaranteed to be non-null, for convenience
* @throws VerifyException if {@code reference} is {@code null}
*/
public static <T> T verifyNotNull(@Nullable T reference) {
return verifyNotNull(reference, "expected a non-null reference");
}
/**
* Ensures that {@code reference} is non-null, throwing a {@code VerifyException} with a custom
* message otherwise.
*
* @param errorMessageTemplate a template for the exception message should the
* check fail. The message is formed by replacing each {@code %s}
* placeholder in the template with an argument. These are matched by
* position - the first {@code %s} gets {@code errorMessageArgs[0]}, etc.
* Unmatched arguments will be appended to the formatted message in square
* braces. Unmatched placeholders will be left as-is.
* @param errorMessageArgs the arguments to be substituted into the message
* template. Arguments are converted to strings using
* {@link String#valueOf(Object)}.
* @return {@code reference}, guaranteed to be non-null, for convenience
* @throws VerifyException if {@code reference} is {@code null}
*/
public static <T> T verifyNotNull(
@Nullable T reference,
@Nullable String errorMessageTemplate,
@Nullable Object... errorMessageArgs) {
verify(reference != null, errorMessageTemplate, errorMessageArgs);
return reference;
}
// TODO(kevinb): consider <T> T verifySingleton(Iterable<T>) to take over for
// Iterables.getOnlyElement()
private Verify() {}
}
@@ -1,59 +0,0 @@
/*
* Copyright (C) 2013 The Guava Authors
*
* 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 com.google.common.base;
import com.google.common.annotations.Beta;
import com.google.common.annotations.GwtCompatible;
import javax.annotation.Nullable;
/**
* Exception thrown upon the failure of a
* <a href="https://github.com/google/guava/wiki/ConditionalFailuresExplained">verification
* check</a>, including those performed by the convenience methods of the {@link Verify} class.
*
* @since 17.0
*/
@Beta
@GwtCompatible
public class VerifyException extends RuntimeException {
/** Constructs a {@code VerifyException} with no message. */
public VerifyException() {}
/** Constructs a {@code VerifyException} with the message {@code message}. */
public VerifyException(@Nullable String message) {
super(message);
}
/**
* Constructs a {@code VerifyException} with the cause {@code cause} and a message that is
* {@code null} if {@code cause} is null, and {@code cause.toString()} otherwise.
*
* @since 19.0
*/
public VerifyException(@Nullable Throwable cause) {
super(cause);
}
/**
* Constructs a {@code VerifyException} with the message {@code message} and the cause
* {@code cause}.
*
* @since 19.0
*/
public VerifyException(@Nullable String message, @Nullable Throwable cause) {
super(message, cause);
}
}
@@ -1,213 +0,0 @@
/*
* Copyright (C) 2008 The Guava Authors
*
* 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 com.google.common.base.internal;
import java.lang.ref.PhantomReference;
import java.lang.ref.Reference;
import java.lang.ref.ReferenceQueue;
import java.lang.ref.WeakReference;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import com.google.common.logging.Level;
import com.google.common.logging.Logger;
/**
* Thread that finalizes referents. All references should implement
* {@code com.google.common.base.FinalizableReference}.
*
* <p>While this class is public, we consider it to be *internal* and not part
* of our published API. It is public so we can access it reflectively across
* class loaders in secure environments.
*
* <p>This class can't depend on other Guava code. If we were
* to load this class in the same class loader as the rest of
* Guava, this thread would keep an indirect strong reference
* to the class loader and prevent it from being garbage collected. This
* poses a problem for environments where you want to throw away the class
* loader. For example, dynamically reloading a web application or unloading
* an OSGi bundle.
*
* <p>{@code com.google.common.base.FinalizableReferenceQueue} loads this class
* in its own class loader. That way, this class doesn't prevent the main
* class loader from getting garbage collected, and this class can detect when
* the main class loader has been garbage collected and stop itself.
*/
public class Finalizer implements Runnable {
private static final Logger logger = Logger.getLogger(Finalizer.class.getName());
/** Name of FinalizableReference.class. */
private static final String FINALIZABLE_REFERENCE = "com.google.common.base.FinalizableReference";
/**
* Starts the Finalizer thread. FinalizableReferenceQueue calls this method
* reflectively.
*
* @param finalizableReferenceClass FinalizableReference.class.
* @param queue a reference queue that the thread will poll.
* @param frqReference a phantom reference to the FinalizableReferenceQueue, which will be
* queued either when the FinalizableReferenceQueue is no longer referenced anywhere, or when
* its close() method is called.
*/
public static void startFinalizer(
Class<?> finalizableReferenceClass,
ReferenceQueue<Object> queue,
PhantomReference<Object> frqReference) {
/*
* We use FinalizableReference.class for two things:
*
* 1) To invoke FinalizableReference.finalizeReferent()
*
* 2) To detect when FinalizableReference's class loader has to be garbage
* collected, at which point, Finalizer can stop running
*/
if (!finalizableReferenceClass.getName().equals(FINALIZABLE_REFERENCE)) {
throw new IllegalArgumentException("Expected " + FINALIZABLE_REFERENCE + ".");
}
Finalizer finalizer = new Finalizer(finalizableReferenceClass, queue, frqReference);
Thread thread = new Thread(finalizer);
thread.setName(Finalizer.class.getName());
thread.setDaemon(true);
try {
if (inheritableThreadLocals != null) {
inheritableThreadLocals.set(thread, null);
}
} catch (Throwable t) {
logger.log(
Level.INFO,
"Failed to clear thread local values inherited by reference finalizer thread.",
t);
}
thread.start();
}
private final WeakReference<Class<?>> finalizableReferenceClassReference;
private final PhantomReference<Object> frqReference;
private final ReferenceQueue<Object> queue;
private static final Field inheritableThreadLocals = getInheritableThreadLocalsField();
/** Constructs a new finalizer thread. */
private Finalizer(
Class<?> finalizableReferenceClass,
ReferenceQueue<Object> queue,
PhantomReference<Object> frqReference) {
this.queue = queue;
this.finalizableReferenceClassReference =
new WeakReference<Class<?>>(finalizableReferenceClass);
// Keep track of the FRQ that started us so we know when to stop.
this.frqReference = frqReference;
}
/**
* Loops continuously, pulling references off the queue and cleaning them up.
*/
@SuppressWarnings("InfiniteLoopStatement")
@Override
public void run() {
while (true) {
try {
if (!cleanUp(queue.remove())) {
break;
}
} catch (InterruptedException e) {
// ignore
}
}
}
/**
* Cleans up a single reference. Catches and logs all throwables.
* @return true if the caller should continue, false if the associated FinalizableReferenceQueue
* is no longer referenced.
*/
private boolean cleanUp(Reference<?> reference) {
Method finalizeReferentMethod = getFinalizeReferentMethod();
if (finalizeReferentMethod == null) {
return false;
}
do {
/*
* This is for the benefit of phantom references. Weak and soft
* references will have already been cleared by this point.
*/
reference.clear();
if (reference == frqReference) {
/*
* The client no longer has a reference to the
* FinalizableReferenceQueue. We can stop.
*/
return false;
}
try {
finalizeReferentMethod.invoke(reference);
} catch (Throwable t) {
logger.log(Level.SEVERE, "Error cleaning up after reference.", t);
}
/*
* Loop as long as we have references available so as not to waste
* CPU looking up the Method over and over again.
*/
} while ((reference = queue.poll()) != null);
return true;
}
/**
* Looks up FinalizableReference.finalizeReferent() method.
*/
private Method getFinalizeReferentMethod() {
Class<?> finalizableReferenceClass = finalizableReferenceClassReference.get();
if (finalizableReferenceClass == null) {
/*
* FinalizableReference's class loader was reclaimed. While there's a
* chance that other finalizable references could be enqueued
* subsequently (at which point the class loader would be resurrected
* by virtue of us having a strong reference to it), we should pretty
* much just shut down and make sure we don't keep it alive any longer
* than necessary.
*/
return null;
}
try {
return finalizableReferenceClass.getMethod("finalizeReferent");
} catch (NoSuchMethodException e) {
throw new AssertionError(e);
}
}
public static Field getInheritableThreadLocalsField() {
try {
Field inheritableThreadLocals = Thread.class.getDeclaredField("inheritableThreadLocals");
inheritableThreadLocals.setAccessible(true);
return inheritableThreadLocals;
} catch (Throwable t) {
logger.log(
Level.INFO,
"Couldn't access Thread.inheritableThreadLocals. Reference finalizer threads will "
+ "inherit thread local values.");
return null;
}
}
}
@@ -1,66 +0,0 @@
/*
* Copyright (C) 2007 The Guava Authors
*
* 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.
*/
/**
* Basic utility libraries and interfaces.
*
* <p>This package is a part of the open-source
* <a href="http://guava-libraries.googlecode.com">Guava libraries</a>.
*
* <h2>Contents</h2>
*
* <h3>String-related utilities</h3>
*
* <ul>
* <li>{@link com.google.common.base.Ascii}
* <li>{@link com.google.common.base.CaseFormat}
* <li>{@link com.google.common.base.CharMatcher}
* <li>{@link com.google.common.base.Charsets}
* <li>{@link com.google.common.base.Joiner}
* <li>{@link com.google.common.base.Splitter}
* <li>{@link com.google.common.base.Strings}
* </ul>
*
* <h3>Function types</h3>
*
* <ul>
* <li>{@link com.google.common.base.Function},
* {@link com.google.common.base.Functions}
* <li>{@link com.google.common.base.Predicate},
* {@link com.google.common.base.Predicates}
* <li>{@link com.google.common.base.Equivalence}
* <li>{@link com.google.common.base.Converter}
* <li>{@link com.google.common.base.Supplier},
* {@link com.google.common.base.Suppliers}
* </ul>
*
* <h3>Other</h3>
*
* <ul>
* <li>{@link com.google.common.base.Defaults}
* <li>{@link com.google.common.base.Enums}
* <li>{@link com.google.common.base.Objects}
* <li>{@link com.google.common.base.Optional}
* <li>{@link com.google.common.base.Preconditions}
* <li>{@link com.google.common.base.Stopwatch}
* <li>{@link com.google.common.base.Throwables}
* </ul>
*
*/
@ParametersAreNonnullByDefault
package com.google.common.base;
import javax.annotation.ParametersAreNonnullByDefault;
@@ -1,274 +0,0 @@
/*
* Copyright (C) 2011 The Guava Authors
*
* 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 com.google.common.cache;
import com.google.common.annotations.GwtCompatible;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Maps;
import java.util.Map;
import java.util.concurrent.Callable;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.ExecutionException;
/**
* This class provides a skeletal implementation of the {@code Cache} interface to minimize the
* effort required to implement this interface.
*
* <p>To implement a cache, the programmer needs only to extend this class and provide an
* implementation for the {@link #put} and {@link #getIfPresent} methods. {@link #getAllPresent} is
* implemented in terms of {@link #getIfPresent}; {@link #putAll} is implemented in terms of
* {@link #put}, {@link #invalidateAll(Iterable)} is implemented in terms of {@link #invalidate}.
* The method {@link #cleanUp} is a no-op. All other methods throw an
* {@link UnsupportedOperationException}.
*
* @author Charles Fry
* @since 10.0
*/
@GwtCompatible
public abstract class AbstractCache<K, V> implements Cache<K, V> {
/** Constructor for use by subclasses. */
protected AbstractCache() {}
/**
* @since 11.0
*/
@Override
public V get(K key, Callable<? extends V> valueLoader) throws ExecutionException {
throw new UnsupportedOperationException();
}
/**
* This implementation of {@code getAllPresent} lacks any insight into the internal cache data
* structure, and is thus forced to return the query keys instead of the cached keys. This is only
* possible with an unsafe cast which requires {@code keys} to actually be of type {@code K}.
*
* {@inheritDoc}
*
* @since 11.0
*/
@Override
public ImmutableMap<K, V> getAllPresent(Iterable<?> keys) {
Map<K, V> result = Maps.newLinkedHashMap();
for (Object key : keys) {
if (!result.containsKey(key)) {
@SuppressWarnings("unchecked")
K castKey = (K) key;
V value = getIfPresent(key);
if (value != null) {
result.put(castKey, value);
}
}
}
return ImmutableMap.copyOf(result);
}
/**
* @since 11.0
*/
@Override
public void put(K key, V value) {
throw new UnsupportedOperationException();
}
/**
* @since 12.0
*/
@Override
public void putAll(Map<? extends K, ? extends V> m) {
for (Map.Entry<? extends K, ? extends V> entry : m.entrySet()) {
put(entry.getKey(), entry.getValue());
}
}
@Override
public void cleanUp() {}
@Override
public long size() {
throw new UnsupportedOperationException();
}
@Override
public void invalidate(Object key) {
throw new UnsupportedOperationException();
}
/**
* @since 11.0
*/
@Override
public void invalidateAll(Iterable<?> keys) {
for (Object key : keys) {
invalidate(key);
}
}
@Override
public void invalidateAll() {
throw new UnsupportedOperationException();
}
@Override
public CacheStats stats() {
throw new UnsupportedOperationException();
}
@Override
public ConcurrentMap<K, V> asMap() {
throw new UnsupportedOperationException();
}
/**
* Accumulates statistics during the operation of a {@link Cache} for presentation by {@link
* Cache#stats}. This is solely intended for consumption by {@code Cache} implementors.
*
* @since 10.0
*/
public interface StatsCounter {
/**
* Records cache hits. This should be called when a cache request returns a cached value.
*
* @param count the number of hits to record
* @since 11.0
*/
void recordHits(int count);
/**
* Records cache misses. This should be called when a cache request returns a value that was
* not found in the cache. This method should be called by the loading thread, as well as by
* threads blocking on the load. Multiple concurrent calls to {@link Cache} lookup methods with
* the same key on an absent value should result in a single call to either
* {@code recordLoadSuccess} or {@code recordLoadException} and multiple calls to this method,
* despite all being served by the results of a single load operation.
*
* @param count the number of misses to record
* @since 11.0
*/
void recordMisses(int count);
/**
* Records the successful load of a new entry. This should be called when a cache request
* causes an entry to be loaded, and the loading completes successfully. In contrast to
* {@link #recordMisses}, this method should only be called by the loading thread.
*
* @param loadTime the number of nanoseconds the cache spent computing or retrieving the new
* value
*/
void recordLoadSuccess(long loadTime);
/**
* Records the failed load of a new entry. This should be called when a cache request causes
* an entry to be loaded, but an exception is thrown while loading the entry. In contrast to
* {@link #recordMisses}, this method should only be called by the loading thread.
*
* @param loadTime the number of nanoseconds the cache spent computing or retrieving the new
* value prior to an exception being thrown
*/
void recordLoadException(long loadTime);
/**
* Records the eviction of an entry from the cache. This should only been called when an entry
* is evicted due to the cache's eviction strategy, and not as a result of manual {@linkplain
* Cache#invalidate invalidations}.
*/
void recordEviction();
/**
* Returns a snapshot of this counter's values. Note that this may be an inconsistent view, as
* it may be interleaved with update operations.
*/
CacheStats snapshot();
}
/**
* A thread-safe {@link StatsCounter} implementation for use by {@link Cache} implementors.
*
* @since 10.0
*/
public static final class SimpleStatsCounter implements StatsCounter {
private final LongAddable hitCount = LongAddables.create();
private final LongAddable missCount = LongAddables.create();
private final LongAddable loadSuccessCount = LongAddables.create();
private final LongAddable loadExceptionCount = LongAddables.create();
private final LongAddable totalLoadTime = LongAddables.create();
private final LongAddable evictionCount = LongAddables.create();
/**
* Constructs an instance with all counts initialized to zero.
*/
public SimpleStatsCounter() {}
/**
* @since 11.0
*/
@Override
public void recordHits(int count) {
hitCount.add(count);
}
/**
* @since 11.0
*/
@Override
public void recordMisses(int count) {
missCount.add(count);
}
@Override
public void recordLoadSuccess(long loadTime) {
loadSuccessCount.increment();
totalLoadTime.add(loadTime);
}
@Override
public void recordLoadException(long loadTime) {
loadExceptionCount.increment();
totalLoadTime.add(loadTime);
}
@Override
public void recordEviction() {
evictionCount.increment();
}
@Override
public CacheStats snapshot() {
return new CacheStats(
hitCount.sum(),
missCount.sum(),
loadSuccessCount.sum(),
loadExceptionCount.sum(),
totalLoadTime.sum(),
evictionCount.sum());
}
/**
* Increments all counters by the values in {@code other}.
*/
public void incrementBy(StatsCounter other) {
CacheStats otherStats = other.snapshot();
hitCount.add(otherStats.hitCount());
missCount.add(otherStats.missCount());
loadSuccessCount.add(otherStats.loadSuccessCount());
loadExceptionCount.add(otherStats.loadExceptionCount());
totalLoadTime.add(otherStats.totalLoadTime());
evictionCount.add(otherStats.evictionCount());
}
}
}
@@ -1,77 +0,0 @@
/*
* Copyright (C) 2011 The Guava Authors
*
* 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 com.google.common.cache;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Maps;
import com.google.common.util.concurrent.UncheckedExecutionException;
import java.util.Map;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
/**
* This class provides a skeletal implementation of the {@code Cache} interface to minimize the
* effort required to implement this interface.
*
* <p>To implement a cache, the programmer needs only to extend this class and provide an
* implementation for the {@link #get(Object)} and {@link #getIfPresent} methods.
* {@link #getUnchecked}, {@link #get(Object, Callable)}, and {@link #getAll} are implemented in
* terms of {@code get}; {@link #getAllPresent} is implemented in terms of {@code getIfPresent};
* {@link #putAll} is implemented in terms of {@link #put}, {@link #invalidateAll(Iterable)} is
* implemented in terms of {@link #invalidate}. The method {@link #cleanUp} is a no-op. All other
* methods throw an {@link UnsupportedOperationException}.
*
* @author Charles Fry
* @since 11.0
*/
public abstract class AbstractLoadingCache<K, V>
extends AbstractCache<K, V> implements LoadingCache<K, V> {
/** Constructor for use by subclasses. */
protected AbstractLoadingCache() {}
@Override
public V getUnchecked(K key) {
try {
return get(key);
} catch (ExecutionException e) {
throw new UncheckedExecutionException(e.getCause());
}
}
@Override
public ImmutableMap<K, V> getAll(Iterable<? extends K> keys) throws ExecutionException {
Map<K, V> result = Maps.newLinkedHashMap();
for (K key : keys) {
if (!result.containsKey(key)) {
result.put(key, get(key));
}
}
return ImmutableMap.copyOf(result);
}
@Override
public final V apply(K key) {
return getUnchecked(key);
}
@Override
public void refresh(K key) {
throw new UnsupportedOperationException();
}
}
@@ -1,145 +0,0 @@
/*
* Copyright (C) 2011 The Guava Authors
*
* 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 com.google.common.cache;
import com.google.common.annotations.GwtCompatible;
import com.google.common.collect.ImmutableMap;
import com.google.common.util.concurrent.ExecutionError;
import com.google.common.util.concurrent.UncheckedExecutionException;
import java.util.Map;
import java.util.concurrent.Callable;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.ExecutionException;
import javax.annotation.Nullable;
/**
* A semi-persistent mapping from keys to values. Cache entries are manually added using
* {@link #get(Object, Callable)} or {@link #put(Object, Object)}, and are stored in the cache until
* either evicted or manually invalidated.
*
* <p>Implementations of this interface are expected to be thread-safe, and can be safely accessed
* by multiple concurrent threads.
*
* @author Charles Fry
* @since 10.0
*/
@GwtCompatible
public interface Cache<K, V> {
/**
* Returns the value associated with {@code key} in this cache, or {@code null} if there is no
* cached value for {@code key}.
*
* @since 11.0
*/
@Nullable
V getIfPresent(Object key);
/**
* Returns the value associated with {@code key} in this cache, obtaining that value from
* {@code valueLoader} if necessary. No observable state associated with this cache is modified
* until loading completes. This method provides a simple substitute for the conventional
* "if cached, return; otherwise create, cache and return" pattern.
*
* <p><b>Warning:</b> as with {@link CacheLoader#load}, {@code valueLoader} <b>must not</b> return
* {@code null}; it may either return a non-null value or throw an exception.
*
* @throws ExecutionException if a checked exception was thrown while loading the value
* @throws UncheckedExecutionException if an unchecked exception was thrown while loading the
* value
* @throws ExecutionError if an error was thrown while loading the value
*
* @since 11.0
*/
V get(K key, Callable<? extends V> valueLoader) throws ExecutionException;
/**
* Returns a map of the values associated with {@code keys} in this cache. The returned map will
* only contain entries which are already present in the cache.
*
* @since 11.0
*/
ImmutableMap<K, V> getAllPresent(Iterable<?> keys);
/**
* Associates {@code value} with {@code key} in this cache. If the cache previously contained a
* value associated with {@code key}, the old value is replaced by {@code value}.
*
* <p>Prefer {@link #get(Object, Callable)} when using the conventional "if cached, return;
* otherwise create, cache and return" pattern.
*
* @since 11.0
*/
void put(K key, V value);
/**
* Copies all of the mappings from the specified map to the cache. The effect of this call is
* equivalent to that of calling {@code put(k, v)} on this map once for each mapping from key
* {@code k} to value {@code v} in the specified map. The behavior of this operation is undefined
* if the specified map is modified while the operation is in progress.
*
* @since 12.0
*/
void putAll(Map<? extends K,? extends V> m);
/**
* Discards any cached value for key {@code key}.
*/
void invalidate(Object key);
/**
* Discards any cached values for keys {@code keys}.
*
* @since 11.0
*/
void invalidateAll(Iterable<?> keys);
/**
* Discards all entries in the cache.
*/
void invalidateAll();
/**
* Returns the approximate number of entries in this cache.
*/
long size();
/**
* Returns a current snapshot of this cache's cumulative statistics. All stats are initialized
* to zero, and are monotonically increasing over the lifetime of the cache.
*
*/
CacheStats stats();
/**
* Returns a view of the entries stored in this cache as a thread-safe map. Modifications made to
* the map directly affect the cache.
*
* <p>Iterators from the returned map are at least <i>weakly consistent</i>: they are safe for
* concurrent use, but if the cache is modified (including by eviction) after the iterator is
* created, it is undefined which of the changes (if any) will be reflected in that iterator.
*/
ConcurrentMap<K, V> asMap();
/**
* Performs any pending maintenance operations needed by the cache. Exactly which activities are
* performed -- if any -- is implementation-dependent.
*/
void cleanUp();
}
@@ -1,867 +0,0 @@
/*
* Copyright (C) 2009 The Guava Authors
*
* 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 com.google.common.cache;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState;
import com.google.common.annotations.GwtCompatible;
import com.google.common.annotations.GwtIncompatible;
import com.google.common.base.Ascii;
import com.google.common.base.Equivalence;
import com.google.common.base.MoreObjects;
import com.google.common.base.Supplier;
import com.google.common.base.Suppliers;
import com.google.common.base.Ticker;
import com.google.common.cache.AbstractCache.SimpleStatsCounter;
import com.google.common.cache.AbstractCache.StatsCounter;
import com.google.common.cache.LocalCache.Strength;
import java.lang.ref.SoftReference;
import java.lang.ref.WeakReference;
import java.util.ConcurrentModificationException;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;
import com.google.common.logging.Level;
import com.google.common.logging.Logger;
import javax.annotation.CheckReturnValue;
/**
* <p>A builder of {@link LoadingCache} and {@link Cache} instances having any combination of the
* following features:
*
* <ul>
* <li>automatic loading of entries into the cache
* <li>least-recently-used eviction when a maximum size is exceeded
* <li>time-based expiration of entries, measured since last access or last write
* <li>keys automatically wrapped in {@linkplain WeakReference weak} references
* <li>values automatically wrapped in {@linkplain WeakReference weak} or
* {@linkplain SoftReference soft} references
* <li>notification of evicted (or otherwise removed) entries
* <li>accumulation of cache access statistics
* </ul>
*
*
* <p>These features are all optional; caches can be created using all or none of them. By default
* cache instances created by {@code CacheBuilder} will not perform any type of eviction.
*
* <p>Usage example: <pre> {@code
*
* LoadingCache<Key, Graph> graphs = CacheBuilder.newBuilder()
* .maximumSize(10000)
* .expireAfterWrite(10, TimeUnit.MINUTES)
* .removalListener(MY_LISTENER)
* .build(
* new CacheLoader<Key, Graph>() {
* public Graph load(Key key) throws AnyException {
* return createExpensiveGraph(key);
* }
* });}</pre>
*
* <p>Or equivalently, <pre> {@code
*
* // In real life this would come from a command-line flag or config file
* String spec = "maximumSize=10000,expireAfterWrite=10m";
*
* LoadingCache<Key, Graph> graphs = CacheBuilder.from(spec)
* .removalListener(MY_LISTENER)
* .build(
* new CacheLoader<Key, Graph>() {
* public Graph load(Key key) throws AnyException {
* return createExpensiveGraph(key);
* }
* });}</pre>
*
* <p>The returned cache is implemented as a hash table with similar performance characteristics to
* {@link ConcurrentHashMap}. It implements all optional operations of the {@link LoadingCache} and
* {@link Cache} interfaces. The {@code asMap} view (and its collection views) have <i>weakly
* consistent iterators</i>. This means that they are safe for concurrent use, but if other threads
* modify the cache after the iterator is created, it is undefined which of these changes, if any,
* are reflected in that iterator. These iterators never throw {@link
* ConcurrentModificationException}.
*
* <p><b>Note:</b> by default, the returned cache uses equality comparisons (the
* {@link Object#equals equals} method) to determine equality for keys or values. However, if
* {@link #weakKeys} was specified, the cache uses identity ({@code ==})
* comparisons instead for keys. Likewise, if {@link #weakValues} or {@link #softValues} was
* specified, the cache uses identity comparisons for values.
*
* <p>Entries are automatically evicted from the cache when any of
* {@linkplain #maximumSize(long) maximumSize}, {@linkplain #maximumWeight(long) maximumWeight},
* {@linkplain #expireAfterWrite expireAfterWrite},
* {@linkplain #expireAfterAccess expireAfterAccess}, {@linkplain #weakKeys weakKeys},
* {@linkplain #weakValues weakValues}, or {@linkplain #softValues softValues} are requested.
*
* <p>If {@linkplain #maximumSize(long) maximumSize} or
* {@linkplain #maximumWeight(long) maximumWeight} is requested entries may be evicted on each cache
* modification.
*
* <p>If {@linkplain #expireAfterWrite expireAfterWrite} or
* {@linkplain #expireAfterAccess expireAfterAccess} is requested entries may be evicted on each
* cache modification, on occasional cache accesses, or on calls to {@link Cache#cleanUp}. Expired
* entries may be counted by {@link Cache#size}, but will never be visible to read or write
* operations.
*
* <p>If {@linkplain #weakKeys weakKeys}, {@linkplain #weakValues weakValues}, or
* {@linkplain #softValues softValues} are requested, it is possible for a key or value present in
* the cache to be reclaimed by the garbage collector. Entries with reclaimed keys or values may be
* removed from the cache on each cache modification, on occasional cache accesses, or on calls to
* {@link Cache#cleanUp}; such entries may be counted in {@link Cache#size}, but will never be
* visible to read or write operations.
*
* <p>Certain cache configurations will result in the accrual of periodic maintenance tasks which
* will be performed during write operations, or during occasional read operations in the absence of
* writes. The {@link Cache#cleanUp} method of the returned cache will also perform maintenance, but
* calling it should not be necessary with a high throughput cache. Only caches built with
* {@linkplain #removalListener removalListener}, {@linkplain #expireAfterWrite expireAfterWrite},
* {@linkplain #expireAfterAccess expireAfterAccess}, {@linkplain #weakKeys weakKeys},
* {@linkplain #weakValues weakValues}, or {@linkplain #softValues softValues} perform periodic
* maintenance.
*
* <p>The caches produced by {@code CacheBuilder} are serializable, and the deserialized caches
* retain all the configuration properties of the original cache. Note that the serialized form does
* <i>not</i> include cache contents, but only configuration.
*
* <p>See the Guava User Guide article on <a href=
* "https://github.com/google/guava/wiki/CachesExplained">caching</a> for a higher-level
* explanation.
*
* @param <K> the base key type for all caches created by this builder
* @param <V> the base value type for all caches created by this builder
* @author Charles Fry
* @author Kevin Bourrillion
* @since 10.0
*/
@GwtCompatible(emulated = true)
public final class CacheBuilder<K, V> {
private static final int DEFAULT_INITIAL_CAPACITY = 16;
private static final int DEFAULT_CONCURRENCY_LEVEL = 4;
private static final int DEFAULT_EXPIRATION_NANOS = 0;
private static final int DEFAULT_REFRESH_NANOS = 0;
static final Supplier<? extends StatsCounter> NULL_STATS_COUNTER = Suppliers.ofInstance(
new StatsCounter() {
@Override
public void recordHits(int count) {}
@Override
public void recordMisses(int count) {}
@Override
public void recordLoadSuccess(long loadTime) {}
@Override
public void recordLoadException(long loadTime) {}
@Override
public void recordEviction() {}
@Override
public CacheStats snapshot() {
return EMPTY_STATS;
}
});
static final CacheStats EMPTY_STATS = new CacheStats(0, 0, 0, 0, 0, 0);
static final Supplier<StatsCounter> CACHE_STATS_COUNTER =
new Supplier<StatsCounter>() {
@Override
public StatsCounter get() {
return new SimpleStatsCounter();
}
};
enum NullListener implements RemovalListener<Object, Object> {
INSTANCE;
@Override
public void onRemoval(RemovalNotification<Object, Object> notification) {}
}
enum OneWeigher implements Weigher<Object, Object> {
INSTANCE;
@Override
public int weigh(Object key, Object value) {
return 1;
}
}
static final Ticker NULL_TICKER = new Ticker() {
@Override
public long read() {
return 0;
}
};
private static final Logger logger = Logger.getLogger(CacheBuilder.class.getName());
static final int UNSET_INT = -1;
boolean strictParsing = true;
int initialCapacity = UNSET_INT;
int concurrencyLevel = UNSET_INT;
long maximumSize = UNSET_INT;
long maximumWeight = UNSET_INT;
Weigher<? super K, ? super V> weigher;
Strength keyStrength;
Strength valueStrength;
long expireAfterWriteNanos = UNSET_INT;
long expireAfterAccessNanos = UNSET_INT;
long refreshNanos = UNSET_INT;
Equivalence<Object> keyEquivalence;
Equivalence<Object> valueEquivalence;
RemovalListener<? super K, ? super V> removalListener;
Ticker ticker;
Supplier<? extends StatsCounter> statsCounterSupplier = NULL_STATS_COUNTER;
// TODO(fry): make constructor private and update tests to use newBuilder
CacheBuilder() {}
/**
* Constructs a new {@code CacheBuilder} instance with default settings, including strong keys,
* strong values, and no automatic eviction of any kind.
*/
public static CacheBuilder<Object, Object> newBuilder() {
return new CacheBuilder<Object, Object>();
}
/**
* Constructs a new {@code CacheBuilder} instance with the settings specified in {@code spec}.
*
* @since 12.0
*/
@GwtIncompatible("To be supported")
public static CacheBuilder<Object, Object> from(CacheBuilderSpec spec) {
return spec.toCacheBuilder()
.lenientParsing();
}
/**
* Constructs a new {@code CacheBuilder} instance with the settings specified in {@code spec}.
* This is especially useful for command-line configuration of a {@code CacheBuilder}.
*
* @param spec a String in the format specified by {@link CacheBuilderSpec}
* @since 12.0
*/
@GwtIncompatible("To be supported")
public static CacheBuilder<Object, Object> from(String spec) {
return from(CacheBuilderSpec.parse(spec));
}
/**
* Enables lenient parsing. Useful for tests and spec parsing.
*/
@GwtIncompatible("To be supported")
CacheBuilder<K, V> lenientParsing() {
strictParsing = false;
return this;
}
/**
* Sets a custom {@code Equivalence} strategy for comparing keys.
*
* <p>By default, the cache uses {@link Equivalence#identity} to determine key equality when
* {@link #weakKeys} is specified, and {@link Equivalence#equals()} otherwise.
*/
@GwtIncompatible("To be supported")
CacheBuilder<K, V> keyEquivalence(Equivalence<Object> equivalence) {
checkState(keyEquivalence == null, "key equivalence was already set to %s", keyEquivalence);
keyEquivalence = checkNotNull(equivalence);
return this;
}
Equivalence<Object> getKeyEquivalence() {
return MoreObjects.firstNonNull(keyEquivalence, getKeyStrength().defaultEquivalence());
}
/**
* Sets a custom {@code Equivalence} strategy for comparing values.
*
* <p>By default, the cache uses {@link Equivalence#identity} to determine value equality when
* {@link #weakValues} or {@link #softValues} is specified, and {@link Equivalence#equals()}
* otherwise.
*/
@GwtIncompatible("To be supported")
CacheBuilder<K, V> valueEquivalence(Equivalence<Object> equivalence) {
checkState(valueEquivalence == null,
"value equivalence was already set to %s", valueEquivalence);
this.valueEquivalence = checkNotNull(equivalence);
return this;
}
Equivalence<Object> getValueEquivalence() {
return MoreObjects.firstNonNull(valueEquivalence, getValueStrength().defaultEquivalence());
}
/**
* Sets the minimum total size for the internal hash tables. For example, if the initial capacity
* is {@code 60}, and the concurrency level is {@code 8}, then eight segments are created, each
* having a hash table of size eight. Providing a large enough estimate at construction time
* avoids the need for expensive resizing operations later, but setting this value unnecessarily
* high wastes memory.
*
* @throws IllegalArgumentException if {@code initialCapacity} is negative
* @throws IllegalStateException if an initial capacity was already set
*/
public CacheBuilder<K, V> initialCapacity(int initialCapacity) {
checkState(this.initialCapacity == UNSET_INT, "initial capacity was already set to %s",
this.initialCapacity);
checkArgument(initialCapacity >= 0);
this.initialCapacity = initialCapacity;
return this;
}
int getInitialCapacity() {
return (initialCapacity == UNSET_INT) ? DEFAULT_INITIAL_CAPACITY : initialCapacity;
}
/**
* Guides the allowed concurrency among update operations. Used as a hint for internal sizing. The
* table is internally partitioned to try to permit the indicated number of concurrent updates
* without contention. Because assignment of entries to these partitions is not necessarily
* uniform, the actual concurrency observed may vary. Ideally, you should choose a value to
* accommodate as many threads as will ever concurrently modify the table. Using a significantly
* higher value than you need can waste space and time, and a significantly lower value can lead
* to thread contention. But overestimates and underestimates within an order of magnitude do not
* usually have much noticeable impact. A value of one permits only one thread to modify the cache
* at a time, but since read operations and cache loading computations can proceed concurrently,
* this still yields higher concurrency than full synchronization.
*
* <p> Defaults to 4. <b>Note:</b>The default may change in the future. If you care about this
* value, you should always choose it explicitly.
*
* <p>The current implementation uses the concurrency level to create a fixed number of hashtable
* segments, each governed by its own write lock. The segment lock is taken once for each explicit
* write, and twice for each cache loading computation (once prior to loading the new value,
* and once after loading completes). Much internal cache management is performed at the segment
* granularity. For example, access queues and write queues are kept per segment when they are
* required by the selected eviction algorithm. As such, when writing unit tests it is not
* uncommon to specify {@code concurrencyLevel(1)} in order to achieve more deterministic eviction
* behavior.
*
* <p>Note that future implementations may abandon segment locking in favor of more advanced
* concurrency controls.
*
* @throws IllegalArgumentException if {@code concurrencyLevel} is nonpositive
* @throws IllegalStateException if a concurrency level was already set
*/
public CacheBuilder<K, V> concurrencyLevel(int concurrencyLevel) {
checkState(this.concurrencyLevel == UNSET_INT, "concurrency level was already set to %s",
this.concurrencyLevel);
checkArgument(concurrencyLevel > 0);
this.concurrencyLevel = concurrencyLevel;
return this;
}
int getConcurrencyLevel() {
return (concurrencyLevel == UNSET_INT) ? DEFAULT_CONCURRENCY_LEVEL : concurrencyLevel;
}
/**
* Specifies the maximum number of entries the cache may contain. Note that the cache <b>may evict
* an entry before this limit is exceeded</b>. As the cache size grows close to the maximum, the
* cache evicts entries that are less likely to be used again. For example, the cache may evict an
* entry because it hasn't been used recently or very often.
*
* <p>When {@code size} is zero, elements will be evicted immediately after being loaded into the
* cache. This can be useful in testing, or to disable caching temporarily without a code change.
*
* <p>This feature cannot be used in conjunction with {@link #maximumWeight}.
*
* @param size the maximum size of the cache
* @throws IllegalArgumentException if {@code size} is negative
* @throws IllegalStateException if a maximum size or weight was already set
*/
public CacheBuilder<K, V> maximumSize(long size) {
checkState(this.maximumSize == UNSET_INT, "maximum size was already set to %s",
this.maximumSize);
checkState(this.maximumWeight == UNSET_INT, "maximum weight was already set to %s",
this.maximumWeight);
checkState(this.weigher == null, "maximum size can not be combined with weigher");
checkArgument(size >= 0, "maximum size must not be negative");
this.maximumSize = size;
return this;
}
/**
* Specifies the maximum weight of entries the cache may contain. Weight is determined using the
* {@link Weigher} specified with {@link #weigher}, and use of this method requires a
* corresponding call to {@link #weigher} prior to calling {@link #build}.
*
* <p>Note that the cache <b>may evict an entry before this limit is exceeded</b>. As the cache
* size grows close to the maximum, the cache evicts entries that are less likely to be used
* again. For example, the cache may evict an entry because it hasn't been used recently or very
* often.
*
* <p>When {@code weight} is zero, elements will be evicted immediately after being loaded into
* cache. This can be useful in testing, or to disable caching temporarily without a code
* change.
*
* <p>Note that weight is only used to determine whether the cache is over capacity; it has no
* effect on selecting which entry should be evicted next.
*
* <p>This feature cannot be used in conjunction with {@link #maximumSize}.
*
* @param weight the maximum total weight of entries the cache may contain
* @throws IllegalArgumentException if {@code weight} is negative
* @throws IllegalStateException if a maximum weight or size was already set
* @since 11.0
*/
@GwtIncompatible("To be supported")
public CacheBuilder<K, V> maximumWeight(long weight) {
checkState(this.maximumWeight == UNSET_INT, "maximum weight was already set to %s",
this.maximumWeight);
checkState(this.maximumSize == UNSET_INT, "maximum size was already set to %s",
this.maximumSize);
this.maximumWeight = weight;
checkArgument(weight >= 0, "maximum weight must not be negative");
return this;
}
/**
* Specifies the weigher to use in determining the weight of entries. Entry weight is taken
* into consideration by {@link #maximumWeight(long)} when determining which entries to evict, and
* use of this method requires a corresponding call to {@link #maximumWeight(long)} prior to
* calling {@link #build}. Weights are measured and recorded when entries are inserted into the
* cache, and are thus effectively static during the lifetime of a cache entry.
*
* <p>When the weight of an entry is zero it will not be considered for size-based eviction
* (though it still may be evicted by other means).
*
* <p><b>Important note:</b> Instead of returning <em>this</em> as a {@code CacheBuilder}
* instance, this method returns {@code CacheBuilder<K1, V1>}. From this point on, either the
* original reference or the returned reference may be used to complete configuration and build
* the cache, but only the "generic" one is type-safe. That is, it will properly prevent you from
* building caches whose key or value types are incompatible with the types accepted by the
* weigher already provided; the {@code CacheBuilder} type cannot do this. For best results,
* simply use the standard method-chaining idiom, as illustrated in the documentation at top,
* configuring a {@code CacheBuilder} and building your {@link Cache} all in a single statement.
*
* <p><b>Warning:</b> if you ignore the above advice, and use this {@code CacheBuilder} to build
* a cache whose key or value type is incompatible with the weigher, you will likely experience
* a {@link ClassCastException} at some <i>undefined</i> point in the future.
*
* @param weigher the weigher to use in calculating the weight of cache entries
* @throws IllegalArgumentException if {@code size} is negative
* @throws IllegalStateException if a maximum size was already set
* @since 11.0
*/
@GwtIncompatible("To be supported")
public <K1 extends K, V1 extends V> CacheBuilder<K1, V1> weigher(
Weigher<? super K1, ? super V1> weigher) {
checkState(this.weigher == null);
if (strictParsing) {
checkState(this.maximumSize == UNSET_INT, "weigher can not be combined with maximum size",
this.maximumSize);
}
// safely limiting the kinds of caches this can produce
@SuppressWarnings("unchecked")
CacheBuilder<K1, V1> me = (CacheBuilder<K1, V1>) this;
me.weigher = checkNotNull(weigher);
return me;
}
long getMaximumWeight() {
if (expireAfterWriteNanos == 0 || expireAfterAccessNanos == 0) {
return 0;
}
return (weigher == null) ? maximumSize : maximumWeight;
}
// Make a safe contravariant cast now so we don't have to do it over and over.
@SuppressWarnings("unchecked")
<K1 extends K, V1 extends V> Weigher<K1, V1> getWeigher() {
return (Weigher<K1, V1>) MoreObjects.firstNonNull(weigher, OneWeigher.INSTANCE);
}
/**
* Specifies that each key (not value) stored in the cache should be wrapped in a {@link
* WeakReference} (by default, strong references are used).
*
* <p><b>Warning:</b> when this method is used, the resulting cache will use identity ({@code ==})
* comparison to determine equality of keys.
*
* <p>Entries with keys that have been garbage collected may be counted in {@link Cache#size},
* but will never be visible to read or write operations; such entries are cleaned up as part of
* the routine maintenance described in the class javadoc.
*
* @throws IllegalStateException if the key strength was already set
*/
@GwtIncompatible("java.lang.ref.WeakReference")
public CacheBuilder<K, V> weakKeys() {
return setKeyStrength(Strength.WEAK);
}
CacheBuilder<K, V> setKeyStrength(Strength strength) {
checkState(keyStrength == null, "Key strength was already set to %s", keyStrength);
keyStrength = checkNotNull(strength);
return this;
}
Strength getKeyStrength() {
return MoreObjects.firstNonNull(keyStrength, Strength.STRONG);
}
/**
* Specifies that each value (not key) stored in the cache should be wrapped in a
* {@link WeakReference} (by default, strong references are used).
*
* <p>Weak values will be garbage collected once they are weakly reachable. This makes them a poor
* candidate for caching; consider {@link #softValues} instead.
*
* <p><b>Note:</b> when this method is used, the resulting cache will use identity ({@code ==})
* comparison to determine equality of values.
*
* <p>Entries with values that have been garbage collected may be counted in {@link Cache#size},
* but will never be visible to read or write operations; such entries are cleaned up as part of
* the routine maintenance described in the class javadoc.
*
* @throws IllegalStateException if the value strength was already set
*/
@GwtIncompatible("java.lang.ref.WeakReference")
public CacheBuilder<K, V> weakValues() {
return setValueStrength(Strength.WEAK);
}
/**
* Specifies that each value (not key) stored in the cache should be wrapped in a
* {@link SoftReference} (by default, strong references are used). Softly-referenced objects will
* be garbage-collected in a <i>globally</i> least-recently-used manner, in response to memory
* demand.
*
* <p><b>Warning:</b> in most circumstances it is better to set a per-cache {@linkplain
* #maximumSize(long) maximum size} instead of using soft references. You should only use this
* method if you are well familiar with the practical consequences of soft references.
*
* <p><b>Note:</b> when this method is used, the resulting cache will use identity ({@code ==})
* comparison to determine equality of values.
*
* <p>Entries with values that have been garbage collected may be counted in {@link Cache#size},
* but will never be visible to read or write operations; such entries are cleaned up as part of
* the routine maintenance described in the class javadoc.
*
* @throws IllegalStateException if the value strength was already set
*/
@GwtIncompatible("java.lang.ref.SoftReference")
public CacheBuilder<K, V> softValues() {
return setValueStrength(Strength.SOFT);
}
CacheBuilder<K, V> setValueStrength(Strength strength) {
checkState(valueStrength == null, "Value strength was already set to %s", valueStrength);
valueStrength = checkNotNull(strength);
return this;
}
Strength getValueStrength() {
return MoreObjects.firstNonNull(valueStrength, Strength.STRONG);
}
/**
* Specifies that each entry should be automatically removed from the cache once a fixed duration
* has elapsed after the entry's creation, or the most recent replacement of its value.
*
* <p>When {@code duration} is zero, this method hands off to
* {@link #maximumSize(long) maximumSize}{@code (0)}, ignoring any otherwise-specificed maximum
* size or weight. This can be useful in testing, or to disable caching temporarily without a code
* change.
*
* <p>Expired entries may be counted in {@link Cache#size}, but will never be visible to read or
* write operations. Expired entries are cleaned up as part of the routine maintenance described
* in the class javadoc.
*
* @param duration the length of time after an entry is created that it should be automatically
* removed
* @param unit the unit that {@code duration} is expressed in
* @throws IllegalArgumentException if {@code duration} is negative
* @throws IllegalStateException if the time to live or time to idle was already set
*/
public CacheBuilder<K, V> expireAfterWrite(long duration, TimeUnit unit) {
checkState(expireAfterWriteNanos == UNSET_INT, "expireAfterWrite was already set to %s ns",
expireAfterWriteNanos);
checkArgument(duration >= 0, "duration cannot be negative: %s %s", duration, unit);
this.expireAfterWriteNanos = unit.toNanos(duration);
return this;
}
long getExpireAfterWriteNanos() {
return (expireAfterWriteNanos == UNSET_INT) ? DEFAULT_EXPIRATION_NANOS : expireAfterWriteNanos;
}
/**
* Specifies that each entry should be automatically removed from the cache once a fixed duration
* has elapsed after the entry's creation, the most recent replacement of its value, or its last
* access. Access time is reset by all cache read and write operations (including
* {@code Cache.asMap().get(Object)} and {@code Cache.asMap().put(K, V)}), but not by operations
* on the collection-views of {@link Cache#asMap}.
*
* <p>When {@code duration} is zero, this method hands off to
* {@link #maximumSize(long) maximumSize}{@code (0)}, ignoring any otherwise-specificed maximum
* size or weight. This can be useful in testing, or to disable caching temporarily without a code
* change.
*
* <p>Expired entries may be counted in {@link Cache#size}, but will never be visible to read or
* write operations. Expired entries are cleaned up as part of the routine maintenance described
* in the class javadoc.
*
* @param duration the length of time after an entry is last accessed that it should be
* automatically removed
* @param unit the unit that {@code duration} is expressed in
* @throws IllegalArgumentException if {@code duration} is negative
* @throws IllegalStateException if the time to idle or time to live was already set
*/
public CacheBuilder<K, V> expireAfterAccess(long duration, TimeUnit unit) {
checkState(expireAfterAccessNanos == UNSET_INT, "expireAfterAccess was already set to %s ns",
expireAfterAccessNanos);
checkArgument(duration >= 0, "duration cannot be negative: %s %s", duration, unit);
this.expireAfterAccessNanos = unit.toNanos(duration);
return this;
}
long getExpireAfterAccessNanos() {
return (expireAfterAccessNanos == UNSET_INT)
? DEFAULT_EXPIRATION_NANOS : expireAfterAccessNanos;
}
/**
* Specifies that active entries are eligible for automatic refresh once a fixed duration has
* elapsed after the entry's creation, or the most recent replacement of its value. The semantics
* of refreshes are specified in {@link LoadingCache#refresh}, and are performed by calling
* {@link CacheLoader#reload}.
*
* <p>As the default implementation of {@link CacheLoader#reload} is synchronous, it is
* recommended that users of this method override {@link CacheLoader#reload} with an asynchronous
* implementation; otherwise refreshes will be performed during unrelated cache read and write
* operations.
*
* <p>Currently automatic refreshes are performed when the first stale request for an entry
* occurs. The request triggering refresh will make a blocking call to {@link CacheLoader#reload}
* and immediately return the new value if the returned future is complete, and the old value
* otherwise.
*
* <p><b>Note:</b> <i>all exceptions thrown during refresh will be logged and then swallowed</i>.
*
* @param duration the length of time after an entry is created that it should be considered
* stale, and thus eligible for refresh
* @param unit the unit that {@code duration} is expressed in
* @throws IllegalArgumentException if {@code duration} is negative
* @throws IllegalStateException if the refresh interval was already set
* @since 11.0
*/
@GwtIncompatible("To be supported (synchronously).")
public CacheBuilder<K, V> refreshAfterWrite(long duration, TimeUnit unit) {
checkNotNull(unit);
checkState(refreshNanos == UNSET_INT, "refresh was already set to %s ns", refreshNanos);
checkArgument(duration > 0, "duration must be positive: %s %s", duration, unit);
this.refreshNanos = unit.toNanos(duration);
return this;
}
long getRefreshNanos() {
return (refreshNanos == UNSET_INT) ? DEFAULT_REFRESH_NANOS : refreshNanos;
}
/**
* Specifies a nanosecond-precision time source for this cache. By default,
* {@link System#nanoTime} is used.
*
* <p>The primary intent of this method is to facilitate testing of caches with a fake or mock
* time source.
*
* @throws IllegalStateException if a ticker was already set
*/
public CacheBuilder<K, V> ticker(Ticker ticker) {
checkState(this.ticker == null);
this.ticker = checkNotNull(ticker);
return this;
}
Ticker getTicker(boolean recordsTime) {
if (ticker != null) {
return ticker;
}
return recordsTime ? Ticker.systemTicker() : NULL_TICKER;
}
/**
* Specifies a listener instance that caches should notify each time an entry is removed for any
* {@linkplain RemovalCause reason}. Each cache created by this builder will invoke this listener
* as part of the routine maintenance described in the class documentation above.
*
* <p><b>Warning:</b> after invoking this method, do not continue to use <i>this</i> cache
* builder reference; instead use the reference this method <i>returns</i>. At runtime, these
* point to the same instance, but only the returned reference has the correct generic type
* information so as to ensure type safety. For best results, use the standard method-chaining
* idiom illustrated in the class documentation above, configuring a builder and building your
* cache in a single statement. Failure to heed this advice can result in a {@link
* ClassCastException} being thrown by a cache operation at some <i>undefined</i> point in the
* future.
*
* <p><b>Warning:</b> any exception thrown by {@code listener} will <i>not</i> be propagated to
* the {@code Cache} user, only logged via a {@link Logger}.
*
* @return the cache builder reference that should be used instead of {@code this} for any
* remaining configuration and cache building
* @throws IllegalStateException if a removal listener was already set
*/
@CheckReturnValue
public <K1 extends K, V1 extends V> CacheBuilder<K1, V1> removalListener(
RemovalListener<? super K1, ? super V1> listener) {
checkState(this.removalListener == null);
// safely limiting the kinds of caches this can produce
@SuppressWarnings("unchecked")
CacheBuilder<K1, V1> me = (CacheBuilder<K1, V1>) this;
me.removalListener = checkNotNull(listener);
return me;
}
// Make a safe contravariant cast now so we don't have to do it over and over.
@SuppressWarnings("unchecked")
<K1 extends K, V1 extends V> RemovalListener<K1, V1> getRemovalListener() {
return (RemovalListener<K1, V1>)
MoreObjects.firstNonNull(removalListener, NullListener.INSTANCE);
}
/**
* Enable the accumulation of {@link CacheStats} during the operation of the cache. Without this
* {@link Cache#stats} will return zero for all statistics. Note that recording stats requires
* bookkeeping to be performed with each operation, and thus imposes a performance penalty on
* cache operation.
*
* @since 12.0 (previously, stats collection was automatic)
*/
public CacheBuilder<K, V> recordStats() {
statsCounterSupplier = CACHE_STATS_COUNTER;
return this;
}
boolean isRecordingStats() {
return statsCounterSupplier == CACHE_STATS_COUNTER;
}
Supplier<? extends StatsCounter> getStatsCounterSupplier() {
return statsCounterSupplier;
}
/**
* Builds a cache, which either returns an already-loaded value for a given key or atomically
* computes or retrieves it using the supplied {@code CacheLoader}. If another thread is currently
* loading the value for this key, simply waits for that thread to finish and returns its
* loaded value. Note that multiple threads can concurrently load values for distinct keys.
*
* <p>This method does not alter the state of this {@code CacheBuilder} instance, so it can be
* invoked again to create multiple independent caches.
*
* @param loader the cache loader used to obtain new values
* @return a cache having the requested features
*/
public <K1 extends K, V1 extends V> LoadingCache<K1, V1> build(
CacheLoader<? super K1, V1> loader) {
checkWeightWithWeigher();
return new LocalCache.LocalLoadingCache<K1, V1>(this, loader);
}
/**
* Builds a cache which does not automatically load values when keys are requested.
*
* <p>Consider {@link #build(CacheLoader)} instead, if it is feasible to implement a
* {@code CacheLoader}.
*
* <p>This method does not alter the state of this {@code CacheBuilder} instance, so it can be
* invoked again to create multiple independent caches.
*
* @return a cache having the requested features
* @since 11.0
*/
public <K1 extends K, V1 extends V> Cache<K1, V1> build() {
checkWeightWithWeigher();
checkNonLoadingCache();
return new LocalCache.LocalManualCache<K1, V1>(this);
}
private void checkNonLoadingCache() {
checkState(refreshNanos == UNSET_INT, "refreshAfterWrite requires a LoadingCache");
}
private void checkWeightWithWeigher() {
if (weigher == null) {
checkState(maximumWeight == UNSET_INT, "maximumWeight requires weigher");
} else {
if (strictParsing) {
checkState(maximumWeight != UNSET_INT, "weigher requires maximumWeight");
} else {
if (maximumWeight == UNSET_INT) {
logger.log(Level.WARNING, "ignoring weigher specified without maximumWeight");
}
}
}
}
/**
* Returns a string representation for this CacheBuilder instance. The exact form of the returned
* string is not specified.
*/
@Override
public String toString() {
MoreObjects.ToStringHelper s = MoreObjects.toStringHelper(this);
if (initialCapacity != UNSET_INT) {
s.add("initialCapacity", initialCapacity);
}
if (concurrencyLevel != UNSET_INT) {
s.add("concurrencyLevel", concurrencyLevel);
}
if (maximumSize != UNSET_INT) {
s.add("maximumSize", maximumSize);
}
if (maximumWeight != UNSET_INT) {
s.add("maximumWeight", maximumWeight);
}
if (expireAfterWriteNanos != UNSET_INT) {
s.add("expireAfterWrite", expireAfterWriteNanos + "ns");
}
if (expireAfterAccessNanos != UNSET_INT) {
s.add("expireAfterAccess", expireAfterAccessNanos + "ns");
}
if (keyStrength != null) {
s.add("keyStrength", Ascii.toLowerCase(keyStrength.toString()));
}
if (valueStrength != null) {
s.add("valueStrength", Ascii.toLowerCase(valueStrength.toString()));
}
if (keyEquivalence != null) {
s.addValue("keyEquivalence");
}
if (valueEquivalence != null) {
s.addValue("valueEquivalence");
}
if (removalListener != null) {
s.addValue("removalListener");
}
return s.toString();
}
}
@@ -1,478 +0,0 @@
/*
* Copyright (C) 2011 The Guava Authors
*
* 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 com.google.common.cache;
import static com.google.common.base.Preconditions.checkArgument;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.MoreObjects;
import com.google.common.base.Objects;
import com.google.common.base.Splitter;
import com.google.common.cache.LocalCache.Strength;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import java.util.List;
import java.util.Locale;
import java.util.concurrent.TimeUnit;
import javax.annotation.Nullable;
/**
* A specification of a {@link CacheBuilder} configuration.
*
* <p>{@code CacheBuilderSpec} supports parsing configuration off of a string, which
* makes it especially useful for command-line configuration of a {@code CacheBuilder}.
*
* <p>The string syntax is a series of comma-separated keys or key-value pairs,
* each corresponding to a {@code CacheBuilder} method.
* <ul>
* <li>{@code concurrencyLevel=[integer]}: sets {@link CacheBuilder#concurrencyLevel}.
* <li>{@code initialCapacity=[integer]}: sets {@link CacheBuilder#initialCapacity}.
* <li>{@code maximumSize=[long]}: sets {@link CacheBuilder#maximumSize}.
* <li>{@code maximumWeight=[long]}: sets {@link CacheBuilder#maximumWeight}.
* <li>{@code expireAfterAccess=[duration]}: sets {@link CacheBuilder#expireAfterAccess}.
* <li>{@code expireAfterWrite=[duration]}: sets {@link CacheBuilder#expireAfterWrite}.
* <li>{@code refreshAfterWrite=[duration]}: sets {@link CacheBuilder#refreshAfterWrite}.
* <li>{@code weakKeys}: sets {@link CacheBuilder#weakKeys}.
* <li>{@code softValues}: sets {@link CacheBuilder#softValues}.
* <li>{@code weakValues}: sets {@link CacheBuilder#weakValues}.
* <li>{@code recordStats}: sets {@link CacheBuilder#recordStats}.
* </ul>
*
* <p>The set of supported keys will grow as {@code CacheBuilder} evolves, but existing keys
* will never be removed.
*
* <p>Durations are represented by an integer, followed by one of "d", "h", "m",
* or "s", representing days, hours, minutes, or seconds respectively. (There
* is currently no syntax to request expiration in milliseconds, microseconds,
* or nanoseconds.)
*
* <p>Whitespace before and after commas and equal signs is ignored. Keys may
* not be repeated; it is also illegal to use the following pairs of keys in
* a single value:
* <ul>
* <li>{@code maximumSize} and {@code maximumWeight}
* <li>{@code softValues} and {@code weakValues}
* </ul>
*
* <p>{@code CacheBuilderSpec} does not support configuring {@code CacheBuilder} methods
* with non-value parameters. These must be configured in code.
*
* <p>A new {@code CacheBuilder} can be instantiated from a {@code CacheBuilderSpec} using
* {@link CacheBuilder#from(CacheBuilderSpec)} or {@link CacheBuilder#from(String)}.
*
* @author Adam Winer
* @since 12.0
*/
public final class CacheBuilderSpec {
/** Parses a single value. */
private interface ValueParser {
void parse(CacheBuilderSpec spec, String key, @Nullable String value);
}
/** Splits each key-value pair. */
private static final Splitter KEYS_SPLITTER = Splitter.on(',').trimResults();
/** Splits the key from the value. */
private static final Splitter KEY_VALUE_SPLITTER = Splitter.on('=').trimResults();
/** Map of names to ValueParser. */
private static final ImmutableMap<String, ValueParser> VALUE_PARSERS =
ImmutableMap.<String, ValueParser>builder()
.put("initialCapacity", new InitialCapacityParser())
.put("maximumSize", new MaximumSizeParser())
.put("maximumWeight", new MaximumWeightParser())
.put("concurrencyLevel", new ConcurrencyLevelParser())
.put("weakKeys", new KeyStrengthParser(Strength.WEAK))
.put("softValues", new ValueStrengthParser(Strength.SOFT))
.put("weakValues", new ValueStrengthParser(Strength.WEAK))
.put("recordStats", new RecordStatsParser())
.put("expireAfterAccess", new AccessDurationParser())
.put("expireAfterWrite", new WriteDurationParser())
.put("refreshAfterWrite", new RefreshDurationParser())
.put("refreshInterval", new RefreshDurationParser())
.build();
@VisibleForTesting Integer initialCapacity;
@VisibleForTesting Long maximumSize;
@VisibleForTesting Long maximumWeight;
@VisibleForTesting Integer concurrencyLevel;
@VisibleForTesting Strength keyStrength;
@VisibleForTesting Strength valueStrength;
@VisibleForTesting Boolean recordStats;
@VisibleForTesting long writeExpirationDuration;
@VisibleForTesting TimeUnit writeExpirationTimeUnit;
@VisibleForTesting long accessExpirationDuration;
@VisibleForTesting TimeUnit accessExpirationTimeUnit;
@VisibleForTesting long refreshDuration;
@VisibleForTesting TimeUnit refreshTimeUnit;
/** Specification; used for toParseableString(). */
private final String specification;
private CacheBuilderSpec(String specification) {
this.specification = specification;
}
/**
* Creates a CacheBuilderSpec from a string.
*
* @param cacheBuilderSpecification the string form
*/
public static CacheBuilderSpec parse(String cacheBuilderSpecification) {
CacheBuilderSpec spec = new CacheBuilderSpec(cacheBuilderSpecification);
if (!cacheBuilderSpecification.isEmpty()) {
for (String keyValuePair : KEYS_SPLITTER.split(cacheBuilderSpecification)) {
List<String> keyAndValue = ImmutableList.copyOf(KEY_VALUE_SPLITTER.split(keyValuePair));
checkArgument(!keyAndValue.isEmpty(), "blank key-value pair");
checkArgument(keyAndValue.size() <= 2,
"key-value pair %s with more than one equals sign", keyValuePair);
// Find the ValueParser for the current key.
String key = keyAndValue.get(0);
ValueParser valueParser = VALUE_PARSERS.get(key);
checkArgument(valueParser != null, "unknown key %s", key);
String value = keyAndValue.size() == 1 ? null : keyAndValue.get(1);
valueParser.parse(spec, key, value);
}
}
return spec;
}
/**
* Returns a CacheBuilderSpec that will prevent caching.
*/
public static CacheBuilderSpec disableCaching() {
// Maximum size of zero is one way to block caching
return CacheBuilderSpec.parse("maximumSize=0");
}
/**
* Returns a CacheBuilder configured according to this instance's specification.
*/
CacheBuilder<Object, Object> toCacheBuilder() {
CacheBuilder<Object, Object> builder = CacheBuilder.newBuilder();
if (initialCapacity != null) {
builder.initialCapacity(initialCapacity);
}
if (maximumSize != null) {
builder.maximumSize(maximumSize);
}
if (maximumWeight != null) {
builder.maximumWeight(maximumWeight);
}
if (concurrencyLevel != null) {
builder.concurrencyLevel(concurrencyLevel);
}
if (keyStrength != null) {
switch (keyStrength) {
case WEAK:
builder.weakKeys();
break;
default:
throw new AssertionError();
}
}
if (valueStrength != null) {
switch (valueStrength) {
case SOFT:
builder.softValues();
break;
case WEAK:
builder.weakValues();
break;
default:
throw new AssertionError();
}
}
if (recordStats != null && recordStats) {
builder.recordStats();
}
if (writeExpirationTimeUnit != null) {
builder.expireAfterWrite(writeExpirationDuration, writeExpirationTimeUnit);
}
if (accessExpirationTimeUnit != null) {
builder.expireAfterAccess(accessExpirationDuration, accessExpirationTimeUnit);
}
if (refreshTimeUnit != null) {
builder.refreshAfterWrite(refreshDuration, refreshTimeUnit);
}
return builder;
}
/**
* Returns a string that can be used to parse an equivalent
* {@code CacheBuilderSpec}. The order and form of this representation is
* not guaranteed, except that reparsing its output will produce
* a {@code CacheBuilderSpec} equal to this instance.
*/
public String toParsableString() {
return specification;
}
/**
* Returns a string representation for this CacheBuilderSpec instance.
* The form of this representation is not guaranteed.
*/
@Override
public String toString() {
return MoreObjects.toStringHelper(this).addValue(toParsableString()).toString();
}
@Override
public int hashCode() {
return Objects.hashCode(
initialCapacity,
maximumSize,
maximumWeight,
concurrencyLevel,
keyStrength,
valueStrength,
recordStats,
durationInNanos(writeExpirationDuration, writeExpirationTimeUnit),
durationInNanos(accessExpirationDuration, accessExpirationTimeUnit),
durationInNanos(refreshDuration, refreshTimeUnit));
}
@Override
public boolean equals(@Nullable Object obj) {
if (this == obj) {
return true;
}
if (!(obj instanceof CacheBuilderSpec)) {
return false;
}
CacheBuilderSpec that = (CacheBuilderSpec) obj;
return Objects.equal(initialCapacity, that.initialCapacity)
&& Objects.equal(maximumSize, that.maximumSize)
&& Objects.equal(maximumWeight, that.maximumWeight)
&& Objects.equal(concurrencyLevel, that.concurrencyLevel)
&& Objects.equal(keyStrength, that.keyStrength)
&& Objects.equal(valueStrength, that.valueStrength)
&& Objects.equal(recordStats, that.recordStats)
&& Objects.equal(durationInNanos(writeExpirationDuration, writeExpirationTimeUnit),
durationInNanos(that.writeExpirationDuration, that.writeExpirationTimeUnit))
&& Objects.equal(durationInNanos(accessExpirationDuration, accessExpirationTimeUnit),
durationInNanos(that.accessExpirationDuration, that.accessExpirationTimeUnit))
&& Objects.equal(durationInNanos(refreshDuration, refreshTimeUnit),
durationInNanos(that.refreshDuration, that.refreshTimeUnit));
}
/**
* Converts an expiration duration/unit pair into a single Long for hashing and equality.
* Uses nanos to match CacheBuilder implementation.
*/
@Nullable private static Long durationInNanos(long duration, @Nullable TimeUnit unit) {
return (unit == null) ? null : unit.toNanos(duration);
}
/** Base class for parsing integers. */
abstract static class IntegerParser implements ValueParser {
protected abstract void parseInteger(CacheBuilderSpec spec, int value);
@Override
public void parse(CacheBuilderSpec spec, String key, String value) {
checkArgument(value != null && !value.isEmpty(), "value of key %s omitted", key);
try {
parseInteger(spec, Integer.parseInt(value));
} catch (NumberFormatException e) {
throw new IllegalArgumentException(
format("key %s value set to %s, must be integer", key, value), e);
}
}
}
/** Base class for parsing integers. */
abstract static class LongParser implements ValueParser {
protected abstract void parseLong(CacheBuilderSpec spec, long value);
@Override
public void parse(CacheBuilderSpec spec, String key, String value) {
checkArgument(value != null && !value.isEmpty(), "value of key %s omitted", key);
try {
parseLong(spec, Long.parseLong(value));
} catch (NumberFormatException e) {
throw new IllegalArgumentException(
format("key %s value set to %s, must be integer", key, value), e);
}
}
}
/** Parse initialCapacity */
static class InitialCapacityParser extends IntegerParser {
@Override
protected void parseInteger(CacheBuilderSpec spec, int value) {
checkArgument(spec.initialCapacity == null,
"initial capacity was already set to ", spec.initialCapacity);
spec.initialCapacity = value;
}
}
/** Parse maximumSize */
static class MaximumSizeParser extends LongParser {
@Override
protected void parseLong(CacheBuilderSpec spec, long value) {
checkArgument(spec.maximumSize == null,
"maximum size was already set to ", spec.maximumSize);
checkArgument(spec.maximumWeight == null,
"maximum weight was already set to ", spec.maximumWeight);
spec.maximumSize = value;
}
}
/** Parse maximumWeight */
static class MaximumWeightParser extends LongParser {
@Override
protected void parseLong(CacheBuilderSpec spec, long value) {
checkArgument(spec.maximumWeight == null,
"maximum weight was already set to ", spec.maximumWeight);
checkArgument(spec.maximumSize == null,
"maximum size was already set to ", spec.maximumSize);
spec.maximumWeight = value;
}
}
/** Parse concurrencyLevel */
static class ConcurrencyLevelParser extends IntegerParser {
@Override
protected void parseInteger(CacheBuilderSpec spec, int value) {
checkArgument(spec.concurrencyLevel == null,
"concurrency level was already set to ", spec.concurrencyLevel);
spec.concurrencyLevel = value;
}
}
/** Parse weakKeys */
static class KeyStrengthParser implements ValueParser {
private final Strength strength;
public KeyStrengthParser(Strength strength) {
this.strength = strength;
}
@Override
public void parse(CacheBuilderSpec spec, String key, @Nullable String value) {
checkArgument(value == null, "key %s does not take values", key);
checkArgument(spec.keyStrength == null, "%s was already set to %s", key, spec.keyStrength);
spec.keyStrength = strength;
}
}
/** Parse weakValues and softValues */
static class ValueStrengthParser implements ValueParser {
private final Strength strength;
public ValueStrengthParser(Strength strength) {
this.strength = strength;
}
@Override
public void parse(CacheBuilderSpec spec, String key, @Nullable String value) {
checkArgument(value == null, "key %s does not take values", key);
checkArgument(spec.valueStrength == null,
"%s was already set to %s", key, spec.valueStrength);
spec.valueStrength = strength;
}
}
/** Parse recordStats */
static class RecordStatsParser implements ValueParser {
@Override
public void parse(CacheBuilderSpec spec, String key, @Nullable String value) {
checkArgument(value == null, "recordStats does not take values");
checkArgument(spec.recordStats == null, "recordStats already set");
spec.recordStats = true;
}
}
/** Base class for parsing times with durations */
abstract static class DurationParser implements ValueParser {
protected abstract void parseDuration(
CacheBuilderSpec spec,
long duration,
TimeUnit unit);
@Override
public void parse(CacheBuilderSpec spec, String key, String value) {
checkArgument(value != null && !value.isEmpty(), "value of key %s omitted", key);
try {
char lastChar = value.charAt(value.length() - 1);
TimeUnit timeUnit;
switch (lastChar) {
case 'd':
timeUnit = TimeUnit.DAYS;
break;
case 'h':
timeUnit = TimeUnit.HOURS;
break;
case 'm':
timeUnit = TimeUnit.MINUTES;
break;
case 's':
timeUnit = TimeUnit.SECONDS;
break;
default:
throw new IllegalArgumentException(
format("key %s invalid format. was %s, must end with one of [dDhHmMsS]",
key, value));
}
long duration = Long.parseLong(value.substring(0, value.length() - 1));
parseDuration(spec, duration, timeUnit);
} catch (NumberFormatException e) {
throw new IllegalArgumentException(
format("key %s value set to %s, must be integer", key, value));
}
}
}
/** Parse expireAfterAccess */
static class AccessDurationParser extends DurationParser {
@Override protected void parseDuration(CacheBuilderSpec spec, long duration, TimeUnit unit) {
checkArgument(spec.accessExpirationTimeUnit == null, "expireAfterAccess already set");
spec.accessExpirationDuration = duration;
spec.accessExpirationTimeUnit = unit;
}
}
/** Parse expireAfterWrite */
static class WriteDurationParser extends DurationParser {
@Override protected void parseDuration(CacheBuilderSpec spec, long duration, TimeUnit unit) {
checkArgument(spec.writeExpirationTimeUnit == null, "expireAfterWrite already set");
spec.writeExpirationDuration = duration;
spec.writeExpirationTimeUnit = unit;
}
}
/** Parse refreshAfterWrite */
static class RefreshDurationParser extends DurationParser {
@Override protected void parseDuration(CacheBuilderSpec spec, long duration, TimeUnit unit) {
checkArgument(spec.refreshTimeUnit == null, "refreshAfterWrite already set");
spec.refreshDuration = duration;
spec.refreshTimeUnit = unit;
}
}
private static String format(String format, Object... args) {
return String.format(Locale.ROOT, format, args);
}
}
@@ -1,246 +0,0 @@
/*
* Copyright (C) 2011 The Guava Authors
*
* 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 com.google.common.cache;
import static com.google.common.base.Preconditions.checkNotNull;
import com.google.common.annotations.GwtCompatible;
import com.google.common.annotations.GwtIncompatible;
import com.google.common.base.Function;
import com.google.common.base.Supplier;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.ListenableFutureTask;
import java.io.Serializable;
import java.util.Map;
import java.util.concurrent.Callable;
import java.util.concurrent.Executor;
/**
* Computes or retrieves values, based on a key, for use in populating a {@link LoadingCache}.
*
* <p>Most implementations will only need to implement {@link #load}. Other methods may be
* overridden as desired.
*
* <p>Usage example: <pre> {@code
*
* CacheLoader<Key, Graph> loader = new CacheLoader<Key, Graph>() {
* public Graph load(Key key) throws AnyException {
* return createExpensiveGraph(key);
* }
* };
* LoadingCache<Key, Graph> cache = CacheBuilder.newBuilder().build(loader);}</pre>
*
* @author Charles Fry
* @since 10.0
*/
@GwtCompatible(emulated = true)
public abstract class CacheLoader<K, V> {
/**
* Constructor for use by subclasses.
*/
protected CacheLoader() {}
/**
* Computes or retrieves the value corresponding to {@code key}.
*
* @param key the non-null key whose value should be loaded
* @return the value associated with {@code key}; <b>must not be null</b>
* @throws Exception if unable to load the result
* @throws InterruptedException if this method is interrupted. {@code InterruptedException} is
* treated like any other {@code Exception} in all respects except that, when it is caught,
* the thread's interrupt status is set
*/
public abstract V load(K key) throws Exception;
/**
* Computes or retrieves a replacement value corresponding to an already-cached {@code key}. This
* method is called when an existing cache entry is refreshed by
* {@link CacheBuilder#refreshAfterWrite}, or through a call to {@link LoadingCache#refresh}.
*
* <p>This implementation synchronously delegates to {@link #load}. It is recommended that it be
* overridden with an asynchronous implementation when using
* {@link CacheBuilder#refreshAfterWrite}.
*
* <p><b>Note:</b> <i>all exceptions thrown by this method will be logged and then swallowed</i>.
*
* @param key the non-null key whose value should be loaded
* @param oldValue the non-null old value corresponding to {@code key}
* @return the future new value associated with {@code key};
* <b>must not be null, must not return null</b>
* @throws Exception if unable to reload the result
* @throws InterruptedException if this method is interrupted. {@code InterruptedException} is
* treated like any other {@code Exception} in all respects except that, when it is caught,
* the thread's interrupt status is set
* @since 11.0
*/
@GwtIncompatible("Futures")
public ListenableFuture<V> reload(K key, V oldValue) throws Exception {
checkNotNull(key);
checkNotNull(oldValue);
return Futures.immediateFuture(load(key));
}
/**
* Computes or retrieves the values corresponding to {@code keys}. This method is called by
* {@link LoadingCache#getAll}.
*
* <p>If the returned map doesn't contain all requested {@code keys} then the entries it does
* contain will be cached, but {@code getAll} will throw an exception. If the returned map
* contains extra keys not present in {@code keys} then all returned entries will be cached,
* but only the entries for {@code keys} will be returned from {@code getAll}.
*
* <p>This method should be overriden when bulk retrieval is significantly more efficient than
* many individual lookups. Note that {@link LoadingCache#getAll} will defer to individual calls
* to {@link LoadingCache#get} if this method is not overriden.
*
* @param keys the unique, non-null keys whose values should be loaded
* @return a map from each key in {@code keys} to the value associated with that key;
* <b>may not contain null values</b>
* @throws Exception if unable to load the result
* @throws InterruptedException if this method is interrupted. {@code InterruptedException} is
* treated like any other {@code Exception} in all respects except that, when it is caught,
* the thread's interrupt status is set
* @since 11.0
*/
public Map<K, V> loadAll(Iterable<? extends K> keys) throws Exception {
// This will be caught by getAll(), causing it to fall back to multiple calls to
// LoadingCache.get
throw new UnsupportedLoadingOperationException();
}
/**
* Returns a cache loader based on an <i>existing</i> function instance. Note that there's no need
* to create a <i>new</i> function just to pass it in here; just subclass {@code CacheLoader} and
* implement {@link #load load} instead.
*
* @param function the function to be used for loading values; must never return {@code null}
* @return a cache loader that loads values by passing each key to {@code function}
*/
public static <K, V> CacheLoader<K, V> from(Function<K, V> function) {
return new FunctionToCacheLoader<K, V>(function);
}
private static final class FunctionToCacheLoader<K, V>
extends CacheLoader<K, V> implements Serializable {
private final Function<K, V> computingFunction;
public FunctionToCacheLoader(Function<K, V> computingFunction) {
this.computingFunction = checkNotNull(computingFunction);
}
@Override
public V load(K key) {
return computingFunction.apply(checkNotNull(key));
}
private static final long serialVersionUID = 0;
}
/**
* Returns a cache loader based on an <i>existing</i> supplier instance. Note that there's no need
* to create a <i>new</i> supplier just to pass it in here; just subclass {@code CacheLoader} and
* implement {@link #load load} instead.
*
* @param supplier the supplier to be used for loading values; must never return {@code null}
* @return a cache loader that loads values by calling {@link Supplier#get}, irrespective of the
* key
*/
public static <V> CacheLoader<Object, V> from(Supplier<V> supplier) {
return new SupplierToCacheLoader<V>(supplier);
}
/**
* Returns a {@code CacheLoader} which wraps {@code loader}, executing calls to
* {@link CacheLoader#reload} using {@code executor}.
*
* <p>This method is useful only when {@code loader.reload} has a synchronous implementation,
* such as {@linkplain #reload the default implementation}.
*
* @since 17.0
*/
@GwtIncompatible("Executor + Futures")
public static <K, V> CacheLoader<K, V> asyncReloading(final CacheLoader<K, V> loader,
final Executor executor) {
checkNotNull(loader);
checkNotNull(executor);
return new CacheLoader<K, V>() {
@Override
public V load(K key) throws Exception {
return loader.load(key);
}
@Override
public ListenableFuture<V> reload(final K key, final V oldValue) throws Exception {
ListenableFutureTask<V> task = ListenableFutureTask.create(new Callable<V>() {
@Override
public V call() throws Exception {
return loader.reload(key, oldValue).get();
}
});
executor.execute(task);
return task;
}
@Override
public Map<K, V> loadAll(Iterable<? extends K> keys) throws Exception {
return loader.loadAll(keys);
}
};
}
private static final class SupplierToCacheLoader<V>
extends CacheLoader<Object, V> implements Serializable {
private final Supplier<V> computingSupplier;
public SupplierToCacheLoader(Supplier<V> computingSupplier) {
this.computingSupplier = checkNotNull(computingSupplier);
}
@Override
public V load(Object key) {
checkNotNull(key);
return computingSupplier.get();
}
private static final long serialVersionUID = 0;
}
/**
* Exception thrown by {@code loadAll()} to indicate that it is not supported.
*
* @since 19.0
*/
public static final class UnsupportedLoadingOperationException
extends UnsupportedOperationException {
// Package-private because this should only be thrown by loadAll() when it is not overridden.
// Cache implementors may want to catch it but should not need to be able to throw it.
UnsupportedLoadingOperationException() {}
}
/**
* Thrown to indicate that an invalid response was returned from a call to {@link CacheLoader}.
*
* @since 11.0
*/
public static final class InvalidCacheLoadException extends RuntimeException {
public InvalidCacheLoadException(String message) {
super(message);
}
}
}
@@ -1,274 +0,0 @@
/*
* Copyright (C) 2011 The Guava Authors
*
* 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 com.google.common.cache;
import static com.google.common.base.Preconditions.checkArgument;
import com.google.common.annotations.GwtCompatible;
import com.google.common.base.MoreObjects;
import com.google.common.base.Objects;
import java.util.concurrent.Callable;
import javax.annotation.Nullable;
/**
* Statistics about the performance of a {@link Cache}. Instances of this class are immutable.
*
* <p>Cache statistics are incremented according to the following rules:
*
* <ul>
* <li>When a cache lookup encounters an existing cache entry {@code hitCount} is incremented.
* <li>When a cache lookup first encounters a missing cache entry, a new entry is loaded.
* <ul>
* <li>After successfully loading an entry {@code missCount} and {@code loadSuccessCount} are
* incremented, and the total loading time, in nanoseconds, is added to
* {@code totalLoadTime}.
* <li>When an exception is thrown while loading an entry, {@code missCount} and {@code
* loadExceptionCount} are incremented, and the total loading time, in nanoseconds, is
* added to {@code totalLoadTime}.
* <li>Cache lookups that encounter a missing cache entry that is still loading will wait
* for loading to complete (whether successful or not) and then increment {@code missCount}.
* </ul>
* <li>When an entry is evicted from the cache, {@code evictionCount} is incremented.
* <li>No stats are modified when a cache entry is invalidated or manually removed.
* <li>No stats are modified by operations invoked on the {@linkplain Cache#asMap asMap} view of
* the cache.
* </ul>
*
* <p>A lookup is specifically defined as an invocation of one of the methods
* {@link LoadingCache#get(Object)}, {@link LoadingCache#getUnchecked(Object)},
* {@link Cache#get(Object, Callable)}, or {@link LoadingCache#getAll(Iterable)}.
*
* @author Charles Fry
* @since 10.0
*/
@GwtCompatible
public final class CacheStats {
private final long hitCount;
private final long missCount;
private final long loadSuccessCount;
private final long loadExceptionCount;
private final long totalLoadTime;
private final long evictionCount;
/**
* Constructs a new {@code CacheStats} instance.
*
* <p>Five parameters of the same type in a row is a bad thing, but this class is not constructed
* by end users and is too fine-grained for a builder.
*/
public CacheStats(long hitCount, long missCount, long loadSuccessCount,
long loadExceptionCount, long totalLoadTime, long evictionCount) {
checkArgument(hitCount >= 0);
checkArgument(missCount >= 0);
checkArgument(loadSuccessCount >= 0);
checkArgument(loadExceptionCount >= 0);
checkArgument(totalLoadTime >= 0);
checkArgument(evictionCount >= 0);
this.hitCount = hitCount;
this.missCount = missCount;
this.loadSuccessCount = loadSuccessCount;
this.loadExceptionCount = loadExceptionCount;
this.totalLoadTime = totalLoadTime;
this.evictionCount = evictionCount;
}
/**
* Returns the number of times {@link Cache} lookup methods have returned either a cached or
* uncached value. This is defined as {@code hitCount + missCount}.
*/
public long requestCount() {
return hitCount + missCount;
}
/**
* Returns the number of times {@link Cache} lookup methods have returned a cached value.
*/
public long hitCount() {
return hitCount;
}
/**
* Returns the ratio of cache requests which were hits. This is defined as
* {@code hitCount / requestCount}, or {@code 1.0} when {@code requestCount == 0}.
* Note that {@code hitRate + missRate =~ 1.0}.
*/
public double hitRate() {
long requestCount = requestCount();
return (requestCount == 0) ? 1.0 : (double) hitCount / requestCount;
}
/**
* Returns the number of times {@link Cache} lookup methods have returned an uncached (newly
* loaded) value, or null. Multiple concurrent calls to {@link Cache} lookup methods on an absent
* value can result in multiple misses, all returning the results of a single cache load
* operation.
*/
public long missCount() {
return missCount;
}
/**
* Returns the ratio of cache requests which were misses. This is defined as
* {@code missCount / requestCount}, or {@code 0.0} when {@code requestCount == 0}.
* Note that {@code hitRate + missRate =~ 1.0}. Cache misses include all requests which
* weren't cache hits, including requests which resulted in either successful or failed loading
* attempts, and requests which waited for other threads to finish loading. It is thus the case
* that {@code missCount &gt;= loadSuccessCount + loadExceptionCount}. Multiple
* concurrent misses for the same key will result in a single load operation.
*/
public double missRate() {
long requestCount = requestCount();
return (requestCount == 0) ? 0.0 : (double) missCount / requestCount;
}
/**
* Returns the total number of times that {@link Cache} lookup methods attempted to load new
* values. This includes both successful load operations, as well as those that threw
* exceptions. This is defined as {@code loadSuccessCount + loadExceptionCount}.
*/
public long loadCount() {
return loadSuccessCount + loadExceptionCount;
}
/**
* Returns the number of times {@link Cache} lookup methods have successfully loaded a new value.
* This is always incremented in conjunction with {@link #missCount}, though {@code missCount}
* is also incremented when an exception is encountered during cache loading (see
* {@link #loadExceptionCount}). Multiple concurrent misses for the same key will result in a
* single load operation.
*/
public long loadSuccessCount() {
return loadSuccessCount;
}
/**
* Returns the number of times {@link Cache} lookup methods threw an exception while loading a
* new value. This is always incremented in conjunction with {@code missCount}, though
* {@code missCount} is also incremented when cache loading completes successfully (see
* {@link #loadSuccessCount}). Multiple concurrent misses for the same key will result in a
* single load operation.
*/
public long loadExceptionCount() {
return loadExceptionCount;
}
/**
* Returns the ratio of cache loading attempts which threw exceptions. This is defined as
* {@code loadExceptionCount / (loadSuccessCount + loadExceptionCount)}, or
* {@code 0.0} when {@code loadSuccessCount + loadExceptionCount == 0}.
*/
public double loadExceptionRate() {
long totalLoadCount = loadSuccessCount + loadExceptionCount;
return (totalLoadCount == 0)
? 0.0
: (double) loadExceptionCount / totalLoadCount;
}
/**
* Returns the total number of nanoseconds the cache has spent loading new values. This can be
* used to calculate the miss penalty. This value is increased every time
* {@code loadSuccessCount} or {@code loadExceptionCount} is incremented.
*/
public long totalLoadTime() {
return totalLoadTime;
}
/**
* Returns the average time spent loading new values. This is defined as
* {@code totalLoadTime / (loadSuccessCount + loadExceptionCount)}.
*/
public double averageLoadPenalty() {
long totalLoadCount = loadSuccessCount + loadExceptionCount;
return (totalLoadCount == 0)
? 0.0
: (double) totalLoadTime / totalLoadCount;
}
/**
* Returns the number of times an entry has been evicted. This count does not include manual
* {@linkplain Cache#invalidate invalidations}.
*/
public long evictionCount() {
return evictionCount;
}
/**
* Returns a new {@code CacheStats} representing the difference between this {@code CacheStats}
* and {@code other}. Negative values, which aren't supported by {@code CacheStats} will be
* rounded up to zero.
*/
public CacheStats minus(CacheStats other) {
return new CacheStats(
Math.max(0, hitCount - other.hitCount),
Math.max(0, missCount - other.missCount),
Math.max(0, loadSuccessCount - other.loadSuccessCount),
Math.max(0, loadExceptionCount - other.loadExceptionCount),
Math.max(0, totalLoadTime - other.totalLoadTime),
Math.max(0, evictionCount - other.evictionCount));
}
/**
* Returns a new {@code CacheStats} representing the sum of this {@code CacheStats}
* and {@code other}.
*
* @since 11.0
*/
public CacheStats plus(CacheStats other) {
return new CacheStats(
hitCount + other.hitCount,
missCount + other.missCount,
loadSuccessCount + other.loadSuccessCount,
loadExceptionCount + other.loadExceptionCount,
totalLoadTime + other.totalLoadTime,
evictionCount + other.evictionCount);
}
@Override
public int hashCode() {
return Objects.hashCode(hitCount, missCount, loadSuccessCount, loadExceptionCount,
totalLoadTime, evictionCount);
}
@Override
public boolean equals(@Nullable Object object) {
if (object instanceof CacheStats) {
CacheStats other = (CacheStats) object;
return hitCount == other.hitCount
&& missCount == other.missCount
&& loadSuccessCount == other.loadSuccessCount
&& loadExceptionCount == other.loadExceptionCount
&& totalLoadTime == other.totalLoadTime
&& evictionCount == other.evictionCount;
}
return false;
}
@Override
public String toString() {
return MoreObjects.toStringHelper(this)
.add("hitCount", hitCount)
.add("missCount", missCount)
.add("loadSuccessCount", loadSuccessCount)
.add("loadExceptionCount", loadExceptionCount)
.add("totalLoadTime", totalLoadTime)
.add("evictionCount", evictionCount)
.toString();
}
}
@@ -1,143 +0,0 @@
/*
* Copyright (C) 2011 The Guava Authors
*
* 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 com.google.common.cache;
import com.google.common.base.Preconditions;
import com.google.common.collect.ForwardingObject;
import com.google.common.collect.ImmutableMap;
import java.util.Map;
import java.util.concurrent.Callable;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.ExecutionException;
import javax.annotation.Nullable;
/**
* A cache which forwards all its method calls to another cache. Subclasses should override one or
* more methods to modify the behavior of the backing cache as desired per the
* <a href="http://en.wikipedia.org/wiki/Decorator_pattern">decorator pattern</a>.
*
* @author Charles Fry
* @since 10.0
*/
public abstract class ForwardingCache<K, V> extends ForwardingObject implements Cache<K, V> {
/** Constructor for use by subclasses. */
protected ForwardingCache() {}
@Override
protected abstract Cache<K, V> delegate();
/**
* @since 11.0
*/
@Override
@Nullable
public V getIfPresent(Object key) {
return delegate().getIfPresent(key);
}
/**
* @since 11.0
*/
@Override
public V get(K key, Callable<? extends V> valueLoader) throws ExecutionException {
return delegate().get(key, valueLoader);
}
/**
* @since 11.0
*/
@Override
public ImmutableMap<K, V> getAllPresent(Iterable<?> keys) {
return delegate().getAllPresent(keys);
}
/**
* @since 11.0
*/
@Override
public void put(K key, V value) {
delegate().put(key, value);
}
/**
* @since 12.0
*/
@Override
public void putAll(Map<? extends K,? extends V> m) {
delegate().putAll(m);
}
@Override
public void invalidate(Object key) {
delegate().invalidate(key);
}
/**
* @since 11.0
*/
@Override
public void invalidateAll(Iterable<?> keys) {
delegate().invalidateAll(keys);
}
@Override
public void invalidateAll() {
delegate().invalidateAll();
}
@Override
public long size() {
return delegate().size();
}
@Override
public CacheStats stats() {
return delegate().stats();
}
@Override
public ConcurrentMap<K, V> asMap() {
return delegate().asMap();
}
@Override
public void cleanUp() {
delegate().cleanUp();
}
/**
* A simplified version of {@link ForwardingCache} where subclasses can pass in an already
* constructed {@link Cache} as the delegate.
*
* @since 10.0
*/
public abstract static class SimpleForwardingCache<K, V> extends ForwardingCache<K, V> {
private final Cache<K, V> delegate;
protected SimpleForwardingCache(Cache<K, V> delegate) {
this.delegate = Preconditions.checkNotNull(delegate);
}
@Override
protected final Cache<K, V> delegate() {
return delegate;
}
}
}
@@ -1,88 +0,0 @@
/*
* Copyright (C) 2011 The Guava Authors
*
* 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 com.google.common.cache;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableMap;
import java.util.concurrent.ExecutionException;
/**
* A cache which forwards all its method calls to another cache. Subclasses should override one or
* more methods to modify the behavior of the backing cache as desired per the
* <a href="http://en.wikipedia.org/wiki/Decorator_pattern">decorator pattern</a>.
*
* <p>Note that {@link #get}, {@link #getUnchecked}, and {@link #apply} all expose the same
* underlying functionality, so should probably be overridden as a group.
*
* @author Charles Fry
* @since 11.0
*/
public abstract class ForwardingLoadingCache<K, V>
extends ForwardingCache<K, V> implements LoadingCache<K, V> {
/** Constructor for use by subclasses. */
protected ForwardingLoadingCache() {}
@Override
protected abstract LoadingCache<K, V> delegate();
@Override
public V get(K key) throws ExecutionException {
return delegate().get(key);
}
@Override
public V getUnchecked(K key) {
return delegate().getUnchecked(key);
}
@Override
public ImmutableMap<K, V> getAll(Iterable<? extends K> keys) throws ExecutionException {
return delegate().getAll(keys);
}
@Override
public V apply(K key) {
return delegate().apply(key);
}
@Override
public void refresh(K key) {
delegate().refresh(key);
}
/**
* A simplified version of {@link ForwardingLoadingCache} where subclasses can pass in an already
* constructed {@link LoadingCache} as the delegate.
*
* @since 10.0
*/
public abstract static class SimpleForwardingLoadingCache<K, V>
extends ForwardingLoadingCache<K, V> {
private final LoadingCache<K, V> delegate;
protected SimpleForwardingLoadingCache(LoadingCache<K, V> delegate) {
this.delegate = Preconditions.checkNotNull(delegate);
}
@Override
protected final LoadingCache<K, V> delegate() {
return delegate;
}
}
}
@@ -1,162 +0,0 @@
/*
* Copyright (C) 2011 The Guava Authors
*
* 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 com.google.common.cache;
import com.google.common.annotations.GwtCompatible;
import com.google.common.base.Function;
import com.google.common.collect.ImmutableMap;
import com.google.common.util.concurrent.ExecutionError;
import com.google.common.util.concurrent.UncheckedExecutionException;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.ExecutionException;
/**
* A semi-persistent mapping from keys to values. Values are automatically loaded by the cache,
* and are stored in the cache until either evicted or manually invalidated.
*
* <p>Implementations of this interface are expected to be thread-safe, and can be safely accessed
* by multiple concurrent threads.
*
* <p>When evaluated as a {@link Function}, a cache yields the same result as invoking
* {@link #getUnchecked}.
*
* @author Charles Fry
* @since 11.0
*/
@GwtCompatible
public interface LoadingCache<K, V> extends Cache<K, V>, Function<K, V> {
/**
* Returns the value associated with {@code key} in this cache, first loading that value if
* necessary. No observable state associated with this cache is modified until loading completes.
*
* <p>If another call to {@link #get} or {@link #getUnchecked} is currently loading the value for
* {@code key}, simply waits for that thread to finish and returns its loaded value. Note that
* multiple threads can concurrently load values for distinct keys.
*
* <p>Caches loaded by a {@link CacheLoader} will call {@link CacheLoader#load} to load new values
* into the cache. Newly loaded values are added to the cache using
* {@code Cache.asMap().putIfAbsent} after loading has completed; if another value was associated
* with {@code key} while the new value was loading then a removal notification will be sent for
* the new value.
*
* <p>If the cache loader associated with this cache is known not to throw checked
* exceptions, then prefer {@link #getUnchecked} over this method.
*
* @throws ExecutionException if a checked exception was thrown while loading the value. ({@code
* ExecutionException} is thrown <a
* href="https://github.com/google/guava/wiki/CachesExplained#interruption">even if
* computation was interrupted by an {@code InterruptedException}</a>.)
* @throws UncheckedExecutionException if an unchecked exception was thrown while loading the
* value
* @throws ExecutionError if an error was thrown while loading the value
*/
V get(K key) throws ExecutionException;
/**
* Returns the value associated with {@code key} in this cache, first loading that value if
* necessary. No observable state associated with this cache is modified until loading
* completes. Unlike {@link #get}, this method does not throw a checked exception, and thus should
* only be used in situations where checked exceptions are not thrown by the cache loader.
*
* <p>If another call to {@link #get} or {@link #getUnchecked} is currently loading the value for
* {@code key}, simply waits for that thread to finish and returns its loaded value. Note that
* multiple threads can concurrently load values for distinct keys.
*
* <p>Caches loaded by a {@link CacheLoader} will call {@link CacheLoader#load} to load new values
* into the cache. Newly loaded values are added to the cache using
* {@code Cache.asMap().putIfAbsent} after loading has completed; if another value was associated
* with {@code key} while the new value was loading then a removal notification will be sent for
* the new value.
*
* <p><b>Warning:</b> this method silently converts checked exceptions to unchecked exceptions,
* and should not be used with cache loaders which throw checked exceptions. In such cases use
* {@link #get} instead.
*
* @throws UncheckedExecutionException if an exception was thrown while loading the value. (As
* explained in the last paragraph above, this should be an unchecked exception only.)
* @throws ExecutionError if an error was thrown while loading the value
*/
V getUnchecked(K key);
/**
* Returns a map of the values associated with {@code keys}, creating or retrieving those values
* if necessary. The returned map contains entries that were already cached, combined with newly
* loaded entries; it will never contain null keys or values.
*
* <p>Caches loaded by a {@link CacheLoader} will issue a single request to
* {@link CacheLoader#loadAll} for all keys which are not already present in the cache. All
* entries returned by {@link CacheLoader#loadAll} will be stored in the cache, over-writing
* any previously cached values. This method will throw an exception if
* {@link CacheLoader#loadAll} returns {@code null}, returns a map containing null keys or values,
* or fails to return an entry for each requested key.
*
* <p>Note that duplicate elements in {@code keys}, as determined by {@link Object#equals}, will
* be ignored.
*
* @throws ExecutionException if a checked exception was thrown while loading the value. ({@code
* ExecutionException} is thrown <a
* href="https://github.com/google/guava/wiki/CachesExplained#interruption">even if
* computation was interrupted by an {@code InterruptedException}</a>.)
* @throws UncheckedExecutionException if an unchecked exception was thrown while loading the
* values
* @throws ExecutionError if an error was thrown while loading the values
* @since 11.0
*/
ImmutableMap<K, V> getAll(Iterable<? extends K> keys) throws ExecutionException;
/**
* @deprecated Provided to satisfy the {@code Function} interface; use {@link #get} or
* {@link #getUnchecked} instead.
* @throws UncheckedExecutionException if an exception was thrown while loading the value. (As
* described in the documentation for {@link #getUnchecked}, {@code LoadingCache} should be
* used as a {@code Function} only with cache loaders that throw only unchecked exceptions.)
*/
@Deprecated
@Override
V apply(K key);
/**
* Loads a new value for key {@code key}, possibly asynchronously. While the new value is loading
* the previous value (if any) will continue to be returned by {@code get(key)} unless it is
* evicted. If the new value is loaded successfully it will replace the previous value in the
* cache; if an exception is thrown while refreshing the previous value will remain, <i>and the
* exception will be logged (using {@link com.google.common.logging.Logger}) and swallowed</i>.
*
* <p>Caches loaded by a {@link CacheLoader} will call {@link CacheLoader#reload} if the
* cache currently contains a value for {@code key}, and {@link CacheLoader#load} otherwise.
* Loading is asynchronous only if {@link CacheLoader#reload} was overridden with an
* asynchronous implementation.
*
* <p>Returns without doing anything if another thread is currently loading the value for
* {@code key}. If the cache loader associated with this cache performs refresh asynchronously
* then this method may return before refresh completes.
*
* @since 11.0
*/
void refresh(K key);
/**
* {@inheritDoc}
*
* <p><b>Note that although the view <i>is</i> modifiable, no method on the returned map will ever
* cause entries to be automatically loaded.</b>
*/
@Override
ConcurrentMap<K, V> asMap();
}
File diff suppressed because it is too large Load Diff
@@ -1,33 +0,0 @@
/*
* Copyright (C) 2012 The Guava Authors
*
* 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 com.google.common.cache;
import com.google.common.annotations.GwtCompatible;
/**
* Abstract interface for objects that can concurrently add longs.
*
* @author Louis Wasserman
*/
@GwtCompatible
interface LongAddable {
void increment();
void add(long x);
long sum();
}
@@ -1,75 +0,0 @@
/*
* Copyright (C) 2012 The Guava Authors
*
* 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 com.google.common.cache;
import com.google.common.annotations.GwtCompatible;
import com.google.common.base.Supplier;
import java.util.concurrent.atomic.AtomicLong;
/**
* Source of {@link LongAddable} objects that deals with GWT, Unsafe, and all
* that.
*
* @author Louis Wasserman
*/
@GwtCompatible(emulated = true)
final class LongAddables {
private static final Supplier<LongAddable> SUPPLIER;
static {
Supplier<LongAddable> supplier;
try {
new LongAdder(); // trigger static initialization of the LongAdder class, which may fail
supplier = new Supplier<LongAddable>() {
@Override
public LongAddable get() {
return new LongAdder();
}
};
} catch (Throwable t) { // we really want to catch *everything*
supplier = new Supplier<LongAddable>() {
@Override
public LongAddable get() {
return new PureJavaLongAddable();
}
};
}
SUPPLIER = supplier;
}
public static LongAddable create() {
return SUPPLIER.get();
}
private static final class PureJavaLongAddable extends AtomicLong implements LongAddable {
@Override
public void increment() {
getAndIncrement();
}
@Override
public void add(long x) {
getAndAdd(x);
}
@Override
public long sum() {
return get();
}
}
}
@@ -1,210 +0,0 @@
/*
* Written by Doug Lea with assistance from members of JCP JSR-166
* Expert Group and released to the public domain, as explained at
* http://creativecommons.org/publicdomain/zero/1.0/
*/
/*
* Source:
* http://gee.cs.oswego.edu/cgi-bin/viewcvs.cgi/jsr166/src/jsr166e/LongAdder.java?revision=1.17
*/
package com.google.common.cache;
import com.google.common.annotations.GwtCompatible;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.concurrent.atomic.AtomicLong;
/**
* One or more variables that together maintain an initially zero
* {@code long} sum. When updates (method {@link #add}) are contended
* across threads, the set of variables may grow dynamically to reduce
* contention. Method {@link #sum} (or, equivalently, {@link
* #longValue}) returns the current total combined across the
* variables maintaining the sum.
*
* <p>This class is usually preferable to {@link AtomicLong} when
* multiple threads update a common sum that is used for purposes such
* as collecting statistics, not for fine-grained synchronization
* control. Under low update contention, the two classes have similar
* characteristics. But under high contention, expected throughput of
* this class is significantly higher, at the expense of higher space
* consumption.
*
* <p>This class extends {@link Number}, but does <em>not</em> define
* methods such as {@code equals}, {@code hashCode} and {@code
* compareTo} because instances are expected to be mutated, and so are
* not useful as collection keys.
*
* <p><em>jsr166e note: This class is targeted to be placed in
* java.util.concurrent.atomic.</em>
*
* @since 1.8
* @author Doug Lea
*/
@GwtCompatible(emulated = true)
final class LongAdder extends Striped64 implements Serializable, LongAddable {
private static final long serialVersionUID = 7249069246863182397L;
/**
* Version of plus for use in retryUpdate
*/
final long fn(long v, long x) { return v + x; }
/**
* Creates a new adder with initial sum of zero.
*/
public LongAdder() {
}
/**
* Adds the given value.
*
* @param x the value to add
*/
public void add(long x) {
Cell[] as; long b, v; int[] hc; Cell a; int n;
if ((as = cells) != null || !casBase(b = base, b + x)) {
boolean uncontended = true;
if ((hc = threadHashCode.get()) == null ||
as == null || (n = as.length) < 1 ||
(a = as[(n - 1) & hc[0]]) == null ||
!(uncontended = a.cas(v = a.value, v + x)))
retryUpdate(x, hc, uncontended);
}
}
/**
* Equivalent to {@code add(1)}.
*/
public void increment() {
add(1L);
}
/**
* Equivalent to {@code add(-1)}.
*/
public void decrement() {
add(-1L);
}
/**
* Returns the current sum. The returned value is <em>NOT</em> an
* atomic snapshot; invocation in the absence of concurrent
* updates returns an accurate result, but concurrent updates that
* occur while the sum is being calculated might not be
* incorporated.
*
* @return the sum
*/
public long sum() {
long sum = base;
Cell[] as = cells;
if (as != null) {
int n = as.length;
for (int i = 0; i < n; ++i) {
Cell a = as[i];
if (a != null)
sum += a.value;
}
}
return sum;
}
/**
* Resets variables maintaining the sum to zero. This method may
* be a useful alternative to creating a new adder, but is only
* effective if there are no concurrent updates. Because this
* method is intrinsically racy, it should only be used when it is
* known that no threads are concurrently updating.
*/
public void reset() {
internalReset(0L);
}
/**
* Equivalent in effect to {@link #sum} followed by {@link
* #reset}. This method may apply for example during quiescent
* points between multithreaded computations. If there are
* updates concurrent with this method, the returned value is
* <em>not</em> guaranteed to be the final value occurring before
* the reset.
*
* @return the sum
*/
public long sumThenReset() {
long sum = base;
Cell[] as = cells;
base = 0L;
if (as != null) {
int n = as.length;
for (int i = 0; i < n; ++i) {
Cell a = as[i];
if (a != null) {
sum += a.value;
a.value = 0L;
}
}
}
return sum;
}
/**
* Returns the String representation of the {@link #sum}.
* @return the String representation of the {@link #sum}
*/
public String toString() {
return Long.toString(sum());
}
/**
* Equivalent to {@link #sum}.
*
* @return the sum
*/
public long longValue() {
return sum();
}
/**
* Returns the {@link #sum} as an {@code int} after a narrowing
* primitive conversion.
*/
public int intValue() {
return (int)sum();
}
/**
* Returns the {@link #sum} as a {@code float}
* after a widening primitive conversion.
*/
public float floatValue() {
return (float)sum();
}
/**
* Returns the {@link #sum} as a {@code double} after a widening
* primitive conversion.
*/
public double doubleValue() {
return (double)sum();
}
private void writeObject(ObjectOutputStream s) throws IOException {
s.defaultWriteObject();
s.writeLong(sum());
}
private void readObject(ObjectInputStream s)
throws IOException, ClassNotFoundException {
s.defaultReadObject();
busy = 0;
cells = null;
base = s.readLong();
}
}
@@ -1,97 +0,0 @@
/*
* Copyright (C) 2011 The Guava Authors
*
* 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 com.google.common.cache;
import com.google.common.annotations.GwtCompatible;
import java.util.Iterator;
import java.util.Map;
import java.util.concurrent.ConcurrentMap;
/**
* The reason why a cached entry was removed.
*
* @author Charles Fry
* @since 10.0
*/
@GwtCompatible
public enum RemovalCause {
/**
* The entry was manually removed by the user. This can result from the user invoking
* {@link Cache#invalidate}, {@link Cache#invalidateAll(Iterable)}, {@link Cache#invalidateAll()},
* {@link Map#remove}, {@link ConcurrentMap#remove}, or {@link Iterator#remove}.
*/
EXPLICIT {
@Override
boolean wasEvicted() {
return false;
}
},
/**
* The entry itself was not actually removed, but its value was replaced by the user. This can
* result from the user invoking {@link Cache#put}, {@link LoadingCache#refresh}, {@link Map#put},
* {@link Map#putAll}, {@link ConcurrentMap#replace(Object, Object)}, or
* {@link ConcurrentMap#replace(Object, Object, Object)}.
*/
REPLACED {
@Override
boolean wasEvicted() {
return false;
}
},
/**
* The entry was removed automatically because its key or value was garbage-collected. This
* can occur when using {@link CacheBuilder#weakKeys}, {@link CacheBuilder#weakValues}, or
* {@link CacheBuilder#softValues}.
*/
COLLECTED {
@Override
boolean wasEvicted() {
return true;
}
},
/**
* The entry's expiration timestamp has passed. This can occur when using
* {@link CacheBuilder#expireAfterWrite} or {@link CacheBuilder#expireAfterAccess}.
*/
EXPIRED {
@Override
boolean wasEvicted() {
return true;
}
},
/**
* The entry was evicted due to size constraints. This can occur when using
* {@link CacheBuilder#maximumSize} or {@link CacheBuilder#maximumWeight}.
*/
SIZE {
@Override
boolean wasEvicted() {
return true;
}
};
/**
* Returns {@code true} if there was an automatic removal due to eviction (the cause is neither
* {@link #EXPLICIT} nor {@link #REPLACED}).
*/
abstract boolean wasEvicted();
}
@@ -1,49 +0,0 @@
/*
* Copyright (C) 2011 The Guava Authors
*
* 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 com.google.common.cache;
import com.google.common.annotations.GwtCompatible;
/**
* An object that can receive a notification when an entry is removed from a cache. The removal
* resulting in notification could have occured to an entry being manually removed or replaced, or
* due to eviction resulting from timed expiration, exceeding a maximum size, or garbage
* collection.
*
* <p>An instance may be called concurrently by multiple threads to process different entries.
* Implementations of this interface should avoid performing blocking calls or synchronizing on
* shared resources.
*
* @param <K> the most general type of keys this listener can listen for; for
* example {@code Object} if any key is acceptable
* @param <V> the most general type of values this listener can listen for; for
* example {@code Object} if any key is acceptable
* @author Charles Fry
* @since 10.0
*/
@GwtCompatible
public interface RemovalListener<K, V> {
/**
* Notifies the listener that a removal occurred at some point in the past.
*
* <p>This does not always signify that the key is now absent from the cache,
* as it may have already been re-added.
*/
// Technically should accept RemovalNotification<? extends K, ? extends V>, but because
// RemovalNotification is guaranteed covariant, let's make users' lives simpler.
void onRemoval(RemovalNotification<K, V> notification);
}
@@ -1,58 +0,0 @@
/*
* Copyright (C) 2011 The Guava Authors
*
* 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 com.google.common.cache;
import static com.google.common.base.Preconditions.checkNotNull;
import java.util.concurrent.Executor;
/**
* A collection of common removal listeners.
*
* @author Charles Fry
* @since 10.0
*/
public final class RemovalListeners {
private RemovalListeners() {}
/**
* Returns a {@code RemovalListener} which processes all eviction
* notifications using {@code executor}.
*
* @param listener the backing listener
* @param executor the executor with which removal notifications are
* asynchronously executed
*/
public static <K, V> RemovalListener<K, V> asynchronous(
final RemovalListener<K, V> listener, final Executor executor) {
checkNotNull(listener);
checkNotNull(executor);
return new RemovalListener<K, V>() {
@Override
public void onRemoval(final RemovalNotification<K, V> notification) {
executor.execute(new Runnable() {
@Override
public void run() {
listener.onRemoval(notification);
}
});
}
};
}
}
@@ -1,112 +0,0 @@
/*
* Copyright (C) 2011 The Guava Authors
*
* 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 com.google.common.cache;
import static com.google.common.base.Preconditions.checkNotNull;
import com.google.common.annotations.GwtCompatible;
import com.google.common.base.Objects;
import java.util.Map.Entry;
import javax.annotation.Nullable;
/**
* A notification of the removal of a single entry. The key and/or value may be null if they were
* already garbage collected.
*
* <p>Like other {@code Map.Entry} instances associated with {@code CacheBuilder}, this class holds
* strong references to the key and value, regardless of the type of references the cache may be
* using.
*
* @author Charles Fry
* @since 10.0
*/
@GwtCompatible
public final class RemovalNotification<K, V> implements Entry<K, V> {
@Nullable private final K key;
@Nullable private final V value;
private final RemovalCause cause;
/**
* Creates a new {@code RemovalNotification} for the given {@code key}/{@code value} pair, with
* the given {@code cause} for the removal. The {@code key} and/or {@code value} may be
* {@code null} if they were already garbage collected.
*
* @since 19.0
*/
public static <K, V> RemovalNotification<K, V> create(
@Nullable K key, @Nullable V value, RemovalCause cause) {
return new RemovalNotification(key, value, cause);
}
private RemovalNotification(@Nullable K key, @Nullable V value, RemovalCause cause) {
this.key = key;
this.value = value;
this.cause = checkNotNull(cause);
}
/**
* Returns the cause for which the entry was removed.
*/
public RemovalCause getCause() {
return cause;
}
/**
* Returns {@code true} if there was an automatic removal due to eviction (the cause is neither
* {@link RemovalCause#EXPLICIT} nor {@link RemovalCause#REPLACED}).
*/
public boolean wasEvicted() {
return cause.wasEvicted();
}
@Nullable @Override public K getKey() {
return key;
}
@Nullable @Override public V getValue() {
return value;
}
@Override public final V setValue(V value) {
throw new UnsupportedOperationException();
}
@Override public boolean equals(@Nullable Object object) {
if (object instanceof Entry) {
Entry<?, ?> that = (Entry<?, ?>) object;
return Objects.equal(this.getKey(), that.getKey())
&& Objects.equal(this.getValue(), that.getValue());
}
return false;
}
@Override public int hashCode() {
K k = getKey();
V v = getValue();
return ((k == null) ? 0 : k.hashCode()) ^ ((v == null) ? 0 : v.hashCode());
}
/**
* Returns a string representation of the form <code>{key}={value}</code>.
*/
@Override public String toString() {
return getKey() + "=" + getValue();
}
private static final long serialVersionUID = 0;
}
@@ -1,338 +0,0 @@
/*
* Written by Doug Lea with assistance from members of JCP JSR-166
* Expert Group and released to the public domain, as explained at
* http://creativecommons.org/publicdomain/zero/1.0/
*/
/*
* Source:
* http://gee.cs.oswego.edu/cgi-bin/viewcvs.cgi/jsr166/src/jsr166e/Striped64.java?revision=1.9
*/
package com.google.common.cache;
import java.util.Random;
/**
* A package-local class holding common representation and mechanics
* for classes supporting dynamic striping on 64bit values. The class
* extends Number so that concrete subclasses must publicly do so.
*/
abstract class Striped64 extends Number {
/*
* This class maintains a lazily-initialized table of atomically
* updated variables, plus an extra "base" field. The table size
* is a power of two. Indexing uses masked per-thread hash codes.
* Nearly all declarations in this class are package-private,
* accessed directly by subclasses.
*
* Table entries are of class Cell; a variant of AtomicLong padded
* to reduce cache contention on most processors. Padding is
* overkill for most Atomics because they are usually irregularly
* scattered in memory and thus don't interfere much with each
* other. But Atomic objects residing in arrays will tend to be
* placed adjacent to each other, and so will most often share
* cache lines (with a huge negative performance impact) without
* this precaution.
*
* In part because Cells are relatively large, we avoid creating
* them until they are needed. When there is no contention, all
* updates are made to the base field. Upon first contention (a
* failed CAS on base update), the table is initialized to size 2.
* The table size is doubled upon further contention until
* reaching the nearest power of two greater than or equal to the
* number of CPUS. Table slots remain empty (null) until they are
* needed.
*
* A single spinlock ("busy") is used for initializing and
* resizing the table, as well as populating slots with new Cells.
* There is no need for a blocking lock; when the lock is not
* available, threads try other slots (or the base). During these
* retries, there is increased contention and reduced locality,
* which is still better than alternatives.
*
* Per-thread hash codes are initialized to random values.
* Contention and/or table collisions are indicated by failed
* CASes when performing an update operation (see method
* retryUpdate). Upon a collision, if the table size is less than
* the capacity, it is doubled in size unless some other thread
* holds the lock. If a hashed slot is empty, and lock is
* available, a new Cell is created. Otherwise, if the slot
* exists, a CAS is tried. Retries proceed by "double hashing",
* using a secondary hash (Marsaglia XorShift) to try to find a
* free slot.
*
* The table size is capped because, when there are more threads
* than CPUs, supposing that each thread were bound to a CPU,
* there would exist a perfect hash function mapping threads to
* slots that eliminates collisions. When we reach capacity, we
* search for this mapping by randomly varying the hash codes of
* colliding threads. Because search is random, and collisions
* only become known via CAS failures, convergence can be slow,
* and because threads are typically not bound to CPUS forever,
* may not occur at all. However, despite these limitations,
* observed contention rates are typically low in these cases.
*
* It is possible for a Cell to become unused when threads that
* once hashed to it terminate, as well as in the case where
* doubling the table causes no thread to hash to it under
* expanded mask. We do not try to detect or remove such cells,
* under the assumption that for long-running instances, observed
* contention levels will recur, so the cells will eventually be
* needed again; and for short-lived ones, it does not matter.
*/
/**
* Padded variant of AtomicLong supporting only raw accesses plus CAS.
* The value field is placed between pads, hoping that the JVM doesn't
* reorder them.
*
* JVM intrinsics note: It would be possible to use a release-only
* form of CAS here, if it were provided.
*/
static final class Cell {
volatile long p0, p1, p2, p3, p4, p5, p6;
volatile long value;
volatile long q0, q1, q2, q3, q4, q5, q6;
Cell(long x) { value = x; }
final boolean cas(long cmp, long val) {
return UNSAFE.compareAndSwapLong(this, valueOffset, cmp, val);
}
// Unsafe mechanics
private static final sun.misc.Unsafe UNSAFE;
private static final long valueOffset;
static {
try {
UNSAFE = getUnsafe();
Class<?> ak = Cell.class;
valueOffset = UNSAFE.objectFieldOffset
(ak.getDeclaredField("value"));
} catch (Exception e) {
throw new Error(e);
}
}
}
/**
* ThreadLocal holding a single-slot int array holding hash code.
* Unlike the JDK8 version of this class, we use a suboptimal
* int[] representation to avoid introducing a new type that can
* impede class-unloading when ThreadLocals are not removed.
*/
static final ThreadLocal<int[]> threadHashCode = new ThreadLocal<int[]>();
/**
* Generator of new random hash codes
*/
static final Random rng = new Random();
/** Number of CPUS, to place bound on table size */
static final int NCPU = Runtime.getRuntime().availableProcessors();
/**
* Table of cells. When non-null, size is a power of 2.
*/
transient volatile Cell[] cells;
/**
* Base value, used mainly when there is no contention, but also as
* a fallback during table initialization races. Updated via CAS.
*/
transient volatile long base;
/**
* Spinlock (locked via CAS) used when resizing and/or creating Cells.
*/
transient volatile int busy;
/**
* Package-private default constructor
*/
Striped64() {
}
/**
* CASes the base field.
*/
final boolean casBase(long cmp, long val) {
return UNSAFE.compareAndSwapLong(this, baseOffset, cmp, val);
}
/**
* CASes the busy field from 0 to 1 to acquire lock.
*/
final boolean casBusy() {
return UNSAFE.compareAndSwapInt(this, busyOffset, 0, 1);
}
/**
* Computes the function of current and new value. Subclasses
* should open-code this update function for most uses, but the
* virtualized form is needed within retryUpdate.
*
* @param currentValue the current value (of either base or a cell)
* @param newValue the argument from a user update call
* @return result of the update function
*/
abstract long fn(long currentValue, long newValue);
/**
* Handles cases of updates involving initialization, resizing,
* creating new Cells, and/or contention. See above for
* explanation. This method suffers the usual non-modularity
* problems of optimistic retry code, relying on rechecked sets of
* reads.
*
* @param x the value
* @param hc the hash code holder
* @param wasUncontended false if CAS failed before call
*/
final void retryUpdate(long x, int[] hc, boolean wasUncontended) {
int h;
if (hc == null) {
threadHashCode.set(hc = new int[1]); // Initialize randomly
int r = rng.nextInt(); // Avoid zero to allow xorShift rehash
h = hc[0] = (r == 0) ? 1 : r;
}
else
h = hc[0];
boolean collide = false; // True if last slot nonempty
for (;;) {
Cell[] as; Cell a; int n; long v;
if ((as = cells) != null && (n = as.length) > 0) {
if ((a = as[(n - 1) & h]) == null) {
if (busy == 0) { // Try to attach new Cell
Cell r = new Cell(x); // Optimistically create
if (busy == 0 && casBusy()) {
boolean created = false;
try { // Recheck under lock
Cell[] rs; int m, j;
if ((rs = cells) != null &&
(m = rs.length) > 0 &&
rs[j = (m - 1) & h] == null) {
rs[j] = r;
created = true;
}
} finally {
busy = 0;
}
if (created)
break;
continue; // Slot is now non-empty
}
}
collide = false;
}
else if (!wasUncontended) // CAS already known to fail
wasUncontended = true; // Continue after rehash
else if (a.cas(v = a.value, fn(v, x)))
break;
else if (n >= NCPU || cells != as)
collide = false; // At max size or stale
else if (!collide)
collide = true;
else if (busy == 0 && casBusy()) {
try {
if (cells == as) { // Expand table unless stale
Cell[] rs = new Cell[n << 1];
for (int i = 0; i < n; ++i)
rs[i] = as[i];
cells = rs;
}
} finally {
busy = 0;
}
collide = false;
continue; // Retry with expanded table
}
h ^= h << 13; // Rehash
h ^= h >>> 17;
h ^= h << 5;
hc[0] = h; // Record index for next time
}
else if (busy == 0 && cells == as && casBusy()) {
boolean init = false;
try { // Initialize table
if (cells == as) {
Cell[] rs = new Cell[2];
rs[h & 1] = new Cell(x);
cells = rs;
init = true;
}
} finally {
busy = 0;
}
if (init)
break;
}
else if (casBase(v = base, fn(v, x)))
break; // Fall back on using base
}
}
/**
* Sets base and all cells to the given value.
*/
final void internalReset(long initialValue) {
Cell[] as = cells;
base = initialValue;
if (as != null) {
int n = as.length;
for (int i = 0; i < n; ++i) {
Cell a = as[i];
if (a != null)
a.value = initialValue;
}
}
}
// Unsafe mechanics
private static final sun.misc.Unsafe UNSAFE;
private static final long baseOffset;
private static final long busyOffset;
static {
try {
UNSAFE = getUnsafe();
Class<?> sk = Striped64.class;
baseOffset = UNSAFE.objectFieldOffset
(sk.getDeclaredField("base"));
busyOffset = UNSAFE.objectFieldOffset
(sk.getDeclaredField("busy"));
} catch (Exception e) {
throw new Error(e);
}
}
/**
* Returns a sun.misc.Unsafe. Suitable for use in a 3rd party package.
* Replace with a simple call to Unsafe.getUnsafe when integrating
* into a jdk.
*
* @return a sun.misc.Unsafe
*/
private static sun.misc.Unsafe getUnsafe() {
try {
return sun.misc.Unsafe.getUnsafe();
} catch (SecurityException tryReflectionInstead) {}
try {
return java.security.AccessController.doPrivileged
(new java.security.PrivilegedExceptionAction<sun.misc.Unsafe>() {
public sun.misc.Unsafe run() throws Exception {
Class<sun.misc.Unsafe> k = sun.misc.Unsafe.class;
for (java.lang.reflect.Field f : k.getDeclaredFields()) {
f.setAccessible(true);
Object x = f.get(null);
if (k.isInstance(x))
return k.cast(x);
}
throw new NoSuchFieldError("the Unsafe");
}});
} catch (java.security.PrivilegedActionException e) {
throw new RuntimeException("Could not initialize intrinsics",
e.getCause());
}
}
}
@@ -1,35 +0,0 @@
/*
* Copyright (C) 2011 The Guava Authors
*
* 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 com.google.common.cache;
import com.google.common.annotations.GwtCompatible;
/**
* Calculates the weights of cache entries.
*
* @author Charles Fry
* @since 11.0
*/
@GwtCompatible
public interface Weigher<K, V> {
/**
* Returns the weight of a cache entry. There is no unit for entry weights; rather they are simply
* relative to each other.
*
* @return the weight of the entry; must be non-negative
*/
int weigh(K key, V value);
}
@@ -1,38 +0,0 @@
/*
* Copyright (C) 2011 The Guava Authors
*
* 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.
*/
/**
* This package contains caching utilities.
*
* <p>The core interface used to represent caches is {@link com.google.common.cache.Cache}.
* In-memory caches can be configured and created using
* {@link com.google.common.cache.CacheBuilder}, with cache entries being loaded by
* {@link com.google.common.cache.CacheLoader}. Statistics about cache performance are exposed using
* {@link com.google.common.cache.CacheStats}.
*
* <p>See the Guava User Guide article on <a href=
* "https://github.com/google/guava/wiki/CachesExplained">caches</a>.
*
* <p>This package is a part of the open-source
* <a href="http://guava-libraries.googlecode.com">Guava libraries</a>.
*
* @author Charles Fry
*/
@ParametersAreNonnullByDefault
package com.google.common.cache;
import javax.annotation.ParametersAreNonnullByDefault;
@@ -1,445 +0,0 @@
/*
* Copyright (C) 2007 The Guava Authors
*
* 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 com.google.common.collect;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkState;
import static com.google.common.collect.CollectPreconditions.checkRemove;
import com.google.common.annotations.GwtCompatible;
import com.google.common.annotations.GwtIncompatible;
import com.google.common.base.Objects;
import com.google.j2objc.annotations.WeakOuter;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.Collection;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import javax.annotation.Nullable;
/**
* A general-purpose bimap implementation using any two backing {@code Map}
* instances.
*
* <p>Note that this class contains {@code equals()} calls that keep it from
* supporting {@code IdentityHashMap} backing maps.
*
* @author Kevin Bourrillion
* @author Mike Bostock
*/
@GwtCompatible(emulated = true)
abstract class AbstractBiMap<K, V> extends ForwardingMap<K, V>
implements BiMap<K, V>, Serializable {
private transient Map<K, V> delegate;
transient AbstractBiMap<V, K> inverse;
/** Package-private constructor for creating a map-backed bimap. */
AbstractBiMap(Map<K, V> forward, Map<V, K> backward) {
setDelegates(forward, backward);
}
/** Private constructor for inverse bimap. */
private AbstractBiMap(Map<K, V> backward, AbstractBiMap<V, K> forward) {
delegate = backward;
inverse = forward;
}
@Override
protected Map<K, V> delegate() {
return delegate;
}
/**
* Returns its input, or throws an exception if this is not a valid key.
*/
K checkKey(@Nullable K key) {
return key;
}
/**
* Returns its input, or throws an exception if this is not a valid value.
*/
V checkValue(@Nullable V value) {
return value;
}
/**
* Specifies the delegate maps going in each direction. Called by the
* constructor and by subclasses during deserialization.
*/
void setDelegates(Map<K, V> forward, Map<V, K> backward) {
checkState(delegate == null);
checkState(inverse == null);
checkArgument(forward.isEmpty());
checkArgument(backward.isEmpty());
checkArgument(forward != backward);
delegate = forward;
inverse = new Inverse<V, K>(backward, this);
}
void setInverse(AbstractBiMap<V, K> inverse) {
this.inverse = inverse;
}
// Query Operations (optimizations)
@Override
public boolean containsValue(@Nullable Object value) {
return inverse.containsKey(value);
}
// Modification Operations
@Override
public V put(@Nullable K key, @Nullable V value) {
return putInBothMaps(key, value, false);
}
@Override
public V forcePut(@Nullable K key, @Nullable V value) {
return putInBothMaps(key, value, true);
}
private V putInBothMaps(@Nullable K key, @Nullable V value, boolean force) {
checkKey(key);
checkValue(value);
boolean containedKey = containsKey(key);
if (containedKey && Objects.equal(value, get(key))) {
return value;
}
if (force) {
inverse().remove(value);
} else {
checkArgument(!containsValue(value), "value already present: %s", value);
}
V oldValue = delegate.put(key, value);
updateInverseMap(key, containedKey, oldValue, value);
return oldValue;
}
private void updateInverseMap(K key, boolean containedKey, V oldValue, V newValue) {
if (containedKey) {
removeFromInverseMap(oldValue);
}
inverse.delegate.put(newValue, key);
}
@Override
public V remove(@Nullable Object key) {
return containsKey(key) ? removeFromBothMaps(key) : null;
}
private V removeFromBothMaps(Object key) {
V oldValue = delegate.remove(key);
removeFromInverseMap(oldValue);
return oldValue;
}
private void removeFromInverseMap(V oldValue) {
inverse.delegate.remove(oldValue);
}
// Bulk Operations
@Override
public void putAll(Map<? extends K, ? extends V> map) {
for (Entry<? extends K, ? extends V> entry : map.entrySet()) {
put(entry.getKey(), entry.getValue());
}
}
@Override
public void clear() {
delegate.clear();
inverse.delegate.clear();
}
// Views
@Override
public BiMap<V, K> inverse() {
return inverse;
}
private transient Set<K> keySet;
@Override
public Set<K> keySet() {
Set<K> result = keySet;
return (result == null) ? keySet = new KeySet() : result;
}
@WeakOuter
private class KeySet extends ForwardingSet<K> {
@Override
protected Set<K> delegate() {
return delegate.keySet();
}
@Override
public void clear() {
AbstractBiMap.this.clear();
}
@Override
public boolean remove(Object key) {
if (!contains(key)) {
return false;
}
removeFromBothMaps(key);
return true;
}
@Override
public boolean removeAll(Collection<?> keysToRemove) {
return standardRemoveAll(keysToRemove);
}
@Override
public boolean retainAll(Collection<?> keysToRetain) {
return standardRetainAll(keysToRetain);
}
@Override
public Iterator<K> iterator() {
return Maps.keyIterator(entrySet().iterator());
}
}
private transient Set<V> valueSet;
@Override
public Set<V> values() {
/*
* We can almost reuse the inverse's keySet, except we have to fix the
* iteration order so that it is consistent with the forward map.
*/
Set<V> result = valueSet;
return (result == null) ? valueSet = new ValueSet() : result;
}
@WeakOuter
private class ValueSet extends ForwardingSet<V> {
final Set<V> valuesDelegate = inverse.keySet();
@Override
protected Set<V> delegate() {
return valuesDelegate;
}
@Override
public Iterator<V> iterator() {
return Maps.valueIterator(entrySet().iterator());
}
@Override
public Object[] toArray() {
return standardToArray();
}
@Override
public <T> T[] toArray(T[] array) {
return standardToArray(array);
}
@Override
public String toString() {
return standardToString();
}
}
private transient Set<Entry<K, V>> entrySet;
@Override
public Set<Entry<K, V>> entrySet() {
Set<Entry<K, V>> result = entrySet;
return (result == null) ? entrySet = new EntrySet() : result;
}
@WeakOuter
private class EntrySet extends ForwardingSet<Entry<K, V>> {
final Set<Entry<K, V>> esDelegate = delegate.entrySet();
@Override
protected Set<Entry<K, V>> delegate() {
return esDelegate;
}
@Override
public void clear() {
AbstractBiMap.this.clear();
}
@Override
public boolean remove(Object object) {
if (!esDelegate.contains(object)) {
return false;
}
// safe because esDelgate.contains(object).
Entry<?, ?> entry = (Entry<?, ?>) object;
inverse.delegate.remove(entry.getValue());
/*
* Remove the mapping in inverse before removing from esDelegate because
* if entry is part of esDelegate, entry might be invalidated after the
* mapping is removed from esDelegate.
*/
esDelegate.remove(entry);
return true;
}
@Override
public Iterator<Entry<K, V>> iterator() {
final Iterator<Entry<K, V>> iterator = esDelegate.iterator();
return new Iterator<Entry<K, V>>() {
Entry<K, V> entry;
@Override
public boolean hasNext() {
return iterator.hasNext();
}
@Override
public Entry<K, V> next() {
entry = iterator.next();
final Entry<K, V> finalEntry = entry;
return new ForwardingMapEntry<K, V>() {
@Override
protected Entry<K, V> delegate() {
return finalEntry;
}
@Override
public V setValue(V value) {
// Preconditions keep the map and inverse consistent.
checkState(contains(this), "entry no longer in map");
// similar to putInBothMaps, but set via entry
if (Objects.equal(value, getValue())) {
return value;
}
checkArgument(!containsValue(value), "value already present: %s", value);
V oldValue = finalEntry.setValue(value);
checkState(Objects.equal(value, get(getKey())), "entry no longer in map");
updateInverseMap(getKey(), true, oldValue, value);
return oldValue;
}
};
}
@Override
public void remove() {
checkRemove(entry != null);
V value = entry.getValue();
iterator.remove();
removeFromInverseMap(value);
}
};
}
// See java.util.Collections.CheckedEntrySet for details on attacks.
@Override
public Object[] toArray() {
return standardToArray();
}
@Override
public <T> T[] toArray(T[] array) {
return standardToArray(array);
}
@Override
public boolean contains(Object o) {
return Maps.containsEntryImpl(delegate(), o);
}
@Override
public boolean containsAll(Collection<?> c) {
return standardContainsAll(c);
}
@Override
public boolean removeAll(Collection<?> c) {
return standardRemoveAll(c);
}
@Override
public boolean retainAll(Collection<?> c) {
return standardRetainAll(c);
}
}
/** The inverse of any other {@code AbstractBiMap} subclass. */
private static class Inverse<K, V> extends AbstractBiMap<K, V> {
private Inverse(Map<K, V> backward, AbstractBiMap<V, K> forward) {
super(backward, forward);
}
/*
* Serialization stores the forward bimap, the inverse of this inverse.
* Deserialization calls inverse() on the forward bimap and returns that
* inverse.
*
* If a bimap and its inverse are serialized together, the deserialized
* instances have inverse() methods that return the other.
*/
@Override
K checkKey(K key) {
return inverse.checkValue(key);
}
@Override
V checkValue(V value) {
return inverse.checkKey(value);
}
/**
* @serialData the forward bimap
*/
@GwtIncompatible("java.io.ObjectOuputStream")
private void writeObject(ObjectOutputStream stream) throws IOException {
stream.defaultWriteObject();
stream.writeObject(inverse());
}
@GwtIncompatible("java.io.ObjectInputStream")
@SuppressWarnings("unchecked") // reading data stored by writeObject
private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException {
stream.defaultReadObject();
setInverse((AbstractBiMap<V, K>) stream.readObject());
}
@GwtIncompatible("Not needed in the emulated source.")
Object readResolve() {
return inverse().inverse();
}
@GwtIncompatible("Not needed in emulated source.")
private static final long serialVersionUID = 0;
}
@GwtIncompatible("Not needed in emulated source.")
private static final long serialVersionUID = 0;
}
@@ -1,108 +0,0 @@
/*
* Copyright (C) 2009 The Guava Authors
*
* 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 com.google.common.collect;
import static com.google.common.base.Preconditions.checkPositionIndex;
import com.google.common.annotations.GwtCompatible;
import java.util.ListIterator;
import java.util.NoSuchElementException;
/**
* This class provides a skeletal implementation of the {@link ListIterator}
* interface across a fixed number of elements that may be retrieved by
* position. It does not support {@link #remove}, {@link #set}, or {@link #add}.
*
* @author Jared Levy
*/
@GwtCompatible
abstract class AbstractIndexedListIterator<E> extends UnmodifiableListIterator<E> {
private final int size;
private int position;
/**
* Returns the element with the specified index. This method is called by
* {@link #next()}.
*/
protected abstract E get(int index);
/**
* Constructs an iterator across a sequence of the given size whose initial
* position is 0. That is, the first call to {@link #next()} will return the
* first element (or throw {@link NoSuchElementException} if {@code size} is
* zero).
*
* @throws IllegalArgumentException if {@code size} is negative
*/
protected AbstractIndexedListIterator(int size) {
this(size, 0);
}
/**
* Constructs an iterator across a sequence of the given size with the given
* initial position. That is, the first call to {@link #nextIndex()} will
* return {@code position}, and the first call to {@link #next()} will return
* the element at that index, if available. Calls to {@link #previous()} can
* retrieve the preceding {@code position} elements.
*
* @throws IndexOutOfBoundsException if {@code position} is negative or is
* greater than {@code size}
* @throws IllegalArgumentException if {@code size} is negative
*/
protected AbstractIndexedListIterator(int size, int position) {
checkPositionIndex(position, size);
this.size = size;
this.position = position;
}
@Override
public final boolean hasNext() {
return position < size;
}
@Override
public final E next() {
if (!hasNext()) {
throw new NoSuchElementException();
}
return get(position++);
}
@Override
public final int nextIndex() {
return position;
}
@Override
public final boolean hasPrevious() {
return position > 0;
}
@Override
public final E previous() {
if (!hasPrevious()) {
throw new NoSuchElementException();
}
return get(--position);
}
@Override
public final int previousIndex() {
return position - 1;
}
}
@@ -1,175 +0,0 @@
/*
* Copyright (C) 2007 The Guava Authors
*
* 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 com.google.common.collect;
import static com.google.common.base.Preconditions.checkState;
import com.google.common.annotations.GwtCompatible;
import java.util.NoSuchElementException;
/**
* This class provides a skeletal implementation of the {@code Iterator}
* interface, to make this interface easier to implement for certain types of
* data sources.
*
* <p>{@code Iterator} requires its implementations to support querying the
* end-of-data status without changing the iterator's state, using the {@link
* #hasNext} method. But many data sources, such as {@link
* java.io.Reader#read()}, do not expose this information; the only way to
* discover whether there is any data left is by trying to retrieve it. These
* types of data sources are ordinarily difficult to write iterators for. But
* using this class, one must implement only the {@link #computeNext} method,
* and invoke the {@link #endOfData} method when appropriate.
*
* <p>Another example is an iterator that skips over null elements in a backing
* iterator. This could be implemented as: <pre> {@code
*
* public static Iterator<String> skipNulls(final Iterator<String> in) {
* return new AbstractIterator<String>() {
* protected String computeNext() {
* while (in.hasNext()) {
* String s = in.next();
* if (s != null) {
* return s;
* }
* }
* return endOfData();
* }
* };
* }}</pre>
*
* <p>This class supports iterators that include null elements.
*
* @author Kevin Bourrillion
* @since 2.0
*/
// When making changes to this class, please also update the copy at
// com.google.common.base.AbstractIterator
@GwtCompatible
public abstract class AbstractIterator<T> extends UnmodifiableIterator<T> {
private State state = State.NOT_READY;
/** Constructor for use by subclasses. */
protected AbstractIterator() {}
private enum State {
/** We have computed the next element and haven't returned it yet. */
READY,
/** We haven't yet computed or have already returned the element. */
NOT_READY,
/** We have reached the end of the data and are finished. */
DONE,
/** We've suffered an exception and are kaput. */
FAILED,
}
private T next;
/**
* Returns the next element. <b>Note:</b> the implementation must call {@link
* #endOfData()} when there are no elements left in the iteration. Failure to
* do so could result in an infinite loop.
*
* <p>The initial invocation of {@link #hasNext()} or {@link #next()} calls
* this method, as does the first invocation of {@code hasNext} or {@code
* next} following each successful call to {@code next}. Once the
* implementation either invokes {@code endOfData} or throws an exception,
* {@code computeNext} is guaranteed to never be called again.
*
* <p>If this method throws an exception, it will propagate outward to the
* {@code hasNext} or {@code next} invocation that invoked this method. Any
* further attempts to use the iterator will result in an {@link
* IllegalStateException}.
*
* <p>The implementation of this method may not invoke the {@code hasNext},
* {@code next}, or {@link #peek()} methods on this instance; if it does, an
* {@code IllegalStateException} will result.
*
* @return the next element if there was one. If {@code endOfData} was called
* during execution, the return value will be ignored.
* @throws RuntimeException if any unrecoverable error happens. This exception
* will propagate outward to the {@code hasNext()}, {@code next()}, or
* {@code peek()} invocation that invoked this method. Any further
* attempts to use the iterator will result in an
* {@link IllegalStateException}.
*/
protected abstract T computeNext();
/**
* Implementations of {@link #computeNext} <b>must</b> invoke this method when
* there are no elements left in the iteration.
*
* @return {@code null}; a convenience so your {@code computeNext}
* implementation can use the simple statement {@code return endOfData();}
*/
protected final T endOfData() {
state = State.DONE;
return null;
}
@Override
public final boolean hasNext() {
checkState(state != State.FAILED);
switch (state) {
case DONE:
return false;
case READY:
return true;
default:
}
return tryToComputeNext();
}
private boolean tryToComputeNext() {
state = State.FAILED; // temporary pessimism
next = computeNext();
if (state != State.DONE) {
state = State.READY;
return true;
}
return false;
}
@Override
public final T next() {
if (!hasNext()) {
throw new NoSuchElementException();
}
state = State.NOT_READY;
T result = next;
next = null;
return result;
}
/**
* Returns the next element in the iteration without advancing the iteration,
* according to the contract of {@link PeekingIterator#peek()}.
*
* <p>Implementations of {@code AbstractIterator} that wish to expose this
* functionality should implement {@code PeekingIterator}.
*/
public final T peek() {
if (!hasNext()) {
throw new NoSuchElementException();
}
return next;
}
}
@@ -1,131 +0,0 @@
/*
* Copyright (C) 2007 The Guava Authors
*
* 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 com.google.common.collect;
import com.google.common.annotations.GwtCompatible;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import javax.annotation.Nullable;
/**
* Basic implementation of the {@link ListMultimap} interface. It's a wrapper
* around {@link AbstractMapBasedMultimap} that converts the returned collections into
* {@code Lists}. The {@link #createCollection} method must return a {@code
* List}.
*
* @author Jared Levy
* @since 2.0
*/
@GwtCompatible
abstract class AbstractListMultimap<K, V> extends AbstractMapBasedMultimap<K, V>
implements ListMultimap<K, V> {
/**
* Creates a new multimap that uses the provided map.
*
* @param map place to store the mapping from each key to its corresponding
* values
*/
protected AbstractListMultimap(Map<K, Collection<V>> map) {
super(map);
}
@Override
abstract List<V> createCollection();
@Override
List<V> createUnmodifiableEmptyCollection() {
return ImmutableList.of();
}
// Following Javadoc copied from ListMultimap.
/**
* {@inheritDoc}
*
* <p>Because the values for a given key may have duplicates and follow the
* insertion ordering, this method returns a {@link List}, instead of the
* {@link Collection} specified in the {@link Multimap} interface.
*/
@Override
public List<V> get(@Nullable K key) {
return (List<V>) super.get(key);
}
/**
* {@inheritDoc}
*
* <p>Because the values for a given key may have duplicates and follow the
* insertion ordering, this method returns a {@link List}, instead of the
* {@link Collection} specified in the {@link Multimap} interface.
*/
@Override
public List<V> removeAll(@Nullable Object key) {
return (List<V>) super.removeAll(key);
}
/**
* {@inheritDoc}
*
* <p>Because the values for a given key may have duplicates and follow the
* insertion ordering, this method returns a {@link List}, instead of the
* {@link Collection} specified in the {@link Multimap} interface.
*/
@Override
public List<V> replaceValues(@Nullable K key, Iterable<? extends V> values) {
return (List<V>) super.replaceValues(key, values);
}
/**
* Stores a key-value pair in the multimap.
*
* @param key key to store in the multimap
* @param value value to store in the multimap
* @return {@code true} always
*/
@Override
public boolean put(@Nullable K key, @Nullable V value) {
return super.put(key, value);
}
/**
* {@inheritDoc}
*
* <p>Though the method signature doesn't say so explicitly, the returned map
* has {@link List} values.
*/
@Override
public Map<K, Collection<V>> asMap() {
return super.asMap();
}
/**
* Compares the specified object to this multimap for equality.
*
* <p>Two {@code ListMultimap} instances are equal if, for each key, they
* contain the same values in the same order. If the value orderings disagree,
* the multimaps will not be considered equal.
*/
@Override
public boolean equals(@Nullable Object object) {
return super.equals(object);
}
private static final long serialVersionUID = 6588350623831699109L;
}
File diff suppressed because it is too large Load Diff
@@ -1,302 +0,0 @@
/*
* Copyright (C) 2007 The Guava Authors
*
* 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 com.google.common.collect;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.collect.CollectPreconditions.checkNonnegative;
import static com.google.common.collect.CollectPreconditions.checkRemove;
import com.google.common.annotations.GwtCompatible;
import com.google.common.annotations.GwtIncompatible;
import com.google.common.primitives.Ints;
import java.io.InvalidObjectException;
import java.io.ObjectStreamException;
import java.io.Serializable;
import java.util.ConcurrentModificationException;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import javax.annotation.Nullable;
/**
* Basic implementation of {@code Multiset<E>} backed by an instance of {@code
* Map<E, Count>}.
*
* <p>For serialization to work, the subclass must specify explicit {@code
* readObject} and {@code writeObject} methods.
*
* @author Kevin Bourrillion
*/
@GwtCompatible(emulated = true)
abstract class AbstractMapBasedMultiset<E> extends AbstractMultiset<E> implements Serializable {
private transient Map<E, Count> backingMap;
/*
* Cache the size for efficiency. Using a long lets us avoid the need for
* overflow checking and ensures that size() will function correctly even if
* the multiset had once been larger than Integer.MAX_VALUE.
*/
private transient long size;
/** Standard constructor. */
protected AbstractMapBasedMultiset(Map<E, Count> backingMap) {
this.backingMap = checkNotNull(backingMap);
this.size = super.size();
}
/** Used during deserialization only. The backing map must be empty. */
void setBackingMap(Map<E, Count> backingMap) {
this.backingMap = backingMap;
}
// Required Implementations
/**
* {@inheritDoc}
*
* <p>Invoking {@link Multiset.Entry#getCount} on an entry in the returned
* set always returns the current count of that element in the multiset, as
* opposed to the count at the time the entry was retrieved.
*/
@Override
public Set<Multiset.Entry<E>> entrySet() {
return super.entrySet();
}
@Override
Iterator<Entry<E>> entryIterator() {
final Iterator<Map.Entry<E, Count>> backingEntries = backingMap.entrySet().iterator();
return new Iterator<Multiset.Entry<E>>() {
Map.Entry<E, Count> toRemove;
@Override
public boolean hasNext() {
return backingEntries.hasNext();
}
@Override
public Multiset.Entry<E> next() {
final Map.Entry<E, Count> mapEntry = backingEntries.next();
toRemove = mapEntry;
return new Multisets.AbstractEntry<E>() {
@Override
public E getElement() {
return mapEntry.getKey();
}
@Override
public int getCount() {
Count count = mapEntry.getValue();
if (count == null || count.get() == 0) {
Count frequency = backingMap.get(getElement());
if (frequency != null) {
return frequency.get();
}
}
return (count == null) ? 0 : count.get();
}
};
}
@Override
public void remove() {
checkRemove(toRemove != null);
size -= toRemove.getValue().getAndSet(0);
backingEntries.remove();
toRemove = null;
}
};
}
@Override
public void clear() {
for (Count frequency : backingMap.values()) {
frequency.set(0);
}
backingMap.clear();
size = 0L;
}
@Override
int distinctElements() {
return backingMap.size();
}
// Optimizations - Query Operations
@Override
public int size() {
return Ints.saturatedCast(size);
}
@Override
public Iterator<E> iterator() {
return new MapBasedMultisetIterator();
}
/*
* Not subclassing AbstractMultiset$MultisetIterator because next() needs to
* retrieve the Map.Entry<E, Count> entry, which can then be used for
* a more efficient remove() call.
*/
private class MapBasedMultisetIterator implements Iterator<E> {
final Iterator<Map.Entry<E, Count>> entryIterator;
Map.Entry<E, Count> currentEntry;
int occurrencesLeft;
boolean canRemove;
MapBasedMultisetIterator() {
this.entryIterator = backingMap.entrySet().iterator();
}
@Override
public boolean hasNext() {
return occurrencesLeft > 0 || entryIterator.hasNext();
}
@Override
public E next() {
if (occurrencesLeft == 0) {
currentEntry = entryIterator.next();
occurrencesLeft = currentEntry.getValue().get();
}
occurrencesLeft--;
canRemove = true;
return currentEntry.getKey();
}
@Override
public void remove() {
checkRemove(canRemove);
int frequency = currentEntry.getValue().get();
if (frequency <= 0) {
throw new ConcurrentModificationException();
}
if (currentEntry.getValue().addAndGet(-1) == 0) {
entryIterator.remove();
}
size--;
canRemove = false;
}
}
@Override
public int count(@Nullable Object element) {
Count frequency = Maps.safeGet(backingMap, element);
return (frequency == null) ? 0 : frequency.get();
}
// Optional Operations - Modification Operations
/**
* {@inheritDoc}
*
* @throws IllegalArgumentException if the call would result in more than
* {@link Integer#MAX_VALUE} occurrences of {@code element} in this
* multiset.
*/
@Override
public int add(@Nullable E element, int occurrences) {
if (occurrences == 0) {
return count(element);
}
checkArgument(occurrences > 0, "occurrences cannot be negative: %s", occurrences);
Count frequency = backingMap.get(element);
int oldCount;
if (frequency == null) {
oldCount = 0;
backingMap.put(element, new Count(occurrences));
} else {
oldCount = frequency.get();
long newCount = (long) oldCount + (long) occurrences;
checkArgument(newCount <= Integer.MAX_VALUE, "too many occurrences: %s", newCount);
frequency.getAndAdd(occurrences);
}
size += occurrences;
return oldCount;
}
@Override
public int remove(@Nullable Object element, int occurrences) {
if (occurrences == 0) {
return count(element);
}
checkArgument(occurrences > 0, "occurrences cannot be negative: %s", occurrences);
Count frequency = backingMap.get(element);
if (frequency == null) {
return 0;
}
int oldCount = frequency.get();
int numberRemoved;
if (oldCount > occurrences) {
numberRemoved = occurrences;
} else {
numberRemoved = oldCount;
backingMap.remove(element);
}
frequency.addAndGet(-numberRemoved);
size -= numberRemoved;
return oldCount;
}
// Roughly a 33% performance improvement over AbstractMultiset.setCount().
@Override
public int setCount(@Nullable E element, int count) {
checkNonnegative(count, "count");
Count existingCounter;
int oldCount;
if (count == 0) {
existingCounter = backingMap.remove(element);
oldCount = getAndSet(existingCounter, count);
} else {
existingCounter = backingMap.get(element);
oldCount = getAndSet(existingCounter, count);
if (existingCounter == null) {
backingMap.put(element, new Count(count));
}
}
size += (count - oldCount);
return oldCount;
}
private static int getAndSet(Count i, int count) {
if (i == null) {
return 0;
}
return i.getAndSet(count);
}
// Don't allow default serialization.
@GwtIncompatible("java.io.ObjectStreamException")
private void readObjectNoData() throws ObjectStreamException {
throw new InvalidObjectException("Stream data required");
}
@GwtIncompatible("not needed in emulated source.")
private static final long serialVersionUID = -2250766705698539974L;
}
@@ -1,70 +0,0 @@
/*
* Copyright (C) 2007 The Guava Authors
*
* 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 com.google.common.collect;
import com.google.common.annotations.GwtCompatible;
import com.google.common.base.Objects;
import java.util.Map.Entry;
import javax.annotation.Nullable;
/**
* Implementation of the {@code equals}, {@code hashCode}, and {@code toString}
* methods of {@code Entry}.
*
* @author Jared Levy
*/
@GwtCompatible
abstract class AbstractMapEntry<K, V> implements Entry<K, V> {
@Override
public abstract K getKey();
@Override
public abstract V getValue();
@Override
public V setValue(V value) {
throw new UnsupportedOperationException();
}
@Override
public boolean equals(@Nullable Object object) {
if (object instanceof Entry) {
Entry<?, ?> that = (Entry<?, ?>) object;
return Objects.equal(this.getKey(), that.getKey())
&& Objects.equal(this.getValue(), that.getValue());
}
return false;
}
@Override
public int hashCode() {
K k = getKey();
V v = getValue();
return ((k == null) ? 0 : k.hashCode()) ^ ((v == null) ? 0 : v.hashCode());
}
/**
* Returns a string representation of the form {@code {key}={value}}.
*/
@Override
public String toString() {
return getKey() + "=" + getValue();
}
}
@@ -1,251 +0,0 @@
/*
* Copyright (C) 2012 The Guava Authors
*
* 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 com.google.common.collect;
import static com.google.common.base.Preconditions.checkNotNull;
import com.google.common.annotations.GwtCompatible;
import com.google.j2objc.annotations.WeakOuter;
import java.util.AbstractCollection;
import java.util.Collection;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import javax.annotation.Nullable;
/**
* A skeleton {@code Multimap} implementation, not necessarily in terms of a {@code Map}.
*
* @author Louis Wasserman
*/
@GwtCompatible
abstract class AbstractMultimap<K, V> implements Multimap<K, V> {
@Override
public boolean isEmpty() {
return size() == 0;
}
@Override
public boolean containsValue(@Nullable Object value) {
for (Collection<V> collection : asMap().values()) {
if (collection.contains(value)) {
return true;
}
}
return false;
}
@Override
public boolean containsEntry(@Nullable Object key, @Nullable Object value) {
Collection<V> collection = asMap().get(key);
return collection != null && collection.contains(value);
}
@Override
public boolean remove(@Nullable Object key, @Nullable Object value) {
Collection<V> collection = asMap().get(key);
return collection != null && collection.remove(value);
}
@Override
public boolean put(@Nullable K key, @Nullable V value) {
return get(key).add(value);
}
@Override
public boolean putAll(@Nullable K key, Iterable<? extends V> values) {
checkNotNull(values);
// make sure we only call values.iterator() once
// and we only call get(key) if values is nonempty
if (values instanceof Collection) {
Collection<? extends V> valueCollection = (Collection<? extends V>) values;
return !valueCollection.isEmpty() && get(key).addAll(valueCollection);
} else {
Iterator<? extends V> valueItr = values.iterator();
return valueItr.hasNext() && Iterators.addAll(get(key), valueItr);
}
}
@Override
public boolean putAll(Multimap<? extends K, ? extends V> multimap) {
boolean changed = false;
for (Map.Entry<? extends K, ? extends V> entry : multimap.entries()) {
changed |= put(entry.getKey(), entry.getValue());
}
return changed;
}
@Override
public Collection<V> replaceValues(@Nullable K key, Iterable<? extends V> values) {
checkNotNull(values);
Collection<V> result = removeAll(key);
putAll(key, values);
return result;
}
private transient Collection<Entry<K, V>> entries;
@Override
public Collection<Entry<K, V>> entries() {
Collection<Entry<K, V>> result = entries;
return (result == null) ? entries = createEntries() : result;
}
Collection<Entry<K, V>> createEntries() {
if (this instanceof SetMultimap) {
return new EntrySet();
} else {
return new Entries();
}
}
@WeakOuter
private class Entries extends Multimaps.Entries<K, V> {
@Override
Multimap<K, V> multimap() {
return AbstractMultimap.this;
}
@Override
public Iterator<Entry<K, V>> iterator() {
return entryIterator();
}
}
@WeakOuter
private class EntrySet extends Entries implements Set<Entry<K, V>> {
@Override
public int hashCode() {
return Sets.hashCodeImpl(this);
}
@Override
public boolean equals(@Nullable Object obj) {
return Sets.equalsImpl(this, obj);
}
}
abstract Iterator<Entry<K, V>> entryIterator();
private transient Set<K> keySet;
@Override
public Set<K> keySet() {
Set<K> result = keySet;
return (result == null) ? keySet = createKeySet() : result;
}
Set<K> createKeySet() {
return new Maps.KeySet<K, Collection<V>>(asMap());
}
private transient Multiset<K> keys;
@Override
public Multiset<K> keys() {
Multiset<K> result = keys;
return (result == null) ? keys = createKeys() : result;
}
Multiset<K> createKeys() {
return new Multimaps.Keys<K, V>(this);
}
private transient Collection<V> values;
@Override
public Collection<V> values() {
Collection<V> result = values;
return (result == null) ? values = createValues() : result;
}
Collection<V> createValues() {
return new Values();
}
@WeakOuter
class Values extends AbstractCollection<V> {
@Override
public Iterator<V> iterator() {
return valueIterator();
}
@Override
public int size() {
return AbstractMultimap.this.size();
}
@Override
public boolean contains(@Nullable Object o) {
return AbstractMultimap.this.containsValue(o);
}
@Override
public void clear() {
AbstractMultimap.this.clear();
}
}
Iterator<V> valueIterator() {
return Maps.valueIterator(entries().iterator());
}
private transient Map<K, Collection<V>> asMap;
@Override
public Map<K, Collection<V>> asMap() {
Map<K, Collection<V>> result = asMap;
return (result == null) ? asMap = createAsMap() : result;
}
abstract Map<K, Collection<V>> createAsMap();
// Comparison and hashing
@Override
public boolean equals(@Nullable Object object) {
return Multimaps.equalsImpl(this, object);
}
/**
* Returns the hash code for this multimap.
*
* <p>The hash code of a multimap is defined as the hash code of the map view,
* as returned by {@link Multimap#asMap}.
*
* @see Map#hashCode
*/
@Override
public int hashCode() {
return asMap().hashCode();
}
/**
* Returns a string representation of the multimap, generated by calling
* {@code toString} on the map returned by {@link Multimap#asMap}.
*
* @return a string representation of the multimap
*/
@Override
public String toString() {
return asMap().toString();
}
}
@@ -1,243 +0,0 @@
/*
* Copyright (C) 2007 The Guava Authors
*
* 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 com.google.common.collect;
import static com.google.common.collect.Multisets.setCountImpl;
import com.google.common.annotations.GwtCompatible;
import com.google.common.base.Objects;
import com.google.j2objc.annotations.WeakOuter;
import java.util.AbstractCollection;
import java.util.Collection;
import java.util.Iterator;
import java.util.Set;
import javax.annotation.Nullable;
/**
* This class provides a skeletal implementation of the {@link Multiset}
* interface. A new multiset implementation can be created easily by extending
* this class and implementing the {@link Multiset#entrySet()} method, plus
* optionally overriding {@link #add(Object, int)} and
* {@link #remove(Object, int)} to enable modifications to the multiset.
*
* <p>The {@link #count} and {@link #size} implementations all iterate across
* the set returned by {@link Multiset#entrySet()}, as do many methods acting on
* the set returned by {@link #elementSet()}. Override those methods for better
* performance.
*
* @author Kevin Bourrillion
* @author Louis Wasserman
*/
@GwtCompatible
abstract class AbstractMultiset<E> extends AbstractCollection<E> implements Multiset<E> {
// Query Operations
@Override
public int size() {
return Multisets.sizeImpl(this);
}
@Override
public boolean isEmpty() {
return entrySet().isEmpty();
}
@Override
public boolean contains(@Nullable Object element) {
return count(element) > 0;
}
@Override
public Iterator<E> iterator() {
return Multisets.iteratorImpl(this);
}
@Override
public int count(@Nullable Object element) {
for (Entry<E> entry : entrySet()) {
if (Objects.equal(entry.getElement(), element)) {
return entry.getCount();
}
}
return 0;
}
// Modification Operations
@Override
public boolean add(@Nullable E element) {
add(element, 1);
return true;
}
@Override
public int add(@Nullable E element, int occurrences) {
throw new UnsupportedOperationException();
}
@Override
public boolean remove(@Nullable Object element) {
return remove(element, 1) > 0;
}
@Override
public int remove(@Nullable Object element, int occurrences) {
throw new UnsupportedOperationException();
}
@Override
public int setCount(@Nullable E element, int count) {
return setCountImpl(this, element, count);
}
@Override
public boolean setCount(@Nullable E element, int oldCount, int newCount) {
return setCountImpl(this, element, oldCount, newCount);
}
// Bulk Operations
/**
* {@inheritDoc}
*
* <p>This implementation is highly efficient when {@code elementsToAdd}
* is itself a {@link Multiset}.
*/
@Override
public boolean addAll(Collection<? extends E> elementsToAdd) {
return Multisets.addAllImpl(this, elementsToAdd);
}
@Override
public boolean removeAll(Collection<?> elementsToRemove) {
return Multisets.removeAllImpl(this, elementsToRemove);
}
@Override
public boolean retainAll(Collection<?> elementsToRetain) {
return Multisets.retainAllImpl(this, elementsToRetain);
}
@Override
public void clear() {
Iterators.clear(entryIterator());
}
// Views
private transient Set<E> elementSet;
@Override
public Set<E> elementSet() {
Set<E> result = elementSet;
if (result == null) {
elementSet = result = createElementSet();
}
return result;
}
/**
* Creates a new instance of this multiset's element set, which will be
* returned by {@link #elementSet()}.
*/
Set<E> createElementSet() {
return new ElementSet();
}
@WeakOuter
class ElementSet extends Multisets.ElementSet<E> {
@Override
Multiset<E> multiset() {
return AbstractMultiset.this;
}
}
abstract Iterator<Entry<E>> entryIterator();
abstract int distinctElements();
private transient Set<Entry<E>> entrySet;
@Override
public Set<Entry<E>> entrySet() {
Set<Entry<E>> result = entrySet;
if (result == null) {
entrySet = result = createEntrySet();
}
return result;
}
@WeakOuter
class EntrySet extends Multisets.EntrySet<E> {
@Override
Multiset<E> multiset() {
return AbstractMultiset.this;
}
@Override
public Iterator<Entry<E>> iterator() {
return entryIterator();
}
@Override
public int size() {
return distinctElements();
}
}
Set<Entry<E>> createEntrySet() {
return new EntrySet();
}
// Object methods
/**
* {@inheritDoc}
*
* <p>This implementation returns {@code true} if {@code object} is a multiset
* of the same size and if, for each element, the two multisets have the same
* count.
*/
@Override
public boolean equals(@Nullable Object object) {
return Multisets.equalsImpl(this, object);
}
/**
* {@inheritDoc}
*
* <p>This implementation returns the hash code of {@link
* Multiset#entrySet()}.
*/
@Override
public int hashCode() {
return entrySet().hashCode();
}
/**
* {@inheritDoc}
*
* <p>This implementation returns the result of invoking {@code toString} on
* {@link Multiset#entrySet()}.
*/
@Override
public String toString() {
return entrySet().toString();
}
}
@@ -1,178 +0,0 @@
/*
* Copyright (C) 2012 The Guava Authors
*
* 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 com.google.common.collect;
import com.google.common.collect.Maps.IteratorBasedAbstractMap;
import java.util.Iterator;
import java.util.NavigableMap;
import java.util.NavigableSet;
import java.util.NoSuchElementException;
import java.util.Set;
import java.util.SortedMap;
import javax.annotation.Nullable;
/**
* Skeletal implementation of {@link NavigableMap}.
*
* @author Louis Wasserman
*/
abstract class AbstractNavigableMap<K, V> extends IteratorBasedAbstractMap<K, V>
implements NavigableMap<K, V> {
@Override
@Nullable
public abstract V get(@Nullable Object key);
@Override
@Nullable
public Entry<K, V> firstEntry() {
return Iterators.getNext(entryIterator(), null);
}
@Override
@Nullable
public Entry<K, V> lastEntry() {
return Iterators.getNext(descendingEntryIterator(), null);
}
@Override
@Nullable
public Entry<K, V> pollFirstEntry() {
return Iterators.pollNext(entryIterator());
}
@Override
@Nullable
public Entry<K, V> pollLastEntry() {
return Iterators.pollNext(descendingEntryIterator());
}
@Override
public K firstKey() {
Entry<K, V> entry = firstEntry();
if (entry == null) {
throw new NoSuchElementException();
} else {
return entry.getKey();
}
}
@Override
public K lastKey() {
Entry<K, V> entry = lastEntry();
if (entry == null) {
throw new NoSuchElementException();
} else {
return entry.getKey();
}
}
@Override
@Nullable
public Entry<K, V> lowerEntry(K key) {
return headMap(key, false).lastEntry();
}
@Override
@Nullable
public Entry<K, V> floorEntry(K key) {
return headMap(key, true).lastEntry();
}
@Override
@Nullable
public Entry<K, V> ceilingEntry(K key) {
return tailMap(key, true).firstEntry();
}
@Override
@Nullable
public Entry<K, V> higherEntry(K key) {
return tailMap(key, false).firstEntry();
}
@Override
public K lowerKey(K key) {
return Maps.keyOrNull(lowerEntry(key));
}
@Override
public K floorKey(K key) {
return Maps.keyOrNull(floorEntry(key));
}
@Override
public K ceilingKey(K key) {
return Maps.keyOrNull(ceilingEntry(key));
}
@Override
public K higherKey(K key) {
return Maps.keyOrNull(higherEntry(key));
}
abstract Iterator<Entry<K, V>> descendingEntryIterator();
@Override
public SortedMap<K, V> subMap(K fromKey, K toKey) {
return subMap(fromKey, true, toKey, false);
}
@Override
public SortedMap<K, V> headMap(K toKey) {
return headMap(toKey, false);
}
@Override
public SortedMap<K, V> tailMap(K fromKey) {
return tailMap(fromKey, true);
}
@Override
public NavigableSet<K> navigableKeySet() {
return new Maps.NavigableKeySet<K, V>(this);
}
@Override
public Set<K> keySet() {
return navigableKeySet();
}
@Override
public NavigableSet<K> descendingKeySet() {
return descendingMap().navigableKeySet();
}
@Override
public NavigableMap<K, V> descendingMap() {
return new DescendingMap();
}
private final class DescendingMap extends Maps.DescendingMap<K, V> {
@Override
NavigableMap<K, V> forward() {
return AbstractNavigableMap.this;
}
@Override
Iterator<Entry<K, V>> entryIterator() {
return descendingEntryIterator();
}
}
}
@@ -1,102 +0,0 @@
/*
* Copyright (C) 2011 The Guava Authors
*
* 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 com.google.common.collect;
import javax.annotation.Nullable;
/**
* A skeletal implementation of {@code RangeSet}.
*
* @author Louis Wasserman
*/
abstract class AbstractRangeSet<C extends Comparable> implements RangeSet<C> {
AbstractRangeSet() {}
@Override
public boolean contains(C value) {
return rangeContaining(value) != null;
}
@Override
public abstract Range<C> rangeContaining(C value);
@Override
public boolean isEmpty() {
return asRanges().isEmpty();
}
@Override
public void add(Range<C> range) {
throw new UnsupportedOperationException();
}
@Override
public void remove(Range<C> range) {
throw new UnsupportedOperationException();
}
@Override
public void clear() {
remove(Range.<C>all());
}
@Override
public boolean enclosesAll(RangeSet<C> other) {
for (Range<C> range : other.asRanges()) {
if (!encloses(range)) {
return false;
}
}
return true;
}
@Override
public void addAll(RangeSet<C> other) {
for (Range<C> range : other.asRanges()) {
add(range);
}
}
@Override
public void removeAll(RangeSet<C> other) {
for (Range<C> range : other.asRanges()) {
remove(range);
}
}
@Override
public abstract boolean encloses(Range<C> otherRange);
@Override
public boolean equals(@Nullable Object obj) {
if (obj == this) {
return true;
} else if (obj instanceof RangeSet) {
RangeSet<?> other = (RangeSet<?>) obj;
return this.asRanges().equals(other.asRanges());
}
return false;
}
@Override
public final int hashCode() {
return asRanges().hashCode();
}
@Override
public final String toString() {
return asRanges().toString();
}
}
@@ -1,79 +0,0 @@
/*
* Copyright (C) 2010 The Guava Authors
*
* 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 com.google.common.collect;
import com.google.common.annotations.GwtCompatible;
import java.util.NoSuchElementException;
import javax.annotation.Nullable;
/**
* This class provides a skeletal implementation of the {@code Iterator}
* interface for sequences whose next element can always be derived from the
* previous element. Null elements are not supported, nor is the
* {@link #remove()} method.
*
* <p>Example: <pre> {@code
*
* Iterator<Integer> powersOfTwo =
* new AbstractSequentialIterator<Integer>(1) {
* protected Integer computeNext(Integer previous) {
* return (previous == 1 << 30) ? null : previous * 2;
* }
* };}</pre>
*
* @author Chris Povirk
* @since 12.0 (in Guava as {@code AbstractLinkedIterator} since 8.0)
*/
@GwtCompatible
public abstract class AbstractSequentialIterator<T> extends UnmodifiableIterator<T> {
private T nextOrNull;
/**
* Creates a new iterator with the given first element, or, if {@code
* firstOrNull} is null, creates a new empty iterator.
*/
protected AbstractSequentialIterator(@Nullable T firstOrNull) {
this.nextOrNull = firstOrNull;
}
/**
* Returns the element that follows {@code previous}, or returns {@code null}
* if no elements remain. This method is invoked during each call to
* {@link #next()} in order to compute the result of a <i>future</i> call to
* {@code next()}.
*/
protected abstract T computeNext(T previous);
@Override
public final boolean hasNext() {
return nextOrNull != null;
}
@Override
public final T next() {
if (!hasNext()) {
throw new NoSuchElementException();
}
try {
return nextOrNull;
} finally {
nextOrNull = computeNext(nextOrNull);
}
}
}
@@ -1,144 +0,0 @@
/*
* Copyright (C) 2007 The Guava Authors
*
* 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 com.google.common.collect;
import com.google.common.annotations.GwtCompatible;
import java.util.Collection;
import java.util.Map;
import java.util.Set;
import javax.annotation.Nullable;
/**
* Basic implementation of the {@link SetMultimap} interface. It's a wrapper
* around {@link AbstractMapBasedMultimap} that converts the returned collections into
* {@code Sets}. The {@link #createCollection} method must return a {@code Set}.
*
* @author Jared Levy
*/
@GwtCompatible
abstract class AbstractSetMultimap<K, V> extends AbstractMapBasedMultimap<K, V>
implements SetMultimap<K, V> {
/**
* Creates a new multimap that uses the provided map.
*
* @param map place to store the mapping from each key to its corresponding
* values
*/
protected AbstractSetMultimap(Map<K, Collection<V>> map) {
super(map);
}
@Override
abstract Set<V> createCollection();
@Override
Set<V> createUnmodifiableEmptyCollection() {
return ImmutableSet.of();
}
// Following Javadoc copied from SetMultimap.
/**
* {@inheritDoc}
*
* <p>Because a {@code SetMultimap} has unique values for a given key, this
* method returns a {@link Set}, instead of the {@link Collection} specified
* in the {@link Multimap} interface.
*/
@Override
public Set<V> get(@Nullable K key) {
return (Set<V>) super.get(key);
}
/**
* {@inheritDoc}
*
* <p>Because a {@code SetMultimap} has unique values for a given key, this
* method returns a {@link Set}, instead of the {@link Collection} specified
* in the {@link Multimap} interface.
*/
@Override
public Set<Map.Entry<K, V>> entries() {
return (Set<Map.Entry<K, V>>) super.entries();
}
/**
* {@inheritDoc}
*
* <p>Because a {@code SetMultimap} has unique values for a given key, this
* method returns a {@link Set}, instead of the {@link Collection} specified
* in the {@link Multimap} interface.
*/
@Override
public Set<V> removeAll(@Nullable Object key) {
return (Set<V>) super.removeAll(key);
}
/**
* {@inheritDoc}
*
* <p>Because a {@code SetMultimap} has unique values for a given key, this
* method returns a {@link Set}, instead of the {@link Collection} specified
* in the {@link Multimap} interface.
*
* <p>Any duplicates in {@code values} will be stored in the multimap once.
*/
@Override
public Set<V> replaceValues(@Nullable K key, Iterable<? extends V> values) {
return (Set<V>) super.replaceValues(key, values);
}
/**
* {@inheritDoc}
*
* <p>Though the method signature doesn't say so explicitly, the returned map
* has {@link Set} values.
*/
@Override
public Map<K, Collection<V>> asMap() {
return super.asMap();
}
/**
* Stores a key-value pair in the multimap.
*
* @param key key to store in the multimap
* @param value value to store in the multimap
* @return {@code true} if the method increased the size of the multimap, or
* {@code false} if the multimap already contained the key-value pair
*/
@Override
public boolean put(@Nullable K key, @Nullable V value) {
return super.put(key, value);
}
/**
* Compares the specified object to this multimap for equality.
*
* <p>Two {@code SetMultimap} instances are equal if, for each key, they
* contain the same values. Equality does not depend on the ordering of keys
* or values.
*/
@Override
public boolean equals(@Nullable Object object) {
return super.equals(object);
}
private static final long serialVersionUID = 7431625294878419160L;
}
@@ -1,55 +0,0 @@
/*
* Copyright (C) 2012 The Guava Authors
*
* 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 com.google.common.collect;
import com.google.common.annotations.GwtCompatible;
import java.util.Collection;
import java.util.SortedMap;
import java.util.SortedSet;
/**
* Basic implementation of a {@link SortedSetMultimap} with a sorted key set.
*
* <p>This superclass allows {@code TreeMultimap} to override methods to return
* navigable set and map types in non-GWT only, while GWT code will inherit the
* SortedMap/SortedSet overrides.
*
* @author Louis Wasserman
*/
@GwtCompatible
abstract class AbstractSortedKeySortedSetMultimap<K, V> extends AbstractSortedSetMultimap<K, V> {
AbstractSortedKeySortedSetMultimap(SortedMap<K, Collection<V>> map) {
super(map);
}
@Override
public SortedMap<K, Collection<V>> asMap() {
return (SortedMap<K, Collection<V>>) super.asMap();
}
@Override
SortedMap<K, Collection<V>> backingMap() {
return (SortedMap<K, Collection<V>>) super.backingMap();
}
@Override
public SortedSet<K> keySet() {
return (SortedSet<K>) super.keySet();
}
}
@@ -1,148 +0,0 @@
/*
* Copyright (C) 2011 The Guava Authors
*
* 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 com.google.common.collect;
import static com.google.common.base.Preconditions.checkNotNull;
import com.google.common.annotations.GwtCompatible;
import com.google.j2objc.annotations.WeakOuter;
import java.util.Comparator;
import java.util.Iterator;
import java.util.NavigableSet;
import javax.annotation.Nullable;
/**
* This class provides a skeletal implementation of the {@link SortedMultiset} interface.
*
* <p>The {@link #count} and {@link #size} implementations all iterate across the set returned by
* {@link Multiset#entrySet()}, as do many methods acting on the set returned by
* {@link #elementSet()}. Override those methods for better performance.
*
* @author Louis Wasserman
*/
@GwtCompatible(emulated = true)
abstract class AbstractSortedMultiset<E> extends AbstractMultiset<E> implements SortedMultiset<E> {
@GwtTransient final Comparator<? super E> comparator;
// needed for serialization
@SuppressWarnings("unchecked")
AbstractSortedMultiset() {
this((Comparator) Ordering.natural());
}
AbstractSortedMultiset(Comparator<? super E> comparator) {
this.comparator = checkNotNull(comparator);
}
@Override
public NavigableSet<E> elementSet() {
return (NavigableSet<E>) super.elementSet();
}
@Override
NavigableSet<E> createElementSet() {
return new SortedMultisets.NavigableElementSet<E>(this);
}
@Override
public Comparator<? super E> comparator() {
return comparator;
}
@Override
public Entry<E> firstEntry() {
Iterator<Entry<E>> entryIterator = entryIterator();
return entryIterator.hasNext() ? entryIterator.next() : null;
}
@Override
public Entry<E> lastEntry() {
Iterator<Entry<E>> entryIterator = descendingEntryIterator();
return entryIterator.hasNext() ? entryIterator.next() : null;
}
@Override
public Entry<E> pollFirstEntry() {
Iterator<Entry<E>> entryIterator = entryIterator();
if (entryIterator.hasNext()) {
Entry<E> result = entryIterator.next();
result = Multisets.immutableEntry(result.getElement(), result.getCount());
entryIterator.remove();
return result;
}
return null;
}
@Override
public Entry<E> pollLastEntry() {
Iterator<Entry<E>> entryIterator = descendingEntryIterator();
if (entryIterator.hasNext()) {
Entry<E> result = entryIterator.next();
result = Multisets.immutableEntry(result.getElement(), result.getCount());
entryIterator.remove();
return result;
}
return null;
}
@Override
public SortedMultiset<E> subMultiset(
@Nullable E fromElement,
BoundType fromBoundType,
@Nullable E toElement,
BoundType toBoundType) {
// These are checked elsewhere, but NullPointerTester wants them checked eagerly.
checkNotNull(fromBoundType);
checkNotNull(toBoundType);
return tailMultiset(fromElement, fromBoundType).headMultiset(toElement, toBoundType);
}
abstract Iterator<Entry<E>> descendingEntryIterator();
Iterator<E> descendingIterator() {
return Multisets.iteratorImpl(descendingMultiset());
}
private transient SortedMultiset<E> descendingMultiset;
@Override
public SortedMultiset<E> descendingMultiset() {
SortedMultiset<E> result = descendingMultiset;
return (result == null) ? descendingMultiset = createDescendingMultiset() : result;
}
SortedMultiset<E> createDescendingMultiset() {
@WeakOuter
class DescendingMultisetImpl extends DescendingMultiset<E> {
@Override
SortedMultiset<E> forwardMultiset() {
return AbstractSortedMultiset.this;
}
@Override
Iterator<Entry<E>> entryIterator() {
return descendingEntryIterator();
}
@Override
public Iterator<E> iterator() {
return descendingIterator();
}
}
return new DescendingMultisetImpl();
}
}

Some files were not shown because too many files have changed in this diff Show More