fork skaia from source
This commit is contained in:
commit
bc46ad7f01
1988 changed files with 233868 additions and 0 deletions
BIN
etc/decompiled.zip
Normal file
BIN
etc/decompiled.zip
Normal file
Binary file not shown.
BIN
etc/source.jar
Normal file
BIN
etc/source.jar
Normal file
Binary file not shown.
133
src/main/Log4j-config.xsd
Normal file
133
src/main/Log4j-config.xsd
Normal file
|
@ -0,0 +1,133 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
this work for additional information regarding copyright ownership.
|
||||
The ASF licenses this file to You 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.
|
||||
|
||||
-->
|
||||
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" attributeFormDefault="unqualified">
|
||||
<xs:element name="Configuration" type="ConfigurationType"/>
|
||||
<xs:complexType name="ConfigurationType">
|
||||
<xs:sequence>
|
||||
<xs:element name="Properties" type="PropertiesType"/>
|
||||
<xs:choice minOccurs="0" maxOccurs="1">
|
||||
<xs:element name="Filters" type="FiltersType"/>
|
||||
<xs:element name="Filter" type="FilterType"/>
|
||||
</xs:choice>
|
||||
<xs:element name="ThresholdFilter" type="ThresholdFilterType"/>
|
||||
<xs:element name="Appenders" type="AppendersType"/>
|
||||
<xs:element name="Loggers" type="LoggersType"/>
|
||||
</xs:sequence>
|
||||
<xs:attribute name="packages" type="xs:string"/>
|
||||
<xs:attribute name="status" type="xs:string"/>
|
||||
<xs:attribute name="strict" type="xs:string"/>
|
||||
<xs:attribute name="name" type="xs:string"/>
|
||||
<xs:attribute name="advertiser" type="xs:string"/>
|
||||
</xs:complexType>
|
||||
<xs:complexType name="PropertiesType">
|
||||
<xs:sequence>
|
||||
<xs:element name="Property" type="PropertyType"/>
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
<xs:complexType name="AppenderType">
|
||||
<xs:sequence>
|
||||
<xs:element name="Layout" type="LayoutType" minOccurs="0"/>
|
||||
<xs:choice minOccurs="0" maxOccurs="1">
|
||||
<xs:element name="Filters" type="FiltersType"/>
|
||||
<xs:element name="Filter" type="FilterType"/>
|
||||
</xs:choice>
|
||||
</xs:sequence>
|
||||
<xs:attribute name="type" type="xs:string" use="required"/>
|
||||
<xs:attribute name="name" type="xs:string" use="required"/>
|
||||
<xs:attribute name="fileName" type="xs:string" use="optional"/>
|
||||
</xs:complexType>
|
||||
<xs:complexType name="RootType">
|
||||
<xs:sequence>
|
||||
<xs:element name="AppenderRef" type="AppenderRefType" minOccurs="1" maxOccurs="unbounded"/>
|
||||
</xs:sequence>
|
||||
<xs:attribute name="level" type="xs:string"/>
|
||||
</xs:complexType>
|
||||
<xs:complexType name="PropertyType">
|
||||
<xs:simpleContent>
|
||||
<xs:extension base="xs:string">
|
||||
<xs:attribute name="name" type="xs:string"/>
|
||||
</xs:extension>
|
||||
</xs:simpleContent>
|
||||
</xs:complexType>
|
||||
<xs:complexType name="KeyValuePairType">
|
||||
<xs:simpleContent>
|
||||
<xs:extension base="xs:string">
|
||||
<xs:attribute name="key" type="xs:string"/>
|
||||
<xs:attribute name="value" type="xs:string"/>
|
||||
</xs:extension>
|
||||
</xs:simpleContent>
|
||||
</xs:complexType>
|
||||
<xs:complexType name="AppendersType">
|
||||
<xs:sequence>
|
||||
<xs:element name="Appender" type="AppenderType" minOccurs="1" maxOccurs="unbounded"/>
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
<xs:complexType name="AppenderRefType">
|
||||
<xs:simpleContent>
|
||||
<xs:extension base="xs:string">
|
||||
<xs:attribute name="ref" type="xs:string" use="required"/>
|
||||
</xs:extension>
|
||||
</xs:simpleContent>
|
||||
</xs:complexType>
|
||||
<xs:complexType name="LoggerType">
|
||||
<xs:sequence>
|
||||
<xs:choice minOccurs="0" maxOccurs="1">
|
||||
<xs:element name="Filters" type="FiltersType"/>
|
||||
<xs:element name="Filter" type="FilterType"/>
|
||||
</xs:choice>
|
||||
<xs:element name="AppenderRef" type="AppenderRefType"/>
|
||||
</xs:sequence>
|
||||
<xs:attribute name="name" type="xs:string" use="required"/>
|
||||
<xs:attribute name="level" type="xs:string" use="optional"/>
|
||||
<xs:attribute name="additivity" type="xs:string" use="optional"/>
|
||||
</xs:complexType>
|
||||
<xs:complexType name="FilterType" mixed="true">
|
||||
<xs:sequence>
|
||||
<xs:element name="KeyValuePair" type="KeyValuePairType" minOccurs="0"/>
|
||||
</xs:sequence>
|
||||
<xs:attribute name="type" type="xs:string" use="required"/>
|
||||
<xs:attribute name="level" type="xs:string" use="optional"/>
|
||||
<xs:attribute name="marker" type="xs:string" use="optional"/>
|
||||
<xs:attribute name="onMatch" type="xs:string" use="optional"/>
|
||||
<xs:attribute name="onMismatch" type="xs:string" use="optional"/>
|
||||
</xs:complexType>
|
||||
<xs:complexType name="FiltersType">
|
||||
<xs:sequence>
|
||||
<xs:element name="Filter" type="FilterType" minOccurs="0" maxOccurs="unbounded"/>
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
<xs:complexType name="LoggersType" mixed="true">
|
||||
<xs:sequence>
|
||||
<xs:element name="Logger" type="LoggerType" minOccurs="0" maxOccurs="unbounded"/>
|
||||
<xs:element name="Root" type="RootType" minOccurs="1" maxOccurs="1"/>
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
<xs:complexType name="LayoutType" mixed="true">
|
||||
<xs:sequence>
|
||||
<xs:element name="Pattern" type="xs:string" minOccurs="0"/>
|
||||
</xs:sequence>
|
||||
<xs:attribute name="Type" type="xs:string" use="required"/>
|
||||
<xs:attribute name="Pattern" type="xs:string" use="optional"/>
|
||||
</xs:complexType>
|
||||
<xs:complexType name="ThresholdFilterType">
|
||||
<xs:attribute name="level" type="xs:string" use="optional"/>
|
||||
<xs:attribute name="onMatch" type="xs:string" use="optional"/>
|
||||
<xs:attribute name="onMismatch" type="xs:string" use="optional"/>
|
||||
</xs:complexType>
|
||||
</xs:schema>
|
67
src/main/Log4j-events.dtd
Normal file
67
src/main/Log4j-events.dtd
Normal file
|
@ -0,0 +1,67 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
this work for additional information regarding copyright ownership.
|
||||
The ASF licenses this file to You 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.
|
||||
-->
|
||||
<!--the entity declarations may be overridden in the internal subset-->
|
||||
<!--namespace prefixes-->
|
||||
<!ENTITY % log4j_prefix "log4j">
|
||||
<!--namespace prefix to namespace uri mappings-->
|
||||
<!ENTITY % log4j_prefix.. "%log4j_prefix;:">
|
||||
<!--namespaces attributes for root element-->
|
||||
<!ENTITY % documentElementAttributes " xmlns:%log4j_prefix; CDATA 'http://logging.apache.org/log4j/2.0/events'">
|
||||
<!--the declarations below should not be modified-->
|
||||
<!--element name mappings-->
|
||||
<!ENTITY % log4j..Events "%log4j_prefix..;Events">
|
||||
<!ENTITY % log4j..Event "%log4j_prefix..;Event">
|
||||
<!ENTITY % log4j..Message "%log4j_prefix..;Message">
|
||||
<!ENTITY % log4j..Marker "%log4j_prefix..;Marker">
|
||||
<!ATTLIST %log4j..Marker;
|
||||
parent CDATA #IMPLIED
|
||||
>
|
||||
<!ENTITY % log4j..NDC "%log4j_prefix..;NDC">
|
||||
<!ENTITY % log4j..Throwable "%log4j_prefix..;Throwable">
|
||||
<!ENTITY % log4j..LocationInfo "%log4j_prefix..;LocationInfo">
|
||||
<!ENTITY % log4j..Properties "%log4j_prefix..;Properties">
|
||||
<!ENTITY % log4j..Data "%log4j_prefix..;Data">
|
||||
<!--element and attribute declarations-->
|
||||
<!--Log4J 2.0 XML Schema-->
|
||||
<!ELEMENT %log4j..Events; ((%log4j..Event;)*)>
|
||||
<!ATTLIST %log4j..Events;
|
||||
%documentElementAttributes;
|
||||
>
|
||||
<!ELEMENT %log4j..Event; (%log4j..Message;, (%log4j..NDC;)?, (%log4j..Marker;)?, (%log4j..Throwable;)?, (%log4j..LocationInfo;)?, (%log4j..Properties;)?)>
|
||||
<!ATTLIST %log4j..Event;
|
||||
logger CDATA #REQUIRED
|
||||
timestamp NMTOKEN #REQUIRED
|
||||
level (OFF | FATAL | ERROR | WARN | INFO | DEBUG | TRACE | ALL) #REQUIRED
|
||||
thread CDATA #REQUIRED
|
||||
>
|
||||
<!ELEMENT %log4j..Message; ANY>
|
||||
<!ELEMENT %log4j..NDC; ANY>
|
||||
<!ELEMENT %log4j..Throwable; ANY>
|
||||
<!ELEMENT %log4j..LocationInfo; EMPTY>
|
||||
<!ATTLIST %log4j..LocationInfo;
|
||||
class CDATA #REQUIRED
|
||||
method CDATA #REQUIRED
|
||||
file CDATA #REQUIRED
|
||||
line NMTOKEN #REQUIRED
|
||||
>
|
||||
<!ELEMENT %log4j..Properties; ((%log4j..Data;)+)>
|
||||
<!ELEMENT %log4j..Data; EMPTY>
|
||||
<!ATTLIST %log4j..Data;
|
||||
name CDATA #REQUIRED
|
||||
value CDATA #REQUIRED
|
||||
>
|
78
src/main/Log4j-events.xsd
Normal file
78
src/main/Log4j-events.xsd
Normal file
|
@ -0,0 +1,78 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
this work for additional information regarding copyright ownership.
|
||||
The ASF licenses this file to You 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.
|
||||
-->
|
||||
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:log4j="http://logging.apache.org/log4j/2.0/events" targetNamespace="http://logging.apache.org/log4j/2.0/events" elementFormDefault="qualified" attributeFormDefault="unqualified">
|
||||
<xs:element name="Events">
|
||||
<xs:annotation>
|
||||
<xs:documentation>Log4J 2.0 XML Schema for XML log event files.</xs:documentation>
|
||||
</xs:annotation>
|
||||
<xs:complexType>
|
||||
<xs:sequence>
|
||||
<xs:element name="Event" minOccurs="0" maxOccurs="unbounded">
|
||||
<xs:complexType>
|
||||
<xs:sequence>
|
||||
<xs:element name="Message"/>
|
||||
<xs:element name="NDC" minOccurs="0"/>
|
||||
<xs:element name="Marker" minOccurs="0">
|
||||
<xs:complexType mixed="true">
|
||||
<xs:attribute name="parent" type="xs:string" use="optional"/>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
<xs:element name="Throwable" minOccurs="0"/>
|
||||
<xs:element name="LocationInfo" minOccurs="0">
|
||||
<xs:complexType>
|
||||
<xs:attribute name="class" type="xs:string" use="required"/>
|
||||
<xs:attribute name="method" type="xs:string" use="required"/>
|
||||
<xs:attribute name="file" type="xs:string" use="required"/>
|
||||
<xs:attribute name="line" type="xs:int" use="required"/>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
<xs:element name="Properties" minOccurs="0">
|
||||
<xs:complexType>
|
||||
<xs:sequence>
|
||||
<xs:element name="Data" maxOccurs="unbounded">
|
||||
<xs:complexType>
|
||||
<xs:attribute name="name" type="xs:string" use="required"/>
|
||||
<xs:attribute name="value" use="required"/>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
</xs:sequence>
|
||||
<xs:attribute name="logger" type="xs:string" use="required"/>
|
||||
<xs:attribute name="timestamp" type="xs:long" use="required"/>
|
||||
<xs:attribute name="level" type="log4j:LevelEnum" use="required"/>
|
||||
<xs:attribute name="thread" type="xs:string" use="required"/>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
<xs:simpleType name="LevelEnum">
|
||||
<xs:restriction base="xs:string">
|
||||
<xs:enumeration value="OFF"/>
|
||||
<xs:enumeration value="FATAL"/>
|
||||
<xs:enumeration value="ERROR"/>
|
||||
<xs:enumeration value="WARN"/>
|
||||
<xs:enumeration value="INFO"/>
|
||||
<xs:enumeration value="DEBUG"/>
|
||||
<xs:enumeration value="TRACE"/>
|
||||
<xs:enumeration value="ALL"/>
|
||||
</xs:restriction>
|
||||
</xs:simpleType>
|
||||
</xs:schema>
|
31
src/main/Log4j-levels.xsd
Normal file
31
src/main/Log4j-levels.xsd
Normal file
|
@ -0,0 +1,31 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
this work for additional information regarding copyright ownership.
|
||||
The ASF licenses this file to You 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.
|
||||
-->
|
||||
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:log4j="http://logging.apache.org/log4j/2.0/events" targetNamespace="http://logging.apache.org/log4j/2.0/events" elementFormDefault="qualified" attributeFormDefault="unqualified">
|
||||
<xs:simpleType name="LevelEnum">
|
||||
<xs:restriction base="xs:string">
|
||||
<xs:enumeration value="OFF"/>
|
||||
<xs:enumeration value="FATAL"/>
|
||||
<xs:enumeration value="ERROR"/>
|
||||
<xs:enumeration value="WARN"/>
|
||||
<xs:enumeration value="INFO"/>
|
||||
<xs:enumeration value="DEBUG"/>
|
||||
<xs:enumeration value="TRACE"/>
|
||||
<xs:enumeration value="ALL"/>
|
||||
</xs:restriction>
|
||||
</xs:simpleType>
|
||||
</xs:schema>
|
8
src/main/META-INF/MANIFEST.MF
Normal file
8
src/main/META-INF/MANIFEST.MF
Normal file
|
@ -0,0 +1,8 @@
|
|||
Manifest-Version: 1.0
|
||||
Implementation-Version: v1.0
|
||||
Archiver-Version: Plexus Archiver
|
||||
Built-By: Andrew
|
||||
Created-By: Apache Maven 3.0.5
|
||||
Build-Jdk: 1.8.0_171
|
||||
Main-Class: net.mc.main.Main
|
||||
|
BIN
src/main/Minecraft_Logo.png
Normal file
BIN
src/main/Minecraft_Logo.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 30 KiB |
BIN
src/main/cakehoohoohoo.png
Normal file
BIN
src/main/cakehoohoohoo.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 199 B |
23
src/main/com/evilco/mc/nbt/error/TagNotFoundException.java
Normal file
23
src/main/com/evilco/mc/nbt/error/TagNotFoundException.java
Normal file
|
@ -0,0 +1,23 @@
|
|||
package com.evilco.mc.nbt.error;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public class TagNotFoundException extends IOException {
|
||||
private static final long serialVersionUID = -4631008535746749103L;
|
||||
|
||||
public TagNotFoundException() {
|
||||
super("The tag does not exist");
|
||||
}
|
||||
|
||||
public TagNotFoundException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public TagNotFoundException(Throwable cause) {
|
||||
super(cause);
|
||||
}
|
||||
|
||||
public TagNotFoundException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
package com.evilco.mc.nbt.error;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public class UnexpectedTagTypeException extends IOException {
|
||||
private static final long serialVersionUID = -6604963428978583800L;
|
||||
|
||||
public UnexpectedTagTypeException() {
|
||||
super("The tag is not of the expected type");
|
||||
}
|
||||
|
||||
public UnexpectedTagTypeException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public UnexpectedTagTypeException(Throwable cause) {
|
||||
super(cause);
|
||||
}
|
||||
|
||||
public UnexpectedTagTypeException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
}
|
40
src/main/com/evilco/mc/nbt/stream/NbtInputStream.java
Normal file
40
src/main/com/evilco/mc/nbt/stream/NbtInputStream.java
Normal file
|
@ -0,0 +1,40 @@
|
|||
package com.evilco.mc.nbt.stream;
|
||||
|
||||
import com.evilco.mc.nbt.tag.ITag;
|
||||
import com.evilco.mc.nbt.tag.TagType;
|
||||
import java.io.DataInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.lang.reflect.Constructor;
|
||||
|
||||
public class NbtInputStream extends DataInputStream {
|
||||
public NbtInputStream(InputStream in) {
|
||||
super(in);
|
||||
}
|
||||
|
||||
public ITag readTag() throws IOException {
|
||||
byte type = this.readByte();
|
||||
TagType tagType = TagType.valueOf(type);
|
||||
if (tagType == null) {
|
||||
throw new IOException("Invalid NBT tag: Found unknown tag type " + type + ".");
|
||||
} else {
|
||||
return tagType == TagType.END ? null : this.readTag(tagType, false);
|
||||
}
|
||||
}
|
||||
|
||||
public ITag readTag(TagType type, boolean anonymous) throws IOException {
|
||||
Constructor constructor = null;
|
||||
|
||||
try {
|
||||
constructor = type.tagType.getConstructor(NbtInputStream.class, Boolean.TYPE);
|
||||
} catch (NoSuchMethodException var6) {
|
||||
throw new IOException("Invalid NBT implementation state: Type " + type.tagType.getName() + " has no de-serialization constructor.");
|
||||
}
|
||||
|
||||
try {
|
||||
return (ITag)constructor.newInstance(this, anonymous);
|
||||
} catch (Exception var5) {
|
||||
throw new IOException("Invalid NBT implementation state: Type " + type.tagType.getName() + " in (" + this.getClass().getName() + ") has no valid constructor: " + var5.getMessage(), var5);
|
||||
}
|
||||
}
|
||||
}
|
17
src/main/com/evilco/mc/nbt/stream/NbtOutputStream.java
Normal file
17
src/main/com/evilco/mc/nbt/stream/NbtOutputStream.java
Normal file
|
@ -0,0 +1,17 @@
|
|||
package com.evilco.mc.nbt.stream;
|
||||
|
||||
import com.evilco.mc.nbt.tag.ITag;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
|
||||
public class NbtOutputStream extends DataOutputStream {
|
||||
public NbtOutputStream(OutputStream out) {
|
||||
super(out);
|
||||
}
|
||||
|
||||
public void write(ITag tag) throws IOException {
|
||||
this.writeByte(tag.getTagID());
|
||||
tag.write(this, false);
|
||||
}
|
||||
}
|
76
src/main/com/evilco/mc/nbt/tag/AbstractTag.java
Normal file
76
src/main/com/evilco/mc/nbt/tag/AbstractTag.java
Normal file
|
@ -0,0 +1,76 @@
|
|||
package com.evilco.mc.nbt.tag;
|
||||
|
||||
import com.evilco.mc.nbt.stream.NbtInputStream;
|
||||
import com.evilco.mc.nbt.stream.NbtOutputStream;
|
||||
import com.google.common.base.Preconditions;
|
||||
import java.io.IOException;
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
public abstract class AbstractTag implements ITag {
|
||||
protected String name;
|
||||
protected ITagContainer parent = null;
|
||||
|
||||
public AbstractTag(@Nonnull String name) {
|
||||
this.setName(name);
|
||||
}
|
||||
|
||||
public AbstractTag(@Nonnull NbtInputStream inputStream, boolean anonymous) throws IOException {
|
||||
Preconditions.checkNotNull(inputStream, "inputStream");
|
||||
if (!anonymous) {
|
||||
int nameSize = inputStream.readShort();
|
||||
byte[] nameBytes = new byte[nameSize];
|
||||
inputStream.readFully(nameBytes);
|
||||
this.setName(new String(nameBytes, STRING_CHARSET));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return this.name;
|
||||
}
|
||||
|
||||
public byte[] getNameBytes() {
|
||||
return this.name.getBytes(STRING_CHARSET);
|
||||
}
|
||||
|
||||
public ITagContainer getParent() {
|
||||
return this.parent;
|
||||
}
|
||||
|
||||
public abstract byte getTagID();
|
||||
|
||||
public void setName(@Nonnull String name) {
|
||||
Preconditions.checkNotNull(name, "name");
|
||||
if (this.getParent() != null) {
|
||||
this.getParent().removeTag(this);
|
||||
}
|
||||
|
||||
this.name = name;
|
||||
if (this.getParent() != null) {
|
||||
if (this.getParent() instanceof IAnonymousTagContainer) {
|
||||
((IAnonymousTagContainer)this.getParent()).addTag(this);
|
||||
} else {
|
||||
((INamedTagContainer)this.getParent()).setTag(this);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void setParent(@Nullable ITagContainer parent) {
|
||||
if (this.getParent() != null) {
|
||||
this.getParent().removeTag(this);
|
||||
}
|
||||
|
||||
this.parent = parent;
|
||||
}
|
||||
|
||||
public void write(NbtOutputStream outputStream, boolean anonymous) throws IOException {
|
||||
if (!anonymous) {
|
||||
byte[] name = this.getNameBytes();
|
||||
outputStream.writeShort(name.length);
|
||||
outputStream.write(name);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
15
src/main/com/evilco/mc/nbt/tag/IAnonymousTagContainer.java
Normal file
15
src/main/com/evilco/mc/nbt/tag/IAnonymousTagContainer.java
Normal file
|
@ -0,0 +1,15 @@
|
|||
package com.evilco.mc.nbt.tag;
|
||||
|
||||
import com.evilco.mc.nbt.error.UnexpectedTagTypeException;
|
||||
import java.util.List;
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
public interface IAnonymousTagContainer extends ITagContainer {
|
||||
void addTag(@Nonnull ITag var1);
|
||||
|
||||
List<ITag> getTags();
|
||||
|
||||
<T extends ITag> List<T> getTags(Class<T> var1) throws UnexpectedTagTypeException;
|
||||
|
||||
void setTag(int var1, @Nonnull ITag var2);
|
||||
}
|
18
src/main/com/evilco/mc/nbt/tag/INamedTagContainer.java
Normal file
18
src/main/com/evilco/mc/nbt/tag/INamedTagContainer.java
Normal file
|
@ -0,0 +1,18 @@
|
|||
package com.evilco.mc.nbt.tag;
|
||||
|
||||
import com.evilco.mc.nbt.error.TagNotFoundException;
|
||||
import com.evilco.mc.nbt.error.UnexpectedTagTypeException;
|
||||
import java.util.Map;
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
public interface INamedTagContainer extends ITagContainer {
|
||||
ITag getTag(@Nonnull String var1);
|
||||
|
||||
<T extends ITag> T getTag(String var1, Class<T> var2) throws UnexpectedTagTypeException, TagNotFoundException;
|
||||
|
||||
Map<String, ITag> getTags();
|
||||
|
||||
void removeTag(@Nonnull String var1);
|
||||
|
||||
void setTag(@Nonnull ITag var1);
|
||||
}
|
25
src/main/com/evilco/mc/nbt/tag/ITag.java
Normal file
25
src/main/com/evilco/mc/nbt/tag/ITag.java
Normal file
|
@ -0,0 +1,25 @@
|
|||
package com.evilco.mc.nbt.tag;
|
||||
|
||||
import com.evilco.mc.nbt.stream.NbtOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.Charset;
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
public interface ITag {
|
||||
Charset STRING_CHARSET = Charset.forName("UTF-8");
|
||||
|
||||
String getName();
|
||||
|
||||
byte[] getNameBytes();
|
||||
|
||||
ITagContainer getParent();
|
||||
|
||||
byte getTagID();
|
||||
|
||||
void setName(@Nonnull String var1);
|
||||
|
||||
void setParent(@Nullable ITagContainer var1);
|
||||
|
||||
void write(NbtOutputStream var1, boolean var2) throws IOException;
|
||||
}
|
7
src/main/com/evilco/mc/nbt/tag/ITagContainer.java
Normal file
7
src/main/com/evilco/mc/nbt/tag/ITagContainer.java
Normal file
|
@ -0,0 +1,7 @@
|
|||
package com.evilco.mc.nbt.tag;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
public interface ITagContainer extends ITag {
|
||||
void removeTag(@Nonnull ITag var1);
|
||||
}
|
37
src/main/com/evilco/mc/nbt/tag/TagByte.java
Normal file
37
src/main/com/evilco/mc/nbt/tag/TagByte.java
Normal file
|
@ -0,0 +1,37 @@
|
|||
package com.evilco.mc.nbt.tag;
|
||||
|
||||
import com.evilco.mc.nbt.stream.NbtInputStream;
|
||||
import com.evilco.mc.nbt.stream.NbtOutputStream;
|
||||
import java.io.IOException;
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
public class TagByte extends AbstractTag {
|
||||
protected byte value;
|
||||
|
||||
public TagByte(@Nonnull String name, byte value) {
|
||||
super(name);
|
||||
this.setValue(value);
|
||||
}
|
||||
|
||||
public TagByte(@Nonnull NbtInputStream inputStream, boolean anonymous) throws IOException {
|
||||
super(inputStream, anonymous);
|
||||
this.setValue(inputStream.readByte());
|
||||
}
|
||||
|
||||
public byte getTagID() {
|
||||
return TagType.BYTE.typeID;
|
||||
}
|
||||
|
||||
public byte getValue() {
|
||||
return this.value;
|
||||
}
|
||||
|
||||
public void setValue(byte b) {
|
||||
this.value = b;
|
||||
}
|
||||
|
||||
public void write(NbtOutputStream outputStream, boolean anonymous) throws IOException {
|
||||
super.write(outputStream, anonymous);
|
||||
outputStream.write(this.getValue());
|
||||
}
|
||||
}
|
43
src/main/com/evilco/mc/nbt/tag/TagByteArray.java
Normal file
43
src/main/com/evilco/mc/nbt/tag/TagByteArray.java
Normal file
|
@ -0,0 +1,43 @@
|
|||
package com.evilco.mc.nbt.tag;
|
||||
|
||||
import com.evilco.mc.nbt.stream.NbtInputStream;
|
||||
import com.evilco.mc.nbt.stream.NbtOutputStream;
|
||||
import com.google.common.base.Preconditions;
|
||||
import java.io.IOException;
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
public class TagByteArray extends AbstractTag {
|
||||
protected byte[] value;
|
||||
|
||||
public TagByteArray(@Nonnull String name, @Nonnull byte[] value) {
|
||||
super(name);
|
||||
this.setValue(value);
|
||||
}
|
||||
|
||||
public TagByteArray(@Nonnull NbtInputStream inputStream, boolean anonymous) throws IOException {
|
||||
super(inputStream, anonymous);
|
||||
int size = inputStream.readInt();
|
||||
byte[] data = new byte[size];
|
||||
inputStream.readFully(data);
|
||||
this.setValue(data);
|
||||
}
|
||||
|
||||
public byte getTagID() {
|
||||
return TagType.BYTE_ARRAY.typeID;
|
||||
}
|
||||
|
||||
public byte[] getValue() {
|
||||
return this.value;
|
||||
}
|
||||
|
||||
public void setValue(@Nonnull byte[] b) {
|
||||
Preconditions.checkNotNull(b, "b");
|
||||
this.value = b;
|
||||
}
|
||||
|
||||
public void write(NbtOutputStream outputStream, boolean anonymous) throws IOException {
|
||||
super.write(outputStream, anonymous);
|
||||
outputStream.writeInt(this.value.length);
|
||||
outputStream.write(this.value);
|
||||
}
|
||||
}
|
175
src/main/com/evilco/mc/nbt/tag/TagCompound.java
Normal file
175
src/main/com/evilco/mc/nbt/tag/TagCompound.java
Normal file
|
@ -0,0 +1,175 @@
|
|||
package com.evilco.mc.nbt.tag;
|
||||
|
||||
import com.evilco.mc.nbt.error.TagNotFoundException;
|
||||
import com.evilco.mc.nbt.error.UnexpectedTagTypeException;
|
||||
import com.evilco.mc.nbt.stream.NbtInputStream;
|
||||
import com.evilco.mc.nbt.stream.NbtOutputStream;
|
||||
import com.google.common.base.Preconditions;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
public class TagCompound extends AbstractTag implements INamedTagContainer {
|
||||
protected Map<String, ITag> tags = new HashMap();
|
||||
|
||||
public TagCompound(String name) {
|
||||
super(name);
|
||||
}
|
||||
|
||||
public TagCompound(@Nonnull NbtInputStream inputStream, boolean anonymous) throws IOException {
|
||||
super(inputStream, anonymous);
|
||||
|
||||
while(true) {
|
||||
byte type = inputStream.readByte();
|
||||
TagType tagType = TagType.valueOf(type);
|
||||
if (tagType == null) {
|
||||
throw new IOException("Could not find a tag for type ID " + type + ".");
|
||||
}
|
||||
|
||||
if (tagType == TagType.END) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.setTag(inputStream.readTag(tagType, false));
|
||||
}
|
||||
}
|
||||
|
||||
public ITag getTag(@Nonnull String name) {
|
||||
Preconditions.checkNotNull(name, "name");
|
||||
return (ITag)this.tags.get(name);
|
||||
}
|
||||
|
||||
public <T extends ITag> T getTag(String name, Class<T> tagClass) throws UnexpectedTagTypeException, TagNotFoundException {
|
||||
ITag tag = this.getTag(name);
|
||||
if (tag == null) {
|
||||
throw new TagNotFoundException("The compound tag is missing a " + name + " entry");
|
||||
} else if (!tagClass.isInstance(tag)) {
|
||||
throw new UnexpectedTagTypeException("The compound entry " + name + " should be of type " + tagClass.getSimpleName() + ", but is of type " + tag.getClass().getSimpleName());
|
||||
} else {
|
||||
return tag;
|
||||
}
|
||||
}
|
||||
|
||||
public TagCompound getCompound(String name) throws UnexpectedTagTypeException, TagNotFoundException {
|
||||
return (TagCompound)this.getTag(name, TagCompound.class);
|
||||
}
|
||||
|
||||
public int getInteger(String name) throws UnexpectedTagTypeException, TagNotFoundException {
|
||||
return ((TagInteger)this.getTag(name, TagInteger.class)).getValue();
|
||||
}
|
||||
|
||||
public short getShort(String name) throws UnexpectedTagTypeException, TagNotFoundException {
|
||||
return ((TagShort)this.getTag(name, TagShort.class)).getValue();
|
||||
}
|
||||
|
||||
public byte getByte(String name) throws UnexpectedTagTypeException, TagNotFoundException {
|
||||
return ((TagByte)this.getTag(name, TagByte.class)).getValue();
|
||||
}
|
||||
|
||||
public long getLong(String name) throws UnexpectedTagTypeException, TagNotFoundException {
|
||||
return ((TagLong)this.getTag(name, TagLong.class)).getValue();
|
||||
}
|
||||
|
||||
public double getDouble(String name) throws UnexpectedTagTypeException, TagNotFoundException {
|
||||
return ((TagDouble)this.getTag(name, TagDouble.class)).getValue();
|
||||
}
|
||||
|
||||
public float getFloat(String name) throws UnexpectedTagTypeException, TagNotFoundException {
|
||||
return ((TagFloat)this.getTag(name, TagFloat.class)).getValue();
|
||||
}
|
||||
|
||||
public String getString(String name) throws UnexpectedTagTypeException, TagNotFoundException {
|
||||
return ((TagString)this.getTag(name, TagString.class)).getValue();
|
||||
}
|
||||
|
||||
public <T extends ITag> List<T> getList(String name, Class<T> itemClass) throws UnexpectedTagTypeException, TagNotFoundException {
|
||||
return ((TagList)this.getTag(name, TagList.class)).getTags(itemClass);
|
||||
}
|
||||
|
||||
public int[] getIntegerArray(String name) throws UnexpectedTagTypeException, TagNotFoundException {
|
||||
return ((TagIntegerArray)this.getTag(name, TagIntegerArray.class)).getValues();
|
||||
}
|
||||
|
||||
public byte[] getByteArray(String name) throws UnexpectedTagTypeException, TagNotFoundException {
|
||||
return ((TagByteArray)this.getTag(name, TagByteArray.class)).getValue();
|
||||
}
|
||||
|
||||
public String[] getStringArray(String name) throws UnexpectedTagTypeException, TagNotFoundException {
|
||||
List<TagString> tags = this.getList(name, TagString.class);
|
||||
String[] array = new String[tags.size()];
|
||||
|
||||
for(int i = 0; i < tags.size(); ++i) {
|
||||
array[i] = ((TagString)tags.get(i)).getValue();
|
||||
}
|
||||
|
||||
return array;
|
||||
}
|
||||
|
||||
public double[] getDoubleArray(String name) throws UnexpectedTagTypeException, TagNotFoundException {
|
||||
List<TagDouble> tags = this.getList(name, TagDouble.class);
|
||||
double[] array = new double[tags.size()];
|
||||
|
||||
for(int i = 0; i < tags.size(); ++i) {
|
||||
array[i] = ((TagDouble)tags.get(i)).getValue();
|
||||
}
|
||||
|
||||
return array;
|
||||
}
|
||||
|
||||
public float[] getFloatArray(String name) throws UnexpectedTagTypeException, TagNotFoundException {
|
||||
List<TagFloat> tags = this.getList(name, TagFloat.class);
|
||||
float[] array = new float[tags.size()];
|
||||
|
||||
for(int i = 0; i < tags.size(); ++i) {
|
||||
array[i] = ((TagFloat)tags.get(i)).getValue();
|
||||
}
|
||||
|
||||
return array;
|
||||
}
|
||||
|
||||
public Map<String, ITag> getTags() {
|
||||
return (new ImmutableMap.Builder()).putAll(this.tags).build();
|
||||
}
|
||||
|
||||
public void removeTag(@Nonnull ITag tag) {
|
||||
Preconditions.checkNotNull(tag, "tag");
|
||||
this.tags.remove(tag.getName());
|
||||
}
|
||||
|
||||
public void removeTag(@Nonnull String tag) {
|
||||
Preconditions.checkNotNull(tag, "tag");
|
||||
this.tags.remove(tag);
|
||||
}
|
||||
|
||||
public void setTag(@Nonnull ITag tag) {
|
||||
Preconditions.checkNotNull(tag, "tag");
|
||||
if (this.tags.containsKey(tag)) {
|
||||
((ITag)this.tags.get(tag.getName())).setParent((ITagContainer)null);
|
||||
}
|
||||
|
||||
this.tags.put(tag.getName(), tag);
|
||||
tag.setParent(this);
|
||||
}
|
||||
|
||||
public byte getTagID() {
|
||||
return TagType.COMPOUND.typeID;
|
||||
}
|
||||
|
||||
public void write(NbtOutputStream outputStream, boolean anonymous) throws IOException {
|
||||
super.write(outputStream, anonymous);
|
||||
Iterator var3 = this.tags.entrySet().iterator();
|
||||
|
||||
while(var3.hasNext()) {
|
||||
Entry<String, ITag> tagEntry = (Entry)var3.next();
|
||||
outputStream.writeByte(((ITag)tagEntry.getValue()).getTagID());
|
||||
((ITag)tagEntry.getValue()).write(outputStream, false);
|
||||
}
|
||||
|
||||
outputStream.writeByte(TagType.END.typeID);
|
||||
}
|
||||
}
|
37
src/main/com/evilco/mc/nbt/tag/TagDouble.java
Normal file
37
src/main/com/evilco/mc/nbt/tag/TagDouble.java
Normal file
|
@ -0,0 +1,37 @@
|
|||
package com.evilco.mc.nbt.tag;
|
||||
|
||||
import com.evilco.mc.nbt.stream.NbtInputStream;
|
||||
import com.evilco.mc.nbt.stream.NbtOutputStream;
|
||||
import java.io.IOException;
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
public class TagDouble extends AbstractTag {
|
||||
protected double value;
|
||||
|
||||
public TagDouble(@Nonnull String name, double value) {
|
||||
super(name);
|
||||
this.setValue(value);
|
||||
}
|
||||
|
||||
public TagDouble(@Nonnull NbtInputStream inputStream, boolean anonymous) throws IOException {
|
||||
super(inputStream, anonymous);
|
||||
this.setValue(inputStream.readDouble());
|
||||
}
|
||||
|
||||
public byte getTagID() {
|
||||
return TagType.DOUBLE.typeID;
|
||||
}
|
||||
|
||||
public double getValue() {
|
||||
return this.value;
|
||||
}
|
||||
|
||||
public void setValue(double d) {
|
||||
this.value = d;
|
||||
}
|
||||
|
||||
public void write(NbtOutputStream outputStream, boolean anonymous) throws IOException {
|
||||
super.write(outputStream, anonymous);
|
||||
outputStream.writeDouble(this.value);
|
||||
}
|
||||
}
|
37
src/main/com/evilco/mc/nbt/tag/TagFloat.java
Normal file
37
src/main/com/evilco/mc/nbt/tag/TagFloat.java
Normal file
|
@ -0,0 +1,37 @@
|
|||
package com.evilco.mc.nbt.tag;
|
||||
|
||||
import com.evilco.mc.nbt.stream.NbtInputStream;
|
||||
import com.evilco.mc.nbt.stream.NbtOutputStream;
|
||||
import java.io.IOException;
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
public class TagFloat extends AbstractTag {
|
||||
protected float value;
|
||||
|
||||
public TagFloat(@Nonnull String name, float value) {
|
||||
super(name);
|
||||
this.setValue(value);
|
||||
}
|
||||
|
||||
public TagFloat(@Nonnull NbtInputStream inputStream, boolean anonymous) throws IOException {
|
||||
super(inputStream, anonymous);
|
||||
this.setValue(inputStream.readFloat());
|
||||
}
|
||||
|
||||
public byte getTagID() {
|
||||
return TagType.FLOAT.typeID;
|
||||
}
|
||||
|
||||
public float getValue() {
|
||||
return this.value;
|
||||
}
|
||||
|
||||
public void setValue(float f) {
|
||||
this.value = f;
|
||||
}
|
||||
|
||||
public void write(NbtOutputStream outputStream, boolean anonymous) throws IOException {
|
||||
super.write(outputStream, anonymous);
|
||||
outputStream.writeFloat(this.value);
|
||||
}
|
||||
}
|
37
src/main/com/evilco/mc/nbt/tag/TagInteger.java
Normal file
37
src/main/com/evilco/mc/nbt/tag/TagInteger.java
Normal file
|
@ -0,0 +1,37 @@
|
|||
package com.evilco.mc.nbt.tag;
|
||||
|
||||
import com.evilco.mc.nbt.stream.NbtInputStream;
|
||||
import com.evilco.mc.nbt.stream.NbtOutputStream;
|
||||
import java.io.IOException;
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
public class TagInteger extends AbstractTag {
|
||||
protected int value;
|
||||
|
||||
public TagInteger(@Nonnull String name, int value) {
|
||||
super(name);
|
||||
this.setValue(value);
|
||||
}
|
||||
|
||||
public TagInteger(@Nonnull NbtInputStream inputStream, boolean anonymous) throws IOException {
|
||||
super(inputStream, anonymous);
|
||||
this.setValue(inputStream.readInt());
|
||||
}
|
||||
|
||||
public byte getTagID() {
|
||||
return TagType.INTEGER.typeID;
|
||||
}
|
||||
|
||||
public int getValue() {
|
||||
return this.value;
|
||||
}
|
||||
|
||||
public void setValue(int i) {
|
||||
this.value = i;
|
||||
}
|
||||
|
||||
public void write(NbtOutputStream outputStream, boolean anonymous) throws IOException {
|
||||
super.write(outputStream, anonymous);
|
||||
outputStream.writeInt(this.value);
|
||||
}
|
||||
}
|
54
src/main/com/evilco/mc/nbt/tag/TagIntegerArray.java
Normal file
54
src/main/com/evilco/mc/nbt/tag/TagIntegerArray.java
Normal file
|
@ -0,0 +1,54 @@
|
|||
package com.evilco.mc.nbt.tag;
|
||||
|
||||
import com.evilco.mc.nbt.stream.NbtInputStream;
|
||||
import com.evilco.mc.nbt.stream.NbtOutputStream;
|
||||
import com.google.common.base.Preconditions;
|
||||
import java.io.IOException;
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
public class TagIntegerArray extends AbstractTag {
|
||||
protected int[] values;
|
||||
|
||||
public TagIntegerArray(@Nonnull String name, @Nonnull int[] values) {
|
||||
super(name);
|
||||
this.setValues(values);
|
||||
}
|
||||
|
||||
public TagIntegerArray(@Nonnull NbtInputStream inputStream, boolean anonymous) throws IOException {
|
||||
super(inputStream, anonymous);
|
||||
int size = inputStream.readInt();
|
||||
int[] data = new int[size];
|
||||
|
||||
for(int i = 0; i < size; ++i) {
|
||||
data[i] = inputStream.readInt();
|
||||
}
|
||||
|
||||
this.values = data;
|
||||
}
|
||||
|
||||
public byte getTagID() {
|
||||
return TagType.INTEGER_ARRAY.typeID;
|
||||
}
|
||||
|
||||
public int[] getValues() {
|
||||
return this.values;
|
||||
}
|
||||
|
||||
public void setValues(@Nonnull int[] i) {
|
||||
Preconditions.checkNotNull(i, "i");
|
||||
this.values = i;
|
||||
}
|
||||
|
||||
public void write(NbtOutputStream outputStream, boolean anonymous) throws IOException {
|
||||
super.write(outputStream, anonymous);
|
||||
outputStream.writeInt(this.values.length);
|
||||
int[] var3 = this.values;
|
||||
int var4 = var3.length;
|
||||
|
||||
for(int var5 = 0; var5 < var4; ++var5) {
|
||||
int i = var3[var5];
|
||||
outputStream.writeInt(i);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
90
src/main/com/evilco/mc/nbt/tag/TagList.java
Normal file
90
src/main/com/evilco/mc/nbt/tag/TagList.java
Normal file
|
@ -0,0 +1,90 @@
|
|||
package com.evilco.mc.nbt.tag;
|
||||
|
||||
import com.evilco.mc.nbt.error.UnexpectedTagTypeException;
|
||||
import com.evilco.mc.nbt.stream.NbtInputStream;
|
||||
import com.evilco.mc.nbt.stream.NbtOutputStream;
|
||||
import com.google.common.base.Preconditions;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
public class TagList extends AbstractTag implements IAnonymousTagContainer {
|
||||
protected List<ITag> tagList;
|
||||
|
||||
public TagList(@Nonnull String name) {
|
||||
super(name);
|
||||
this.tagList = new ArrayList();
|
||||
}
|
||||
|
||||
public TagList(@Nonnull String name, @Nonnull List<ITag> tagList) {
|
||||
super(name);
|
||||
Preconditions.checkNotNull(tagList, "tagList");
|
||||
this.tagList = tagList;
|
||||
}
|
||||
|
||||
public TagList(@Nonnull NbtInputStream inputStream, boolean anonymous) throws IOException {
|
||||
super(inputStream, anonymous);
|
||||
this.tagList = new ArrayList();
|
||||
byte type = inputStream.readByte();
|
||||
TagType tagType = TagType.valueOf(type);
|
||||
int size = inputStream.readInt();
|
||||
if (tagType != TagType.END) {
|
||||
for(int i = 0; i < size; ++i) {
|
||||
this.addTag(inputStream.readTag(tagType, true));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public void addTag(@Nonnull ITag tag) {
|
||||
this.tagList.add(tag);
|
||||
}
|
||||
|
||||
public List<ITag> getTags() {
|
||||
return (new ImmutableList.Builder()).addAll((Iterable)this.tagList).build();
|
||||
}
|
||||
|
||||
public <T extends ITag> List<T> getTags(Class<T> tagClass) throws UnexpectedTagTypeException {
|
||||
ImmutableList.Builder<T> builder = new ImmutableList.Builder();
|
||||
Iterator var3 = this.tagList.iterator();
|
||||
|
||||
while(var3.hasNext()) {
|
||||
ITag tag = (ITag)var3.next();
|
||||
if (!tagClass.isInstance(tag)) {
|
||||
throw new UnexpectedTagTypeException("The list entry should be of type " + tagClass.getSimpleName() + ", but is of type " + tag.getClass().getSimpleName());
|
||||
}
|
||||
|
||||
builder.add((Object)tag);
|
||||
}
|
||||
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
public byte getTagID() {
|
||||
return TagType.LIST.typeID;
|
||||
}
|
||||
|
||||
public void removeTag(@Nonnull ITag tag) {
|
||||
this.tagList.remove(tag);
|
||||
}
|
||||
|
||||
public void setTag(int i, @Nonnull ITag tag) {
|
||||
this.tagList.set(i, tag);
|
||||
}
|
||||
|
||||
public void write(NbtOutputStream outputStream, boolean anonymous) throws IOException {
|
||||
super.write(outputStream, anonymous);
|
||||
outputStream.writeByte(this.tagList.size() > 0 ? ((ITag)this.tagList.get(0)).getTagID() : TagType.END.typeID);
|
||||
outputStream.writeInt(this.tagList.size());
|
||||
Iterator var3 = this.tagList.iterator();
|
||||
|
||||
while(var3.hasNext()) {
|
||||
ITag tag = (ITag)var3.next();
|
||||
tag.write(outputStream, true);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
37
src/main/com/evilco/mc/nbt/tag/TagLong.java
Normal file
37
src/main/com/evilco/mc/nbt/tag/TagLong.java
Normal file
|
@ -0,0 +1,37 @@
|
|||
package com.evilco.mc.nbt.tag;
|
||||
|
||||
import com.evilco.mc.nbt.stream.NbtInputStream;
|
||||
import com.evilco.mc.nbt.stream.NbtOutputStream;
|
||||
import java.io.IOException;
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
public class TagLong extends AbstractTag {
|
||||
protected long value;
|
||||
|
||||
public TagLong(@Nonnull String name, long value) {
|
||||
super(name);
|
||||
this.setValue(value);
|
||||
}
|
||||
|
||||
public TagLong(@Nonnull NbtInputStream inputStream, boolean anonymous) throws IOException {
|
||||
super(inputStream, anonymous);
|
||||
this.setValue(inputStream.readLong());
|
||||
}
|
||||
|
||||
public byte getTagID() {
|
||||
return TagType.LONG.typeID;
|
||||
}
|
||||
|
||||
public long getValue() {
|
||||
return this.value;
|
||||
}
|
||||
|
||||
public void setValue(long l) {
|
||||
this.value = l;
|
||||
}
|
||||
|
||||
public void write(NbtOutputStream outputStream, boolean anonymous) throws IOException {
|
||||
super.write(outputStream, anonymous);
|
||||
outputStream.writeLong(this.value);
|
||||
}
|
||||
}
|
37
src/main/com/evilco/mc/nbt/tag/TagShort.java
Normal file
37
src/main/com/evilco/mc/nbt/tag/TagShort.java
Normal file
|
@ -0,0 +1,37 @@
|
|||
package com.evilco.mc.nbt.tag;
|
||||
|
||||
import com.evilco.mc.nbt.stream.NbtInputStream;
|
||||
import com.evilco.mc.nbt.stream.NbtOutputStream;
|
||||
import java.io.IOException;
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
public class TagShort extends AbstractTag {
|
||||
protected short value;
|
||||
|
||||
public TagShort(@Nonnull String name, short value) {
|
||||
super(name);
|
||||
this.setValue(value);
|
||||
}
|
||||
|
||||
public TagShort(@Nonnull NbtInputStream inputStream, boolean anonymous) throws IOException {
|
||||
super(inputStream, anonymous);
|
||||
this.setValue(inputStream.readShort());
|
||||
}
|
||||
|
||||
public byte getTagID() {
|
||||
return TagType.SHORT.typeID;
|
||||
}
|
||||
|
||||
public short getValue() {
|
||||
return this.value;
|
||||
}
|
||||
|
||||
public void setValue(short s) {
|
||||
this.value = s;
|
||||
}
|
||||
|
||||
public void write(NbtOutputStream outputStream, boolean anonymous) throws IOException {
|
||||
super.write(outputStream, anonymous);
|
||||
outputStream.writeShort(this.value);
|
||||
}
|
||||
}
|
42
src/main/com/evilco/mc/nbt/tag/TagString.java
Normal file
42
src/main/com/evilco/mc/nbt/tag/TagString.java
Normal file
|
@ -0,0 +1,42 @@
|
|||
package com.evilco.mc.nbt.tag;
|
||||
|
||||
import com.evilco.mc.nbt.stream.NbtInputStream;
|
||||
import com.evilco.mc.nbt.stream.NbtOutputStream;
|
||||
import java.io.IOException;
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
public class TagString extends AbstractTag {
|
||||
protected String value;
|
||||
|
||||
public TagString(@Nonnull String name, @Nonnull String value) {
|
||||
super(name);
|
||||
this.setValue(value);
|
||||
}
|
||||
|
||||
public TagString(@Nonnull NbtInputStream inputStream, boolean anonymous) throws IOException {
|
||||
super(inputStream, anonymous);
|
||||
int size = inputStream.readShort();
|
||||
byte[] data = new byte[size];
|
||||
inputStream.readFully(data);
|
||||
this.setValue(new String(data, ITag.STRING_CHARSET));
|
||||
}
|
||||
|
||||
public byte getTagID() {
|
||||
return TagType.STRING.typeID;
|
||||
}
|
||||
|
||||
public String getValue() {
|
||||
return this.value;
|
||||
}
|
||||
|
||||
public void setValue(@Nonnull String s) {
|
||||
this.value = s;
|
||||
}
|
||||
|
||||
public void write(NbtOutputStream outputStream, boolean anonymous) throws IOException {
|
||||
super.write(outputStream, anonymous);
|
||||
byte[] outputBytes = this.value.getBytes(ITag.STRING_CHARSET);
|
||||
outputStream.writeShort(outputBytes.length);
|
||||
outputStream.write(outputBytes);
|
||||
}
|
||||
}
|
45
src/main/com/evilco/mc/nbt/tag/TagType.java
Normal file
45
src/main/com/evilco/mc/nbt/tag/TagType.java
Normal file
|
@ -0,0 +1,45 @@
|
|||
package com.evilco.mc.nbt.tag;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import java.util.Map;
|
||||
|
||||
public enum TagType {
|
||||
BYTE(1, TagByte.class),
|
||||
BYTE_ARRAY(7, TagByteArray.class),
|
||||
COMPOUND(10, TagCompound.class),
|
||||
DOUBLE(6, TagDouble.class),
|
||||
END(0, (Class)null),
|
||||
FLOAT(5, TagFloat.class),
|
||||
INTEGER(3, TagInteger.class),
|
||||
INTEGER_ARRAY(11, TagIntegerArray.class),
|
||||
LIST(9, TagList.class),
|
||||
LONG(4, TagLong.class),
|
||||
SHORT(2, TagShort.class),
|
||||
STRING(8, TagString.class);
|
||||
|
||||
protected static final Map<Byte, TagType> typeMap;
|
||||
public final Class<? extends ITag> tagType;
|
||||
public final byte typeID;
|
||||
|
||||
private TagType(int typeID, Class<? extends ITag> type) {
|
||||
this.typeID = (byte)typeID;
|
||||
this.tagType = type;
|
||||
}
|
||||
|
||||
public static TagType valueOf(byte typeID) {
|
||||
return (TagType)typeMap.get(typeID);
|
||||
}
|
||||
|
||||
static {
|
||||
ImmutableMap.Builder<Byte, TagType> mapBuilder = new ImmutableMap.Builder();
|
||||
TagType[] var1 = values();
|
||||
int var2 = var1.length;
|
||||
|
||||
for(int var3 = 0; var3 < var2; ++var3) {
|
||||
TagType type = var1[var3];
|
||||
mapBuilder.put(type.typeID, type);
|
||||
}
|
||||
|
||||
typeMap = mapBuilder.build();
|
||||
}
|
||||
}
|
14
src/main/com/google/common/annotations/Beta.java
Normal file
14
src/main/com/google/common/annotations/Beta.java
Normal file
|
@ -0,0 +1,14 @@
|
|||
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;
|
||||
|
||||
@Retention(RetentionPolicy.CLASS)
|
||||
@Target({ElementType.ANNOTATION_TYPE, ElementType.CONSTRUCTOR, ElementType.FIELD, ElementType.METHOD, ElementType.TYPE})
|
||||
@Documented
|
||||
@GwtCompatible
|
||||
public @interface Beta {
|
||||
}
|
17
src/main/com/google/common/annotations/GwtCompatible.java
Normal file
17
src/main/com/google/common/annotations/GwtCompatible.java
Normal file
|
@ -0,0 +1,17 @@
|
|||
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;
|
||||
|
||||
@Retention(RetentionPolicy.CLASS)
|
||||
@Target({ElementType.TYPE, ElementType.METHOD})
|
||||
@Documented
|
||||
@GwtCompatible
|
||||
public @interface GwtCompatible {
|
||||
boolean serializable() default false;
|
||||
|
||||
boolean emulated() default false;
|
||||
}
|
15
src/main/com/google/common/annotations/GwtIncompatible.java
Normal file
15
src/main/com/google/common/annotations/GwtIncompatible.java
Normal file
|
@ -0,0 +1,15 @@
|
|||
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;
|
||||
|
||||
@Retention(RetentionPolicy.CLASS)
|
||||
@Target({ElementType.TYPE, ElementType.METHOD, ElementType.CONSTRUCTOR, ElementType.FIELD})
|
||||
@Documented
|
||||
@GwtCompatible
|
||||
public @interface GwtIncompatible {
|
||||
String value();
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
package com.google.common.annotations;
|
||||
|
||||
@GwtCompatible
|
||||
public @interface VisibleForTesting {
|
||||
}
|
69
src/main/com/google/common/base/Absent.java
Normal file
69
src/main/com/google/common/base/Absent.java
Normal file
|
@ -0,0 +1,69 @@
|
|||
package com.google.common.base;
|
||||
|
||||
import com.google.common.annotations.GwtCompatible;
|
||||
import java.util.Collections;
|
||||
import java.util.Set;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
@GwtCompatible
|
||||
final class Absent<T> extends Optional<T> {
|
||||
static final Absent<Object> INSTANCE = new Absent();
|
||||
private static final long serialVersionUID = 0L;
|
||||
|
||||
static <T> Optional<T> withType() {
|
||||
return INSTANCE;
|
||||
}
|
||||
|
||||
private Absent() {
|
||||
}
|
||||
|
||||
public boolean isPresent() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public T get() {
|
||||
throw new IllegalStateException("Optional.get() cannot be called on an absent value");
|
||||
}
|
||||
|
||||
public T or(T defaultValue) {
|
||||
return Preconditions.checkNotNull(defaultValue, "use Optional.orNull() instead of Optional.or(null)");
|
||||
}
|
||||
|
||||
public Optional<T> or(Optional<? extends T> secondChoice) {
|
||||
return (Optional)Preconditions.checkNotNull(secondChoice);
|
||||
}
|
||||
|
||||
public T or(Supplier<? extends T> supplier) {
|
||||
return Preconditions.checkNotNull(supplier.get(), "use Optional.orNull() instead of a Supplier that returns null");
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public T orNull() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public Set<T> asSet() {
|
||||
return Collections.emptySet();
|
||||
}
|
||||
|
||||
public <V> Optional<V> transform(Function<? super T, V> function) {
|
||||
Preconditions.checkNotNull(function);
|
||||
return Optional.absent();
|
||||
}
|
||||
|
||||
public boolean equals(@Nullable Object object) {
|
||||
return object == this;
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
return 1502476572;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return "Optional.absent()";
|
||||
}
|
||||
|
||||
private Object readResolve() {
|
||||
return INSTANCE;
|
||||
}
|
||||
}
|
67
src/main/com/google/common/base/AbstractIterator.java
Normal file
67
src/main/com/google/common/base/AbstractIterator.java
Normal file
|
@ -0,0 +1,67 @@
|
|||
package com.google.common.base;
|
||||
|
||||
import com.google.common.annotations.GwtCompatible;
|
||||
import java.util.Iterator;
|
||||
import java.util.NoSuchElementException;
|
||||
|
||||
@GwtCompatible
|
||||
abstract class AbstractIterator<T> implements Iterator<T> {
|
||||
private AbstractIterator.State state;
|
||||
private T next;
|
||||
|
||||
protected AbstractIterator() {
|
||||
this.state = AbstractIterator.State.NOT_READY;
|
||||
}
|
||||
|
||||
protected abstract T computeNext();
|
||||
|
||||
protected final T endOfData() {
|
||||
this.state = AbstractIterator.State.DONE;
|
||||
return null;
|
||||
}
|
||||
|
||||
public final boolean hasNext() {
|
||||
Preconditions.checkState(this.state != AbstractIterator.State.FAILED);
|
||||
switch(this.state) {
|
||||
case DONE:
|
||||
return false;
|
||||
case READY:
|
||||
return true;
|
||||
default:
|
||||
return this.tryToComputeNext();
|
||||
}
|
||||
}
|
||||
|
||||
private boolean tryToComputeNext() {
|
||||
this.state = AbstractIterator.State.FAILED;
|
||||
this.next = this.computeNext();
|
||||
if (this.state != AbstractIterator.State.DONE) {
|
||||
this.state = AbstractIterator.State.READY;
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public final T next() {
|
||||
if (!this.hasNext()) {
|
||||
throw new NoSuchElementException();
|
||||
} else {
|
||||
this.state = AbstractIterator.State.NOT_READY;
|
||||
T result = this.next;
|
||||
this.next = null;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
public final void remove() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
private static enum State {
|
||||
READY,
|
||||
NOT_READY,
|
||||
DONE,
|
||||
FAILED;
|
||||
}
|
||||
}
|
183
src/main/com/google/common/base/Ascii.java
Normal file
183
src/main/com/google/common/base/Ascii.java
Normal file
|
@ -0,0 +1,183 @@
|
|||
package com.google.common.base;
|
||||
|
||||
import com.google.common.annotations.Beta;
|
||||
import com.google.common.annotations.GwtCompatible;
|
||||
import javax.annotation.CheckReturnValue;
|
||||
|
||||
@GwtCompatible
|
||||
public final class Ascii {
|
||||
public static final byte NUL = 0;
|
||||
public static final byte SOH = 1;
|
||||
public static final byte STX = 2;
|
||||
public static final byte ETX = 3;
|
||||
public static final byte EOT = 4;
|
||||
public static final byte ENQ = 5;
|
||||
public static final byte ACK = 6;
|
||||
public static final byte BEL = 7;
|
||||
public static final byte BS = 8;
|
||||
public static final byte HT = 9;
|
||||
public static final byte LF = 10;
|
||||
public static final byte NL = 10;
|
||||
public static final byte VT = 11;
|
||||
public static final byte FF = 12;
|
||||
public static final byte CR = 13;
|
||||
public static final byte SO = 14;
|
||||
public static final byte SI = 15;
|
||||
public static final byte DLE = 16;
|
||||
public static final byte DC1 = 17;
|
||||
public static final byte XON = 17;
|
||||
public static final byte DC2 = 18;
|
||||
public static final byte DC3 = 19;
|
||||
public static final byte XOFF = 19;
|
||||
public static final byte DC4 = 20;
|
||||
public static final byte NAK = 21;
|
||||
public static final byte SYN = 22;
|
||||
public static final byte ETB = 23;
|
||||
public static final byte CAN = 24;
|
||||
public static final byte EM = 25;
|
||||
public static final byte SUB = 26;
|
||||
public static final byte ESC = 27;
|
||||
public static final byte FS = 28;
|
||||
public static final byte GS = 29;
|
||||
public static final byte RS = 30;
|
||||
public static final byte US = 31;
|
||||
public static final byte SP = 32;
|
||||
public static final byte SPACE = 32;
|
||||
public static final byte DEL = 127;
|
||||
public static final char MIN = '\u0000';
|
||||
public static final char MAX = '\u007f';
|
||||
|
||||
private Ascii() {
|
||||
}
|
||||
|
||||
public static String toLowerCase(String string) {
|
||||
int length = string.length();
|
||||
|
||||
for(int i = 0; i < length; ++i) {
|
||||
if (isUpperCase(string.charAt(i))) {
|
||||
char[] chars;
|
||||
for(chars = string.toCharArray(); i < length; ++i) {
|
||||
char c = chars[i];
|
||||
if (isUpperCase(c)) {
|
||||
chars[i] = (char)(c ^ 32);
|
||||
}
|
||||
}
|
||||
|
||||
return String.valueOf(chars);
|
||||
}
|
||||
}
|
||||
|
||||
return string;
|
||||
}
|
||||
|
||||
public static String toLowerCase(CharSequence chars) {
|
||||
if (chars instanceof String) {
|
||||
return toLowerCase((String)chars);
|
||||
} else {
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
public static char toLowerCase(char c) {
|
||||
return isUpperCase(c) ? (char)(c ^ 32) : c;
|
||||
}
|
||||
|
||||
public static String toUpperCase(String string) {
|
||||
int length = string.length();
|
||||
|
||||
for(int i = 0; i < length; ++i) {
|
||||
if (isLowerCase(string.charAt(i))) {
|
||||
char[] chars;
|
||||
for(chars = string.toCharArray(); i < length; ++i) {
|
||||
char c = chars[i];
|
||||
if (isLowerCase(c)) {
|
||||
chars[i] = (char)(c & 95);
|
||||
}
|
||||
}
|
||||
|
||||
return String.valueOf(chars);
|
||||
}
|
||||
}
|
||||
|
||||
return string;
|
||||
}
|
||||
|
||||
public static String toUpperCase(CharSequence chars) {
|
||||
if (chars instanceof String) {
|
||||
return toUpperCase((String)chars);
|
||||
} else {
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
public static char toUpperCase(char c) {
|
||||
return isLowerCase(c) ? (char)(c & 95) : c;
|
||||
}
|
||||
|
||||
public static boolean isLowerCase(char c) {
|
||||
return c >= 'a' && c <= 'z';
|
||||
}
|
||||
|
||||
public static boolean isUpperCase(char c) {
|
||||
return c >= 'A' && c <= 'Z';
|
||||
}
|
||||
|
||||
@CheckReturnValue
|
||||
@Beta
|
||||
public static String truncate(CharSequence seq, int maxLength, String truncationIndicator) {
|
||||
Preconditions.checkNotNull(seq);
|
||||
int truncationLength = maxLength - truncationIndicator.length();
|
||||
Preconditions.checkArgument(truncationLength >= 0, "maxLength (%s) must be >= length of the truncation indicator (%s)", maxLength, truncationIndicator.length());
|
||||
if (((CharSequence)seq).length() <= maxLength) {
|
||||
String string = ((CharSequence)seq).toString();
|
||||
if (string.length() <= maxLength) {
|
||||
return string;
|
||||
}
|
||||
|
||||
seq = string;
|
||||
}
|
||||
|
||||
return (new StringBuilder(maxLength)).append((CharSequence)seq, 0, truncationLength).append(truncationIndicator).toString();
|
||||
}
|
||||
|
||||
@Beta
|
||||
public static boolean equalsIgnoreCase(CharSequence s1, CharSequence s2) {
|
||||
int length = s1.length();
|
||||
if (s1 == s2) {
|
||||
return true;
|
||||
} else if (length != s2.length()) {
|
||||
return false;
|
||||
} else {
|
||||
for(int i = 0; i < length; ++i) {
|
||||
char c1 = s1.charAt(i);
|
||||
char c2 = s2.charAt(i);
|
||||
if (c1 != c2) {
|
||||
int alphaIndex = getAlphaIndex(c1);
|
||||
if (alphaIndex >= 26 || alphaIndex != getAlphaIndex(c2)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
private static int getAlphaIndex(char c) {
|
||||
return (char)((c | 32) - 97);
|
||||
}
|
||||
}
|
154
src/main/com/google/common/base/CaseFormat.java
Normal file
154
src/main/com/google/common/base/CaseFormat.java
Normal file
|
@ -0,0 +1,154 @@
|
|||
package com.google.common.base;
|
||||
|
||||
import com.google.common.annotations.Beta;
|
||||
import com.google.common.annotations.GwtCompatible;
|
||||
import java.io.Serializable;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
@GwtCompatible
|
||||
public enum CaseFormat {
|
||||
LOWER_HYPHEN(CharMatcher.is('-'), "-") {
|
||||
String normalizeWord(String word) {
|
||||
return Ascii.toLowerCase(word);
|
||||
}
|
||||
|
||||
String convert(CaseFormat format, String s) {
|
||||
if (format == LOWER_UNDERSCORE) {
|
||||
return s.replace('-', '_');
|
||||
} else {
|
||||
return format == UPPER_UNDERSCORE ? Ascii.toUpperCase(s.replace('-', '_')) : super.convert(format, s);
|
||||
}
|
||||
}
|
||||
},
|
||||
LOWER_UNDERSCORE(CharMatcher.is('_'), "_") {
|
||||
String normalizeWord(String word) {
|
||||
return Ascii.toLowerCase(word);
|
||||
}
|
||||
|
||||
String convert(CaseFormat format, String s) {
|
||||
if (format == LOWER_HYPHEN) {
|
||||
return s.replace('_', '-');
|
||||
} else {
|
||||
return format == UPPER_UNDERSCORE ? Ascii.toUpperCase(s) : super.convert(format, s);
|
||||
}
|
||||
}
|
||||
},
|
||||
LOWER_CAMEL(CharMatcher.inRange('A', 'Z'), "") {
|
||||
String normalizeWord(String word) {
|
||||
return CaseFormat.firstCharOnlyToUpper(word);
|
||||
}
|
||||
},
|
||||
UPPER_CAMEL(CharMatcher.inRange('A', 'Z'), "") {
|
||||
String normalizeWord(String word) {
|
||||
return CaseFormat.firstCharOnlyToUpper(word);
|
||||
}
|
||||
},
|
||||
UPPER_UNDERSCORE(CharMatcher.is('_'), "_") {
|
||||
String normalizeWord(String word) {
|
||||
return Ascii.toUpperCase(word);
|
||||
}
|
||||
|
||||
String convert(CaseFormat format, String s) {
|
||||
if (format == LOWER_HYPHEN) {
|
||||
return Ascii.toLowerCase(s.replace('_', '-'));
|
||||
} else {
|
||||
return format == LOWER_UNDERSCORE ? Ascii.toLowerCase(s) : super.convert(format, s);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
private final CharMatcher wordBoundary;
|
||||
private final String wordSeparator;
|
||||
|
||||
private CaseFormat(CharMatcher wordBoundary, String wordSeparator) {
|
||||
this.wordBoundary = wordBoundary;
|
||||
this.wordSeparator = wordSeparator;
|
||||
}
|
||||
|
||||
public final String to(CaseFormat format, String str) {
|
||||
Preconditions.checkNotNull(format);
|
||||
Preconditions.checkNotNull(str);
|
||||
return format == this ? str : this.convert(format, str);
|
||||
}
|
||||
|
||||
String convert(CaseFormat format, String s) {
|
||||
StringBuilder out = null;
|
||||
int i = 0;
|
||||
int j = -1;
|
||||
|
||||
while(true) {
|
||||
++j;
|
||||
if ((j = this.wordBoundary.indexIn(s, j)) == -1) {
|
||||
return i == 0 ? format.normalizeFirstWord(s) : out.append(format.normalizeWord(s.substring(i))).toString();
|
||||
}
|
||||
|
||||
if (i == 0) {
|
||||
out = new StringBuilder(s.length() + 4 * this.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 + this.wordSeparator.length();
|
||||
}
|
||||
}
|
||||
|
||||
@Beta
|
||||
public Converter<String, String> converterTo(CaseFormat targetFormat) {
|
||||
return new CaseFormat.StringConverter(this, targetFormat);
|
||||
}
|
||||
|
||||
abstract String normalizeWord(String var1);
|
||||
|
||||
private String normalizeFirstWord(String word) {
|
||||
return this == LOWER_CAMEL ? Ascii.toLowerCase(word) : this.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();
|
||||
}
|
||||
|
||||
// $FF: synthetic method
|
||||
CaseFormat(CharMatcher x2, String x3, Object x4) {
|
||||
this(x2, x3);
|
||||
}
|
||||
|
||||
private static final class StringConverter extends Converter<String, String> implements Serializable {
|
||||
private final CaseFormat sourceFormat;
|
||||
private final CaseFormat targetFormat;
|
||||
private static final long serialVersionUID = 0L;
|
||||
|
||||
StringConverter(CaseFormat sourceFormat, CaseFormat targetFormat) {
|
||||
this.sourceFormat = (CaseFormat)Preconditions.checkNotNull(sourceFormat);
|
||||
this.targetFormat = (CaseFormat)Preconditions.checkNotNull(targetFormat);
|
||||
}
|
||||
|
||||
protected String doForward(String s) {
|
||||
return s == null ? null : this.sourceFormat.to(this.targetFormat, s);
|
||||
}
|
||||
|
||||
protected String doBackward(String s) {
|
||||
return s == null ? null : this.targetFormat.to(this.sourceFormat, s);
|
||||
}
|
||||
|
||||
public boolean equals(@Nullable Object object) {
|
||||
if (!(object instanceof CaseFormat.StringConverter)) {
|
||||
return false;
|
||||
} else {
|
||||
CaseFormat.StringConverter that = (CaseFormat.StringConverter)object;
|
||||
return this.sourceFormat.equals(that.sourceFormat) && this.targetFormat.equals(that.targetFormat);
|
||||
}
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
return this.sourceFormat.hashCode() ^ this.targetFormat.hashCode();
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
String var1 = String.valueOf(String.valueOf(this.sourceFormat));
|
||||
String var2 = String.valueOf(String.valueOf(this.targetFormat));
|
||||
return (new StringBuilder(14 + var1.length() + var2.length())).append(var1).append(".converterTo(").append(var2).append(")").toString();
|
||||
}
|
||||
}
|
||||
}
|
988
src/main/com/google/common/base/CharMatcher.java
Normal file
988
src/main/com/google/common/base/CharMatcher.java
Normal file
|
@ -0,0 +1,988 @@
|
|||
package com.google.common.base;
|
||||
|
||||
import com.google.common.annotations.Beta;
|
||||
import com.google.common.annotations.GwtCompatible;
|
||||
import com.google.common.annotations.GwtIncompatible;
|
||||
import java.util.Arrays;
|
||||
import java.util.BitSet;
|
||||
import javax.annotation.CheckReturnValue;
|
||||
|
||||
@Beta
|
||||
@GwtCompatible(
|
||||
emulated = true
|
||||
)
|
||||
public abstract class CharMatcher implements Predicate<Character> {
|
||||
public static final CharMatcher BREAKING_WHITESPACE = new CharMatcher() {
|
||||
public boolean matches(char c) {
|
||||
switch(c) {
|
||||
case '\t':
|
||||
case '\n':
|
||||
case '\u000b':
|
||||
case '\f':
|
||||
case '\r':
|
||||
case ' ':
|
||||
case '\u0085':
|
||||
case ' ':
|
||||
case '\u2028':
|
||||
case '\u2029':
|
||||
case ' ':
|
||||
case ' ':
|
||||
return true;
|
||||
case ' ':
|
||||
return false;
|
||||
default:
|
||||
return c >= 8192 && c <= 8202;
|
||||
}
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return "CharMatcher.BREAKING_WHITESPACE";
|
||||
}
|
||||
};
|
||||
public static final CharMatcher ASCII = inRange('\u0000', '\u007f', "CharMatcher.ASCII");
|
||||
private static final String ZEROES = "0٠۰߀०০੦૦୦௦౦೦൦๐໐༠၀႐០᠐᥆᧐᭐᮰᱀᱐꘠꣐꤀꩐0";
|
||||
private static final String NINES;
|
||||
public static final CharMatcher DIGIT;
|
||||
public static final CharMatcher JAVA_DIGIT;
|
||||
public static final CharMatcher JAVA_LETTER;
|
||||
public static final CharMatcher JAVA_LETTER_OR_DIGIT;
|
||||
public static final CharMatcher JAVA_UPPER_CASE;
|
||||
public static final CharMatcher JAVA_LOWER_CASE;
|
||||
public static final CharMatcher JAVA_ISO_CONTROL;
|
||||
public static final CharMatcher INVISIBLE;
|
||||
public static final CharMatcher SINGLE_WIDTH;
|
||||
public static final CharMatcher ANY;
|
||||
public static final CharMatcher NONE;
|
||||
final String description;
|
||||
private static final int DISTINCT_CHARS = 65536;
|
||||
static final String WHITESPACE_TABLE = " \r\u0085 \u2029\u000b \t \f \u2028\n ";
|
||||
static final int WHITESPACE_MULTIPLIER = 1682554634;
|
||||
static final int WHITESPACE_SHIFT;
|
||||
public static final CharMatcher WHITESPACE;
|
||||
|
||||
private static String showCharacter(char c) {
|
||||
String hex = "0123456789ABCDEF";
|
||||
char[] tmp = new char[]{'\\', 'u', '\u0000', '\u0000', '\u0000', '\u0000'};
|
||||
|
||||
for(int i = 0; i < 4; ++i) {
|
||||
tmp[5 - i] = hex.charAt(c & 15);
|
||||
c = (char)(c >> 4);
|
||||
}
|
||||
|
||||
return String.copyValueOf(tmp);
|
||||
}
|
||||
|
||||
public static CharMatcher is(final char match) {
|
||||
String var2 = String.valueOf(String.valueOf(showCharacter(match)));
|
||||
String description = (new StringBuilder(18 + var2.length())).append("CharMatcher.is('").append(var2).append("')").toString();
|
||||
return new CharMatcher.FastMatcher(description) {
|
||||
public boolean matches(char c) {
|
||||
return c == match;
|
||||
}
|
||||
|
||||
public String replaceFrom(CharSequence sequence, char replacement) {
|
||||
return sequence.toString().replace(match, replacement);
|
||||
}
|
||||
|
||||
public CharMatcher and(CharMatcher other) {
|
||||
return (CharMatcher)(other.matches(match) ? this : NONE);
|
||||
}
|
||||
|
||||
public CharMatcher or(CharMatcher other) {
|
||||
return other.matches(match) ? other : super.or(other);
|
||||
}
|
||||
|
||||
public CharMatcher negate() {
|
||||
return isNot(match);
|
||||
}
|
||||
|
||||
@GwtIncompatible("java.util.BitSet")
|
||||
void setBits(BitSet table) {
|
||||
table.set(match);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public static CharMatcher isNot(final char match) {
|
||||
String var2 = String.valueOf(String.valueOf(showCharacter(match)));
|
||||
String description = (new StringBuilder(21 + var2.length())).append("CharMatcher.isNot('").append(var2).append("')").toString();
|
||||
return new CharMatcher.FastMatcher(description) {
|
||||
public boolean matches(char c) {
|
||||
return c != match;
|
||||
}
|
||||
|
||||
public CharMatcher and(CharMatcher other) {
|
||||
return other.matches(match) ? super.and(other) : other;
|
||||
}
|
||||
|
||||
public CharMatcher or(CharMatcher other) {
|
||||
return (CharMatcher)(other.matches(match) ? ANY : this);
|
||||
}
|
||||
|
||||
@GwtIncompatible("java.util.BitSet")
|
||||
void setBits(BitSet table) {
|
||||
table.set(0, match);
|
||||
table.set(match + 1, 65536);
|
||||
}
|
||||
|
||||
public CharMatcher negate() {
|
||||
return is(match);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public static CharMatcher anyOf(CharSequence sequence) {
|
||||
switch(sequence.length()) {
|
||||
case 0:
|
||||
return NONE;
|
||||
case 1:
|
||||
return is(sequence.charAt(0));
|
||||
case 2:
|
||||
return isEither(sequence.charAt(0), sequence.charAt(1));
|
||||
default:
|
||||
final char[] chars = sequence.toString().toCharArray();
|
||||
Arrays.sort(chars);
|
||||
StringBuilder description = new StringBuilder("CharMatcher.anyOf(\"");
|
||||
char[] arr$ = chars;
|
||||
int len$ = chars.length;
|
||||
|
||||
for(int i$ = 0; i$ < len$; ++i$) {
|
||||
char c = arr$[i$];
|
||||
description.append(showCharacter(c));
|
||||
}
|
||||
|
||||
description.append("\")");
|
||||
return new CharMatcher(description.toString()) {
|
||||
public boolean matches(char c) {
|
||||
return Arrays.binarySearch(chars, c) >= 0;
|
||||
}
|
||||
|
||||
@GwtIncompatible("java.util.BitSet")
|
||||
void setBits(BitSet table) {
|
||||
char[] arr$ = chars;
|
||||
int len$ = arr$.length;
|
||||
|
||||
for(int i$ = 0; i$ < len$; ++i$) {
|
||||
char c = arr$[i$];
|
||||
table.set(c);
|
||||
}
|
||||
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
private static CharMatcher isEither(final char match1, final char match2) {
|
||||
String var3 = String.valueOf(String.valueOf(showCharacter(match1)));
|
||||
String var4 = String.valueOf(String.valueOf(showCharacter(match2)));
|
||||
String description = (new StringBuilder(21 + var3.length() + var4.length())).append("CharMatcher.anyOf(\"").append(var3).append(var4).append("\")").toString();
|
||||
return new CharMatcher.FastMatcher(description) {
|
||||
public boolean matches(char c) {
|
||||
return c == match1 || c == match2;
|
||||
}
|
||||
|
||||
@GwtIncompatible("java.util.BitSet")
|
||||
void setBits(BitSet table) {
|
||||
table.set(match1);
|
||||
table.set(match2);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public static CharMatcher noneOf(CharSequence sequence) {
|
||||
return anyOf(sequence).negate();
|
||||
}
|
||||
|
||||
public static CharMatcher inRange(char startInclusive, char endInclusive) {
|
||||
Preconditions.checkArgument(endInclusive >= startInclusive);
|
||||
String var3 = String.valueOf(String.valueOf(showCharacter(startInclusive)));
|
||||
String var4 = String.valueOf(String.valueOf(showCharacter(endInclusive)));
|
||||
String description = (new StringBuilder(27 + var3.length() + var4.length())).append("CharMatcher.inRange('").append(var3).append("', '").append(var4).append("')").toString();
|
||||
return inRange(startInclusive, endInclusive, description);
|
||||
}
|
||||
|
||||
static CharMatcher inRange(final char startInclusive, final char endInclusive, String description) {
|
||||
return new CharMatcher.FastMatcher(description) {
|
||||
public boolean matches(char c) {
|
||||
return startInclusive <= c && c <= endInclusive;
|
||||
}
|
||||
|
||||
@GwtIncompatible("java.util.BitSet")
|
||||
void setBits(BitSet table) {
|
||||
table.set(startInclusive, endInclusive + 1);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public static CharMatcher forPredicate(final Predicate<? super Character> predicate) {
|
||||
Preconditions.checkNotNull(predicate);
|
||||
if (predicate instanceof CharMatcher) {
|
||||
return (CharMatcher)predicate;
|
||||
} else {
|
||||
String var2 = String.valueOf(String.valueOf(predicate));
|
||||
String description = (new StringBuilder(26 + var2.length())).append("CharMatcher.forPredicate(").append(var2).append(")").toString();
|
||||
return new CharMatcher(description) {
|
||||
public boolean matches(char c) {
|
||||
return predicate.apply(c);
|
||||
}
|
||||
|
||||
public boolean apply(Character character) {
|
||||
return predicate.apply(Preconditions.checkNotNull(character));
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
CharMatcher(String description) {
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
protected CharMatcher() {
|
||||
this.description = super.toString();
|
||||
}
|
||||
|
||||
public abstract boolean matches(char var1);
|
||||
|
||||
public CharMatcher negate() {
|
||||
return new CharMatcher.NegatedMatcher(this);
|
||||
}
|
||||
|
||||
public CharMatcher and(CharMatcher other) {
|
||||
return new CharMatcher.And(this, (CharMatcher)Preconditions.checkNotNull(other));
|
||||
}
|
||||
|
||||
public CharMatcher or(CharMatcher other) {
|
||||
return new CharMatcher.Or(this, (CharMatcher)Preconditions.checkNotNull(other));
|
||||
}
|
||||
|
||||
public CharMatcher precomputed() {
|
||||
return Platform.precomputeCharMatcher(this);
|
||||
}
|
||||
|
||||
CharMatcher withToString(String description) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@GwtIncompatible("java.util.BitSet")
|
||||
CharMatcher precomputedInternal() {
|
||||
BitSet table = new BitSet();
|
||||
this.setBits(table);
|
||||
int totalCharacters = table.cardinality();
|
||||
if (totalCharacters * 2 <= 65536) {
|
||||
return precomputedPositive(totalCharacters, table, this.description);
|
||||
} else {
|
||||
table.flip(0, 65536);
|
||||
int negatedCharacters = 65536 - totalCharacters;
|
||||
String suffix = ".negate()";
|
||||
String var10000;
|
||||
if (this.description.endsWith(suffix)) {
|
||||
var10000 = this.description.substring(0, this.description.length() - suffix.length());
|
||||
} else {
|
||||
var10000 = String.valueOf(this.description);
|
||||
String var10001 = String.valueOf(suffix);
|
||||
if (var10001.length() != 0) {
|
||||
var10000 = var10000.concat(var10001);
|
||||
} else {
|
||||
String var10002 = new String;
|
||||
var10001 = var10000;
|
||||
var10000 = var10002;
|
||||
var10002.<init>(var10001);
|
||||
}
|
||||
}
|
||||
|
||||
String negatedDescription = var10000;
|
||||
return new CharMatcher.NegatedFastMatcher(this.toString(), precomputedPositive(negatedCharacters, table, negatedDescription));
|
||||
}
|
||||
}
|
||||
|
||||
@GwtIncompatible("java.util.BitSet")
|
||||
private static CharMatcher precomputedPositive(int totalCharacters, BitSet table, String description) {
|
||||
switch(totalCharacters) {
|
||||
case 0:
|
||||
return NONE;
|
||||
case 1:
|
||||
return is((char)table.nextSetBit(0));
|
||||
case 2:
|
||||
char c1 = (char)table.nextSetBit(0);
|
||||
char c2 = (char)table.nextSetBit(c1 + 1);
|
||||
return isEither(c1, c2);
|
||||
default:
|
||||
return (CharMatcher)(isSmall(totalCharacters, table.length()) ? SmallCharMatcher.from(table, description) : new CharMatcher.BitSetMatcher(table, description));
|
||||
}
|
||||
}
|
||||
|
||||
@GwtIncompatible("SmallCharMatcher")
|
||||
private static boolean isSmall(int totalCharacters, int tableLength) {
|
||||
return totalCharacters <= 1023 && tableLength > totalCharacters * 4 * 16;
|
||||
}
|
||||
|
||||
@GwtIncompatible("java.util.BitSet")
|
||||
void setBits(BitSet table) {
|
||||
for(int c = 65535; c >= 0; --c) {
|
||||
if (this.matches((char)c)) {
|
||||
table.set(c);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public boolean matchesAnyOf(CharSequence sequence) {
|
||||
return !this.matchesNoneOf(sequence);
|
||||
}
|
||||
|
||||
public boolean matchesAllOf(CharSequence sequence) {
|
||||
for(int i = sequence.length() - 1; i >= 0; --i) {
|
||||
if (!this.matches(sequence.charAt(i))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean matchesNoneOf(CharSequence sequence) {
|
||||
return this.indexIn(sequence) == -1;
|
||||
}
|
||||
|
||||
public int indexIn(CharSequence sequence) {
|
||||
int length = sequence.length();
|
||||
|
||||
for(int i = 0; i < length; ++i) {
|
||||
if (this.matches(sequence.charAt(i))) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
public int indexIn(CharSequence sequence, int start) {
|
||||
int length = sequence.length();
|
||||
Preconditions.checkPositionIndex(start, length);
|
||||
|
||||
for(int i = start; i < length; ++i) {
|
||||
if (this.matches(sequence.charAt(i))) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
public int lastIndexIn(CharSequence sequence) {
|
||||
for(int i = sequence.length() - 1; i >= 0; --i) {
|
||||
if (this.matches(sequence.charAt(i))) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
public int countIn(CharSequence sequence) {
|
||||
int count = 0;
|
||||
|
||||
for(int i = 0; i < sequence.length(); ++i) {
|
||||
if (this.matches(sequence.charAt(i))) {
|
||||
++count;
|
||||
}
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
@CheckReturnValue
|
||||
public String removeFrom(CharSequence sequence) {
|
||||
String string = sequence.toString();
|
||||
int pos = this.indexIn(string);
|
||||
if (pos == -1) {
|
||||
return string;
|
||||
} else {
|
||||
char[] chars = string.toCharArray();
|
||||
int spread = 1;
|
||||
|
||||
label25:
|
||||
while(true) {
|
||||
++pos;
|
||||
|
||||
while(pos != chars.length) {
|
||||
if (this.matches(chars[pos])) {
|
||||
++spread;
|
||||
continue label25;
|
||||
}
|
||||
|
||||
chars[pos - spread] = chars[pos];
|
||||
++pos;
|
||||
}
|
||||
|
||||
return new String(chars, 0, pos - spread);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@CheckReturnValue
|
||||
public String retainFrom(CharSequence sequence) {
|
||||
return this.negate().removeFrom(sequence);
|
||||
}
|
||||
|
||||
@CheckReturnValue
|
||||
public String replaceFrom(CharSequence sequence, char replacement) {
|
||||
String string = sequence.toString();
|
||||
int pos = this.indexIn(string);
|
||||
if (pos == -1) {
|
||||
return string;
|
||||
} else {
|
||||
char[] chars = string.toCharArray();
|
||||
chars[pos] = replacement;
|
||||
|
||||
for(int i = pos + 1; i < chars.length; ++i) {
|
||||
if (this.matches(chars[i])) {
|
||||
chars[i] = replacement;
|
||||
}
|
||||
}
|
||||
|
||||
return new String(chars);
|
||||
}
|
||||
}
|
||||
|
||||
@CheckReturnValue
|
||||
public String replaceFrom(CharSequence sequence, CharSequence replacement) {
|
||||
int replacementLen = replacement.length();
|
||||
if (replacementLen == 0) {
|
||||
return this.removeFrom(sequence);
|
||||
} else if (replacementLen == 1) {
|
||||
return this.replaceFrom(sequence, replacement.charAt(0));
|
||||
} else {
|
||||
String string = sequence.toString();
|
||||
int pos = this.indexIn(string);
|
||||
if (pos == -1) {
|
||||
return string;
|
||||
} else {
|
||||
int len = string.length();
|
||||
StringBuilder buf = new StringBuilder(len * 3 / 2 + 16);
|
||||
int oldpos = 0;
|
||||
|
||||
do {
|
||||
buf.append(string, oldpos, pos);
|
||||
buf.append(replacement);
|
||||
oldpos = pos + 1;
|
||||
pos = this.indexIn(string, oldpos);
|
||||
} while(pos != -1);
|
||||
|
||||
buf.append(string, oldpos, len);
|
||||
return buf.toString();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@CheckReturnValue
|
||||
public String trimFrom(CharSequence sequence) {
|
||||
int len = sequence.length();
|
||||
|
||||
int first;
|
||||
for(first = 0; first < len && this.matches(sequence.charAt(first)); ++first) {
|
||||
}
|
||||
|
||||
int last;
|
||||
for(last = len - 1; last > first && this.matches(sequence.charAt(last)); --last) {
|
||||
}
|
||||
|
||||
return sequence.subSequence(first, last + 1).toString();
|
||||
}
|
||||
|
||||
@CheckReturnValue
|
||||
public String trimLeadingFrom(CharSequence sequence) {
|
||||
int len = sequence.length();
|
||||
|
||||
for(int first = 0; first < len; ++first) {
|
||||
if (!this.matches(sequence.charAt(first))) {
|
||||
return sequence.subSequence(first, len).toString();
|
||||
}
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
@CheckReturnValue
|
||||
public String trimTrailingFrom(CharSequence sequence) {
|
||||
int len = sequence.length();
|
||||
|
||||
for(int last = len - 1; last >= 0; --last) {
|
||||
if (!this.matches(sequence.charAt(last))) {
|
||||
return sequence.subSequence(0, last + 1).toString();
|
||||
}
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
@CheckReturnValue
|
||||
public String collapseFrom(CharSequence sequence, char replacement) {
|
||||
int len = sequence.length();
|
||||
|
||||
for(int i = 0; i < len; ++i) {
|
||||
char c = sequence.charAt(i);
|
||||
if (this.matches(c)) {
|
||||
if (c != replacement || i != len - 1 && this.matches(sequence.charAt(i + 1))) {
|
||||
StringBuilder builder = (new StringBuilder(len)).append(sequence.subSequence(0, i)).append(replacement);
|
||||
return this.finishCollapseFrom(sequence, i + 1, len, replacement, builder, true);
|
||||
}
|
||||
|
||||
++i;
|
||||
}
|
||||
}
|
||||
|
||||
return sequence.toString();
|
||||
}
|
||||
|
||||
@CheckReturnValue
|
||||
public String trimAndCollapseFrom(CharSequence sequence, char replacement) {
|
||||
int len = sequence.length();
|
||||
|
||||
int first;
|
||||
for(first = 0; first < len && this.matches(sequence.charAt(first)); ++first) {
|
||||
}
|
||||
|
||||
int last;
|
||||
for(last = len - 1; last > first && this.matches(sequence.charAt(last)); --last) {
|
||||
}
|
||||
|
||||
return first == 0 && last == len - 1 ? this.collapseFrom(sequence, replacement) : this.finishCollapseFrom(sequence, first, last + 1, replacement, new StringBuilder(last + 1 - first), false);
|
||||
}
|
||||
|
||||
private String finishCollapseFrom(CharSequence sequence, int start, int end, char replacement, StringBuilder builder, boolean inMatchingGroup) {
|
||||
for(int i = start; i < end; ++i) {
|
||||
char c = sequence.charAt(i);
|
||||
if (this.matches(c)) {
|
||||
if (!inMatchingGroup) {
|
||||
builder.append(replacement);
|
||||
inMatchingGroup = true;
|
||||
}
|
||||
} else {
|
||||
builder.append(c);
|
||||
inMatchingGroup = false;
|
||||
}
|
||||
}
|
||||
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
/** @deprecated */
|
||||
@Deprecated
|
||||
public boolean apply(Character character) {
|
||||
return this.matches(character);
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return this.description;
|
||||
}
|
||||
|
||||
static {
|
||||
StringBuilder builder = new StringBuilder("0٠۰߀०০੦૦୦௦౦೦൦๐໐༠၀႐០᠐᥆᧐᭐᮰᱀᱐꘠꣐꤀꩐0".length());
|
||||
|
||||
for(int i = 0; i < "0٠۰߀०০੦૦୦௦౦೦൦๐໐༠၀႐០᠐᥆᧐᭐᮰᱀᱐꘠꣐꤀꩐0".length(); ++i) {
|
||||
builder.append((char)("0٠۰߀०০੦૦୦௦౦೦൦๐໐༠၀႐០᠐᥆᧐᭐᮰᱀᱐꘠꣐꤀꩐0".charAt(i) + 9));
|
||||
}
|
||||
|
||||
NINES = builder.toString();
|
||||
DIGIT = new CharMatcher.RangesMatcher("CharMatcher.DIGIT", "0٠۰߀०০੦૦୦௦౦೦൦๐໐༠၀႐០᠐᥆᧐᭐᮰᱀᱐꘠꣐꤀꩐0".toCharArray(), NINES.toCharArray());
|
||||
JAVA_DIGIT = new CharMatcher("CharMatcher.JAVA_DIGIT") {
|
||||
public boolean matches(char c) {
|
||||
return Character.isDigit(c);
|
||||
}
|
||||
};
|
||||
JAVA_LETTER = new CharMatcher("CharMatcher.JAVA_LETTER") {
|
||||
public boolean matches(char c) {
|
||||
return Character.isLetter(c);
|
||||
}
|
||||
};
|
||||
JAVA_LETTER_OR_DIGIT = new CharMatcher("CharMatcher.JAVA_LETTER_OR_DIGIT") {
|
||||
public boolean matches(char c) {
|
||||
return Character.isLetterOrDigit(c);
|
||||
}
|
||||
};
|
||||
JAVA_UPPER_CASE = new CharMatcher("CharMatcher.JAVA_UPPER_CASE") {
|
||||
public boolean matches(char c) {
|
||||
return Character.isUpperCase(c);
|
||||
}
|
||||
};
|
||||
JAVA_LOWER_CASE = new CharMatcher("CharMatcher.JAVA_LOWER_CASE") {
|
||||
public boolean matches(char c) {
|
||||
return Character.isLowerCase(c);
|
||||
}
|
||||
};
|
||||
JAVA_ISO_CONTROL = inRange('\u0000', '\u001f').or(inRange('\u007f', '\u009f')).withToString("CharMatcher.JAVA_ISO_CONTROL");
|
||||
INVISIBLE = new CharMatcher.RangesMatcher("CharMatcher.INVISIBLE", "\u0000\u007f\u00ad\u0600\u061c\u06dd\u070f \u2028 \u2066\u2067\u2068\u2069\u206a \ud800\ufeff\ufff9\ufffa".toCharArray(), " \u00ad\u0604\u061c\u06dd\u070f \u200f \u2064\u2066\u2067\u2068\u2069\u206f \uf8ff\ufeff\ufff9\ufffb".toCharArray());
|
||||
SINGLE_WIDTH = new CharMatcher.RangesMatcher("CharMatcher.SINGLE_WIDTH", "\u0000־א׳\u0600ݐ\u0e00Ḁ℀ﭐﹰ。".toCharArray(), "ӹ־ת״ۿݿ\u0e7f₯℺\ufdff\ufeffᅵ".toCharArray());
|
||||
ANY = new CharMatcher.FastMatcher("CharMatcher.ANY") {
|
||||
public boolean matches(char c) {
|
||||
return true;
|
||||
}
|
||||
|
||||
public int indexIn(CharSequence sequence) {
|
||||
return sequence.length() == 0 ? -1 : 0;
|
||||
}
|
||||
|
||||
public int indexIn(CharSequence sequence, int start) {
|
||||
int length = sequence.length();
|
||||
Preconditions.checkPositionIndex(start, length);
|
||||
return start == length ? -1 : start;
|
||||
}
|
||||
|
||||
public int lastIndexIn(CharSequence sequence) {
|
||||
return sequence.length() - 1;
|
||||
}
|
||||
|
||||
public boolean matchesAllOf(CharSequence sequence) {
|
||||
Preconditions.checkNotNull(sequence);
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean matchesNoneOf(CharSequence sequence) {
|
||||
return sequence.length() == 0;
|
||||
}
|
||||
|
||||
public String removeFrom(CharSequence sequence) {
|
||||
Preconditions.checkNotNull(sequence);
|
||||
return "";
|
||||
}
|
||||
|
||||
public String replaceFrom(CharSequence sequence, char replacement) {
|
||||
char[] array = new char[sequence.length()];
|
||||
Arrays.fill(array, replacement);
|
||||
return new String(array);
|
||||
}
|
||||
|
||||
public String replaceFrom(CharSequence sequence, CharSequence replacement) {
|
||||
StringBuilder retval = new StringBuilder(sequence.length() * replacement.length());
|
||||
|
||||
for(int i = 0; i < sequence.length(); ++i) {
|
||||
retval.append(replacement);
|
||||
}
|
||||
|
||||
return retval.toString();
|
||||
}
|
||||
|
||||
public String collapseFrom(CharSequence sequence, char replacement) {
|
||||
return sequence.length() == 0 ? "" : String.valueOf(replacement);
|
||||
}
|
||||
|
||||
public String trimFrom(CharSequence sequence) {
|
||||
Preconditions.checkNotNull(sequence);
|
||||
return "";
|
||||
}
|
||||
|
||||
public int countIn(CharSequence sequence) {
|
||||
return sequence.length();
|
||||
}
|
||||
|
||||
public CharMatcher and(CharMatcher other) {
|
||||
return (CharMatcher)Preconditions.checkNotNull(other);
|
||||
}
|
||||
|
||||
public CharMatcher or(CharMatcher other) {
|
||||
Preconditions.checkNotNull(other);
|
||||
return this;
|
||||
}
|
||||
|
||||
public CharMatcher negate() {
|
||||
return NONE;
|
||||
}
|
||||
};
|
||||
NONE = new CharMatcher.FastMatcher("CharMatcher.NONE") {
|
||||
public boolean matches(char c) {
|
||||
return false;
|
||||
}
|
||||
|
||||
public int indexIn(CharSequence sequence) {
|
||||
Preconditions.checkNotNull(sequence);
|
||||
return -1;
|
||||
}
|
||||
|
||||
public int indexIn(CharSequence sequence, int start) {
|
||||
int length = sequence.length();
|
||||
Preconditions.checkPositionIndex(start, length);
|
||||
return -1;
|
||||
}
|
||||
|
||||
public int lastIndexIn(CharSequence sequence) {
|
||||
Preconditions.checkNotNull(sequence);
|
||||
return -1;
|
||||
}
|
||||
|
||||
public boolean matchesAllOf(CharSequence sequence) {
|
||||
return sequence.length() == 0;
|
||||
}
|
||||
|
||||
public boolean matchesNoneOf(CharSequence sequence) {
|
||||
Preconditions.checkNotNull(sequence);
|
||||
return true;
|
||||
}
|
||||
|
||||
public String removeFrom(CharSequence sequence) {
|
||||
return sequence.toString();
|
||||
}
|
||||
|
||||
public String replaceFrom(CharSequence sequence, char replacement) {
|
||||
return sequence.toString();
|
||||
}
|
||||
|
||||
public String replaceFrom(CharSequence sequence, CharSequence replacement) {
|
||||
Preconditions.checkNotNull(replacement);
|
||||
return sequence.toString();
|
||||
}
|
||||
|
||||
public String collapseFrom(CharSequence sequence, char replacement) {
|
||||
return sequence.toString();
|
||||
}
|
||||
|
||||
public String trimFrom(CharSequence sequence) {
|
||||
return sequence.toString();
|
||||
}
|
||||
|
||||
public String trimLeadingFrom(CharSequence sequence) {
|
||||
return sequence.toString();
|
||||
}
|
||||
|
||||
public String trimTrailingFrom(CharSequence sequence) {
|
||||
return sequence.toString();
|
||||
}
|
||||
|
||||
public int countIn(CharSequence sequence) {
|
||||
Preconditions.checkNotNull(sequence);
|
||||
return 0;
|
||||
}
|
||||
|
||||
public CharMatcher and(CharMatcher other) {
|
||||
Preconditions.checkNotNull(other);
|
||||
return this;
|
||||
}
|
||||
|
||||
public CharMatcher or(CharMatcher other) {
|
||||
return (CharMatcher)Preconditions.checkNotNull(other);
|
||||
}
|
||||
|
||||
public CharMatcher negate() {
|
||||
return ANY;
|
||||
}
|
||||
};
|
||||
WHITESPACE_SHIFT = Integer.numberOfLeadingZeros(" \r\u0085 \u2029\u000b \t \f \u2028\n ".length() - 1);
|
||||
WHITESPACE = new CharMatcher.FastMatcher("WHITESPACE") {
|
||||
public boolean matches(char c) {
|
||||
return " \r\u0085 \u2029\u000b \t \f \u2028\n ".charAt(1682554634 * c >>> WHITESPACE_SHIFT) == c;
|
||||
}
|
||||
|
||||
@GwtIncompatible("java.util.BitSet")
|
||||
void setBits(BitSet table) {
|
||||
for(int i = 0; i < " \r\u0085 \u2029\u000b \t \f \u2028\n ".length(); ++i) {
|
||||
table.set(" \r\u0085 \u2029\u000b \t \f \u2028\n ".charAt(i));
|
||||
}
|
||||
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@GwtIncompatible("java.util.BitSet")
|
||||
private static class BitSetMatcher extends CharMatcher.FastMatcher {
|
||||
private final BitSet table;
|
||||
|
||||
private BitSetMatcher(BitSet table, String description) {
|
||||
super(description);
|
||||
if (table.length() + 64 < table.size()) {
|
||||
table = (BitSet)table.clone();
|
||||
}
|
||||
|
||||
this.table = table;
|
||||
}
|
||||
|
||||
public boolean matches(char c) {
|
||||
return this.table.get(c);
|
||||
}
|
||||
|
||||
void setBits(BitSet bitSet) {
|
||||
bitSet.or(this.table);
|
||||
}
|
||||
|
||||
// $FF: synthetic method
|
||||
BitSetMatcher(BitSet x0, String x1, Object x2) {
|
||||
this(x0, x1);
|
||||
}
|
||||
}
|
||||
|
||||
static final class NegatedFastMatcher extends CharMatcher.NegatedMatcher {
|
||||
NegatedFastMatcher(CharMatcher original) {
|
||||
super(original);
|
||||
}
|
||||
|
||||
NegatedFastMatcher(String toString, CharMatcher original) {
|
||||
super(toString, original);
|
||||
}
|
||||
|
||||
public final CharMatcher precomputed() {
|
||||
return this;
|
||||
}
|
||||
|
||||
CharMatcher withToString(String description) {
|
||||
return new CharMatcher.NegatedFastMatcher(description, this.original);
|
||||
}
|
||||
}
|
||||
|
||||
abstract static class FastMatcher extends CharMatcher {
|
||||
FastMatcher() {
|
||||
}
|
||||
|
||||
FastMatcher(String description) {
|
||||
super(description);
|
||||
}
|
||||
|
||||
public final CharMatcher precomputed() {
|
||||
return this;
|
||||
}
|
||||
|
||||
public CharMatcher negate() {
|
||||
return new CharMatcher.NegatedFastMatcher(this);
|
||||
}
|
||||
}
|
||||
|
||||
private static class Or extends CharMatcher {
|
||||
final CharMatcher first;
|
||||
final CharMatcher second;
|
||||
|
||||
Or(CharMatcher a, CharMatcher b, String description) {
|
||||
super(description);
|
||||
this.first = (CharMatcher)Preconditions.checkNotNull(a);
|
||||
this.second = (CharMatcher)Preconditions.checkNotNull(b);
|
||||
}
|
||||
|
||||
Or(CharMatcher a, CharMatcher b) {
|
||||
String var3 = String.valueOf(String.valueOf(a));
|
||||
String var4 = String.valueOf(String.valueOf(b));
|
||||
this(a, b, (new StringBuilder(18 + var3.length() + var4.length())).append("CharMatcher.or(").append(var3).append(", ").append(var4).append(")").toString());
|
||||
}
|
||||
|
||||
@GwtIncompatible("java.util.BitSet")
|
||||
void setBits(BitSet table) {
|
||||
this.first.setBits(table);
|
||||
this.second.setBits(table);
|
||||
}
|
||||
|
||||
public boolean matches(char c) {
|
||||
return this.first.matches(c) || this.second.matches(c);
|
||||
}
|
||||
|
||||
CharMatcher withToString(String description) {
|
||||
return new CharMatcher.Or(this.first, this.second, description);
|
||||
}
|
||||
}
|
||||
|
||||
private static class And extends CharMatcher {
|
||||
final CharMatcher first;
|
||||
final CharMatcher second;
|
||||
|
||||
And(CharMatcher a, CharMatcher b) {
|
||||
String var3 = String.valueOf(String.valueOf(a));
|
||||
String var4 = String.valueOf(String.valueOf(b));
|
||||
this(a, b, (new StringBuilder(19 + var3.length() + var4.length())).append("CharMatcher.and(").append(var3).append(", ").append(var4).append(")").toString());
|
||||
}
|
||||
|
||||
And(CharMatcher a, CharMatcher b, String description) {
|
||||
super(description);
|
||||
this.first = (CharMatcher)Preconditions.checkNotNull(a);
|
||||
this.second = (CharMatcher)Preconditions.checkNotNull(b);
|
||||
}
|
||||
|
||||
public boolean matches(char c) {
|
||||
return this.first.matches(c) && this.second.matches(c);
|
||||
}
|
||||
|
||||
@GwtIncompatible("java.util.BitSet")
|
||||
void setBits(BitSet table) {
|
||||
BitSet tmp1 = new BitSet();
|
||||
this.first.setBits(tmp1);
|
||||
BitSet tmp2 = new BitSet();
|
||||
this.second.setBits(tmp2);
|
||||
tmp1.and(tmp2);
|
||||
table.or(tmp1);
|
||||
}
|
||||
|
||||
CharMatcher withToString(String description) {
|
||||
return new CharMatcher.And(this.first, this.second, description);
|
||||
}
|
||||
}
|
||||
|
||||
private static class NegatedMatcher extends CharMatcher {
|
||||
final CharMatcher original;
|
||||
|
||||
NegatedMatcher(String toString, CharMatcher original) {
|
||||
super(toString);
|
||||
this.original = original;
|
||||
}
|
||||
|
||||
NegatedMatcher(CharMatcher original) {
|
||||
String var2 = String.valueOf(String.valueOf(original));
|
||||
this((new StringBuilder(9 + var2.length())).append(var2).append(".negate()").toString(), original);
|
||||
}
|
||||
|
||||
public boolean matches(char c) {
|
||||
return !this.original.matches(c);
|
||||
}
|
||||
|
||||
public boolean matchesAllOf(CharSequence sequence) {
|
||||
return this.original.matchesNoneOf(sequence);
|
||||
}
|
||||
|
||||
public boolean matchesNoneOf(CharSequence sequence) {
|
||||
return this.original.matchesAllOf(sequence);
|
||||
}
|
||||
|
||||
public int countIn(CharSequence sequence) {
|
||||
return sequence.length() - this.original.countIn(sequence);
|
||||
}
|
||||
|
||||
@GwtIncompatible("java.util.BitSet")
|
||||
void setBits(BitSet table) {
|
||||
BitSet tmp = new BitSet();
|
||||
this.original.setBits(tmp);
|
||||
tmp.flip(0, 65536);
|
||||
table.or(tmp);
|
||||
}
|
||||
|
||||
public CharMatcher negate() {
|
||||
return this.original;
|
||||
}
|
||||
|
||||
CharMatcher withToString(String description) {
|
||||
return new CharMatcher.NegatedMatcher(description, this.original);
|
||||
}
|
||||
}
|
||||
|
||||
private static class RangesMatcher extends CharMatcher {
|
||||
private final char[] rangeStarts;
|
||||
private final char[] rangeEnds;
|
||||
|
||||
RangesMatcher(String description, char[] rangeStarts, char[] rangeEnds) {
|
||||
super(description);
|
||||
this.rangeStarts = rangeStarts;
|
||||
this.rangeEnds = rangeEnds;
|
||||
Preconditions.checkArgument(rangeStarts.length == rangeEnds.length);
|
||||
|
||||
for(int i = 0; i < rangeStarts.length; ++i) {
|
||||
Preconditions.checkArgument(rangeStarts[i] <= rangeEnds[i]);
|
||||
if (i + 1 < rangeStarts.length) {
|
||||
Preconditions.checkArgument(rangeEnds[i] < rangeStarts[i + 1]);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public boolean matches(char c) {
|
||||
int index = Arrays.binarySearch(this.rangeStarts, c);
|
||||
if (index >= 0) {
|
||||
return true;
|
||||
} else {
|
||||
index = ~index - 1;
|
||||
return index >= 0 && c <= this.rangeEnds[index];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
25
src/main/com/google/common/base/Charsets.java
Normal file
25
src/main/com/google/common/base/Charsets.java
Normal file
|
@ -0,0 +1,25 @@
|
|||
package com.google.common.base;
|
||||
|
||||
import com.google.common.annotations.GwtCompatible;
|
||||
import com.google.common.annotations.GwtIncompatible;
|
||||
import java.nio.charset.Charset;
|
||||
|
||||
@GwtCompatible(
|
||||
emulated = true
|
||||
)
|
||||
public final class Charsets {
|
||||
@GwtIncompatible("Non-UTF-8 Charset")
|
||||
public static final Charset US_ASCII = Charset.forName("US-ASCII");
|
||||
@GwtIncompatible("Non-UTF-8 Charset")
|
||||
public static final Charset ISO_8859_1 = Charset.forName("ISO-8859-1");
|
||||
public static final Charset UTF_8 = Charset.forName("UTF-8");
|
||||
@GwtIncompatible("Non-UTF-8 Charset")
|
||||
public static final Charset UTF_16BE = Charset.forName("UTF-16BE");
|
||||
@GwtIncompatible("Non-UTF-8 Charset")
|
||||
public static final Charset UTF_16LE = Charset.forName("UTF-16LE");
|
||||
@GwtIncompatible("Non-UTF-8 Charset")
|
||||
public static final Charset UTF_16 = Charset.forName("UTF-16");
|
||||
|
||||
private Charsets() {
|
||||
}
|
||||
}
|
272
src/main/com/google/common/base/Converter.java
Normal file
272
src/main/com/google/common/base/Converter.java
Normal file
|
@ -0,0 +1,272 @@
|
|||
package com.google.common.base;
|
||||
|
||||
import com.google.common.annotations.Beta;
|
||||
import com.google.common.annotations.GwtCompatible;
|
||||
import java.io.Serializable;
|
||||
import java.util.Iterator;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
@Beta
|
||||
@GwtCompatible
|
||||
public abstract class Converter<A, B> implements Function<A, B> {
|
||||
private final boolean handleNullAutomatically;
|
||||
private transient Converter<B, A> reverse;
|
||||
|
||||
protected Converter() {
|
||||
this(true);
|
||||
}
|
||||
|
||||
Converter(boolean handleNullAutomatically) {
|
||||
this.handleNullAutomatically = handleNullAutomatically;
|
||||
}
|
||||
|
||||
protected abstract B doForward(A var1);
|
||||
|
||||
protected abstract A doBackward(B var1);
|
||||
|
||||
@Nullable
|
||||
public final B convert(@Nullable A a) {
|
||||
return this.correctedDoForward(a);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
B correctedDoForward(@Nullable A a) {
|
||||
if (this.handleNullAutomatically) {
|
||||
return a == null ? null : Preconditions.checkNotNull(this.doForward(a));
|
||||
} else {
|
||||
return this.doForward(a);
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
A correctedDoBackward(@Nullable B b) {
|
||||
if (this.handleNullAutomatically) {
|
||||
return b == null ? null : Preconditions.checkNotNull(this.doBackward(b));
|
||||
} else {
|
||||
return this.doBackward(b);
|
||||
}
|
||||
}
|
||||
|
||||
public Iterable<B> convertAll(final Iterable<? extends A> fromIterable) {
|
||||
Preconditions.checkNotNull(fromIterable, "fromIterable");
|
||||
return new Iterable<B>() {
|
||||
public Iterator<B> iterator() {
|
||||
return new Iterator<B>() {
|
||||
private final Iterator<? extends A> fromIterator = fromIterable.iterator();
|
||||
|
||||
public boolean hasNext() {
|
||||
return this.fromIterator.hasNext();
|
||||
}
|
||||
|
||||
public B next() {
|
||||
return Converter.this.convert(this.fromIterator.next());
|
||||
}
|
||||
|
||||
public void remove() {
|
||||
this.fromIterator.remove();
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public Converter<B, A> reverse() {
|
||||
Converter<B, A> result = this.reverse;
|
||||
return result == null ? (this.reverse = new Converter.ReverseConverter(this)) : result;
|
||||
}
|
||||
|
||||
public final <C> Converter<A, C> andThen(Converter<B, C> secondConverter) {
|
||||
return this.doAndThen(secondConverter);
|
||||
}
|
||||
|
||||
<C> Converter<A, C> doAndThen(Converter<B, C> secondConverter) {
|
||||
return new Converter.ConverterComposition(this, (Converter)Preconditions.checkNotNull(secondConverter));
|
||||
}
|
||||
|
||||
/** @deprecated */
|
||||
@Deprecated
|
||||
@Nullable
|
||||
public final B apply(@Nullable A a) {
|
||||
return this.convert(a);
|
||||
}
|
||||
|
||||
public boolean equals(@Nullable Object object) {
|
||||
return super.equals(object);
|
||||
}
|
||||
|
||||
public static <A, B> Converter<A, B> from(Function<? super A, ? extends B> forwardFunction, Function<? super B, ? extends A> backwardFunction) {
|
||||
return new Converter.FunctionBasedConverter(forwardFunction, backwardFunction);
|
||||
}
|
||||
|
||||
public static <T> Converter<T, T> identity() {
|
||||
return Converter.IdentityConverter.INSTANCE;
|
||||
}
|
||||
|
||||
private static final class IdentityConverter<T> extends Converter<T, T> implements Serializable {
|
||||
static final Converter.IdentityConverter INSTANCE = new Converter.IdentityConverter();
|
||||
private static final long serialVersionUID = 0L;
|
||||
|
||||
protected T doForward(T t) {
|
||||
return t;
|
||||
}
|
||||
|
||||
protected T doBackward(T t) {
|
||||
return t;
|
||||
}
|
||||
|
||||
public Converter.IdentityConverter<T> reverse() {
|
||||
return this;
|
||||
}
|
||||
|
||||
<S> Converter<T, S> doAndThen(Converter<T, S> otherConverter) {
|
||||
return (Converter)Preconditions.checkNotNull(otherConverter, "otherConverter");
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return "Converter.identity()";
|
||||
}
|
||||
|
||||
private Object readResolve() {
|
||||
return INSTANCE;
|
||||
}
|
||||
}
|
||||
|
||||
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 = (Function)Preconditions.checkNotNull(forwardFunction);
|
||||
this.backwardFunction = (Function)Preconditions.checkNotNull(backwardFunction);
|
||||
}
|
||||
|
||||
protected B doForward(A a) {
|
||||
return this.forwardFunction.apply(a);
|
||||
}
|
||||
|
||||
protected A doBackward(B b) {
|
||||
return this.backwardFunction.apply(b);
|
||||
}
|
||||
|
||||
public boolean equals(@Nullable Object object) {
|
||||
if (!(object instanceof Converter.FunctionBasedConverter)) {
|
||||
return false;
|
||||
} else {
|
||||
Converter.FunctionBasedConverter<?, ?> that = (Converter.FunctionBasedConverter)object;
|
||||
return this.forwardFunction.equals(that.forwardFunction) && this.backwardFunction.equals(that.backwardFunction);
|
||||
}
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
return this.forwardFunction.hashCode() * 31 + this.backwardFunction.hashCode();
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
String var1 = String.valueOf(String.valueOf(this.forwardFunction));
|
||||
String var2 = String.valueOf(String.valueOf(this.backwardFunction));
|
||||
return (new StringBuilder(18 + var1.length() + var2.length())).append("Converter.from(").append(var1).append(", ").append(var2).append(")").toString();
|
||||
}
|
||||
|
||||
// $FF: synthetic method
|
||||
FunctionBasedConverter(Function x0, Function x1, Object x2) {
|
||||
this(x0, x1);
|
||||
}
|
||||
}
|
||||
|
||||
private static final class ConverterComposition<A, B, C> extends Converter<A, C> implements Serializable {
|
||||
final Converter<A, B> first;
|
||||
final Converter<B, C> second;
|
||||
private static final long serialVersionUID = 0L;
|
||||
|
||||
ConverterComposition(Converter<A, B> first, Converter<B, C> second) {
|
||||
this.first = first;
|
||||
this.second = second;
|
||||
}
|
||||
|
||||
protected C doForward(A a) {
|
||||
throw new AssertionError();
|
||||
}
|
||||
|
||||
protected A doBackward(C c) {
|
||||
throw new AssertionError();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
C correctedDoForward(@Nullable A a) {
|
||||
return this.second.correctedDoForward(this.first.correctedDoForward(a));
|
||||
}
|
||||
|
||||
@Nullable
|
||||
A correctedDoBackward(@Nullable C c) {
|
||||
return this.first.correctedDoBackward(this.second.correctedDoBackward(c));
|
||||
}
|
||||
|
||||
public boolean equals(@Nullable Object object) {
|
||||
if (!(object instanceof Converter.ConverterComposition)) {
|
||||
return false;
|
||||
} else {
|
||||
Converter.ConverterComposition<?, ?, ?> that = (Converter.ConverterComposition)object;
|
||||
return this.first.equals(that.first) && this.second.equals(that.second);
|
||||
}
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
return 31 * this.first.hashCode() + this.second.hashCode();
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
String var1 = String.valueOf(String.valueOf(this.first));
|
||||
String var2 = String.valueOf(String.valueOf(this.second));
|
||||
return (new StringBuilder(10 + var1.length() + var2.length())).append(var1).append(".andThen(").append(var2).append(")").toString();
|
||||
}
|
||||
}
|
||||
|
||||
private static final class ReverseConverter<A, B> extends Converter<B, A> implements Serializable {
|
||||
final Converter<A, B> original;
|
||||
private static final long serialVersionUID = 0L;
|
||||
|
||||
ReverseConverter(Converter<A, B> original) {
|
||||
this.original = original;
|
||||
}
|
||||
|
||||
protected A doForward(B b) {
|
||||
throw new AssertionError();
|
||||
}
|
||||
|
||||
protected B doBackward(A a) {
|
||||
throw new AssertionError();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
A correctedDoForward(@Nullable B b) {
|
||||
return this.original.correctedDoBackward(b);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
B correctedDoBackward(@Nullable A a) {
|
||||
return this.original.correctedDoForward(a);
|
||||
}
|
||||
|
||||
public Converter<A, B> reverse() {
|
||||
return this.original;
|
||||
}
|
||||
|
||||
public boolean equals(@Nullable Object object) {
|
||||
if (object instanceof Converter.ReverseConverter) {
|
||||
Converter.ReverseConverter<?, ?> that = (Converter.ReverseConverter)object;
|
||||
return this.original.equals(that.original);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
return ~this.original.hashCode();
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
String var1 = String.valueOf(String.valueOf(this.original));
|
||||
return (new StringBuilder(10 + var1.length())).append(var1).append(".reverse()").toString();
|
||||
}
|
||||
}
|
||||
}
|
36
src/main/com/google/common/base/Defaults.java
Normal file
36
src/main/com/google/common/base/Defaults.java
Normal file
|
@ -0,0 +1,36 @@
|
|||
package com.google.common.base;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
public final class Defaults {
|
||||
private static final Map<Class<?>, Object> DEFAULTS;
|
||||
|
||||
private Defaults() {
|
||||
}
|
||||
|
||||
private static <T> void put(Map<Class<?>, Object> map, Class<T> type, T value) {
|
||||
map.put(type, value);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static <T> T defaultValue(Class<T> type) {
|
||||
T t = DEFAULTS.get(Preconditions.checkNotNull(type));
|
||||
return t;
|
||||
}
|
||||
|
||||
static {
|
||||
Map<Class<?>, Object> map = new HashMap();
|
||||
put(map, Boolean.TYPE, false);
|
||||
put(map, Character.TYPE, '\u0000');
|
||||
put(map, Byte.TYPE, (byte)0);
|
||||
put(map, Short.TYPE, Short.valueOf((short)0));
|
||||
put(map, Integer.TYPE, 0);
|
||||
put(map, Long.TYPE, 0L);
|
||||
put(map, Float.TYPE, 0.0F);
|
||||
put(map, Double.TYPE, 0.0D);
|
||||
DEFAULTS = Collections.unmodifiableMap(map);
|
||||
}
|
||||
}
|
108
src/main/com/google/common/base/Enums.java
Normal file
108
src/main/com/google/common/base/Enums.java
Normal file
|
@ -0,0 +1,108 @@
|
|||
package com.google.common.base;
|
||||
|
||||
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.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.WeakHashMap;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
@GwtCompatible(
|
||||
emulated = true
|
||||
)
|
||||
@Beta
|
||||
public final class Enums {
|
||||
@GwtIncompatible("java.lang.ref.WeakReference")
|
||||
private static final Map<Class<? extends Enum<?>>, Map<String, WeakReference<? extends Enum<?>>>> enumConstantCache = new WeakHashMap();
|
||||
|
||||
private Enums() {
|
||||
}
|
||||
|
||||
@GwtIncompatible("reflection")
|
||||
public static Field getField(Enum<?> enumValue) {
|
||||
Class clazz = enumValue.getDeclaringClass();
|
||||
|
||||
try {
|
||||
return clazz.getDeclaredField(enumValue.name());
|
||||
} catch (NoSuchFieldException var3) {
|
||||
throw new AssertionError(var3);
|
||||
}
|
||||
}
|
||||
|
||||
public static <T extends Enum<T>> Optional<T> getIfPresent(Class<T> enumClass, String value) {
|
||||
Preconditions.checkNotNull(enumClass);
|
||||
Preconditions.checkNotNull(value);
|
||||
return Platform.getEnumIfPresent(enumClass, value);
|
||||
}
|
||||
|
||||
@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();
|
||||
Iterator i$ = EnumSet.allOf(enumClass).iterator();
|
||||
|
||||
while(i$.hasNext()) {
|
||||
T enumInstance = (Enum)i$.next();
|
||||
result.put(enumInstance.name(), new WeakReference(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 = (Map)enumConstantCache.get(enumClass);
|
||||
if (constants == null) {
|
||||
constants = populateCache(enumClass);
|
||||
}
|
||||
|
||||
return constants;
|
||||
}
|
||||
}
|
||||
|
||||
public static <T extends Enum<T>> Converter<String, T> stringConverter(Class<T> enumClass) {
|
||||
return new Enums.StringConverter(enumClass);
|
||||
}
|
||||
|
||||
private static final class StringConverter<T extends Enum<T>> extends Converter<String, T> implements Serializable {
|
||||
private final Class<T> enumClass;
|
||||
private static final long serialVersionUID = 0L;
|
||||
|
||||
StringConverter(Class<T> enumClass) {
|
||||
this.enumClass = (Class)Preconditions.checkNotNull(enumClass);
|
||||
}
|
||||
|
||||
protected T doForward(String value) {
|
||||
return Enum.valueOf(this.enumClass, value);
|
||||
}
|
||||
|
||||
protected String doBackward(T enumValue) {
|
||||
return enumValue.name();
|
||||
}
|
||||
|
||||
public boolean equals(@Nullable Object object) {
|
||||
if (object instanceof Enums.StringConverter) {
|
||||
Enums.StringConverter<?> that = (Enums.StringConverter)object;
|
||||
return this.enumClass.equals(that.enumClass);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
return this.enumClass.hashCode();
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
String var1 = String.valueOf(String.valueOf(this.enumClass.getName()));
|
||||
return (new StringBuilder(29 + var1.length())).append("Enums.stringConverter(").append(var1).append(".class)").toString();
|
||||
}
|
||||
}
|
||||
}
|
175
src/main/com/google/common/base/Equivalence.java
Normal file
175
src/main/com/google/common/base/Equivalence.java
Normal file
|
@ -0,0 +1,175 @@
|
|||
package com.google.common.base;
|
||||
|
||||
import com.google.common.annotations.Beta;
|
||||
import com.google.common.annotations.GwtCompatible;
|
||||
import java.io.Serializable;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
@GwtCompatible
|
||||
public abstract class Equivalence<T> {
|
||||
protected Equivalence() {
|
||||
}
|
||||
|
||||
public final boolean equivalent(@Nullable T a, @Nullable T b) {
|
||||
if (a == b) {
|
||||
return true;
|
||||
} else {
|
||||
return a != null && b != null ? this.doEquivalent(a, b) : false;
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract boolean doEquivalent(T var1, T var2);
|
||||
|
||||
public final int hash(@Nullable T t) {
|
||||
return t == null ? 0 : this.doHash(t);
|
||||
}
|
||||
|
||||
protected abstract int doHash(T var1);
|
||||
|
||||
public final <F> Equivalence<F> onResultOf(Function<F, ? extends T> function) {
|
||||
return new FunctionalEquivalence(function, this);
|
||||
}
|
||||
|
||||
public final <S extends T> Equivalence.Wrapper<S> wrap(@Nullable S reference) {
|
||||
return new Equivalence.Wrapper(this, reference);
|
||||
}
|
||||
|
||||
@GwtCompatible(
|
||||
serializable = true
|
||||
)
|
||||
public final <S extends T> Equivalence<Iterable<S>> pairwise() {
|
||||
return new PairwiseEquivalence(this);
|
||||
}
|
||||
|
||||
@Beta
|
||||
public final Predicate<T> equivalentTo(@Nullable T target) {
|
||||
return new Equivalence.EquivalentToPredicate(this, target);
|
||||
}
|
||||
|
||||
public static Equivalence<Object> equals() {
|
||||
return Equivalence.Equals.INSTANCE;
|
||||
}
|
||||
|
||||
public static Equivalence<Object> identity() {
|
||||
return Equivalence.Identity.INSTANCE;
|
||||
}
|
||||
|
||||
static final class Identity extends Equivalence<Object> implements Serializable {
|
||||
static final Equivalence.Identity INSTANCE = new Equivalence.Identity();
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
protected boolean doEquivalent(Object a, Object b) {
|
||||
return false;
|
||||
}
|
||||
|
||||
protected int doHash(Object o) {
|
||||
return System.identityHashCode(o);
|
||||
}
|
||||
|
||||
private Object readResolve() {
|
||||
return INSTANCE;
|
||||
}
|
||||
}
|
||||
|
||||
static final class Equals extends Equivalence<Object> implements Serializable {
|
||||
static final Equivalence.Equals INSTANCE = new Equivalence.Equals();
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
protected boolean doEquivalent(Object a, Object b) {
|
||||
return a.equals(b);
|
||||
}
|
||||
|
||||
protected int doHash(Object o) {
|
||||
return o.hashCode();
|
||||
}
|
||||
|
||||
private Object readResolve() {
|
||||
return INSTANCE;
|
||||
}
|
||||
}
|
||||
|
||||
private static final class EquivalentToPredicate<T> implements Predicate<T>, Serializable {
|
||||
private final Equivalence<T> equivalence;
|
||||
@Nullable
|
||||
private final T target;
|
||||
private static final long serialVersionUID = 0L;
|
||||
|
||||
EquivalentToPredicate(Equivalence<T> equivalence, @Nullable T target) {
|
||||
this.equivalence = (Equivalence)Preconditions.checkNotNull(equivalence);
|
||||
this.target = target;
|
||||
}
|
||||
|
||||
public boolean apply(@Nullable T input) {
|
||||
return this.equivalence.equivalent(input, this.target);
|
||||
}
|
||||
|
||||
public boolean equals(@Nullable Object obj) {
|
||||
if (this == obj) {
|
||||
return true;
|
||||
} else if (!(obj instanceof Equivalence.EquivalentToPredicate)) {
|
||||
return false;
|
||||
} else {
|
||||
Equivalence.EquivalentToPredicate<?> that = (Equivalence.EquivalentToPredicate)obj;
|
||||
return this.equivalence.equals(that.equivalence) && Objects.equal(this.target, that.target);
|
||||
}
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
return Objects.hashCode(this.equivalence, this.target);
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
String var1 = String.valueOf(String.valueOf(this.equivalence));
|
||||
String var2 = String.valueOf(String.valueOf(this.target));
|
||||
return (new StringBuilder(15 + var1.length() + var2.length())).append(var1).append(".equivalentTo(").append(var2).append(")").toString();
|
||||
}
|
||||
}
|
||||
|
||||
public static final class Wrapper<T> implements Serializable {
|
||||
private final Equivalence<? super T> equivalence;
|
||||
@Nullable
|
||||
private final T reference;
|
||||
private static final long serialVersionUID = 0L;
|
||||
|
||||
private Wrapper(Equivalence<? super T> equivalence, @Nullable T reference) {
|
||||
this.equivalence = (Equivalence)Preconditions.checkNotNull(equivalence);
|
||||
this.reference = reference;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public T get() {
|
||||
return this.reference;
|
||||
}
|
||||
|
||||
public boolean equals(@Nullable Object obj) {
|
||||
if (obj == this) {
|
||||
return true;
|
||||
} else {
|
||||
if (obj instanceof Equivalence.Wrapper) {
|
||||
Equivalence.Wrapper<?> that = (Equivalence.Wrapper)obj;
|
||||
if (this.equivalence.equals(that.equivalence)) {
|
||||
Equivalence<Object> equivalence = this.equivalence;
|
||||
return equivalence.equivalent(this.reference, that.reference);
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
return this.equivalence.hash(this.reference);
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
String var1 = String.valueOf(String.valueOf(this.equivalence));
|
||||
String var2 = String.valueOf(String.valueOf(this.reference));
|
||||
return (new StringBuilder(7 + var1.length() + var2.length())).append(var1).append(".wrap(").append(var2).append(")").toString();
|
||||
}
|
||||
|
||||
// $FF: synthetic method
|
||||
Wrapper(Equivalence x0, Object x1, Object x2) {
|
||||
this(x0, x1);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
package com.google.common.base;
|
||||
|
||||
import java.lang.ref.PhantomReference;
|
||||
|
||||
public abstract class FinalizablePhantomReference<T> extends PhantomReference<T> implements FinalizableReference {
|
||||
protected FinalizablePhantomReference(T referent, FinalizableReferenceQueue queue) {
|
||||
super(referent, queue.queue);
|
||||
queue.cleanUp();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
package com.google.common.base;
|
||||
|
||||
public interface FinalizableReference {
|
||||
void finalizeReferent();
|
||||
}
|
179
src/main/com/google/common/base/FinalizableReferenceQueue.java
Normal file
179
src/main/com/google/common/base/FinalizableReferenceQueue.java
Normal file
|
@ -0,0 +1,179 @@
|
|||
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 java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
public class FinalizableReferenceQueue implements Closeable {
|
||||
private static final Logger logger = Logger.getLogger(FinalizableReferenceQueue.class.getName());
|
||||
private static final String FINALIZER_CLASS_NAME = "com.google.common.base.internal.Finalizer";
|
||||
private static final Method startFinalizer;
|
||||
final ReferenceQueue<Object> queue = new ReferenceQueue();
|
||||
final PhantomReference<Object> frqRef;
|
||||
final boolean threadStarted;
|
||||
|
||||
public FinalizableReferenceQueue() {
|
||||
this.frqRef = new PhantomReference(this, this.queue);
|
||||
boolean threadStarted = false;
|
||||
|
||||
try {
|
||||
startFinalizer.invoke((Object)null, FinalizableReference.class, this.queue, this.frqRef);
|
||||
threadStarted = true;
|
||||
} catch (IllegalAccessException var3) {
|
||||
throw new AssertionError(var3);
|
||||
} catch (Throwable var4) {
|
||||
logger.log(Level.INFO, "Failed to start reference finalizer thread. Reference cleanup will only occur when new references are created.", var4);
|
||||
}
|
||||
|
||||
this.threadStarted = threadStarted;
|
||||
}
|
||||
|
||||
public void close() {
|
||||
this.frqRef.enqueue();
|
||||
this.cleanUp();
|
||||
}
|
||||
|
||||
void cleanUp() {
|
||||
if (!this.threadStarted) {
|
||||
Reference reference;
|
||||
while((reference = this.queue.poll()) != null) {
|
||||
reference.clear();
|
||||
|
||||
try {
|
||||
((FinalizableReference)reference).finalizeReferent();
|
||||
} catch (Throwable var3) {
|
||||
logger.log(Level.SEVERE, "Error cleaning up after reference.", var3);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private static Class<?> loadFinalizer(FinalizableReferenceQueue.FinalizerLoader... loaders) {
|
||||
FinalizableReferenceQueue.FinalizerLoader[] arr$ = loaders;
|
||||
int len$ = loaders.length;
|
||||
|
||||
for(int i$ = 0; i$ < len$; ++i$) {
|
||||
FinalizableReferenceQueue.FinalizerLoader loader = arr$[i$];
|
||||
Class<?> finalizer = loader.loadFinalizer();
|
||||
if (finalizer != null) {
|
||||
return finalizer;
|
||||
}
|
||||
}
|
||||
|
||||
throw new AssertionError();
|
||||
}
|
||||
|
||||
static Method getStartFinalizer(Class<?> finalizer) {
|
||||
try {
|
||||
return finalizer.getMethod("startFinalizer", Class.class, ReferenceQueue.class, PhantomReference.class);
|
||||
} catch (NoSuchMethodException var2) {
|
||||
throw new AssertionError(var2);
|
||||
}
|
||||
}
|
||||
|
||||
static {
|
||||
Class<?> finalizer = loadFinalizer(new FinalizableReferenceQueue.SystemLoader(), new FinalizableReferenceQueue.DecoupledLoader(), new FinalizableReferenceQueue.DirectLoader());
|
||||
startFinalizer = getStartFinalizer(finalizer);
|
||||
}
|
||||
|
||||
static class DirectLoader implements FinalizableReferenceQueue.FinalizerLoader {
|
||||
public Class<?> loadFinalizer() {
|
||||
try {
|
||||
return Class.forName("com.google.common.base.internal.Finalizer");
|
||||
} catch (ClassNotFoundException var2) {
|
||||
throw new AssertionError(var2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static class DecoupledLoader implements FinalizableReferenceQueue.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 ableto garbage collect this class loader. To support reclaiming this class loader, eitherresolve the underlying issue, or move Google Collections to your system class path.";
|
||||
|
||||
public Class<?> loadFinalizer() {
|
||||
try {
|
||||
ClassLoader finalizerLoader = this.newLoader(this.getBaseUrl());
|
||||
return finalizerLoader.loadClass("com.google.common.base.internal.Finalizer");
|
||||
} catch (Exception var2) {
|
||||
FinalizableReferenceQueue.logger.log(Level.WARNING, "Could not load Finalizer in its own class loader.Loading Finalizer in the current class loader instead. As a result, you will not be ableto garbage collect this class loader. To support reclaiming this class loader, eitherresolve the underlying issue, or move Google Collections to your system class path.", var2);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
URL getBaseUrl() throws IOException {
|
||||
String finalizerPath = String.valueOf("com.google.common.base.internal.Finalizer".replace('.', '/')).concat(".class");
|
||||
URL finalizerUrl = this.getClass().getClassLoader().getResource(finalizerPath);
|
||||
if (finalizerUrl == null) {
|
||||
throw new FileNotFoundException(finalizerPath);
|
||||
} else {
|
||||
String urlString = finalizerUrl.toString();
|
||||
if (!urlString.endsWith(finalizerPath)) {
|
||||
IOException var10000 = new IOException;
|
||||
String var10003 = String.valueOf(urlString);
|
||||
String var10002;
|
||||
if (var10003.length() != 0) {
|
||||
var10002 = "Unsupported path style: ".concat(var10003);
|
||||
} else {
|
||||
String var10004 = new String;
|
||||
var10002 = var10004;
|
||||
var10004.<init>("Unsupported path style: ");
|
||||
}
|
||||
|
||||
var10000.<init>(var10002);
|
||||
throw var10000;
|
||||
} else {
|
||||
urlString = urlString.substring(0, urlString.length() - finalizerPath.length());
|
||||
return new URL(finalizerUrl, urlString);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
URLClassLoader newLoader(URL base) {
|
||||
return new URLClassLoader(new URL[]{base}, (ClassLoader)null);
|
||||
}
|
||||
}
|
||||
|
||||
static class SystemLoader implements FinalizableReferenceQueue.FinalizerLoader {
|
||||
@VisibleForTesting
|
||||
static boolean disabled;
|
||||
|
||||
public Class<?> loadFinalizer() {
|
||||
if (disabled) {
|
||||
return null;
|
||||
} else {
|
||||
ClassLoader systemLoader;
|
||||
try {
|
||||
systemLoader = ClassLoader.getSystemClassLoader();
|
||||
} catch (SecurityException var4) {
|
||||
FinalizableReferenceQueue.logger.info("Not allowed to access system class loader.");
|
||||
return null;
|
||||
}
|
||||
|
||||
if (systemLoader != null) {
|
||||
try {
|
||||
return systemLoader.loadClass("com.google.common.base.internal.Finalizer");
|
||||
} catch (ClassNotFoundException var3) {
|
||||
return null;
|
||||
}
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
interface FinalizerLoader {
|
||||
@Nullable
|
||||
Class<?> loadFinalizer();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
package com.google.common.base;
|
||||
|
||||
import java.lang.ref.SoftReference;
|
||||
|
||||
public abstract class FinalizableSoftReference<T> extends SoftReference<T> implements FinalizableReference {
|
||||
protected FinalizableSoftReference(T referent, FinalizableReferenceQueue queue) {
|
||||
super(referent, queue.queue);
|
||||
queue.cleanUp();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
package com.google.common.base;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
|
||||
public abstract class FinalizableWeakReference<T> extends WeakReference<T> implements FinalizableReference {
|
||||
protected FinalizableWeakReference(T referent, FinalizableReferenceQueue queue) {
|
||||
super(referent, queue.queue);
|
||||
queue.cleanUp();
|
||||
}
|
||||
}
|
12
src/main/com/google/common/base/Function.java
Normal file
12
src/main/com/google/common/base/Function.java
Normal file
|
@ -0,0 +1,12 @@
|
|||
package com.google.common.base;
|
||||
|
||||
import com.google.common.annotations.GwtCompatible;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
@GwtCompatible
|
||||
public interface Function<F, T> {
|
||||
@Nullable
|
||||
T apply(@Nullable F var1);
|
||||
|
||||
boolean equals(@Nullable Object var1);
|
||||
}
|
48
src/main/com/google/common/base/FunctionalEquivalence.java
Normal file
48
src/main/com/google/common/base/FunctionalEquivalence.java
Normal file
|
@ -0,0 +1,48 @@
|
|||
package com.google.common.base;
|
||||
|
||||
import com.google.common.annotations.Beta;
|
||||
import com.google.common.annotations.GwtCompatible;
|
||||
import java.io.Serializable;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
@Beta
|
||||
@GwtCompatible
|
||||
final class FunctionalEquivalence<F, T> extends Equivalence<F> implements Serializable {
|
||||
private static final long serialVersionUID = 0L;
|
||||
private final Function<F, ? extends T> function;
|
||||
private final Equivalence<T> resultEquivalence;
|
||||
|
||||
FunctionalEquivalence(Function<F, ? extends T> function, Equivalence<T> resultEquivalence) {
|
||||
this.function = (Function)Preconditions.checkNotNull(function);
|
||||
this.resultEquivalence = (Equivalence)Preconditions.checkNotNull(resultEquivalence);
|
||||
}
|
||||
|
||||
protected boolean doEquivalent(F a, F b) {
|
||||
return this.resultEquivalence.equivalent(this.function.apply(a), this.function.apply(b));
|
||||
}
|
||||
|
||||
protected int doHash(F a) {
|
||||
return this.resultEquivalence.hash(this.function.apply(a));
|
||||
}
|
||||
|
||||
public boolean equals(@Nullable Object obj) {
|
||||
if (obj == this) {
|
||||
return true;
|
||||
} else if (!(obj instanceof FunctionalEquivalence)) {
|
||||
return false;
|
||||
} else {
|
||||
FunctionalEquivalence<?, ?> that = (FunctionalEquivalence)obj;
|
||||
return this.function.equals(that.function) && this.resultEquivalence.equals(that.resultEquivalence);
|
||||
}
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
return Objects.hashCode(this.function, this.resultEquivalence);
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
String var1 = String.valueOf(String.valueOf(this.resultEquivalence));
|
||||
String var2 = String.valueOf(String.valueOf(this.function));
|
||||
return (new StringBuilder(13 + var1.length() + var2.length())).append(var1).append(".onResultOf(").append(var2).append(")").toString();
|
||||
}
|
||||
}
|
277
src/main/com/google/common/base/Functions.java
Normal file
277
src/main/com/google/common/base/Functions.java
Normal file
|
@ -0,0 +1,277 @@
|
|||
package com.google.common.base;
|
||||
|
||||
import com.google.common.annotations.Beta;
|
||||
import com.google.common.annotations.GwtCompatible;
|
||||
import java.io.Serializable;
|
||||
import java.util.Map;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
@GwtCompatible
|
||||
public final class Functions {
|
||||
private Functions() {
|
||||
}
|
||||
|
||||
public static Function<Object, String> toStringFunction() {
|
||||
return Functions.ToStringFunction.INSTANCE;
|
||||
}
|
||||
|
||||
public static <E> Function<E, E> identity() {
|
||||
return Functions.IdentityFunction.INSTANCE;
|
||||
}
|
||||
|
||||
public static <K, V> Function<K, V> forMap(Map<K, V> map) {
|
||||
return new Functions.FunctionForMapNoDefault(map);
|
||||
}
|
||||
|
||||
public static <K, V> Function<K, V> forMap(Map<K, ? extends V> map, @Nullable V defaultValue) {
|
||||
return new Functions.ForMapWithDefault(map, defaultValue);
|
||||
}
|
||||
|
||||
public static <A, B, C> Function<A, C> compose(Function<B, C> g, Function<A, ? extends B> f) {
|
||||
return new Functions.FunctionComposition(g, f);
|
||||
}
|
||||
|
||||
public static <T> Function<T, Boolean> forPredicate(Predicate<T> predicate) {
|
||||
return new Functions.PredicateFunction(predicate);
|
||||
}
|
||||
|
||||
public static <E> Function<Object, E> constant(@Nullable E value) {
|
||||
return new Functions.ConstantFunction(value);
|
||||
}
|
||||
|
||||
@Beta
|
||||
public static <T> Function<Object, T> forSupplier(Supplier<T> supplier) {
|
||||
return new Functions.SupplierFunction(supplier);
|
||||
}
|
||||
|
||||
private static class SupplierFunction<T> implements Function<Object, T>, Serializable {
|
||||
private final Supplier<T> supplier;
|
||||
private static final long serialVersionUID = 0L;
|
||||
|
||||
private SupplierFunction(Supplier<T> supplier) {
|
||||
this.supplier = (Supplier)Preconditions.checkNotNull(supplier);
|
||||
}
|
||||
|
||||
public T apply(@Nullable Object input) {
|
||||
return this.supplier.get();
|
||||
}
|
||||
|
||||
public boolean equals(@Nullable Object obj) {
|
||||
if (obj instanceof Functions.SupplierFunction) {
|
||||
Functions.SupplierFunction<?> that = (Functions.SupplierFunction)obj;
|
||||
return this.supplier.equals(that.supplier);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
return this.supplier.hashCode();
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
String var1 = String.valueOf(String.valueOf(this.supplier));
|
||||
return (new StringBuilder(13 + var1.length())).append("forSupplier(").append(var1).append(")").toString();
|
||||
}
|
||||
|
||||
// $FF: synthetic method
|
||||
SupplierFunction(Supplier x0, Object x1) {
|
||||
this(x0);
|
||||
}
|
||||
}
|
||||
|
||||
private static class ConstantFunction<E> implements Function<Object, E>, Serializable {
|
||||
private final E value;
|
||||
private static final long serialVersionUID = 0L;
|
||||
|
||||
public ConstantFunction(@Nullable E value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public E apply(@Nullable Object from) {
|
||||
return this.value;
|
||||
}
|
||||
|
||||
public boolean equals(@Nullable Object obj) {
|
||||
if (obj instanceof Functions.ConstantFunction) {
|
||||
Functions.ConstantFunction<?> that = (Functions.ConstantFunction)obj;
|
||||
return Objects.equal(this.value, that.value);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
return this.value == null ? 0 : this.value.hashCode();
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
String var1 = String.valueOf(String.valueOf(this.value));
|
||||
return (new StringBuilder(10 + var1.length())).append("constant(").append(var1).append(")").toString();
|
||||
}
|
||||
}
|
||||
|
||||
private static class PredicateFunction<T> implements Function<T, Boolean>, Serializable {
|
||||
private final Predicate<T> predicate;
|
||||
private static final long serialVersionUID = 0L;
|
||||
|
||||
private PredicateFunction(Predicate<T> predicate) {
|
||||
this.predicate = (Predicate)Preconditions.checkNotNull(predicate);
|
||||
}
|
||||
|
||||
public Boolean apply(@Nullable T t) {
|
||||
return this.predicate.apply(t);
|
||||
}
|
||||
|
||||
public boolean equals(@Nullable Object obj) {
|
||||
if (obj instanceof Functions.PredicateFunction) {
|
||||
Functions.PredicateFunction<?> that = (Functions.PredicateFunction)obj;
|
||||
return this.predicate.equals(that.predicate);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
return this.predicate.hashCode();
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
String var1 = String.valueOf(String.valueOf(this.predicate));
|
||||
return (new StringBuilder(14 + var1.length())).append("forPredicate(").append(var1).append(")").toString();
|
||||
}
|
||||
|
||||
// $FF: synthetic method
|
||||
PredicateFunction(Predicate x0, Object x1) {
|
||||
this(x0);
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
private static final long serialVersionUID = 0L;
|
||||
|
||||
public FunctionComposition(Function<B, C> g, Function<A, ? extends B> f) {
|
||||
this.g = (Function)Preconditions.checkNotNull(g);
|
||||
this.f = (Function)Preconditions.checkNotNull(f);
|
||||
}
|
||||
|
||||
public C apply(@Nullable A a) {
|
||||
return this.g.apply(this.f.apply(a));
|
||||
}
|
||||
|
||||
public boolean equals(@Nullable Object obj) {
|
||||
if (!(obj instanceof Functions.FunctionComposition)) {
|
||||
return false;
|
||||
} else {
|
||||
Functions.FunctionComposition<?, ?, ?> that = (Functions.FunctionComposition)obj;
|
||||
return this.f.equals(that.f) && this.g.equals(that.g);
|
||||
}
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
return this.f.hashCode() ^ this.g.hashCode();
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
String var1 = String.valueOf(String.valueOf(this.g));
|
||||
String var2 = String.valueOf(String.valueOf(this.f));
|
||||
return (new StringBuilder(2 + var1.length() + var2.length())).append(var1).append("(").append(var2).append(")").toString();
|
||||
}
|
||||
}
|
||||
|
||||
private static class ForMapWithDefault<K, V> implements Function<K, V>, Serializable {
|
||||
final Map<K, ? extends V> map;
|
||||
final V defaultValue;
|
||||
private static final long serialVersionUID = 0L;
|
||||
|
||||
ForMapWithDefault(Map<K, ? extends V> map, @Nullable V defaultValue) {
|
||||
this.map = (Map)Preconditions.checkNotNull(map);
|
||||
this.defaultValue = defaultValue;
|
||||
}
|
||||
|
||||
public V apply(@Nullable K key) {
|
||||
V result = this.map.get(key);
|
||||
return result == null && !this.map.containsKey(key) ? this.defaultValue : result;
|
||||
}
|
||||
|
||||
public boolean equals(@Nullable Object o) {
|
||||
if (!(o instanceof Functions.ForMapWithDefault)) {
|
||||
return false;
|
||||
} else {
|
||||
Functions.ForMapWithDefault<?, ?> that = (Functions.ForMapWithDefault)o;
|
||||
return this.map.equals(that.map) && Objects.equal(this.defaultValue, that.defaultValue);
|
||||
}
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
return Objects.hashCode(this.map, this.defaultValue);
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
String var1 = String.valueOf(String.valueOf(this.map));
|
||||
String var2 = String.valueOf(String.valueOf(this.defaultValue));
|
||||
return (new StringBuilder(23 + var1.length() + var2.length())).append("forMap(").append(var1).append(", defaultValue=").append(var2).append(")").toString();
|
||||
}
|
||||
}
|
||||
|
||||
private static class FunctionForMapNoDefault<K, V> implements Function<K, V>, Serializable {
|
||||
final Map<K, V> map;
|
||||
private static final long serialVersionUID = 0L;
|
||||
|
||||
FunctionForMapNoDefault(Map<K, V> map) {
|
||||
this.map = (Map)Preconditions.checkNotNull(map);
|
||||
}
|
||||
|
||||
public V apply(@Nullable K key) {
|
||||
V result = this.map.get(key);
|
||||
Preconditions.checkArgument(result != null || this.map.containsKey(key), "Key '%s' not present in map", key);
|
||||
return result;
|
||||
}
|
||||
|
||||
public boolean equals(@Nullable Object o) {
|
||||
if (o instanceof Functions.FunctionForMapNoDefault) {
|
||||
Functions.FunctionForMapNoDefault<?, ?> that = (Functions.FunctionForMapNoDefault)o;
|
||||
return this.map.equals(that.map);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
return this.map.hashCode();
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
String var1 = String.valueOf(String.valueOf(this.map));
|
||||
return (new StringBuilder(8 + var1.length())).append("forMap(").append(var1).append(")").toString();
|
||||
}
|
||||
}
|
||||
|
||||
private static enum IdentityFunction implements Function<Object, Object> {
|
||||
INSTANCE;
|
||||
|
||||
@Nullable
|
||||
public Object apply(@Nullable Object o) {
|
||||
return o;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return "identity";
|
||||
}
|
||||
}
|
||||
|
||||
private static enum ToStringFunction implements Function<Object, String> {
|
||||
INSTANCE;
|
||||
|
||||
public String apply(Object o) {
|
||||
Preconditions.checkNotNull(o);
|
||||
return o.toString();
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return "toString";
|
||||
}
|
||||
}
|
||||
}
|
269
src/main/com/google/common/base/Joiner.java
Normal file
269
src/main/com/google/common/base/Joiner.java
Normal file
|
@ -0,0 +1,269 @@
|
|||
package com.google.common.base;
|
||||
|
||||
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;
|
||||
|
||||
@GwtCompatible
|
||||
public class Joiner {
|
||||
private final String separator;
|
||||
|
||||
public static Joiner on(String separator) {
|
||||
return new Joiner(separator);
|
||||
}
|
||||
|
||||
public static Joiner on(char separator) {
|
||||
return new Joiner(String.valueOf(separator));
|
||||
}
|
||||
|
||||
private Joiner(String separator) {
|
||||
this.separator = (String)Preconditions.checkNotNull(separator);
|
||||
}
|
||||
|
||||
private Joiner(Joiner prototype) {
|
||||
this.separator = prototype.separator;
|
||||
}
|
||||
|
||||
public <A extends Appendable> A appendTo(A appendable, Iterable<?> parts) throws IOException {
|
||||
return this.appendTo(appendable, parts.iterator());
|
||||
}
|
||||
|
||||
public <A extends Appendable> A appendTo(A appendable, Iterator<?> parts) throws IOException {
|
||||
Preconditions.checkNotNull(appendable);
|
||||
if (parts.hasNext()) {
|
||||
appendable.append(this.toString(parts.next()));
|
||||
|
||||
while(parts.hasNext()) {
|
||||
appendable.append(this.separator);
|
||||
appendable.append(this.toString(parts.next()));
|
||||
}
|
||||
}
|
||||
|
||||
return appendable;
|
||||
}
|
||||
|
||||
public final <A extends Appendable> A appendTo(A appendable, Object[] parts) throws IOException {
|
||||
return this.appendTo((Appendable)appendable, (Iterable)Arrays.asList(parts));
|
||||
}
|
||||
|
||||
public final <A extends Appendable> A appendTo(A appendable, @Nullable Object first, @Nullable Object second, Object... rest) throws IOException {
|
||||
return this.appendTo(appendable, iterable(first, second, rest));
|
||||
}
|
||||
|
||||
public final StringBuilder appendTo(StringBuilder builder, Iterable<?> parts) {
|
||||
return this.appendTo(builder, parts.iterator());
|
||||
}
|
||||
|
||||
public final StringBuilder appendTo(StringBuilder builder, Iterator<?> parts) {
|
||||
try {
|
||||
this.appendTo((Appendable)builder, (Iterator)parts);
|
||||
return builder;
|
||||
} catch (IOException var4) {
|
||||
throw new AssertionError(var4);
|
||||
}
|
||||
}
|
||||
|
||||
public final StringBuilder appendTo(StringBuilder builder, Object[] parts) {
|
||||
return this.appendTo((StringBuilder)builder, (Iterable)Arrays.asList(parts));
|
||||
}
|
||||
|
||||
public final StringBuilder appendTo(StringBuilder builder, @Nullable Object first, @Nullable Object second, Object... rest) {
|
||||
return this.appendTo(builder, iterable(first, second, rest));
|
||||
}
|
||||
|
||||
public final String join(Iterable<?> parts) {
|
||||
return this.join(parts.iterator());
|
||||
}
|
||||
|
||||
public final String join(Iterator<?> parts) {
|
||||
return this.appendTo(new StringBuilder(), parts).toString();
|
||||
}
|
||||
|
||||
public final String join(Object[] parts) {
|
||||
return this.join((Iterable)Arrays.asList(parts));
|
||||
}
|
||||
|
||||
public final String join(@Nullable Object first, @Nullable Object second, Object... rest) {
|
||||
return this.join(iterable(first, second, rest));
|
||||
}
|
||||
|
||||
@CheckReturnValue
|
||||
public Joiner useForNull(final String nullText) {
|
||||
Preconditions.checkNotNull(nullText);
|
||||
return new Joiner(this) {
|
||||
CharSequence toString(@Nullable Object part) {
|
||||
return (CharSequence)(part == null ? nullText : Joiner.this.toString(part));
|
||||
}
|
||||
|
||||
public Joiner useForNull(String nullTextx) {
|
||||
throw new UnsupportedOperationException("already specified useForNull");
|
||||
}
|
||||
|
||||
public Joiner skipNulls() {
|
||||
throw new UnsupportedOperationException("already specified useForNull");
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@CheckReturnValue
|
||||
public Joiner skipNulls() {
|
||||
return new Joiner(this) {
|
||||
public <A extends Appendable> A appendTo(A appendable, Iterator<?> parts) throws IOException {
|
||||
Preconditions.checkNotNull(appendable, "appendable");
|
||||
Preconditions.checkNotNull(parts, "parts");
|
||||
|
||||
Object part;
|
||||
while(parts.hasNext()) {
|
||||
part = parts.next();
|
||||
if (part != null) {
|
||||
appendable.append(Joiner.this.toString(part));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
while(parts.hasNext()) {
|
||||
part = parts.next();
|
||||
if (part != null) {
|
||||
appendable.append(Joiner.this.separator);
|
||||
appendable.append(Joiner.this.toString(part));
|
||||
}
|
||||
}
|
||||
|
||||
return appendable;
|
||||
}
|
||||
|
||||
public Joiner useForNull(String nullText) {
|
||||
throw new UnsupportedOperationException("already specified skipNulls");
|
||||
}
|
||||
|
||||
public Joiner.MapJoiner withKeyValueSeparator(String kvs) {
|
||||
throw new UnsupportedOperationException("can't use .skipNulls() with maps");
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@CheckReturnValue
|
||||
public Joiner.MapJoiner withKeyValueSeparator(String keyValueSeparator) {
|
||||
return new Joiner.MapJoiner(this, keyValueSeparator);
|
||||
}
|
||||
|
||||
CharSequence toString(Object part) {
|
||||
Preconditions.checkNotNull(part);
|
||||
return (CharSequence)(part instanceof CharSequence ? (CharSequence)part : part.toString());
|
||||
}
|
||||
|
||||
private static Iterable<Object> iterable(final Object first, final Object second, final Object[] rest) {
|
||||
Preconditions.checkNotNull(rest);
|
||||
return new AbstractList<Object>() {
|
||||
public int size() {
|
||||
return rest.length + 2;
|
||||
}
|
||||
|
||||
public Object get(int index) {
|
||||
switch(index) {
|
||||
case 0:
|
||||
return first;
|
||||
case 1:
|
||||
return second;
|
||||
default:
|
||||
return rest[index - 2];
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// $FF: synthetic method
|
||||
Joiner(Joiner x0, Object x1) {
|
||||
this(x0);
|
||||
}
|
||||
|
||||
public static final class MapJoiner {
|
||||
private final Joiner joiner;
|
||||
private final String keyValueSeparator;
|
||||
|
||||
private MapJoiner(Joiner joiner, String keyValueSeparator) {
|
||||
this.joiner = joiner;
|
||||
this.keyValueSeparator = (String)Preconditions.checkNotNull(keyValueSeparator);
|
||||
}
|
||||
|
||||
public <A extends Appendable> A appendTo(A appendable, Map<?, ?> map) throws IOException {
|
||||
return this.appendTo((Appendable)appendable, (Iterable)map.entrySet());
|
||||
}
|
||||
|
||||
public StringBuilder appendTo(StringBuilder builder, Map<?, ?> map) {
|
||||
return this.appendTo((StringBuilder)builder, (Iterable)map.entrySet());
|
||||
}
|
||||
|
||||
public String join(Map<?, ?> map) {
|
||||
return this.join((Iterable)map.entrySet());
|
||||
}
|
||||
|
||||
@Beta
|
||||
public <A extends Appendable> A appendTo(A appendable, Iterable<? extends Entry<?, ?>> entries) throws IOException {
|
||||
return this.appendTo(appendable, entries.iterator());
|
||||
}
|
||||
|
||||
@Beta
|
||||
public <A extends Appendable> A appendTo(A appendable, Iterator<? extends Entry<?, ?>> parts) throws IOException {
|
||||
Preconditions.checkNotNull(appendable);
|
||||
if (parts.hasNext()) {
|
||||
Entry<?, ?> entry = (Entry)parts.next();
|
||||
appendable.append(this.joiner.toString(entry.getKey()));
|
||||
appendable.append(this.keyValueSeparator);
|
||||
appendable.append(this.joiner.toString(entry.getValue()));
|
||||
|
||||
while(parts.hasNext()) {
|
||||
appendable.append(this.joiner.separator);
|
||||
Entry<?, ?> e = (Entry)parts.next();
|
||||
appendable.append(this.joiner.toString(e.getKey()));
|
||||
appendable.append(this.keyValueSeparator);
|
||||
appendable.append(this.joiner.toString(e.getValue()));
|
||||
}
|
||||
}
|
||||
|
||||
return appendable;
|
||||
}
|
||||
|
||||
@Beta
|
||||
public StringBuilder appendTo(StringBuilder builder, Iterable<? extends Entry<?, ?>> entries) {
|
||||
return this.appendTo(builder, entries.iterator());
|
||||
}
|
||||
|
||||
@Beta
|
||||
public StringBuilder appendTo(StringBuilder builder, Iterator<? extends Entry<?, ?>> entries) {
|
||||
try {
|
||||
this.appendTo((Appendable)builder, (Iterator)entries);
|
||||
return builder;
|
||||
} catch (IOException var4) {
|
||||
throw new AssertionError(var4);
|
||||
}
|
||||
}
|
||||
|
||||
@Beta
|
||||
public String join(Iterable<? extends Entry<?, ?>> entries) {
|
||||
return this.join(entries.iterator());
|
||||
}
|
||||
|
||||
@Beta
|
||||
public String join(Iterator<? extends Entry<?, ?>> entries) {
|
||||
return this.appendTo(new StringBuilder(), entries).toString();
|
||||
}
|
||||
|
||||
@CheckReturnValue
|
||||
public Joiner.MapJoiner useForNull(String nullText) {
|
||||
return new Joiner.MapJoiner(this.joiner.useForNull(nullText), this.keyValueSeparator);
|
||||
}
|
||||
|
||||
// $FF: synthetic method
|
||||
MapJoiner(Joiner x0, String x1, Object x2) {
|
||||
this(x0, x1);
|
||||
}
|
||||
}
|
||||
}
|
170
src/main/com/google/common/base/MoreObjects.java
Normal file
170
src/main/com/google/common/base/MoreObjects.java
Normal file
|
@ -0,0 +1,170 @@
|
|||
package com.google.common.base;
|
||||
|
||||
import com.google.common.annotations.GwtCompatible;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
@GwtCompatible
|
||||
public final class MoreObjects {
|
||||
public static <T> T firstNonNull(@Nullable T first, @Nullable T second) {
|
||||
return first != null ? first : Preconditions.checkNotNull(second);
|
||||
}
|
||||
|
||||
public static MoreObjects.ToStringHelper toStringHelper(Object self) {
|
||||
return new MoreObjects.ToStringHelper(simpleName(self.getClass()));
|
||||
}
|
||||
|
||||
public static MoreObjects.ToStringHelper toStringHelper(Class<?> clazz) {
|
||||
return new MoreObjects.ToStringHelper(simpleName(clazz));
|
||||
}
|
||||
|
||||
public static MoreObjects.ToStringHelper toStringHelper(String className) {
|
||||
return new MoreObjects.ToStringHelper(className);
|
||||
}
|
||||
|
||||
static String simpleName(Class<?> clazz) {
|
||||
String name = clazz.getName();
|
||||
name = name.replaceAll("\\$[0-9]+", "\\$");
|
||||
int start = name.lastIndexOf(36);
|
||||
if (start == -1) {
|
||||
start = name.lastIndexOf(46);
|
||||
}
|
||||
|
||||
return name.substring(start + 1);
|
||||
}
|
||||
|
||||
private MoreObjects() {
|
||||
}
|
||||
|
||||
public static final class ToStringHelper {
|
||||
private final String className;
|
||||
private MoreObjects.ToStringHelper.ValueHolder holderHead;
|
||||
private MoreObjects.ToStringHelper.ValueHolder holderTail;
|
||||
private boolean omitNullValues;
|
||||
|
||||
private ToStringHelper(String className) {
|
||||
this.holderHead = new MoreObjects.ToStringHelper.ValueHolder();
|
||||
this.holderTail = this.holderHead;
|
||||
this.omitNullValues = false;
|
||||
this.className = (String)Preconditions.checkNotNull(className);
|
||||
}
|
||||
|
||||
public MoreObjects.ToStringHelper omitNullValues() {
|
||||
this.omitNullValues = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
public MoreObjects.ToStringHelper add(String name, @Nullable Object value) {
|
||||
return this.addHolder(name, value);
|
||||
}
|
||||
|
||||
public MoreObjects.ToStringHelper add(String name, boolean value) {
|
||||
return this.addHolder(name, String.valueOf(value));
|
||||
}
|
||||
|
||||
public MoreObjects.ToStringHelper add(String name, char value) {
|
||||
return this.addHolder(name, String.valueOf(value));
|
||||
}
|
||||
|
||||
public MoreObjects.ToStringHelper add(String name, double value) {
|
||||
return this.addHolder(name, String.valueOf(value));
|
||||
}
|
||||
|
||||
public MoreObjects.ToStringHelper add(String name, float value) {
|
||||
return this.addHolder(name, String.valueOf(value));
|
||||
}
|
||||
|
||||
public MoreObjects.ToStringHelper add(String name, int value) {
|
||||
return this.addHolder(name, String.valueOf(value));
|
||||
}
|
||||
|
||||
public MoreObjects.ToStringHelper add(String name, long value) {
|
||||
return this.addHolder(name, String.valueOf(value));
|
||||
}
|
||||
|
||||
public MoreObjects.ToStringHelper addValue(@Nullable Object value) {
|
||||
return this.addHolder(value);
|
||||
}
|
||||
|
||||
public MoreObjects.ToStringHelper addValue(boolean value) {
|
||||
return this.addHolder(String.valueOf(value));
|
||||
}
|
||||
|
||||
public MoreObjects.ToStringHelper addValue(char value) {
|
||||
return this.addHolder(String.valueOf(value));
|
||||
}
|
||||
|
||||
public MoreObjects.ToStringHelper addValue(double value) {
|
||||
return this.addHolder(String.valueOf(value));
|
||||
}
|
||||
|
||||
public MoreObjects.ToStringHelper addValue(float value) {
|
||||
return this.addHolder(String.valueOf(value));
|
||||
}
|
||||
|
||||
public MoreObjects.ToStringHelper addValue(int value) {
|
||||
return this.addHolder(String.valueOf(value));
|
||||
}
|
||||
|
||||
public MoreObjects.ToStringHelper addValue(long value) {
|
||||
return this.addHolder(String.valueOf(value));
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
boolean omitNullValuesSnapshot = this.omitNullValues;
|
||||
String nextSeparator = "";
|
||||
StringBuilder builder = (new StringBuilder(32)).append(this.className).append('{');
|
||||
|
||||
for(MoreObjects.ToStringHelper.ValueHolder valueHolder = this.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 MoreObjects.ToStringHelper.ValueHolder addHolder() {
|
||||
MoreObjects.ToStringHelper.ValueHolder valueHolder = new MoreObjects.ToStringHelper.ValueHolder();
|
||||
this.holderTail = this.holderTail.next = valueHolder;
|
||||
return valueHolder;
|
||||
}
|
||||
|
||||
private MoreObjects.ToStringHelper addHolder(@Nullable Object value) {
|
||||
MoreObjects.ToStringHelper.ValueHolder valueHolder = this.addHolder();
|
||||
valueHolder.value = value;
|
||||
return this;
|
||||
}
|
||||
|
||||
private MoreObjects.ToStringHelper addHolder(String name, @Nullable Object value) {
|
||||
MoreObjects.ToStringHelper.ValueHolder valueHolder = this.addHolder();
|
||||
valueHolder.value = value;
|
||||
valueHolder.name = (String)Preconditions.checkNotNull(name);
|
||||
return this;
|
||||
}
|
||||
|
||||
// $FF: synthetic method
|
||||
ToStringHelper(String x0, Object x1) {
|
||||
this(x0);
|
||||
}
|
||||
|
||||
private static final class ValueHolder {
|
||||
String name;
|
||||
Object value;
|
||||
MoreObjects.ToStringHelper.ValueHolder next;
|
||||
|
||||
private ValueHolder() {
|
||||
}
|
||||
|
||||
// $FF: synthetic method
|
||||
ValueHolder(Object x0) {
|
||||
this();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
180
src/main/com/google/common/base/Objects.java
Normal file
180
src/main/com/google/common/base/Objects.java
Normal file
|
@ -0,0 +1,180 @@
|
|||
package com.google.common.base;
|
||||
|
||||
import com.google.common.annotations.GwtCompatible;
|
||||
import java.util.Arrays;
|
||||
import javax.annotation.CheckReturnValue;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
@GwtCompatible
|
||||
public final class Objects {
|
||||
private Objects() {
|
||||
}
|
||||
|
||||
@CheckReturnValue
|
||||
public static boolean equal(@Nullable Object a, @Nullable Object b) {
|
||||
return a == b || a != null && a.equals(b);
|
||||
}
|
||||
|
||||
public static int hashCode(@Nullable Object... objects) {
|
||||
return Arrays.hashCode(objects);
|
||||
}
|
||||
|
||||
/** @deprecated */
|
||||
@Deprecated
|
||||
public static Objects.ToStringHelper toStringHelper(Object self) {
|
||||
return new Objects.ToStringHelper(MoreObjects.simpleName(self.getClass()));
|
||||
}
|
||||
|
||||
/** @deprecated */
|
||||
@Deprecated
|
||||
public static Objects.ToStringHelper toStringHelper(Class<?> clazz) {
|
||||
return new Objects.ToStringHelper(MoreObjects.simpleName(clazz));
|
||||
}
|
||||
|
||||
/** @deprecated */
|
||||
@Deprecated
|
||||
public static Objects.ToStringHelper toStringHelper(String className) {
|
||||
return new Objects.ToStringHelper(className);
|
||||
}
|
||||
|
||||
/** @deprecated */
|
||||
@Deprecated
|
||||
public static <T> T firstNonNull(@Nullable T first, @Nullable T second) {
|
||||
return MoreObjects.firstNonNull(first, second);
|
||||
}
|
||||
|
||||
/** @deprecated */
|
||||
@Deprecated
|
||||
public static final class ToStringHelper {
|
||||
private final String className;
|
||||
private Objects.ToStringHelper.ValueHolder holderHead;
|
||||
private Objects.ToStringHelper.ValueHolder holderTail;
|
||||
private boolean omitNullValues;
|
||||
|
||||
private ToStringHelper(String className) {
|
||||
this.holderHead = new Objects.ToStringHelper.ValueHolder();
|
||||
this.holderTail = this.holderHead;
|
||||
this.omitNullValues = false;
|
||||
this.className = (String)Preconditions.checkNotNull(className);
|
||||
}
|
||||
|
||||
public Objects.ToStringHelper omitNullValues() {
|
||||
this.omitNullValues = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Objects.ToStringHelper add(String name, @Nullable Object value) {
|
||||
return this.addHolder(name, value);
|
||||
}
|
||||
|
||||
public Objects.ToStringHelper add(String name, boolean value) {
|
||||
return this.addHolder(name, String.valueOf(value));
|
||||
}
|
||||
|
||||
public Objects.ToStringHelper add(String name, char value) {
|
||||
return this.addHolder(name, String.valueOf(value));
|
||||
}
|
||||
|
||||
public Objects.ToStringHelper add(String name, double value) {
|
||||
return this.addHolder(name, String.valueOf(value));
|
||||
}
|
||||
|
||||
public Objects.ToStringHelper add(String name, float value) {
|
||||
return this.addHolder(name, String.valueOf(value));
|
||||
}
|
||||
|
||||
public Objects.ToStringHelper add(String name, int value) {
|
||||
return this.addHolder(name, String.valueOf(value));
|
||||
}
|
||||
|
||||
public Objects.ToStringHelper add(String name, long value) {
|
||||
return this.addHolder(name, String.valueOf(value));
|
||||
}
|
||||
|
||||
public Objects.ToStringHelper addValue(@Nullable Object value) {
|
||||
return this.addHolder(value);
|
||||
}
|
||||
|
||||
public Objects.ToStringHelper addValue(boolean value) {
|
||||
return this.addHolder(String.valueOf(value));
|
||||
}
|
||||
|
||||
public Objects.ToStringHelper addValue(char value) {
|
||||
return this.addHolder(String.valueOf(value));
|
||||
}
|
||||
|
||||
public Objects.ToStringHelper addValue(double value) {
|
||||
return this.addHolder(String.valueOf(value));
|
||||
}
|
||||
|
||||
public Objects.ToStringHelper addValue(float value) {
|
||||
return this.addHolder(String.valueOf(value));
|
||||
}
|
||||
|
||||
public Objects.ToStringHelper addValue(int value) {
|
||||
return this.addHolder(String.valueOf(value));
|
||||
}
|
||||
|
||||
public Objects.ToStringHelper addValue(long value) {
|
||||
return this.addHolder(String.valueOf(value));
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
boolean omitNullValuesSnapshot = this.omitNullValues;
|
||||
String nextSeparator = "";
|
||||
StringBuilder builder = (new StringBuilder(32)).append(this.className).append('{');
|
||||
|
||||
for(Objects.ToStringHelper.ValueHolder valueHolder = this.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 Objects.ToStringHelper.ValueHolder addHolder() {
|
||||
Objects.ToStringHelper.ValueHolder valueHolder = new Objects.ToStringHelper.ValueHolder();
|
||||
this.holderTail = this.holderTail.next = valueHolder;
|
||||
return valueHolder;
|
||||
}
|
||||
|
||||
private Objects.ToStringHelper addHolder(@Nullable Object value) {
|
||||
Objects.ToStringHelper.ValueHolder valueHolder = this.addHolder();
|
||||
valueHolder.value = value;
|
||||
return this;
|
||||
}
|
||||
|
||||
private Objects.ToStringHelper addHolder(String name, @Nullable Object value) {
|
||||
Objects.ToStringHelper.ValueHolder valueHolder = this.addHolder();
|
||||
valueHolder.value = value;
|
||||
valueHolder.name = (String)Preconditions.checkNotNull(name);
|
||||
return this;
|
||||
}
|
||||
|
||||
// $FF: synthetic method
|
||||
ToStringHelper(String x0, Object x1) {
|
||||
this(x0);
|
||||
}
|
||||
|
||||
private static final class ValueHolder {
|
||||
String name;
|
||||
Object value;
|
||||
Objects.ToStringHelper.ValueHolder next;
|
||||
|
||||
private ValueHolder() {
|
||||
}
|
||||
|
||||
// $FF: synthetic method
|
||||
ValueHolder(Object x0) {
|
||||
this();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
81
src/main/com/google/common/base/Optional.java
Normal file
81
src/main/com/google/common/base/Optional.java
Normal file
|
@ -0,0 +1,81 @@
|
|||
package com.google.common.base;
|
||||
|
||||
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.Nullable;
|
||||
|
||||
@GwtCompatible(
|
||||
serializable = true
|
||||
)
|
||||
public abstract class Optional<T> implements Serializable {
|
||||
private static final long serialVersionUID = 0L;
|
||||
|
||||
public static <T> Optional<T> absent() {
|
||||
return Absent.withType();
|
||||
}
|
||||
|
||||
public static <T> Optional<T> of(T reference) {
|
||||
return new Present(Preconditions.checkNotNull(reference));
|
||||
}
|
||||
|
||||
public static <T> Optional<T> fromNullable(@Nullable T nullableReference) {
|
||||
return (Optional)(nullableReference == null ? absent() : new Present(nullableReference));
|
||||
}
|
||||
|
||||
Optional() {
|
||||
}
|
||||
|
||||
public abstract boolean isPresent();
|
||||
|
||||
public abstract T get();
|
||||
|
||||
public abstract T or(T var1);
|
||||
|
||||
public abstract Optional<T> or(Optional<? extends T> var1);
|
||||
|
||||
@Beta
|
||||
public abstract T or(Supplier<? extends T> var1);
|
||||
|
||||
@Nullable
|
||||
public abstract T orNull();
|
||||
|
||||
public abstract Set<T> asSet();
|
||||
|
||||
public abstract <V> Optional<V> transform(Function<? super T, V> var1);
|
||||
|
||||
public abstract boolean equals(@Nullable Object var1);
|
||||
|
||||
public abstract int hashCode();
|
||||
|
||||
public abstract String toString();
|
||||
|
||||
@Beta
|
||||
public static <T> Iterable<T> presentInstances(final Iterable<? extends Optional<? extends T>> optionals) {
|
||||
Preconditions.checkNotNull(optionals);
|
||||
return new Iterable<T>() {
|
||||
public Iterator<T> iterator() {
|
||||
return new AbstractIterator<T>() {
|
||||
private final Iterator<? extends Optional<? extends T>> iterator = (Iterator)Preconditions.checkNotNull(optionals.iterator());
|
||||
|
||||
protected T computeNext() {
|
||||
while(true) {
|
||||
if (this.iterator.hasNext()) {
|
||||
Optional<? extends T> optional = (Optional)this.iterator.next();
|
||||
if (!optional.isPresent()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
return optional.get();
|
||||
}
|
||||
|
||||
return this.endOfData();
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
60
src/main/com/google/common/base/PairwiseEquivalence.java
Normal file
60
src/main/com/google/common/base/PairwiseEquivalence.java
Normal file
|
@ -0,0 +1,60 @@
|
|||
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;
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
PairwiseEquivalence(Equivalence<? super T> elementEquivalence) {
|
||||
this.elementEquivalence = (Equivalence)Preconditions.checkNotNull(elementEquivalence);
|
||||
}
|
||||
|
||||
protected boolean doEquivalent(Iterable<T> iterableA, Iterable<T> iterableB) {
|
||||
Iterator<T> iteratorA = iterableA.iterator();
|
||||
Iterator iteratorB = iterableB.iterator();
|
||||
|
||||
while(iteratorA.hasNext() && iteratorB.hasNext()) {
|
||||
if (!this.elementEquivalence.equivalent(iteratorA.next(), iteratorB.next())) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return !iteratorA.hasNext() && !iteratorB.hasNext();
|
||||
}
|
||||
|
||||
protected int doHash(Iterable<T> iterable) {
|
||||
int hash = 78721;
|
||||
|
||||
Object element;
|
||||
for(Iterator i$ = iterable.iterator(); i$.hasNext(); hash = hash * 24943 + this.elementEquivalence.hash(element)) {
|
||||
element = i$.next();
|
||||
}
|
||||
|
||||
return hash;
|
||||
}
|
||||
|
||||
public boolean equals(@Nullable Object object) {
|
||||
if (object instanceof PairwiseEquivalence) {
|
||||
PairwiseEquivalence<?> that = (PairwiseEquivalence)object;
|
||||
return this.elementEquivalence.equals(that.elementEquivalence);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
return this.elementEquivalence.hashCode() ^ 1185147655;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
String var1 = String.valueOf(String.valueOf(this.elementEquivalence));
|
||||
return (new StringBuilder(11 + var1.length())).append(var1).append(".pairwise()").toString();
|
||||
}
|
||||
}
|
25
src/main/com/google/common/base/Platform.java
Normal file
25
src/main/com/google/common/base/Platform.java
Normal file
|
@ -0,0 +1,25 @@
|
|||
package com.google.common.base;
|
||||
|
||||
import com.google.common.annotations.GwtCompatible;
|
||||
import java.lang.ref.WeakReference;
|
||||
|
||||
@GwtCompatible(
|
||||
emulated = true
|
||||
)
|
||||
final class Platform {
|
||||
private Platform() {
|
||||
}
|
||||
|
||||
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 = (WeakReference)Enums.getEnumConstants(enumClass).get(value);
|
||||
return ref == null ? Optional.absent() : Optional.of(enumClass.cast(ref.get()));
|
||||
}
|
||||
}
|
161
src/main/com/google/common/base/Preconditions.java
Normal file
161
src/main/com/google/common/base/Preconditions.java
Normal file
|
@ -0,0 +1,161 @@
|
|||
package com.google.common.base;
|
||||
|
||||
import com.google.common.annotations.GwtCompatible;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
@GwtCompatible
|
||||
public final class Preconditions {
|
||||
private Preconditions() {
|
||||
}
|
||||
|
||||
public static void checkArgument(boolean expression) {
|
||||
if (!expression) {
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
}
|
||||
|
||||
public static void checkArgument(boolean expression, @Nullable Object errorMessage) {
|
||||
if (!expression) {
|
||||
throw new IllegalArgumentException(String.valueOf(errorMessage));
|
||||
}
|
||||
}
|
||||
|
||||
public static void checkArgument(boolean expression, @Nullable String errorMessageTemplate, @Nullable Object... errorMessageArgs) {
|
||||
if (!expression) {
|
||||
throw new IllegalArgumentException(format(errorMessageTemplate, errorMessageArgs));
|
||||
}
|
||||
}
|
||||
|
||||
public static void checkState(boolean expression) {
|
||||
if (!expression) {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
}
|
||||
|
||||
public static void checkState(boolean expression, @Nullable Object errorMessage) {
|
||||
if (!expression) {
|
||||
throw new IllegalStateException(String.valueOf(errorMessage));
|
||||
}
|
||||
}
|
||||
|
||||
public static void checkState(boolean expression, @Nullable String errorMessageTemplate, @Nullable Object... errorMessageArgs) {
|
||||
if (!expression) {
|
||||
throw new IllegalStateException(format(errorMessageTemplate, errorMessageArgs));
|
||||
}
|
||||
}
|
||||
|
||||
public static <T> T checkNotNull(T reference) {
|
||||
if (reference == null) {
|
||||
throw new NullPointerException();
|
||||
} else {
|
||||
return reference;
|
||||
}
|
||||
}
|
||||
|
||||
public static <T> T checkNotNull(T reference, @Nullable Object errorMessage) {
|
||||
if (reference == null) {
|
||||
throw new NullPointerException(String.valueOf(errorMessage));
|
||||
} else {
|
||||
return reference;
|
||||
}
|
||||
}
|
||||
|
||||
public static <T> T checkNotNull(T reference, @Nullable String errorMessageTemplate, @Nullable Object... errorMessageArgs) {
|
||||
if (reference == null) {
|
||||
throw new NullPointerException(format(errorMessageTemplate, errorMessageArgs));
|
||||
} else {
|
||||
return reference;
|
||||
}
|
||||
}
|
||||
|
||||
public static int checkElementIndex(int index, int size) {
|
||||
return checkElementIndex(index, size, "index");
|
||||
}
|
||||
|
||||
public static int checkElementIndex(int index, int size, @Nullable String desc) {
|
||||
if (index >= 0 && index < size) {
|
||||
return index;
|
||||
} else {
|
||||
throw new IndexOutOfBoundsException(badElementIndex(index, size, desc));
|
||||
}
|
||||
}
|
||||
|
||||
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((new StringBuilder(26)).append("negative size: ").append(size).toString());
|
||||
} else {
|
||||
return format("%s (%s) must be less than size (%s)", desc, index, size);
|
||||
}
|
||||
}
|
||||
|
||||
public static int checkPositionIndex(int index, int size) {
|
||||
return checkPositionIndex(index, size, "index");
|
||||
}
|
||||
|
||||
public static int checkPositionIndex(int index, int size, @Nullable String desc) {
|
||||
if (index >= 0 && index <= size) {
|
||||
return index;
|
||||
} else {
|
||||
throw new IndexOutOfBoundsException(badPositionIndex(index, size, desc));
|
||||
}
|
||||
}
|
||||
|
||||
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((new StringBuilder(26)).append("negative size: ").append(size).toString());
|
||||
} else {
|
||||
return format("%s (%s) must not be greater than size (%s)", desc, index, size);
|
||||
}
|
||||
}
|
||||
|
||||
public static void checkPositionIndexes(int start, int end, int size) {
|
||||
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 end >= 0 && end <= size ? format("end index (%s) must not be less than start index (%s)", end, start) : badPositionIndex(end, size, "end index");
|
||||
} else {
|
||||
return badPositionIndex(start, size, "start index");
|
||||
}
|
||||
}
|
||||
|
||||
static String format(String template, @Nullable Object... args) {
|
||||
template = String.valueOf(template);
|
||||
StringBuilder builder = new StringBuilder(template.length() + 16 * args.length);
|
||||
int templateStart = 0;
|
||||
|
||||
int i;
|
||||
int placeholderStart;
|
||||
for(i = 0; i < args.length; templateStart = placeholderStart + 2) {
|
||||
placeholderStart = template.indexOf("%s", templateStart);
|
||||
if (placeholderStart == -1) {
|
||||
break;
|
||||
}
|
||||
|
||||
builder.append(template.substring(templateStart, placeholderStart));
|
||||
builder.append(args[i++]);
|
||||
}
|
||||
|
||||
builder.append(template.substring(templateStart));
|
||||
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();
|
||||
}
|
||||
}
|
11
src/main/com/google/common/base/Predicate.java
Normal file
11
src/main/com/google/common/base/Predicate.java
Normal file
|
@ -0,0 +1,11 @@
|
|||
package com.google.common.base;
|
||||
|
||||
import com.google.common.annotations.GwtCompatible;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
@GwtCompatible
|
||||
public interface Predicate<T> {
|
||||
boolean apply(@Nullable T var1);
|
||||
|
||||
boolean equals(@Nullable Object var1);
|
||||
}
|
536
src/main/com/google/common/base/Predicates.java
Normal file
536
src/main/com/google/common/base/Predicates.java
Normal file
|
@ -0,0 +1,536 @@
|
|||
package com.google.common.base;
|
||||
|
||||
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.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.regex.Pattern;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
@GwtCompatible(
|
||||
emulated = true
|
||||
)
|
||||
public final class Predicates {
|
||||
private static final Joiner COMMA_JOINER = Joiner.on(',');
|
||||
|
||||
private Predicates() {
|
||||
}
|
||||
|
||||
@GwtCompatible(
|
||||
serializable = true
|
||||
)
|
||||
public static <T> Predicate<T> alwaysTrue() {
|
||||
return Predicates.ObjectPredicate.ALWAYS_TRUE.withNarrowedType();
|
||||
}
|
||||
|
||||
@GwtCompatible(
|
||||
serializable = true
|
||||
)
|
||||
public static <T> Predicate<T> alwaysFalse() {
|
||||
return Predicates.ObjectPredicate.ALWAYS_FALSE.withNarrowedType();
|
||||
}
|
||||
|
||||
@GwtCompatible(
|
||||
serializable = true
|
||||
)
|
||||
public static <T> Predicate<T> isNull() {
|
||||
return Predicates.ObjectPredicate.IS_NULL.withNarrowedType();
|
||||
}
|
||||
|
||||
@GwtCompatible(
|
||||
serializable = true
|
||||
)
|
||||
public static <T> Predicate<T> notNull() {
|
||||
return Predicates.ObjectPredicate.NOT_NULL.withNarrowedType();
|
||||
}
|
||||
|
||||
public static <T> Predicate<T> not(Predicate<T> predicate) {
|
||||
return new Predicates.NotPredicate(predicate);
|
||||
}
|
||||
|
||||
public static <T> Predicate<T> and(Iterable<? extends Predicate<? super T>> components) {
|
||||
return new Predicates.AndPredicate(defensiveCopy(components));
|
||||
}
|
||||
|
||||
public static <T> Predicate<T> and(Predicate<? super T>... components) {
|
||||
return new Predicates.AndPredicate(defensiveCopy((Object[])components));
|
||||
}
|
||||
|
||||
public static <T> Predicate<T> and(Predicate<? super T> first, Predicate<? super T> second) {
|
||||
return new Predicates.AndPredicate(asList((Predicate)Preconditions.checkNotNull(first), (Predicate)Preconditions.checkNotNull(second)));
|
||||
}
|
||||
|
||||
public static <T> Predicate<T> or(Iterable<? extends Predicate<? super T>> components) {
|
||||
return new Predicates.OrPredicate(defensiveCopy(components));
|
||||
}
|
||||
|
||||
public static <T> Predicate<T> or(Predicate<? super T>... components) {
|
||||
return new Predicates.OrPredicate(defensiveCopy((Object[])components));
|
||||
}
|
||||
|
||||
public static <T> Predicate<T> or(Predicate<? super T> first, Predicate<? super T> second) {
|
||||
return new Predicates.OrPredicate(asList((Predicate)Preconditions.checkNotNull(first), (Predicate)Preconditions.checkNotNull(second)));
|
||||
}
|
||||
|
||||
public static <T> Predicate<T> equalTo(@Nullable T target) {
|
||||
return (Predicate)(target == null ? isNull() : new Predicates.IsEqualToPredicate(target));
|
||||
}
|
||||
|
||||
@GwtIncompatible("Class.isInstance")
|
||||
public static Predicate<Object> instanceOf(Class<?> clazz) {
|
||||
return new Predicates.InstanceOfPredicate(clazz);
|
||||
}
|
||||
|
||||
@GwtIncompatible("Class.isAssignableFrom")
|
||||
@Beta
|
||||
public static Predicate<Class<?>> assignableFrom(Class<?> clazz) {
|
||||
return new Predicates.AssignableFromPredicate(clazz);
|
||||
}
|
||||
|
||||
public static <T> Predicate<T> in(Collection<? extends T> target) {
|
||||
return new Predicates.InPredicate(target);
|
||||
}
|
||||
|
||||
public static <A, B> Predicate<A> compose(Predicate<B> predicate, Function<A, ? extends B> function) {
|
||||
return new Predicates.CompositionPredicate(predicate, function);
|
||||
}
|
||||
|
||||
@GwtIncompatible("java.util.regex.Pattern")
|
||||
public static Predicate<CharSequence> containsPattern(String pattern) {
|
||||
return new Predicates.ContainsPatternFromStringPredicate(pattern);
|
||||
}
|
||||
|
||||
@GwtIncompatible("java.util.regex.Pattern")
|
||||
public static Predicate<CharSequence> contains(Pattern pattern) {
|
||||
return new Predicates.ContainsPatternPredicate(pattern);
|
||||
}
|
||||
|
||||
private static <T> List<Predicate<? super T>> asList(Predicate<? super T> first, Predicate<? super T> second) {
|
||||
return Arrays.asList(first, second);
|
||||
}
|
||||
|
||||
private static <T> List<T> defensiveCopy(T... array) {
|
||||
return defensiveCopy((Iterable)Arrays.asList(array));
|
||||
}
|
||||
|
||||
static <T> List<T> defensiveCopy(Iterable<T> iterable) {
|
||||
ArrayList<T> list = new ArrayList();
|
||||
Iterator i$ = iterable.iterator();
|
||||
|
||||
while(i$.hasNext()) {
|
||||
T element = i$.next();
|
||||
list.add(Preconditions.checkNotNull(element));
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
@GwtIncompatible("Only used by other GWT-incompatible code.")
|
||||
private static class ContainsPatternFromStringPredicate extends Predicates.ContainsPatternPredicate {
|
||||
private static final long serialVersionUID = 0L;
|
||||
|
||||
ContainsPatternFromStringPredicate(String string) {
|
||||
super(Pattern.compile(string));
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
String var1 = String.valueOf(String.valueOf(this.pattern.pattern()));
|
||||
return (new StringBuilder(28 + var1.length())).append("Predicates.containsPattern(").append(var1).append(")").toString();
|
||||
}
|
||||
}
|
||||
|
||||
@GwtIncompatible("Only used by other GWT-incompatible code.")
|
||||
private static class ContainsPatternPredicate implements Predicate<CharSequence>, Serializable {
|
||||
final Pattern pattern;
|
||||
private static final long serialVersionUID = 0L;
|
||||
|
||||
ContainsPatternPredicate(Pattern pattern) {
|
||||
this.pattern = (Pattern)Preconditions.checkNotNull(pattern);
|
||||
}
|
||||
|
||||
public boolean apply(CharSequence t) {
|
||||
return this.pattern.matcher(t).find();
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
return Objects.hashCode(this.pattern.pattern(), this.pattern.flags());
|
||||
}
|
||||
|
||||
public boolean equals(@Nullable Object obj) {
|
||||
if (!(obj instanceof Predicates.ContainsPatternPredicate)) {
|
||||
return false;
|
||||
} else {
|
||||
Predicates.ContainsPatternPredicate that = (Predicates.ContainsPatternPredicate)obj;
|
||||
return Objects.equal(this.pattern.pattern(), that.pattern.pattern()) && Objects.equal(this.pattern.flags(), that.pattern.flags());
|
||||
}
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
String patternString = Objects.toStringHelper((Object)this.pattern).add("pattern", this.pattern.pattern()).add("pattern.flags", this.pattern.flags()).toString();
|
||||
String var2 = String.valueOf(String.valueOf(patternString));
|
||||
return (new StringBuilder(21 + var2.length())).append("Predicates.contains(").append(var2).append(")").toString();
|
||||
}
|
||||
}
|
||||
|
||||
private static class CompositionPredicate<A, B> implements Predicate<A>, Serializable {
|
||||
final Predicate<B> p;
|
||||
final Function<A, ? extends B> f;
|
||||
private static final long serialVersionUID = 0L;
|
||||
|
||||
private CompositionPredicate(Predicate<B> p, Function<A, ? extends B> f) {
|
||||
this.p = (Predicate)Preconditions.checkNotNull(p);
|
||||
this.f = (Function)Preconditions.checkNotNull(f);
|
||||
}
|
||||
|
||||
public boolean apply(@Nullable A a) {
|
||||
return this.p.apply(this.f.apply(a));
|
||||
}
|
||||
|
||||
public boolean equals(@Nullable Object obj) {
|
||||
if (!(obj instanceof Predicates.CompositionPredicate)) {
|
||||
return false;
|
||||
} else {
|
||||
Predicates.CompositionPredicate<?, ?> that = (Predicates.CompositionPredicate)obj;
|
||||
return this.f.equals(that.f) && this.p.equals(that.p);
|
||||
}
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
return this.f.hashCode() ^ this.p.hashCode();
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
String var1 = String.valueOf(String.valueOf(this.p.toString()));
|
||||
String var2 = String.valueOf(String.valueOf(this.f.toString()));
|
||||
return (new StringBuilder(2 + var1.length() + var2.length())).append(var1).append("(").append(var2).append(")").toString();
|
||||
}
|
||||
|
||||
// $FF: synthetic method
|
||||
CompositionPredicate(Predicate x0, Function x1, Object x2) {
|
||||
this(x0, x1);
|
||||
}
|
||||
}
|
||||
|
||||
private static class InPredicate<T> implements Predicate<T>, Serializable {
|
||||
private final Collection<?> target;
|
||||
private static final long serialVersionUID = 0L;
|
||||
|
||||
private InPredicate(Collection<?> target) {
|
||||
this.target = (Collection)Preconditions.checkNotNull(target);
|
||||
}
|
||||
|
||||
public boolean apply(@Nullable T t) {
|
||||
try {
|
||||
return this.target.contains(t);
|
||||
} catch (NullPointerException var3) {
|
||||
return false;
|
||||
} catch (ClassCastException var4) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean equals(@Nullable Object obj) {
|
||||
if (obj instanceof Predicates.InPredicate) {
|
||||
Predicates.InPredicate<?> that = (Predicates.InPredicate)obj;
|
||||
return this.target.equals(that.target);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
return this.target.hashCode();
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
String var1 = String.valueOf(String.valueOf(this.target));
|
||||
return (new StringBuilder(15 + var1.length())).append("Predicates.in(").append(var1).append(")").toString();
|
||||
}
|
||||
|
||||
// $FF: synthetic method
|
||||
InPredicate(Collection x0, Object x1) {
|
||||
this(x0);
|
||||
}
|
||||
}
|
||||
|
||||
@GwtIncompatible("Class.isAssignableFrom")
|
||||
private static class AssignableFromPredicate implements Predicate<Class<?>>, Serializable {
|
||||
private final Class<?> clazz;
|
||||
private static final long serialVersionUID = 0L;
|
||||
|
||||
private AssignableFromPredicate(Class<?> clazz) {
|
||||
this.clazz = (Class)Preconditions.checkNotNull(clazz);
|
||||
}
|
||||
|
||||
public boolean apply(Class<?> input) {
|
||||
return this.clazz.isAssignableFrom(input);
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
return this.clazz.hashCode();
|
||||
}
|
||||
|
||||
public boolean equals(@Nullable Object obj) {
|
||||
if (obj instanceof Predicates.AssignableFromPredicate) {
|
||||
Predicates.AssignableFromPredicate that = (Predicates.AssignableFromPredicate)obj;
|
||||
return this.clazz == that.clazz;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
String var1 = String.valueOf(String.valueOf(this.clazz.getName()));
|
||||
return (new StringBuilder(27 + var1.length())).append("Predicates.assignableFrom(").append(var1).append(")").toString();
|
||||
}
|
||||
|
||||
// $FF: synthetic method
|
||||
AssignableFromPredicate(Class x0, Object x1) {
|
||||
this(x0);
|
||||
}
|
||||
}
|
||||
|
||||
@GwtIncompatible("Class.isInstance")
|
||||
private static class InstanceOfPredicate implements Predicate<Object>, Serializable {
|
||||
private final Class<?> clazz;
|
||||
private static final long serialVersionUID = 0L;
|
||||
|
||||
private InstanceOfPredicate(Class<?> clazz) {
|
||||
this.clazz = (Class)Preconditions.checkNotNull(clazz);
|
||||
}
|
||||
|
||||
public boolean apply(@Nullable Object o) {
|
||||
return this.clazz.isInstance(o);
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
return this.clazz.hashCode();
|
||||
}
|
||||
|
||||
public boolean equals(@Nullable Object obj) {
|
||||
if (obj instanceof Predicates.InstanceOfPredicate) {
|
||||
Predicates.InstanceOfPredicate that = (Predicates.InstanceOfPredicate)obj;
|
||||
return this.clazz == that.clazz;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
String var1 = String.valueOf(String.valueOf(this.clazz.getName()));
|
||||
return (new StringBuilder(23 + var1.length())).append("Predicates.instanceOf(").append(var1).append(")").toString();
|
||||
}
|
||||
|
||||
// $FF: synthetic method
|
||||
InstanceOfPredicate(Class x0, Object x1) {
|
||||
this(x0);
|
||||
}
|
||||
}
|
||||
|
||||
private static class IsEqualToPredicate<T> implements Predicate<T>, Serializable {
|
||||
private final T target;
|
||||
private static final long serialVersionUID = 0L;
|
||||
|
||||
private IsEqualToPredicate(T target) {
|
||||
this.target = target;
|
||||
}
|
||||
|
||||
public boolean apply(T t) {
|
||||
return this.target.equals(t);
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
return this.target.hashCode();
|
||||
}
|
||||
|
||||
public boolean equals(@Nullable Object obj) {
|
||||
if (obj instanceof Predicates.IsEqualToPredicate) {
|
||||
Predicates.IsEqualToPredicate<?> that = (Predicates.IsEqualToPredicate)obj;
|
||||
return this.target.equals(that.target);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
String var1 = String.valueOf(String.valueOf(this.target));
|
||||
return (new StringBuilder(20 + var1.length())).append("Predicates.equalTo(").append(var1).append(")").toString();
|
||||
}
|
||||
|
||||
// $FF: synthetic method
|
||||
IsEqualToPredicate(Object x0, Object x1) {
|
||||
this(x0);
|
||||
}
|
||||
}
|
||||
|
||||
private static class OrPredicate<T> implements Predicate<T>, Serializable {
|
||||
private final List<? extends Predicate<? super T>> components;
|
||||
private static final long serialVersionUID = 0L;
|
||||
|
||||
private OrPredicate(List<? extends Predicate<? super T>> components) {
|
||||
this.components = components;
|
||||
}
|
||||
|
||||
public boolean apply(@Nullable T t) {
|
||||
for(int i = 0; i < this.components.size(); ++i) {
|
||||
if (((Predicate)this.components.get(i)).apply(t)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
return this.components.hashCode() + 87855567;
|
||||
}
|
||||
|
||||
public boolean equals(@Nullable Object obj) {
|
||||
if (obj instanceof Predicates.OrPredicate) {
|
||||
Predicates.OrPredicate<?> that = (Predicates.OrPredicate)obj;
|
||||
return this.components.equals(that.components);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
String var1 = String.valueOf(String.valueOf(Predicates.COMMA_JOINER.join((Iterable)this.components)));
|
||||
return (new StringBuilder(15 + var1.length())).append("Predicates.or(").append(var1).append(")").toString();
|
||||
}
|
||||
|
||||
// $FF: synthetic method
|
||||
OrPredicate(List x0, Object x1) {
|
||||
this(x0);
|
||||
}
|
||||
}
|
||||
|
||||
private static class AndPredicate<T> implements Predicate<T>, Serializable {
|
||||
private final List<? extends Predicate<? super T>> components;
|
||||
private static final long serialVersionUID = 0L;
|
||||
|
||||
private AndPredicate(List<? extends Predicate<? super T>> components) {
|
||||
this.components = components;
|
||||
}
|
||||
|
||||
public boolean apply(@Nullable T t) {
|
||||
for(int i = 0; i < this.components.size(); ++i) {
|
||||
if (!((Predicate)this.components.get(i)).apply(t)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
return this.components.hashCode() + 306654252;
|
||||
}
|
||||
|
||||
public boolean equals(@Nullable Object obj) {
|
||||
if (obj instanceof Predicates.AndPredicate) {
|
||||
Predicates.AndPredicate<?> that = (Predicates.AndPredicate)obj;
|
||||
return this.components.equals(that.components);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
String var1 = String.valueOf(String.valueOf(Predicates.COMMA_JOINER.join((Iterable)this.components)));
|
||||
return (new StringBuilder(16 + var1.length())).append("Predicates.and(").append(var1).append(")").toString();
|
||||
}
|
||||
|
||||
// $FF: synthetic method
|
||||
AndPredicate(List x0, Object x1) {
|
||||
this(x0);
|
||||
}
|
||||
}
|
||||
|
||||
private static class NotPredicate<T> implements Predicate<T>, Serializable {
|
||||
final Predicate<T> predicate;
|
||||
private static final long serialVersionUID = 0L;
|
||||
|
||||
NotPredicate(Predicate<T> predicate) {
|
||||
this.predicate = (Predicate)Preconditions.checkNotNull(predicate);
|
||||
}
|
||||
|
||||
public boolean apply(@Nullable T t) {
|
||||
return !this.predicate.apply(t);
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
return ~this.predicate.hashCode();
|
||||
}
|
||||
|
||||
public boolean equals(@Nullable Object obj) {
|
||||
if (obj instanceof Predicates.NotPredicate) {
|
||||
Predicates.NotPredicate<?> that = (Predicates.NotPredicate)obj;
|
||||
return this.predicate.equals(that.predicate);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
String var1 = String.valueOf(String.valueOf(this.predicate.toString()));
|
||||
return (new StringBuilder(16 + var1.length())).append("Predicates.not(").append(var1).append(")").toString();
|
||||
}
|
||||
}
|
||||
|
||||
static enum ObjectPredicate implements Predicate<Object> {
|
||||
ALWAYS_TRUE {
|
||||
public boolean apply(@Nullable Object o) {
|
||||
return true;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return "Predicates.alwaysTrue()";
|
||||
}
|
||||
},
|
||||
ALWAYS_FALSE {
|
||||
public boolean apply(@Nullable Object o) {
|
||||
return false;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return "Predicates.alwaysFalse()";
|
||||
}
|
||||
},
|
||||
IS_NULL {
|
||||
public boolean apply(@Nullable Object o) {
|
||||
return o == null;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return "Predicates.isNull()";
|
||||
}
|
||||
},
|
||||
NOT_NULL {
|
||||
public boolean apply(@Nullable Object o) {
|
||||
return o != null;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return "Predicates.notNull()";
|
||||
}
|
||||
};
|
||||
|
||||
private ObjectPredicate() {
|
||||
}
|
||||
|
||||
<T> Predicate<T> withNarrowedType() {
|
||||
return this;
|
||||
}
|
||||
|
||||
// $FF: synthetic method
|
||||
ObjectPredicate(Object x2) {
|
||||
this();
|
||||
}
|
||||
}
|
||||
}
|
69
src/main/com/google/common/base/Present.java
Normal file
69
src/main/com/google/common/base/Present.java
Normal file
|
@ -0,0 +1,69 @@
|
|||
package com.google.common.base;
|
||||
|
||||
import com.google.common.annotations.GwtCompatible;
|
||||
import java.util.Collections;
|
||||
import java.util.Set;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
@GwtCompatible
|
||||
final class Present<T> extends Optional<T> {
|
||||
private final T reference;
|
||||
private static final long serialVersionUID = 0L;
|
||||
|
||||
Present(T reference) {
|
||||
this.reference = reference;
|
||||
}
|
||||
|
||||
public boolean isPresent() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public T get() {
|
||||
return this.reference;
|
||||
}
|
||||
|
||||
public T or(T defaultValue) {
|
||||
Preconditions.checkNotNull(defaultValue, "use Optional.orNull() instead of Optional.or(null)");
|
||||
return this.reference;
|
||||
}
|
||||
|
||||
public Optional<T> or(Optional<? extends T> secondChoice) {
|
||||
Preconditions.checkNotNull(secondChoice);
|
||||
return this;
|
||||
}
|
||||
|
||||
public T or(Supplier<? extends T> supplier) {
|
||||
Preconditions.checkNotNull(supplier);
|
||||
return this.reference;
|
||||
}
|
||||
|
||||
public T orNull() {
|
||||
return this.reference;
|
||||
}
|
||||
|
||||
public Set<T> asSet() {
|
||||
return Collections.singleton(this.reference);
|
||||
}
|
||||
|
||||
public <V> Optional<V> transform(Function<? super T, V> function) {
|
||||
return new Present(Preconditions.checkNotNull(function.apply(this.reference), "the Function passed to Optional.transform() must not return null."));
|
||||
}
|
||||
|
||||
public boolean equals(@Nullable Object object) {
|
||||
if (object instanceof Present) {
|
||||
Present<?> other = (Present)object;
|
||||
return this.reference.equals(other.reference);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
return 1502476572 + this.reference.hashCode();
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
String var1 = String.valueOf(String.valueOf(this.reference));
|
||||
return (new StringBuilder(13 + var1.length())).append("Optional.of(").append(var1).append(")").toString();
|
||||
}
|
||||
}
|
106
src/main/com/google/common/base/SmallCharMatcher.java
Normal file
106
src/main/com/google/common/base/SmallCharMatcher.java
Normal file
|
@ -0,0 +1,106 @@
|
|||
package com.google.common.base;
|
||||
|
||||
import com.google.common.annotations.GwtIncompatible;
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import java.util.BitSet;
|
||||
|
||||
@GwtIncompatible("no precomputation is done in GWT")
|
||||
final class SmallCharMatcher extends CharMatcher.FastMatcher {
|
||||
static final int MAX_SIZE = 1023;
|
||||
private final char[] table;
|
||||
private final boolean containsZero;
|
||||
private final long filter;
|
||||
private static final int C1 = -862048943;
|
||||
private static final int C2 = 461845907;
|
||||
private static final double DESIRED_LOAD_FACTOR = 0.5D;
|
||||
|
||||
private SmallCharMatcher(char[] table, long filter, boolean containsZero, String description) {
|
||||
super(description);
|
||||
this.table = table;
|
||||
this.filter = filter;
|
||||
this.containsZero = containsZero;
|
||||
}
|
||||
|
||||
static int smear(int hashCode) {
|
||||
return 461845907 * Integer.rotateLeft(hashCode * -862048943, 15);
|
||||
}
|
||||
|
||||
private boolean checkFilter(int c) {
|
||||
return 1L == (1L & this.filter >> c);
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
static int chooseTableSize(int setSize) {
|
||||
if (setSize == 1) {
|
||||
return 2;
|
||||
} else {
|
||||
int tableSize;
|
||||
for(tableSize = Integer.highestOneBit(setSize - 1) << 1; (double)tableSize * 0.5D < (double)setSize; tableSize <<= 1) {
|
||||
}
|
||||
|
||||
return tableSize;
|
||||
}
|
||||
}
|
||||
|
||||
static CharMatcher from(BitSet chars, String description) {
|
||||
long filter = 0L;
|
||||
int size = chars.cardinality();
|
||||
boolean containsZero = chars.get(0);
|
||||
char[] table = new char[chooseTableSize(size)];
|
||||
int mask = table.length - 1;
|
||||
|
||||
for(int c = chars.nextSetBit(0); c != -1; c = chars.nextSetBit(c + 1)) {
|
||||
filter |= 1L << c;
|
||||
|
||||
int index;
|
||||
for(index = smear(c) & mask; table[index] != 0; index = index + 1 & mask) {
|
||||
}
|
||||
|
||||
table[index] = (char)c;
|
||||
}
|
||||
|
||||
return new SmallCharMatcher(table, filter, containsZero, description);
|
||||
}
|
||||
|
||||
public boolean matches(char c) {
|
||||
if (c == 0) {
|
||||
return this.containsZero;
|
||||
} else if (!this.checkFilter(c)) {
|
||||
return false;
|
||||
} else {
|
||||
int mask = this.table.length - 1;
|
||||
int startingIndex = smear(c) & mask;
|
||||
int index = startingIndex;
|
||||
|
||||
while(this.table[index] != 0) {
|
||||
if (this.table[index] == c) {
|
||||
return true;
|
||||
}
|
||||
|
||||
index = index + 1 & mask;
|
||||
if (index == startingIndex) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void setBits(BitSet table) {
|
||||
if (this.containsZero) {
|
||||
table.set(0);
|
||||
}
|
||||
|
||||
char[] arr$ = this.table;
|
||||
int len$ = arr$.length;
|
||||
|
||||
for(int i$ = 0; i$ < len$; ++i$) {
|
||||
char c = arr$[i$];
|
||||
if (c != 0) {
|
||||
table.set(c);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
310
src/main/com/google/common/base/Splitter.java
Normal file
310
src/main/com/google/common/base/Splitter.java
Normal file
|
@ -0,0 +1,310 @@
|
|||
package com.google.common.base;
|
||||
|
||||
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;
|
||||
|
||||
@GwtCompatible(
|
||||
emulated = true
|
||||
)
|
||||
public final class Splitter {
|
||||
private final CharMatcher trimmer;
|
||||
private final boolean omitEmptyStrings;
|
||||
private final Splitter.Strategy strategy;
|
||||
private final int limit;
|
||||
|
||||
private Splitter(Splitter.Strategy strategy) {
|
||||
this(strategy, false, CharMatcher.NONE, Integer.MAX_VALUE);
|
||||
}
|
||||
|
||||
private Splitter(Splitter.Strategy strategy, boolean omitEmptyStrings, CharMatcher trimmer, int limit) {
|
||||
this.strategy = strategy;
|
||||
this.omitEmptyStrings = omitEmptyStrings;
|
||||
this.trimmer = trimmer;
|
||||
this.limit = limit;
|
||||
}
|
||||
|
||||
public static Splitter on(char separator) {
|
||||
return on(CharMatcher.is(separator));
|
||||
}
|
||||
|
||||
public static Splitter on(final CharMatcher separatorMatcher) {
|
||||
Preconditions.checkNotNull(separatorMatcher);
|
||||
return new Splitter(new Splitter.Strategy() {
|
||||
public Splitter.SplittingIterator iterator(Splitter splitter, CharSequence toSplit) {
|
||||
return new Splitter.SplittingIterator(splitter, toSplit) {
|
||||
int separatorStart(int start) {
|
||||
return separatorMatcher.indexIn(this.toSplit, start);
|
||||
}
|
||||
|
||||
int separatorEnd(int separatorPosition) {
|
||||
return separatorPosition + 1;
|
||||
}
|
||||
};
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static Splitter on(final String separator) {
|
||||
Preconditions.checkArgument(separator.length() != 0, "The separator may not be the empty string.");
|
||||
return new Splitter(new Splitter.Strategy() {
|
||||
public Splitter.SplittingIterator iterator(Splitter splitter, CharSequence toSplit) {
|
||||
return new Splitter.SplittingIterator(splitter, toSplit) {
|
||||
public int separatorStart(int start) {
|
||||
int separatorLength = separator.length();
|
||||
int p = start;
|
||||
|
||||
label24:
|
||||
for(int last = this.toSplit.length() - separatorLength; p <= last; ++p) {
|
||||
for(int i = 0; i < separatorLength; ++i) {
|
||||
if (this.toSplit.charAt(i + p) != separator.charAt(i)) {
|
||||
continue label24;
|
||||
}
|
||||
}
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
public int separatorEnd(int separatorPosition) {
|
||||
return separatorPosition + separator.length();
|
||||
}
|
||||
};
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@GwtIncompatible("java.util.regex")
|
||||
public static Splitter on(final Pattern separatorPattern) {
|
||||
Preconditions.checkNotNull(separatorPattern);
|
||||
Preconditions.checkArgument(!separatorPattern.matcher("").matches(), "The pattern may not match the empty string: %s", separatorPattern);
|
||||
return new Splitter(new Splitter.Strategy() {
|
||||
public Splitter.SplittingIterator iterator(Splitter splitter, CharSequence toSplit) {
|
||||
final Matcher matcher = separatorPattern.matcher(toSplit);
|
||||
return new Splitter.SplittingIterator(splitter, toSplit) {
|
||||
public int separatorStart(int start) {
|
||||
return matcher.find(start) ? matcher.start() : -1;
|
||||
}
|
||||
|
||||
public int separatorEnd(int separatorPosition) {
|
||||
return matcher.end();
|
||||
}
|
||||
};
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@GwtIncompatible("java.util.regex")
|
||||
public static Splitter onPattern(String separatorPattern) {
|
||||
return on(Pattern.compile(separatorPattern));
|
||||
}
|
||||
|
||||
public static Splitter fixedLength(final int length) {
|
||||
Preconditions.checkArgument(length > 0, "The length may not be less than 1");
|
||||
return new Splitter(new Splitter.Strategy() {
|
||||
public Splitter.SplittingIterator iterator(Splitter splitter, CharSequence toSplit) {
|
||||
return new Splitter.SplittingIterator(splitter, toSplit) {
|
||||
public int separatorStart(int start) {
|
||||
int nextChunkStart = start + length;
|
||||
return nextChunkStart < this.toSplit.length() ? nextChunkStart : -1;
|
||||
}
|
||||
|
||||
public int separatorEnd(int separatorPosition) {
|
||||
return separatorPosition;
|
||||
}
|
||||
};
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@CheckReturnValue
|
||||
public Splitter omitEmptyStrings() {
|
||||
return new Splitter(this.strategy, true, this.trimmer, this.limit);
|
||||
}
|
||||
|
||||
@CheckReturnValue
|
||||
public Splitter limit(int limit) {
|
||||
Preconditions.checkArgument(limit > 0, "must be greater than zero: %s", limit);
|
||||
return new Splitter(this.strategy, this.omitEmptyStrings, this.trimmer, limit);
|
||||
}
|
||||
|
||||
@CheckReturnValue
|
||||
public Splitter trimResults() {
|
||||
return this.trimResults(CharMatcher.WHITESPACE);
|
||||
}
|
||||
|
||||
@CheckReturnValue
|
||||
public Splitter trimResults(CharMatcher trimmer) {
|
||||
Preconditions.checkNotNull(trimmer);
|
||||
return new Splitter(this.strategy, this.omitEmptyStrings, trimmer, this.limit);
|
||||
}
|
||||
|
||||
public Iterable<String> split(final CharSequence sequence) {
|
||||
Preconditions.checkNotNull(sequence);
|
||||
return new Iterable<String>() {
|
||||
public Iterator<String> iterator() {
|
||||
return Splitter.this.splittingIterator(sequence);
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return Joiner.on(", ").appendTo((StringBuilder)(new StringBuilder()).append('['), (Iterable)this).append(']').toString();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private Iterator<String> splittingIterator(CharSequence sequence) {
|
||||
return this.strategy.iterator(this, sequence);
|
||||
}
|
||||
|
||||
@Beta
|
||||
public List<String> splitToList(CharSequence sequence) {
|
||||
Preconditions.checkNotNull(sequence);
|
||||
Iterator<String> iterator = this.splittingIterator(sequence);
|
||||
ArrayList result = new ArrayList();
|
||||
|
||||
while(iterator.hasNext()) {
|
||||
result.add(iterator.next());
|
||||
}
|
||||
|
||||
return Collections.unmodifiableList(result);
|
||||
}
|
||||
|
||||
@CheckReturnValue
|
||||
@Beta
|
||||
public Splitter.MapSplitter withKeyValueSeparator(String separator) {
|
||||
return this.withKeyValueSeparator(on(separator));
|
||||
}
|
||||
|
||||
@CheckReturnValue
|
||||
@Beta
|
||||
public Splitter.MapSplitter withKeyValueSeparator(char separator) {
|
||||
return this.withKeyValueSeparator(on(separator));
|
||||
}
|
||||
|
||||
@CheckReturnValue
|
||||
@Beta
|
||||
public Splitter.MapSplitter withKeyValueSeparator(Splitter keyValueSplitter) {
|
||||
return new Splitter.MapSplitter(this, keyValueSplitter);
|
||||
}
|
||||
|
||||
private abstract static class SplittingIterator extends AbstractIterator<String> {
|
||||
final CharSequence toSplit;
|
||||
final CharMatcher trimmer;
|
||||
final boolean omitEmptyStrings;
|
||||
int offset = 0;
|
||||
int limit;
|
||||
|
||||
abstract int separatorStart(int var1);
|
||||
|
||||
abstract int separatorEnd(int var1);
|
||||
|
||||
protected SplittingIterator(Splitter splitter, CharSequence toSplit) {
|
||||
this.trimmer = splitter.trimmer;
|
||||
this.omitEmptyStrings = splitter.omitEmptyStrings;
|
||||
this.limit = splitter.limit;
|
||||
this.toSplit = toSplit;
|
||||
}
|
||||
|
||||
protected String computeNext() {
|
||||
int nextStart = this.offset;
|
||||
|
||||
while(true) {
|
||||
while(this.offset != -1) {
|
||||
int start = nextStart;
|
||||
int separatorPosition = this.separatorStart(this.offset);
|
||||
int end;
|
||||
if (separatorPosition == -1) {
|
||||
end = this.toSplit.length();
|
||||
this.offset = -1;
|
||||
} else {
|
||||
end = separatorPosition;
|
||||
this.offset = this.separatorEnd(separatorPosition);
|
||||
}
|
||||
|
||||
if (this.offset != nextStart) {
|
||||
while(start < end && this.trimmer.matches(this.toSplit.charAt(start))) {
|
||||
++start;
|
||||
}
|
||||
|
||||
while(end > start && this.trimmer.matches(this.toSplit.charAt(end - 1))) {
|
||||
--end;
|
||||
}
|
||||
|
||||
if (!this.omitEmptyStrings || start != end) {
|
||||
if (this.limit == 1) {
|
||||
end = this.toSplit.length();
|
||||
|
||||
for(this.offset = -1; end > start && this.trimmer.matches(this.toSplit.charAt(end - 1)); --end) {
|
||||
}
|
||||
} else {
|
||||
--this.limit;
|
||||
}
|
||||
|
||||
return this.toSplit.subSequence(start, end).toString();
|
||||
}
|
||||
|
||||
nextStart = this.offset;
|
||||
} else {
|
||||
++this.offset;
|
||||
if (this.offset >= this.toSplit.length()) {
|
||||
this.offset = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return (String)this.endOfData();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private interface Strategy {
|
||||
Iterator<String> iterator(Splitter var1, CharSequence var2);
|
||||
}
|
||||
|
||||
@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;
|
||||
this.entrySplitter = (Splitter)Preconditions.checkNotNull(entrySplitter);
|
||||
}
|
||||
|
||||
public Map<String, String> split(CharSequence sequence) {
|
||||
Map<String, String> map = new LinkedHashMap();
|
||||
Iterator i$ = this.outerSplitter.split(sequence).iterator();
|
||||
|
||||
while(i$.hasNext()) {
|
||||
String entry = (String)i$.next();
|
||||
Iterator<String> entryFields = this.entrySplitter.splittingIterator(entry);
|
||||
Preconditions.checkArgument(entryFields.hasNext(), "Chunk [%s] is not a valid entry", entry);
|
||||
String key = (String)entryFields.next();
|
||||
Preconditions.checkArgument(!map.containsKey(key), "Duplicate key [%s] found.", key);
|
||||
Preconditions.checkArgument(entryFields.hasNext(), "Chunk [%s] is not a valid entry", entry);
|
||||
String value = (String)entryFields.next();
|
||||
map.put(key, value);
|
||||
Preconditions.checkArgument(!entryFields.hasNext(), "Chunk [%s] is not a valid entry", entry);
|
||||
}
|
||||
|
||||
return Collections.unmodifiableMap(map);
|
||||
}
|
||||
|
||||
// $FF: synthetic method
|
||||
MapSplitter(Splitter x0, Splitter x1, Object x2) {
|
||||
this(x0, x1);
|
||||
}
|
||||
}
|
||||
}
|
59
src/main/com/google/common/base/StandardSystemProperty.java
Normal file
59
src/main/com/google/common/base/StandardSystemProperty.java
Normal file
|
@ -0,0 +1,59 @@
|
|||
package com.google.common.base;
|
||||
|
||||
import com.google.common.annotations.Beta;
|
||||
import com.google.common.annotations.GwtIncompatible;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
@Beta
|
||||
@GwtIncompatible("java.lang.System#getProperty")
|
||||
public enum StandardSystemProperty {
|
||||
JAVA_VERSION("java.version"),
|
||||
JAVA_VENDOR("java.vendor"),
|
||||
JAVA_VENDOR_URL("java.vendor.url"),
|
||||
JAVA_HOME("java.home"),
|
||||
JAVA_VM_SPECIFICATION_VERSION("java.vm.specification.version"),
|
||||
JAVA_VM_SPECIFICATION_VENDOR("java.vm.specification.vendor"),
|
||||
JAVA_VM_SPECIFICATION_NAME("java.vm.specification.name"),
|
||||
JAVA_VM_VERSION("java.vm.version"),
|
||||
JAVA_VM_VENDOR("java.vm.vendor"),
|
||||
JAVA_VM_NAME("java.vm.name"),
|
||||
JAVA_SPECIFICATION_VERSION("java.specification.version"),
|
||||
JAVA_SPECIFICATION_VENDOR("java.specification.vendor"),
|
||||
JAVA_SPECIFICATION_NAME("java.specification.name"),
|
||||
JAVA_CLASS_VERSION("java.class.version"),
|
||||
JAVA_CLASS_PATH("java.class.path"),
|
||||
JAVA_LIBRARY_PATH("java.library.path"),
|
||||
JAVA_IO_TMPDIR("java.io.tmpdir"),
|
||||
JAVA_COMPILER("java.compiler"),
|
||||
JAVA_EXT_DIRS("java.ext.dirs"),
|
||||
OS_NAME("os.name"),
|
||||
OS_ARCH("os.arch"),
|
||||
OS_VERSION("os.version"),
|
||||
FILE_SEPARATOR("file.separator"),
|
||||
PATH_SEPARATOR("path.separator"),
|
||||
LINE_SEPARATOR("line.separator"),
|
||||
USER_NAME("user.name"),
|
||||
USER_HOME("user.home"),
|
||||
USER_DIR("user.dir");
|
||||
|
||||
private final String key;
|
||||
|
||||
private StandardSystemProperty(String key) {
|
||||
this.key = key;
|
||||
}
|
||||
|
||||
public String key() {
|
||||
return this.key;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public String value() {
|
||||
return System.getProperty(this.key);
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
String var1 = String.valueOf(String.valueOf(this.key()));
|
||||
String var2 = String.valueOf(String.valueOf(this.value()));
|
||||
return (new StringBuilder(1 + var1.length() + var2.length())).append(var1).append("=").append(var2).toString();
|
||||
}
|
||||
}
|
123
src/main/com/google/common/base/Stopwatch.java
Normal file
123
src/main/com/google/common/base/Stopwatch.java
Normal file
|
@ -0,0 +1,123 @@
|
|||
package com.google.common.base;
|
||||
|
||||
import com.google.common.annotations.Beta;
|
||||
import com.google.common.annotations.GwtCompatible;
|
||||
import com.google.common.annotations.GwtIncompatible;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
@Beta
|
||||
@GwtCompatible(
|
||||
emulated = true
|
||||
)
|
||||
public final class Stopwatch {
|
||||
private final Ticker ticker;
|
||||
private boolean isRunning;
|
||||
private long elapsedNanos;
|
||||
private long startTick;
|
||||
|
||||
public static Stopwatch createUnstarted() {
|
||||
return new Stopwatch();
|
||||
}
|
||||
|
||||
public static Stopwatch createUnstarted(Ticker ticker) {
|
||||
return new Stopwatch(ticker);
|
||||
}
|
||||
|
||||
public static Stopwatch createStarted() {
|
||||
return (new Stopwatch()).start();
|
||||
}
|
||||
|
||||
public static Stopwatch createStarted(Ticker ticker) {
|
||||
return (new Stopwatch(ticker)).start();
|
||||
}
|
||||
|
||||
/** @deprecated */
|
||||
@Deprecated
|
||||
Stopwatch() {
|
||||
this(Ticker.systemTicker());
|
||||
}
|
||||
|
||||
/** @deprecated */
|
||||
@Deprecated
|
||||
Stopwatch(Ticker ticker) {
|
||||
this.ticker = (Ticker)Preconditions.checkNotNull(ticker, "ticker");
|
||||
}
|
||||
|
||||
public boolean isRunning() {
|
||||
return this.isRunning;
|
||||
}
|
||||
|
||||
public Stopwatch start() {
|
||||
Preconditions.checkState(!this.isRunning, "This stopwatch is already running.");
|
||||
this.isRunning = true;
|
||||
this.startTick = this.ticker.read();
|
||||
return this;
|
||||
}
|
||||
|
||||
public Stopwatch stop() {
|
||||
long tick = this.ticker.read();
|
||||
Preconditions.checkState(this.isRunning, "This stopwatch is already stopped.");
|
||||
this.isRunning = false;
|
||||
this.elapsedNanos += tick - this.startTick;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Stopwatch reset() {
|
||||
this.elapsedNanos = 0L;
|
||||
this.isRunning = false;
|
||||
return this;
|
||||
}
|
||||
|
||||
private long elapsedNanos() {
|
||||
return this.isRunning ? this.ticker.read() - this.startTick + this.elapsedNanos : this.elapsedNanos;
|
||||
}
|
||||
|
||||
public long elapsed(TimeUnit desiredUnit) {
|
||||
return desiredUnit.convert(this.elapsedNanos(), TimeUnit.NANOSECONDS);
|
||||
}
|
||||
|
||||
@GwtIncompatible("String.format()")
|
||||
public String toString() {
|
||||
long nanos = this.elapsedNanos();
|
||||
TimeUnit unit = chooseUnit(nanos);
|
||||
double value = (double)nanos / (double)TimeUnit.NANOSECONDS.convert(1L, unit);
|
||||
return String.format("%.4g %s", value, abbreviate(unit));
|
||||
}
|
||||
|
||||
private static TimeUnit chooseUnit(long nanos) {
|
||||
if (TimeUnit.DAYS.convert(nanos, TimeUnit.NANOSECONDS) > 0L) {
|
||||
return TimeUnit.DAYS;
|
||||
} else if (TimeUnit.HOURS.convert(nanos, TimeUnit.NANOSECONDS) > 0L) {
|
||||
return TimeUnit.HOURS;
|
||||
} else if (TimeUnit.MINUTES.convert(nanos, TimeUnit.NANOSECONDS) > 0L) {
|
||||
return TimeUnit.MINUTES;
|
||||
} else if (TimeUnit.SECONDS.convert(nanos, TimeUnit.NANOSECONDS) > 0L) {
|
||||
return TimeUnit.SECONDS;
|
||||
} else if (TimeUnit.MILLISECONDS.convert(nanos, TimeUnit.NANOSECONDS) > 0L) {
|
||||
return TimeUnit.MILLISECONDS;
|
||||
} else {
|
||||
return TimeUnit.MICROSECONDS.convert(nanos, TimeUnit.NANOSECONDS) > 0L ? TimeUnit.MICROSECONDS : TimeUnit.NANOSECONDS;
|
||||
}
|
||||
}
|
||||
|
||||
private static String abbreviate(TimeUnit unit) {
|
||||
switch(unit) {
|
||||
case NANOSECONDS:
|
||||
return "ns";
|
||||
case MICROSECONDS:
|
||||
return "μ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();
|
||||
}
|
||||
}
|
||||
}
|
119
src/main/com/google/common/base/Strings.java
Normal file
119
src/main/com/google/common/base/Strings.java
Normal file
|
@ -0,0 +1,119 @@
|
|||
package com.google.common.base;
|
||||
|
||||
import com.google.common.annotations.GwtCompatible;
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
@GwtCompatible
|
||||
public final class Strings {
|
||||
private Strings() {
|
||||
}
|
||||
|
||||
public static String nullToEmpty(@Nullable String string) {
|
||||
return string == null ? "" : string;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static String emptyToNull(@Nullable String string) {
|
||||
return isNullOrEmpty(string) ? null : string;
|
||||
}
|
||||
|
||||
public static boolean isNullOrEmpty(@Nullable String string) {
|
||||
return string == null || string.length() == 0;
|
||||
}
|
||||
|
||||
public static String padStart(String string, int minLength, char padChar) {
|
||||
Preconditions.checkNotNull(string);
|
||||
if (string.length() >= minLength) {
|
||||
return string;
|
||||
} else {
|
||||
StringBuilder sb = new StringBuilder(minLength);
|
||||
|
||||
for(int i = string.length(); i < minLength; ++i) {
|
||||
sb.append(padChar);
|
||||
}
|
||||
|
||||
sb.append(string);
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
|
||||
public static String padEnd(String string, int minLength, char padChar) {
|
||||
Preconditions.checkNotNull(string);
|
||||
if (string.length() >= minLength) {
|
||||
return string;
|
||||
} else {
|
||||
StringBuilder sb = new StringBuilder(minLength);
|
||||
sb.append(string);
|
||||
|
||||
for(int i = string.length(); i < minLength; ++i) {
|
||||
sb.append(padChar);
|
||||
}
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
|
||||
public static String repeat(String string, int count) {
|
||||
Preconditions.checkNotNull(string);
|
||||
if (count <= 1) {
|
||||
Preconditions.checkArgument(count >= 0, "invalid count: %s", count);
|
||||
return count == 0 ? "" : string;
|
||||
} else {
|
||||
int len = string.length();
|
||||
long longSize = (long)len * (long)count;
|
||||
int size = (int)longSize;
|
||||
if ((long)size != longSize) {
|
||||
throw new ArrayIndexOutOfBoundsException((new StringBuilder(51)).append("Required array size too large: ").append(longSize).toString());
|
||||
} else {
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static String commonPrefix(CharSequence a, CharSequence b) {
|
||||
Preconditions.checkNotNull(a);
|
||||
Preconditions.checkNotNull(b);
|
||||
int maxPrefixLength = Math.min(a.length(), b.length());
|
||||
|
||||
int p;
|
||||
for(p = 0; 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();
|
||||
}
|
||||
|
||||
public static String commonSuffix(CharSequence a, CharSequence b) {
|
||||
Preconditions.checkNotNull(a);
|
||||
Preconditions.checkNotNull(b);
|
||||
int maxSuffixLength = Math.min(a.length(), b.length());
|
||||
|
||||
int s;
|
||||
for(s = 0; 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();
|
||||
}
|
||||
|
||||
@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));
|
||||
}
|
||||
}
|
8
src/main/com/google/common/base/Supplier.java
Normal file
8
src/main/com/google/common/base/Supplier.java
Normal file
|
@ -0,0 +1,8 @@
|
|||
package com.google.common.base;
|
||||
|
||||
import com.google.common.annotations.GwtCompatible;
|
||||
|
||||
@GwtCompatible
|
||||
public interface Supplier<T> {
|
||||
T get();
|
||||
}
|
213
src/main/com/google/common/base/Suppliers.java
Normal file
213
src/main/com/google/common/base/Suppliers.java
Normal file
|
@ -0,0 +1,213 @@
|
|||
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.Nullable;
|
||||
|
||||
@GwtCompatible
|
||||
public final class Suppliers {
|
||||
private Suppliers() {
|
||||
}
|
||||
|
||||
public static <F, T> Supplier<T> compose(Function<? super F, T> function, Supplier<F> supplier) {
|
||||
Preconditions.checkNotNull(function);
|
||||
Preconditions.checkNotNull(supplier);
|
||||
return new Suppliers.SupplierComposition(function, supplier);
|
||||
}
|
||||
|
||||
public static <T> Supplier<T> memoize(Supplier<T> delegate) {
|
||||
return (Supplier)(delegate instanceof Suppliers.MemoizingSupplier ? delegate : new Suppliers.MemoizingSupplier((Supplier)Preconditions.checkNotNull(delegate)));
|
||||
}
|
||||
|
||||
public static <T> Supplier<T> memoizeWithExpiration(Supplier<T> delegate, long duration, TimeUnit unit) {
|
||||
return new Suppliers.ExpiringMemoizingSupplier(delegate, duration, unit);
|
||||
}
|
||||
|
||||
public static <T> Supplier<T> ofInstance(@Nullable T instance) {
|
||||
return new Suppliers.SupplierOfInstance(instance);
|
||||
}
|
||||
|
||||
public static <T> Supplier<T> synchronizedSupplier(Supplier<T> delegate) {
|
||||
return new Suppliers.ThreadSafeSupplier((Supplier)Preconditions.checkNotNull(delegate));
|
||||
}
|
||||
|
||||
@Beta
|
||||
public static <T> Function<Supplier<T>, T> supplierFunction() {
|
||||
Suppliers.SupplierFunction<T> sf = Suppliers.SupplierFunctionImpl.INSTANCE;
|
||||
return sf;
|
||||
}
|
||||
|
||||
private static enum SupplierFunctionImpl implements Suppliers.SupplierFunction<Object> {
|
||||
INSTANCE;
|
||||
|
||||
public Object apply(Supplier<Object> input) {
|
||||
return input.get();
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return "Suppliers.supplierFunction()";
|
||||
}
|
||||
}
|
||||
|
||||
private interface SupplierFunction<T> extends Function<Supplier<T>, T> {
|
||||
}
|
||||
|
||||
private static class ThreadSafeSupplier<T> implements Supplier<T>, Serializable {
|
||||
final Supplier<T> delegate;
|
||||
private static final long serialVersionUID = 0L;
|
||||
|
||||
ThreadSafeSupplier(Supplier<T> delegate) {
|
||||
this.delegate = delegate;
|
||||
}
|
||||
|
||||
public T get() {
|
||||
synchronized(this.delegate) {
|
||||
return this.delegate.get();
|
||||
}
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
String var1 = String.valueOf(String.valueOf(this.delegate));
|
||||
return (new StringBuilder(32 + var1.length())).append("Suppliers.synchronizedSupplier(").append(var1).append(")").toString();
|
||||
}
|
||||
}
|
||||
|
||||
private static class SupplierOfInstance<T> implements Supplier<T>, Serializable {
|
||||
final T instance;
|
||||
private static final long serialVersionUID = 0L;
|
||||
|
||||
SupplierOfInstance(@Nullable T instance) {
|
||||
this.instance = instance;
|
||||
}
|
||||
|
||||
public T get() {
|
||||
return this.instance;
|
||||
}
|
||||
|
||||
public boolean equals(@Nullable Object obj) {
|
||||
if (obj instanceof Suppliers.SupplierOfInstance) {
|
||||
Suppliers.SupplierOfInstance<?> that = (Suppliers.SupplierOfInstance)obj;
|
||||
return Objects.equal(this.instance, that.instance);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
return Objects.hashCode(this.instance);
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
String var1 = String.valueOf(String.valueOf(this.instance));
|
||||
return (new StringBuilder(22 + var1.length())).append("Suppliers.ofInstance(").append(var1).append(")").toString();
|
||||
}
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
static class ExpiringMemoizingSupplier<T> implements Supplier<T>, Serializable {
|
||||
final Supplier<T> delegate;
|
||||
final long durationNanos;
|
||||
transient volatile T value;
|
||||
transient volatile long expirationNanos;
|
||||
private static final long serialVersionUID = 0L;
|
||||
|
||||
ExpiringMemoizingSupplier(Supplier<T> delegate, long duration, TimeUnit unit) {
|
||||
this.delegate = (Supplier)Preconditions.checkNotNull(delegate);
|
||||
this.durationNanos = unit.toNanos(duration);
|
||||
Preconditions.checkArgument(duration > 0L);
|
||||
}
|
||||
|
||||
public T get() {
|
||||
long nanos = this.expirationNanos;
|
||||
long now = Platform.systemNanoTime();
|
||||
if (nanos == 0L || now - nanos >= 0L) {
|
||||
synchronized(this) {
|
||||
if (nanos == this.expirationNanos) {
|
||||
T t = this.delegate.get();
|
||||
this.value = t;
|
||||
nanos = now + this.durationNanos;
|
||||
this.expirationNanos = nanos == 0L ? 1L : nanos;
|
||||
return t;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return this.value;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
String var1 = String.valueOf(String.valueOf(this.delegate));
|
||||
long var2 = this.durationNanos;
|
||||
return (new StringBuilder(62 + var1.length())).append("Suppliers.memoizeWithExpiration(").append(var1).append(", ").append(var2).append(", NANOS)").toString();
|
||||
}
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
static class MemoizingSupplier<T> implements Supplier<T>, Serializable {
|
||||
final Supplier<T> delegate;
|
||||
transient volatile boolean initialized;
|
||||
transient T value;
|
||||
private static final long serialVersionUID = 0L;
|
||||
|
||||
MemoizingSupplier(Supplier<T> delegate) {
|
||||
this.delegate = delegate;
|
||||
}
|
||||
|
||||
public T get() {
|
||||
if (!this.initialized) {
|
||||
synchronized(this) {
|
||||
if (!this.initialized) {
|
||||
T t = this.delegate.get();
|
||||
this.value = t;
|
||||
this.initialized = true;
|
||||
return t;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return this.value;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
String var1 = String.valueOf(String.valueOf(this.delegate));
|
||||
return (new StringBuilder(19 + var1.length())).append("Suppliers.memoize(").append(var1).append(")").toString();
|
||||
}
|
||||
}
|
||||
|
||||
private static class SupplierComposition<F, T> implements Supplier<T>, Serializable {
|
||||
final Function<? super F, T> function;
|
||||
final Supplier<F> supplier;
|
||||
private static final long serialVersionUID = 0L;
|
||||
|
||||
SupplierComposition(Function<? super F, T> function, Supplier<F> supplier) {
|
||||
this.function = function;
|
||||
this.supplier = supplier;
|
||||
}
|
||||
|
||||
public T get() {
|
||||
return this.function.apply(this.supplier.get());
|
||||
}
|
||||
|
||||
public boolean equals(@Nullable Object obj) {
|
||||
if (!(obj instanceof Suppliers.SupplierComposition)) {
|
||||
return false;
|
||||
} else {
|
||||
Suppliers.SupplierComposition<?, ?> that = (Suppliers.SupplierComposition)obj;
|
||||
return this.function.equals(that.function) && this.supplier.equals(that.supplier);
|
||||
}
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
return Objects.hashCode(this.function, this.supplier);
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
String var1 = String.valueOf(String.valueOf(this.function));
|
||||
String var2 = String.valueOf(String.valueOf(this.supplier));
|
||||
return (new StringBuilder(21 + var1.length() + var2.length())).append("Suppliers.compose(").append(var1).append(", ").append(var2).append(")").toString();
|
||||
}
|
||||
}
|
||||
}
|
68
src/main/com/google/common/base/Throwables.java
Normal file
68
src/main/com/google/common/base/Throwables.java
Normal file
|
@ -0,0 +1,68 @@
|
|||
package com.google.common.base;
|
||||
|
||||
import com.google.common.annotations.Beta;
|
||||
import java.io.PrintWriter;
|
||||
import java.io.StringWriter;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
public final class Throwables {
|
||||
private Throwables() {
|
||||
}
|
||||
|
||||
public static <X extends Throwable> void propagateIfInstanceOf(@Nullable Throwable throwable, Class<X> declaredType) throws X {
|
||||
if (throwable != null && declaredType.isInstance(throwable)) {
|
||||
throw (Throwable)declaredType.cast(throwable);
|
||||
}
|
||||
}
|
||||
|
||||
public static void propagateIfPossible(@Nullable Throwable throwable) {
|
||||
propagateIfInstanceOf(throwable, Error.class);
|
||||
propagateIfInstanceOf(throwable, RuntimeException.class);
|
||||
}
|
||||
|
||||
public static <X extends Throwable> void propagateIfPossible(@Nullable Throwable throwable, Class<X> declaredType) throws X {
|
||||
propagateIfInstanceOf(throwable, declaredType);
|
||||
propagateIfPossible(throwable);
|
||||
}
|
||||
|
||||
public static <X1 extends Throwable, X2 extends Throwable> void propagateIfPossible(@Nullable Throwable throwable, Class<X1> declaredType1, Class<X2> declaredType2) throws X1, X2 {
|
||||
Preconditions.checkNotNull(declaredType2);
|
||||
propagateIfInstanceOf(throwable, declaredType1);
|
||||
propagateIfPossible(throwable, declaredType2);
|
||||
}
|
||||
|
||||
public static RuntimeException propagate(Throwable throwable) {
|
||||
propagateIfPossible((Throwable)Preconditions.checkNotNull(throwable));
|
||||
throw new RuntimeException(throwable);
|
||||
}
|
||||
|
||||
public static Throwable getRootCause(Throwable throwable) {
|
||||
Throwable cause;
|
||||
while((cause = throwable.getCause()) != null) {
|
||||
throwable = cause;
|
||||
}
|
||||
|
||||
return throwable;
|
||||
}
|
||||
|
||||
@Beta
|
||||
public static List<Throwable> getCausalChain(Throwable throwable) {
|
||||
Preconditions.checkNotNull(throwable);
|
||||
|
||||
ArrayList causes;
|
||||
for(causes = new ArrayList(4); throwable != null; throwable = throwable.getCause()) {
|
||||
causes.add(throwable);
|
||||
}
|
||||
|
||||
return Collections.unmodifiableList(causes);
|
||||
}
|
||||
|
||||
public static String getStackTraceAsString(Throwable throwable) {
|
||||
StringWriter stringWriter = new StringWriter();
|
||||
throwable.printStackTrace(new PrintWriter(stringWriter));
|
||||
return stringWriter.toString();
|
||||
}
|
||||
}
|
23
src/main/com/google/common/base/Ticker.java
Normal file
23
src/main/com/google/common/base/Ticker.java
Normal file
|
@ -0,0 +1,23 @@
|
|||
package com.google.common.base;
|
||||
|
||||
import com.google.common.annotations.Beta;
|
||||
import com.google.common.annotations.GwtCompatible;
|
||||
|
||||
@Beta
|
||||
@GwtCompatible
|
||||
public abstract class Ticker {
|
||||
private static final Ticker SYSTEM_TICKER = new Ticker() {
|
||||
public long read() {
|
||||
return Platform.systemNanoTime();
|
||||
}
|
||||
};
|
||||
|
||||
protected Ticker() {
|
||||
}
|
||||
|
||||
public abstract long read();
|
||||
|
||||
public static Ticker systemTicker() {
|
||||
return SYSTEM_TICKER;
|
||||
}
|
||||
}
|
123
src/main/com/google/common/base/Utf8.java
Normal file
123
src/main/com/google/common/base/Utf8.java
Normal file
|
@ -0,0 +1,123 @@
|
|||
package com.google.common.base;
|
||||
|
||||
import com.google.common.annotations.Beta;
|
||||
import com.google.common.annotations.GwtCompatible;
|
||||
|
||||
@Beta
|
||||
@GwtCompatible
|
||||
public final class Utf8 {
|
||||
public static int encodedLength(CharSequence sequence) {
|
||||
int utf16Length = sequence.length();
|
||||
int utf8Length = utf16Length;
|
||||
|
||||
int i;
|
||||
for(i = 0; i < utf16Length && sequence.charAt(i) < 128; ++i) {
|
||||
}
|
||||
|
||||
while(i < utf16Length) {
|
||||
char c = sequence.charAt(i);
|
||||
if (c >= 2048) {
|
||||
utf8Length += encodedLengthGeneral(sequence, i);
|
||||
break;
|
||||
}
|
||||
|
||||
utf8Length += 127 - c >>> 31;
|
||||
++i;
|
||||
}
|
||||
|
||||
if (utf8Length < utf16Length) {
|
||||
long var6 = (long)utf8Length + 4294967296L;
|
||||
throw new IllegalArgumentException((new StringBuilder(54)).append("UTF-8 length does not fit in int: ").append(var6).toString());
|
||||
} else {
|
||||
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 < 2048) {
|
||||
utf8Length += 127 - c >>> 31;
|
||||
} else {
|
||||
utf8Length += 2;
|
||||
if ('\ud800' <= c && c <= '\udfff') {
|
||||
int cp = Character.codePointAt(sequence, i);
|
||||
if (cp < 65536) {
|
||||
throw new IllegalArgumentException((new StringBuilder(39)).append("Unpaired surrogate at index ").append(i).toString());
|
||||
}
|
||||
|
||||
++i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return utf8Length;
|
||||
}
|
||||
|
||||
public static boolean isWellFormed(byte[] bytes) {
|
||||
return isWellFormed(bytes, 0, bytes.length);
|
||||
}
|
||||
|
||||
public static boolean isWellFormed(byte[] bytes, int off, int len) {
|
||||
int end = off + len;
|
||||
Preconditions.checkPositionIndexes(off, end, bytes.length);
|
||||
|
||||
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) {
|
||||
byte byte1;
|
||||
do {
|
||||
if (index >= end) {
|
||||
return true;
|
||||
}
|
||||
} while((byte1 = bytes[index++]) >= 0);
|
||||
|
||||
if (byte1 < -32) {
|
||||
if (index == end) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (byte1 < -62 || bytes[index++] > -65) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
byte byte2;
|
||||
if (byte1 < -16) {
|
||||
if (index + 1 >= end) {
|
||||
return false;
|
||||
}
|
||||
|
||||
byte2 = bytes[index++];
|
||||
if (byte2 > -65 || byte1 == -32 && byte2 < -96 || byte1 == -19 && -96 <= byte2 || bytes[index++] > -65) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
if (index + 2 >= end) {
|
||||
return false;
|
||||
}
|
||||
|
||||
byte2 = bytes[index++];
|
||||
if (byte2 > -65 || (byte1 << 28) + (byte2 - -112) >> 30 != 0 || bytes[index++] > -65 || bytes[index++] > -65) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private Utf8() {
|
||||
}
|
||||
}
|
33
src/main/com/google/common/base/Verify.java
Normal file
33
src/main/com/google/common/base/Verify.java
Normal file
|
@ -0,0 +1,33 @@
|
|||
package com.google.common.base;
|
||||
|
||||
import com.google.common.annotations.Beta;
|
||||
import com.google.common.annotations.GwtCompatible;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
@Beta
|
||||
@GwtCompatible
|
||||
public final class Verify {
|
||||
public static void verify(boolean expression) {
|
||||
if (!expression) {
|
||||
throw new VerifyException();
|
||||
}
|
||||
}
|
||||
|
||||
public static void verify(boolean expression, @Nullable String errorMessageTemplate, @Nullable Object... errorMessageArgs) {
|
||||
if (!expression) {
|
||||
throw new VerifyException(Preconditions.format(errorMessageTemplate, errorMessageArgs));
|
||||
}
|
||||
}
|
||||
|
||||
public static <T> T verifyNotNull(@Nullable T reference) {
|
||||
return verifyNotNull(reference, "expected a non-null reference");
|
||||
}
|
||||
|
||||
public static <T> T verifyNotNull(@Nullable T reference, @Nullable String errorMessageTemplate, @Nullable Object... errorMessageArgs) {
|
||||
verify(reference != null, errorMessageTemplate, errorMessageArgs);
|
||||
return reference;
|
||||
}
|
||||
|
||||
private Verify() {
|
||||
}
|
||||
}
|
16
src/main/com/google/common/base/VerifyException.java
Normal file
16
src/main/com/google/common/base/VerifyException.java
Normal file
|
@ -0,0 +1,16 @@
|
|||
package com.google.common.base;
|
||||
|
||||
import com.google.common.annotations.Beta;
|
||||
import com.google.common.annotations.GwtCompatible;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
@Beta
|
||||
@GwtCompatible
|
||||
public class VerifyException extends RuntimeException {
|
||||
public VerifyException() {
|
||||
}
|
||||
|
||||
public VerifyException(@Nullable String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
103
src/main/com/google/common/base/internal/Finalizer.java
Normal file
103
src/main/com/google/common/base/internal/Finalizer.java
Normal file
|
@ -0,0 +1,103 @@
|
|||
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 java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
public class Finalizer implements Runnable {
|
||||
private static final Logger logger = Logger.getLogger(Finalizer.class.getName());
|
||||
private static final String FINALIZABLE_REFERENCE = "com.google.common.base.FinalizableReference";
|
||||
private final WeakReference<Class<?>> finalizableReferenceClassReference;
|
||||
private final PhantomReference<Object> frqReference;
|
||||
private final ReferenceQueue<Object> queue;
|
||||
private static final Field inheritableThreadLocals = getInheritableThreadLocalsField();
|
||||
|
||||
public static void startFinalizer(Class<?> finalizableReferenceClass, ReferenceQueue<Object> queue, PhantomReference<Object> frqReference) {
|
||||
if (!finalizableReferenceClass.getName().equals("com.google.common.base.FinalizableReference")) {
|
||||
throw new IllegalArgumentException("Expected com.google.common.base.FinalizableReference.");
|
||||
} else {
|
||||
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, (Object)null);
|
||||
}
|
||||
} catch (Throwable var6) {
|
||||
logger.log(Level.INFO, "Failed to clear thread local values inherited by reference finalizer thread.", var6);
|
||||
}
|
||||
|
||||
thread.start();
|
||||
}
|
||||
}
|
||||
|
||||
private Finalizer(Class<?> finalizableReferenceClass, ReferenceQueue<Object> queue, PhantomReference<Object> frqReference) {
|
||||
this.queue = queue;
|
||||
this.finalizableReferenceClassReference = new WeakReference(finalizableReferenceClass);
|
||||
this.frqReference = frqReference;
|
||||
}
|
||||
|
||||
public void run() {
|
||||
while(true) {
|
||||
try {
|
||||
if (!this.cleanUp(this.queue.remove())) {
|
||||
return;
|
||||
}
|
||||
} catch (InterruptedException var2) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean cleanUp(Reference<?> reference) {
|
||||
Method finalizeReferentMethod = this.getFinalizeReferentMethod();
|
||||
if (finalizeReferentMethod == null) {
|
||||
return false;
|
||||
} else {
|
||||
do {
|
||||
reference.clear();
|
||||
if (reference == this.frqReference) {
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
finalizeReferentMethod.invoke(reference);
|
||||
} catch (Throwable var4) {
|
||||
logger.log(Level.SEVERE, "Error cleaning up after reference.", var4);
|
||||
}
|
||||
} while((reference = this.queue.poll()) != null);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
private Method getFinalizeReferentMethod() {
|
||||
Class<?> finalizableReferenceClass = (Class)this.finalizableReferenceClassReference.get();
|
||||
if (finalizableReferenceClass == null) {
|
||||
return null;
|
||||
} else {
|
||||
try {
|
||||
return finalizableReferenceClass.getMethod("finalizeReferent");
|
||||
} catch (NoSuchMethodException var3) {
|
||||
throw new AssertionError(var3);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static Field getInheritableThreadLocalsField() {
|
||||
try {
|
||||
Field inheritableThreadLocals = Thread.class.getDeclaredField("inheritableThreadLocals");
|
||||
inheritableThreadLocals.setAccessible(true);
|
||||
return inheritableThreadLocals;
|
||||
} catch (Throwable var1) {
|
||||
logger.log(Level.INFO, "Couldn't access Thread.inheritableThreadLocals. Reference finalizer threads will inherit thread local values.");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
8
src/main/com/google/common/base/package-info.java
Normal file
8
src/main/com/google/common/base/package-info.java
Normal file
|
@ -0,0 +1,8 @@
|
|||
package com.google.common.base;
|
||||
|
||||
import javax.annotation.ParametersAreNonnullByDefault;
|
||||
|
||||
// $FF: synthetic class
|
||||
@ParametersAreNonnullByDefault
|
||||
interface package-info {
|
||||
}
|
148
src/main/com/google/common/cache/AbstractCache.java
vendored
Normal file
148
src/main/com/google/common/cache/AbstractCache.java
vendored
Normal file
|
@ -0,0 +1,148 @@
|
|||
package com.google.common.cache;
|
||||
|
||||
import com.google.common.annotations.Beta;
|
||||
import com.google.common.annotations.GwtCompatible;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.Maps;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
|
||||
@Beta
|
||||
@GwtCompatible
|
||||
public abstract class AbstractCache<K, V> implements Cache<K, V> {
|
||||
protected AbstractCache() {
|
||||
}
|
||||
|
||||
public V get(K key, Callable<? extends V> valueLoader) throws ExecutionException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public ImmutableMap<K, V> getAllPresent(Iterable<?> keys) {
|
||||
Map<K, V> result = Maps.newLinkedHashMap();
|
||||
Iterator i$ = keys.iterator();
|
||||
|
||||
while(i$.hasNext()) {
|
||||
Object key = i$.next();
|
||||
if (!result.containsKey(key)) {
|
||||
V value = this.getIfPresent(key);
|
||||
if (value != null) {
|
||||
result.put(key, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ImmutableMap.copyOf(result);
|
||||
}
|
||||
|
||||
public void put(K key, V value) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public void putAll(Map<? extends K, ? extends V> m) {
|
||||
Iterator i$ = m.entrySet().iterator();
|
||||
|
||||
while(i$.hasNext()) {
|
||||
Entry<? extends K, ? extends V> entry = (Entry)i$.next();
|
||||
this.put(entry.getKey(), entry.getValue());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void cleanUp() {
|
||||
}
|
||||
|
||||
public long size() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public void invalidate(Object key) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public void invalidateAll(Iterable<?> keys) {
|
||||
Iterator i$ = keys.iterator();
|
||||
|
||||
while(i$.hasNext()) {
|
||||
Object key = i$.next();
|
||||
this.invalidate(key);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void invalidateAll() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public CacheStats stats() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public ConcurrentMap<K, V> asMap() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Beta
|
||||
public static final class SimpleStatsCounter implements AbstractCache.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();
|
||||
|
||||
public void recordHits(int count) {
|
||||
this.hitCount.add((long)count);
|
||||
}
|
||||
|
||||
public void recordMisses(int count) {
|
||||
this.missCount.add((long)count);
|
||||
}
|
||||
|
||||
public void recordLoadSuccess(long loadTime) {
|
||||
this.loadSuccessCount.increment();
|
||||
this.totalLoadTime.add(loadTime);
|
||||
}
|
||||
|
||||
public void recordLoadException(long loadTime) {
|
||||
this.loadExceptionCount.increment();
|
||||
this.totalLoadTime.add(loadTime);
|
||||
}
|
||||
|
||||
public void recordEviction() {
|
||||
this.evictionCount.increment();
|
||||
}
|
||||
|
||||
public CacheStats snapshot() {
|
||||
return new CacheStats(this.hitCount.sum(), this.missCount.sum(), this.loadSuccessCount.sum(), this.loadExceptionCount.sum(), this.totalLoadTime.sum(), this.evictionCount.sum());
|
||||
}
|
||||
|
||||
public void incrementBy(AbstractCache.StatsCounter other) {
|
||||
CacheStats otherStats = other.snapshot();
|
||||
this.hitCount.add(otherStats.hitCount());
|
||||
this.missCount.add(otherStats.missCount());
|
||||
this.loadSuccessCount.add(otherStats.loadSuccessCount());
|
||||
this.loadExceptionCount.add(otherStats.loadExceptionCount());
|
||||
this.totalLoadTime.add(otherStats.totalLoadTime());
|
||||
this.evictionCount.add(otherStats.evictionCount());
|
||||
}
|
||||
}
|
||||
|
||||
@Beta
|
||||
public interface StatsCounter {
|
||||
void recordHits(int var1);
|
||||
|
||||
void recordMisses(int var1);
|
||||
|
||||
void recordLoadSuccess(long var1);
|
||||
|
||||
void recordLoadException(long var1);
|
||||
|
||||
void recordEviction();
|
||||
|
||||
CacheStats snapshot();
|
||||
}
|
||||
}
|
45
src/main/com/google/common/cache/AbstractLoadingCache.java
vendored
Normal file
45
src/main/com/google/common/cache/AbstractLoadingCache.java
vendored
Normal file
|
@ -0,0 +1,45 @@
|
|||
package com.google.common.cache;
|
||||
|
||||
import com.google.common.annotations.Beta;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.Maps;
|
||||
import com.google.common.util.concurrent.UncheckedExecutionException;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
|
||||
@Beta
|
||||
public abstract class AbstractLoadingCache<K, V> extends AbstractCache<K, V> implements LoadingCache<K, V> {
|
||||
protected AbstractLoadingCache() {
|
||||
}
|
||||
|
||||
public V getUnchecked(K key) {
|
||||
try {
|
||||
return this.get(key);
|
||||
} catch (ExecutionException var3) {
|
||||
throw new UncheckedExecutionException(var3.getCause());
|
||||
}
|
||||
}
|
||||
|
||||
public ImmutableMap<K, V> getAll(Iterable<? extends K> keys) throws ExecutionException {
|
||||
Map<K, V> result = Maps.newLinkedHashMap();
|
||||
Iterator i$ = keys.iterator();
|
||||
|
||||
while(i$.hasNext()) {
|
||||
K key = i$.next();
|
||||
if (!result.containsKey(key)) {
|
||||
result.put(key, this.get(key));
|
||||
}
|
||||
}
|
||||
|
||||
return ImmutableMap.copyOf(result);
|
||||
}
|
||||
|
||||
public final V apply(K key) {
|
||||
return this.getUnchecked(key);
|
||||
}
|
||||
|
||||
public void refresh(K key) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
}
|
39
src/main/com/google/common/cache/Cache.java
vendored
Normal file
39
src/main/com/google/common/cache/Cache.java
vendored
Normal file
|
@ -0,0 +1,39 @@
|
|||
package com.google.common.cache;
|
||||
|
||||
import com.google.common.annotations.Beta;
|
||||
import com.google.common.annotations.GwtCompatible;
|
||||
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;
|
||||
|
||||
@Beta
|
||||
@GwtCompatible
|
||||
public interface Cache<K, V> {
|
||||
@Nullable
|
||||
V getIfPresent(Object var1);
|
||||
|
||||
V get(K var1, Callable<? extends V> var2) throws ExecutionException;
|
||||
|
||||
ImmutableMap<K, V> getAllPresent(Iterable<?> var1);
|
||||
|
||||
void put(K var1, V var2);
|
||||
|
||||
void putAll(Map<? extends K, ? extends V> var1);
|
||||
|
||||
void invalidate(Object var1);
|
||||
|
||||
void invalidateAll(Iterable<?> var1);
|
||||
|
||||
void invalidateAll();
|
||||
|
||||
long size();
|
||||
|
||||
CacheStats stats();
|
||||
|
||||
ConcurrentMap<K, V> asMap();
|
||||
|
||||
void cleanUp();
|
||||
}
|
388
src/main/com/google/common/cache/CacheBuilder.java
vendored
Normal file
388
src/main/com/google/common/cache/CacheBuilder.java
vendored
Normal file
|
@ -0,0 +1,388 @@
|
|||
package com.google.common.cache;
|
||||
|
||||
import com.google.common.annotations.Beta;
|
||||
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.Preconditions;
|
||||
import com.google.common.base.Supplier;
|
||||
import com.google.common.base.Suppliers;
|
||||
import com.google.common.base.Ticker;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
import javax.annotation.CheckReturnValue;
|
||||
|
||||
@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 AbstractCache.StatsCounter> NULL_STATS_COUNTER = Suppliers.ofInstance(new AbstractCache.StatsCounter() {
|
||||
public void recordHits(int count) {
|
||||
}
|
||||
|
||||
public void recordMisses(int count) {
|
||||
}
|
||||
|
||||
public void recordLoadSuccess(long loadTime) {
|
||||
}
|
||||
|
||||
public void recordLoadException(long loadTime) {
|
||||
}
|
||||
|
||||
public void recordEviction() {
|
||||
}
|
||||
|
||||
public CacheStats snapshot() {
|
||||
return CacheBuilder.EMPTY_STATS;
|
||||
}
|
||||
});
|
||||
static final CacheStats EMPTY_STATS = new CacheStats(0L, 0L, 0L, 0L, 0L, 0L);
|
||||
static final Supplier<AbstractCache.StatsCounter> CACHE_STATS_COUNTER = new Supplier<AbstractCache.StatsCounter>() {
|
||||
public AbstractCache.StatsCounter get() {
|
||||
return new AbstractCache.SimpleStatsCounter();
|
||||
}
|
||||
};
|
||||
static final Ticker NULL_TICKER = new Ticker() {
|
||||
public long read() {
|
||||
return 0L;
|
||||
}
|
||||
};
|
||||
private static final Logger logger = Logger.getLogger(CacheBuilder.class.getName());
|
||||
static final int UNSET_INT = -1;
|
||||
boolean strictParsing = true;
|
||||
int initialCapacity = -1;
|
||||
int concurrencyLevel = -1;
|
||||
long maximumSize = -1L;
|
||||
long maximumWeight = -1L;
|
||||
Weigher<? super K, ? super V> weigher;
|
||||
LocalCache.Strength keyStrength;
|
||||
LocalCache.Strength valueStrength;
|
||||
long expireAfterWriteNanos = -1L;
|
||||
long expireAfterAccessNanos = -1L;
|
||||
long refreshNanos = -1L;
|
||||
Equivalence<Object> keyEquivalence;
|
||||
Equivalence<Object> valueEquivalence;
|
||||
RemovalListener<? super K, ? super V> removalListener;
|
||||
Ticker ticker;
|
||||
Supplier<? extends AbstractCache.StatsCounter> statsCounterSupplier;
|
||||
|
||||
CacheBuilder() {
|
||||
this.statsCounterSupplier = NULL_STATS_COUNTER;
|
||||
}
|
||||
|
||||
public static CacheBuilder<Object, Object> newBuilder() {
|
||||
return new CacheBuilder();
|
||||
}
|
||||
|
||||
@Beta
|
||||
@GwtIncompatible("To be supported")
|
||||
public static CacheBuilder<Object, Object> from(CacheBuilderSpec spec) {
|
||||
return spec.toCacheBuilder().lenientParsing();
|
||||
}
|
||||
|
||||
@Beta
|
||||
@GwtIncompatible("To be supported")
|
||||
public static CacheBuilder<Object, Object> from(String spec) {
|
||||
return from(CacheBuilderSpec.parse(spec));
|
||||
}
|
||||
|
||||
@GwtIncompatible("To be supported")
|
||||
CacheBuilder<K, V> lenientParsing() {
|
||||
this.strictParsing = false;
|
||||
return this;
|
||||
}
|
||||
|
||||
@GwtIncompatible("To be supported")
|
||||
CacheBuilder<K, V> keyEquivalence(Equivalence<Object> equivalence) {
|
||||
Preconditions.checkState(this.keyEquivalence == null, "key equivalence was already set to %s", this.keyEquivalence);
|
||||
this.keyEquivalence = (Equivalence)Preconditions.checkNotNull(equivalence);
|
||||
return this;
|
||||
}
|
||||
|
||||
Equivalence<Object> getKeyEquivalence() {
|
||||
return (Equivalence)MoreObjects.firstNonNull(this.keyEquivalence, this.getKeyStrength().defaultEquivalence());
|
||||
}
|
||||
|
||||
@GwtIncompatible("To be supported")
|
||||
CacheBuilder<K, V> valueEquivalence(Equivalence<Object> equivalence) {
|
||||
Preconditions.checkState(this.valueEquivalence == null, "value equivalence was already set to %s", this.valueEquivalence);
|
||||
this.valueEquivalence = (Equivalence)Preconditions.checkNotNull(equivalence);
|
||||
return this;
|
||||
}
|
||||
|
||||
Equivalence<Object> getValueEquivalence() {
|
||||
return (Equivalence)MoreObjects.firstNonNull(this.valueEquivalence, this.getValueStrength().defaultEquivalence());
|
||||
}
|
||||
|
||||
public CacheBuilder<K, V> initialCapacity(int initialCapacity) {
|
||||
Preconditions.checkState(this.initialCapacity == -1, "initial capacity was already set to %s", this.initialCapacity);
|
||||
Preconditions.checkArgument(initialCapacity >= 0);
|
||||
this.initialCapacity = initialCapacity;
|
||||
return this;
|
||||
}
|
||||
|
||||
int getInitialCapacity() {
|
||||
return this.initialCapacity == -1 ? 16 : this.initialCapacity;
|
||||
}
|
||||
|
||||
public CacheBuilder<K, V> concurrencyLevel(int concurrencyLevel) {
|
||||
Preconditions.checkState(this.concurrencyLevel == -1, "concurrency level was already set to %s", this.concurrencyLevel);
|
||||
Preconditions.checkArgument(concurrencyLevel > 0);
|
||||
this.concurrencyLevel = concurrencyLevel;
|
||||
return this;
|
||||
}
|
||||
|
||||
int getConcurrencyLevel() {
|
||||
return this.concurrencyLevel == -1 ? 4 : this.concurrencyLevel;
|
||||
}
|
||||
|
||||
public CacheBuilder<K, V> maximumSize(long size) {
|
||||
Preconditions.checkState(this.maximumSize == -1L, "maximum size was already set to %s", this.maximumSize);
|
||||
Preconditions.checkState(this.maximumWeight == -1L, "maximum weight was already set to %s", this.maximumWeight);
|
||||
Preconditions.checkState(this.weigher == null, "maximum size can not be combined with weigher");
|
||||
Preconditions.checkArgument(size >= 0L, "maximum size must not be negative");
|
||||
this.maximumSize = size;
|
||||
return this;
|
||||
}
|
||||
|
||||
@GwtIncompatible("To be supported")
|
||||
public CacheBuilder<K, V> maximumWeight(long weight) {
|
||||
Preconditions.checkState(this.maximumWeight == -1L, "maximum weight was already set to %s", this.maximumWeight);
|
||||
Preconditions.checkState(this.maximumSize == -1L, "maximum size was already set to %s", this.maximumSize);
|
||||
this.maximumWeight = weight;
|
||||
Preconditions.checkArgument(weight >= 0L, "maximum weight must not be negative");
|
||||
return this;
|
||||
}
|
||||
|
||||
@GwtIncompatible("To be supported")
|
||||
public <K1 extends K, V1 extends V> CacheBuilder<K1, V1> weigher(Weigher<? super K1, ? super V1> weigher) {
|
||||
Preconditions.checkState(this.weigher == null);
|
||||
if (this.strictParsing) {
|
||||
Preconditions.checkState(this.maximumSize == -1L, "weigher can not be combined with maximum size", this.maximumSize);
|
||||
}
|
||||
|
||||
this.weigher = (Weigher)Preconditions.checkNotNull(weigher);
|
||||
return this;
|
||||
}
|
||||
|
||||
long getMaximumWeight() {
|
||||
if (this.expireAfterWriteNanos != 0L && this.expireAfterAccessNanos != 0L) {
|
||||
return this.weigher == null ? this.maximumSize : this.maximumWeight;
|
||||
} else {
|
||||
return 0L;
|
||||
}
|
||||
}
|
||||
|
||||
<K1 extends K, V1 extends V> Weigher<K1, V1> getWeigher() {
|
||||
return (Weigher)MoreObjects.firstNonNull(this.weigher, CacheBuilder.OneWeigher.INSTANCE);
|
||||
}
|
||||
|
||||
@GwtIncompatible("java.lang.ref.WeakReference")
|
||||
public CacheBuilder<K, V> weakKeys() {
|
||||
return this.setKeyStrength(LocalCache.Strength.WEAK);
|
||||
}
|
||||
|
||||
CacheBuilder<K, V> setKeyStrength(LocalCache.Strength strength) {
|
||||
Preconditions.checkState(this.keyStrength == null, "Key strength was already set to %s", this.keyStrength);
|
||||
this.keyStrength = (LocalCache.Strength)Preconditions.checkNotNull(strength);
|
||||
return this;
|
||||
}
|
||||
|
||||
LocalCache.Strength getKeyStrength() {
|
||||
return (LocalCache.Strength)MoreObjects.firstNonNull(this.keyStrength, LocalCache.Strength.STRONG);
|
||||
}
|
||||
|
||||
@GwtIncompatible("java.lang.ref.WeakReference")
|
||||
public CacheBuilder<K, V> weakValues() {
|
||||
return this.setValueStrength(LocalCache.Strength.WEAK);
|
||||
}
|
||||
|
||||
@GwtIncompatible("java.lang.ref.SoftReference")
|
||||
public CacheBuilder<K, V> softValues() {
|
||||
return this.setValueStrength(LocalCache.Strength.SOFT);
|
||||
}
|
||||
|
||||
CacheBuilder<K, V> setValueStrength(LocalCache.Strength strength) {
|
||||
Preconditions.checkState(this.valueStrength == null, "Value strength was already set to %s", this.valueStrength);
|
||||
this.valueStrength = (LocalCache.Strength)Preconditions.checkNotNull(strength);
|
||||
return this;
|
||||
}
|
||||
|
||||
LocalCache.Strength getValueStrength() {
|
||||
return (LocalCache.Strength)MoreObjects.firstNonNull(this.valueStrength, LocalCache.Strength.STRONG);
|
||||
}
|
||||
|
||||
public CacheBuilder<K, V> expireAfterWrite(long duration, TimeUnit unit) {
|
||||
Preconditions.checkState(this.expireAfterWriteNanos == -1L, "expireAfterWrite was already set to %s ns", this.expireAfterWriteNanos);
|
||||
Preconditions.checkArgument(duration >= 0L, "duration cannot be negative: %s %s", duration, unit);
|
||||
this.expireAfterWriteNanos = unit.toNanos(duration);
|
||||
return this;
|
||||
}
|
||||
|
||||
long getExpireAfterWriteNanos() {
|
||||
return this.expireAfterWriteNanos == -1L ? 0L : this.expireAfterWriteNanos;
|
||||
}
|
||||
|
||||
public CacheBuilder<K, V> expireAfterAccess(long duration, TimeUnit unit) {
|
||||
Preconditions.checkState(this.expireAfterAccessNanos == -1L, "expireAfterAccess was already set to %s ns", this.expireAfterAccessNanos);
|
||||
Preconditions.checkArgument(duration >= 0L, "duration cannot be negative: %s %s", duration, unit);
|
||||
this.expireAfterAccessNanos = unit.toNanos(duration);
|
||||
return this;
|
||||
}
|
||||
|
||||
long getExpireAfterAccessNanos() {
|
||||
return this.expireAfterAccessNanos == -1L ? 0L : this.expireAfterAccessNanos;
|
||||
}
|
||||
|
||||
@Beta
|
||||
@GwtIncompatible("To be supported (synchronously).")
|
||||
public CacheBuilder<K, V> refreshAfterWrite(long duration, TimeUnit unit) {
|
||||
Preconditions.checkNotNull(unit);
|
||||
Preconditions.checkState(this.refreshNanos == -1L, "refresh was already set to %s ns", this.refreshNanos);
|
||||
Preconditions.checkArgument(duration > 0L, "duration must be positive: %s %s", duration, unit);
|
||||
this.refreshNanos = unit.toNanos(duration);
|
||||
return this;
|
||||
}
|
||||
|
||||
long getRefreshNanos() {
|
||||
return this.refreshNanos == -1L ? 0L : this.refreshNanos;
|
||||
}
|
||||
|
||||
public CacheBuilder<K, V> ticker(Ticker ticker) {
|
||||
Preconditions.checkState(this.ticker == null);
|
||||
this.ticker = (Ticker)Preconditions.checkNotNull(ticker);
|
||||
return this;
|
||||
}
|
||||
|
||||
Ticker getTicker(boolean recordsTime) {
|
||||
if (this.ticker != null) {
|
||||
return this.ticker;
|
||||
} else {
|
||||
return recordsTime ? Ticker.systemTicker() : NULL_TICKER;
|
||||
}
|
||||
}
|
||||
|
||||
@CheckReturnValue
|
||||
public <K1 extends K, V1 extends V> CacheBuilder<K1, V1> removalListener(RemovalListener<? super K1, ? super V1> listener) {
|
||||
Preconditions.checkState(this.removalListener == null);
|
||||
this.removalListener = (RemovalListener)Preconditions.checkNotNull(listener);
|
||||
return this;
|
||||
}
|
||||
|
||||
<K1 extends K, V1 extends V> RemovalListener<K1, V1> getRemovalListener() {
|
||||
return (RemovalListener)MoreObjects.firstNonNull(this.removalListener, CacheBuilder.NullListener.INSTANCE);
|
||||
}
|
||||
|
||||
public CacheBuilder<K, V> recordStats() {
|
||||
this.statsCounterSupplier = CACHE_STATS_COUNTER;
|
||||
return this;
|
||||
}
|
||||
|
||||
boolean isRecordingStats() {
|
||||
return this.statsCounterSupplier == CACHE_STATS_COUNTER;
|
||||
}
|
||||
|
||||
Supplier<? extends AbstractCache.StatsCounter> getStatsCounterSupplier() {
|
||||
return this.statsCounterSupplier;
|
||||
}
|
||||
|
||||
public <K1 extends K, V1 extends V> LoadingCache<K1, V1> build(CacheLoader<? super K1, V1> loader) {
|
||||
this.checkWeightWithWeigher();
|
||||
return new LocalCache.LocalLoadingCache(this, loader);
|
||||
}
|
||||
|
||||
public <K1 extends K, V1 extends V> Cache<K1, V1> build() {
|
||||
this.checkWeightWithWeigher();
|
||||
this.checkNonLoadingCache();
|
||||
return new LocalCache.LocalManualCache(this);
|
||||
}
|
||||
|
||||
private void checkNonLoadingCache() {
|
||||
Preconditions.checkState(this.refreshNanos == -1L, "refreshAfterWrite requires a LoadingCache");
|
||||
}
|
||||
|
||||
private void checkWeightWithWeigher() {
|
||||
if (this.weigher == null) {
|
||||
Preconditions.checkState(this.maximumWeight == -1L, "maximumWeight requires weigher");
|
||||
} else if (this.strictParsing) {
|
||||
Preconditions.checkState(this.maximumWeight != -1L, "weigher requires maximumWeight");
|
||||
} else if (this.maximumWeight == -1L) {
|
||||
logger.log(Level.WARNING, "ignoring weigher specified without maximumWeight");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
MoreObjects.ToStringHelper s = MoreObjects.toStringHelper((Object)this);
|
||||
if (this.initialCapacity != -1) {
|
||||
s.add("initialCapacity", this.initialCapacity);
|
||||
}
|
||||
|
||||
if (this.concurrencyLevel != -1) {
|
||||
s.add("concurrencyLevel", this.concurrencyLevel);
|
||||
}
|
||||
|
||||
if (this.maximumSize != -1L) {
|
||||
s.add("maximumSize", this.maximumSize);
|
||||
}
|
||||
|
||||
if (this.maximumWeight != -1L) {
|
||||
s.add("maximumWeight", this.maximumWeight);
|
||||
}
|
||||
|
||||
long var2;
|
||||
if (this.expireAfterWriteNanos != -1L) {
|
||||
var2 = this.expireAfterWriteNanos;
|
||||
s.add("expireAfterWrite", (new StringBuilder(22)).append(var2).append("ns").toString());
|
||||
}
|
||||
|
||||
if (this.expireAfterAccessNanos != -1L) {
|
||||
var2 = this.expireAfterAccessNanos;
|
||||
s.add("expireAfterAccess", (new StringBuilder(22)).append(var2).append("ns").toString());
|
||||
}
|
||||
|
||||
if (this.keyStrength != null) {
|
||||
s.add("keyStrength", Ascii.toLowerCase(this.keyStrength.toString()));
|
||||
}
|
||||
|
||||
if (this.valueStrength != null) {
|
||||
s.add("valueStrength", Ascii.toLowerCase(this.valueStrength.toString()));
|
||||
}
|
||||
|
||||
if (this.keyEquivalence != null) {
|
||||
s.addValue("keyEquivalence");
|
||||
}
|
||||
|
||||
if (this.valueEquivalence != null) {
|
||||
s.addValue("valueEquivalence");
|
||||
}
|
||||
|
||||
if (this.removalListener != null) {
|
||||
s.addValue("removalListener");
|
||||
}
|
||||
|
||||
return s.toString();
|
||||
}
|
||||
|
||||
static enum OneWeigher implements Weigher<Object, Object> {
|
||||
INSTANCE;
|
||||
|
||||
public int weigh(Object key, Object value) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
static enum NullListener implements RemovalListener<Object, Object> {
|
||||
INSTANCE;
|
||||
|
||||
public void onRemoval(RemovalNotification<Object, Object> notification) {
|
||||
}
|
||||
}
|
||||
}
|
325
src/main/com/google/common/cache/CacheBuilderSpec.java
vendored
Normal file
325
src/main/com/google/common/cache/CacheBuilderSpec.java
vendored
Normal file
|
@ -0,0 +1,325 @@
|
|||
package com.google.common.cache;
|
||||
|
||||
import com.google.common.annotations.Beta;
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import com.google.common.base.MoreObjects;
|
||||
import com.google.common.base.Objects;
|
||||
import com.google.common.base.Preconditions;
|
||||
import com.google.common.base.Splitter;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
@Beta
|
||||
public final class CacheBuilderSpec {
|
||||
private static final Splitter KEYS_SPLITTER = Splitter.on(',').trimResults();
|
||||
private static final Splitter KEY_VALUE_SPLITTER = Splitter.on('=').trimResults();
|
||||
private static final ImmutableMap<String, CacheBuilderSpec.ValueParser> VALUE_PARSERS;
|
||||
@VisibleForTesting
|
||||
Integer initialCapacity;
|
||||
@VisibleForTesting
|
||||
Long maximumSize;
|
||||
@VisibleForTesting
|
||||
Long maximumWeight;
|
||||
@VisibleForTesting
|
||||
Integer concurrencyLevel;
|
||||
@VisibleForTesting
|
||||
LocalCache.Strength keyStrength;
|
||||
@VisibleForTesting
|
||||
LocalCache.Strength valueStrength;
|
||||
@VisibleForTesting
|
||||
Boolean recordStats;
|
||||
@VisibleForTesting
|
||||
long writeExpirationDuration;
|
||||
@VisibleForTesting
|
||||
TimeUnit writeExpirationTimeUnit;
|
||||
@VisibleForTesting
|
||||
long accessExpirationDuration;
|
||||
@VisibleForTesting
|
||||
TimeUnit accessExpirationTimeUnit;
|
||||
@VisibleForTesting
|
||||
long refreshDuration;
|
||||
@VisibleForTesting
|
||||
TimeUnit refreshTimeUnit;
|
||||
private final String specification;
|
||||
|
||||
private CacheBuilderSpec(String specification) {
|
||||
this.specification = specification;
|
||||
}
|
||||
|
||||
public static CacheBuilderSpec parse(String cacheBuilderSpecification) {
|
||||
CacheBuilderSpec spec = new CacheBuilderSpec(cacheBuilderSpecification);
|
||||
if (!cacheBuilderSpecification.isEmpty()) {
|
||||
Iterator i$ = KEYS_SPLITTER.split(cacheBuilderSpecification).iterator();
|
||||
|
||||
while(i$.hasNext()) {
|
||||
String keyValuePair = (String)i$.next();
|
||||
List<String> keyAndValue = ImmutableList.copyOf(KEY_VALUE_SPLITTER.split(keyValuePair));
|
||||
Preconditions.checkArgument(!keyAndValue.isEmpty(), "blank key-value pair");
|
||||
Preconditions.checkArgument(keyAndValue.size() <= 2, "key-value pair %s with more than one equals sign", keyValuePair);
|
||||
String key = (String)keyAndValue.get(0);
|
||||
CacheBuilderSpec.ValueParser valueParser = (CacheBuilderSpec.ValueParser)VALUE_PARSERS.get(key);
|
||||
Preconditions.checkArgument(valueParser != null, "unknown key %s", key);
|
||||
String value = keyAndValue.size() == 1 ? null : (String)keyAndValue.get(1);
|
||||
valueParser.parse(spec, key, value);
|
||||
}
|
||||
}
|
||||
|
||||
return spec;
|
||||
}
|
||||
|
||||
public static CacheBuilderSpec disableCaching() {
|
||||
return parse("maximumSize=0");
|
||||
}
|
||||
|
||||
CacheBuilder<Object, Object> toCacheBuilder() {
|
||||
CacheBuilder<Object, Object> builder = CacheBuilder.newBuilder();
|
||||
if (this.initialCapacity != null) {
|
||||
builder.initialCapacity(this.initialCapacity);
|
||||
}
|
||||
|
||||
if (this.maximumSize != null) {
|
||||
builder.maximumSize(this.maximumSize);
|
||||
}
|
||||
|
||||
if (this.maximumWeight != null) {
|
||||
builder.maximumWeight(this.maximumWeight);
|
||||
}
|
||||
|
||||
if (this.concurrencyLevel != null) {
|
||||
builder.concurrencyLevel(this.concurrencyLevel);
|
||||
}
|
||||
|
||||
if (this.keyStrength != null) {
|
||||
switch(this.keyStrength) {
|
||||
case WEAK:
|
||||
builder.weakKeys();
|
||||
break;
|
||||
default:
|
||||
throw new AssertionError();
|
||||
}
|
||||
}
|
||||
|
||||
if (this.valueStrength != null) {
|
||||
switch(this.valueStrength) {
|
||||
case WEAK:
|
||||
builder.weakValues();
|
||||
break;
|
||||
case SOFT:
|
||||
builder.softValues();
|
||||
break;
|
||||
default:
|
||||
throw new AssertionError();
|
||||
}
|
||||
}
|
||||
|
||||
if (this.recordStats != null && this.recordStats) {
|
||||
builder.recordStats();
|
||||
}
|
||||
|
||||
if (this.writeExpirationTimeUnit != null) {
|
||||
builder.expireAfterWrite(this.writeExpirationDuration, this.writeExpirationTimeUnit);
|
||||
}
|
||||
|
||||
if (this.accessExpirationTimeUnit != null) {
|
||||
builder.expireAfterAccess(this.accessExpirationDuration, this.accessExpirationTimeUnit);
|
||||
}
|
||||
|
||||
if (this.refreshTimeUnit != null) {
|
||||
builder.refreshAfterWrite(this.refreshDuration, this.refreshTimeUnit);
|
||||
}
|
||||
|
||||
return builder;
|
||||
}
|
||||
|
||||
public String toParsableString() {
|
||||
return this.specification;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return MoreObjects.toStringHelper((Object)this).addValue(this.toParsableString()).toString();
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
return Objects.hashCode(this.initialCapacity, this.maximumSize, this.maximumWeight, this.concurrencyLevel, this.keyStrength, this.valueStrength, this.recordStats, durationInNanos(this.writeExpirationDuration, this.writeExpirationTimeUnit), durationInNanos(this.accessExpirationDuration, this.accessExpirationTimeUnit), durationInNanos(this.refreshDuration, this.refreshTimeUnit));
|
||||
}
|
||||
|
||||
public boolean equals(@Nullable Object obj) {
|
||||
if (this == obj) {
|
||||
return true;
|
||||
} else if (!(obj instanceof CacheBuilderSpec)) {
|
||||
return false;
|
||||
} else {
|
||||
CacheBuilderSpec that = (CacheBuilderSpec)obj;
|
||||
return Objects.equal(this.initialCapacity, that.initialCapacity) && Objects.equal(this.maximumSize, that.maximumSize) && Objects.equal(this.maximumWeight, that.maximumWeight) && Objects.equal(this.concurrencyLevel, that.concurrencyLevel) && Objects.equal(this.keyStrength, that.keyStrength) && Objects.equal(this.valueStrength, that.valueStrength) && Objects.equal(this.recordStats, that.recordStats) && Objects.equal(durationInNanos(this.writeExpirationDuration, this.writeExpirationTimeUnit), durationInNanos(that.writeExpirationDuration, that.writeExpirationTimeUnit)) && Objects.equal(durationInNanos(this.accessExpirationDuration, this.accessExpirationTimeUnit), durationInNanos(that.accessExpirationDuration, that.accessExpirationTimeUnit)) && Objects.equal(durationInNanos(this.refreshDuration, this.refreshTimeUnit), durationInNanos(that.refreshDuration, that.refreshTimeUnit));
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static Long durationInNanos(long duration, @Nullable TimeUnit unit) {
|
||||
return unit == null ? null : unit.toNanos(duration);
|
||||
}
|
||||
|
||||
static {
|
||||
VALUE_PARSERS = ImmutableMap.builder().put("initialCapacity", new CacheBuilderSpec.InitialCapacityParser()).put("maximumSize", new CacheBuilderSpec.MaximumSizeParser()).put("maximumWeight", new CacheBuilderSpec.MaximumWeightParser()).put("concurrencyLevel", new CacheBuilderSpec.ConcurrencyLevelParser()).put("weakKeys", new CacheBuilderSpec.KeyStrengthParser(LocalCache.Strength.WEAK)).put("softValues", new CacheBuilderSpec.ValueStrengthParser(LocalCache.Strength.SOFT)).put("weakValues", new CacheBuilderSpec.ValueStrengthParser(LocalCache.Strength.WEAK)).put("recordStats", new CacheBuilderSpec.RecordStatsParser()).put("expireAfterAccess", new CacheBuilderSpec.AccessDurationParser()).put("expireAfterWrite", new CacheBuilderSpec.WriteDurationParser()).put("refreshAfterWrite", new CacheBuilderSpec.RefreshDurationParser()).put("refreshInterval", new CacheBuilderSpec.RefreshDurationParser()).build();
|
||||
}
|
||||
|
||||
static class RefreshDurationParser extends CacheBuilderSpec.DurationParser {
|
||||
protected void parseDuration(CacheBuilderSpec spec, long duration, TimeUnit unit) {
|
||||
Preconditions.checkArgument(spec.refreshTimeUnit == null, "refreshAfterWrite already set");
|
||||
spec.refreshDuration = duration;
|
||||
spec.refreshTimeUnit = unit;
|
||||
}
|
||||
}
|
||||
|
||||
static class WriteDurationParser extends CacheBuilderSpec.DurationParser {
|
||||
protected void parseDuration(CacheBuilderSpec spec, long duration, TimeUnit unit) {
|
||||
Preconditions.checkArgument(spec.writeExpirationTimeUnit == null, "expireAfterWrite already set");
|
||||
spec.writeExpirationDuration = duration;
|
||||
spec.writeExpirationTimeUnit = unit;
|
||||
}
|
||||
}
|
||||
|
||||
static class AccessDurationParser extends CacheBuilderSpec.DurationParser {
|
||||
protected void parseDuration(CacheBuilderSpec spec, long duration, TimeUnit unit) {
|
||||
Preconditions.checkArgument(spec.accessExpirationTimeUnit == null, "expireAfterAccess already set");
|
||||
spec.accessExpirationDuration = duration;
|
||||
spec.accessExpirationTimeUnit = unit;
|
||||
}
|
||||
}
|
||||
|
||||
abstract static class DurationParser implements CacheBuilderSpec.ValueParser {
|
||||
protected abstract void parseDuration(CacheBuilderSpec var1, long var2, TimeUnit var4);
|
||||
|
||||
public void parse(CacheBuilderSpec spec, String key, String value) {
|
||||
Preconditions.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(String.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));
|
||||
this.parseDuration(spec, duration, timeUnit);
|
||||
} catch (NumberFormatException var8) {
|
||||
throw new IllegalArgumentException(String.format("key %s value set to %s, must be integer", key, value));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static class RecordStatsParser implements CacheBuilderSpec.ValueParser {
|
||||
public void parse(CacheBuilderSpec spec, String key, @Nullable String value) {
|
||||
Preconditions.checkArgument(value == null, "recordStats does not take values");
|
||||
Preconditions.checkArgument(spec.recordStats == null, "recordStats already set");
|
||||
spec.recordStats = true;
|
||||
}
|
||||
}
|
||||
|
||||
static class ValueStrengthParser implements CacheBuilderSpec.ValueParser {
|
||||
private final LocalCache.Strength strength;
|
||||
|
||||
public ValueStrengthParser(LocalCache.Strength strength) {
|
||||
this.strength = strength;
|
||||
}
|
||||
|
||||
public void parse(CacheBuilderSpec spec, String key, @Nullable String value) {
|
||||
Preconditions.checkArgument(value == null, "key %s does not take values", key);
|
||||
Preconditions.checkArgument(spec.valueStrength == null, "%s was already set to %s", key, spec.valueStrength);
|
||||
spec.valueStrength = this.strength;
|
||||
}
|
||||
}
|
||||
|
||||
static class KeyStrengthParser implements CacheBuilderSpec.ValueParser {
|
||||
private final LocalCache.Strength strength;
|
||||
|
||||
public KeyStrengthParser(LocalCache.Strength strength) {
|
||||
this.strength = strength;
|
||||
}
|
||||
|
||||
public void parse(CacheBuilderSpec spec, String key, @Nullable String value) {
|
||||
Preconditions.checkArgument(value == null, "key %s does not take values", key);
|
||||
Preconditions.checkArgument(spec.keyStrength == null, "%s was already set to %s", key, spec.keyStrength);
|
||||
spec.keyStrength = this.strength;
|
||||
}
|
||||
}
|
||||
|
||||
static class ConcurrencyLevelParser extends CacheBuilderSpec.IntegerParser {
|
||||
protected void parseInteger(CacheBuilderSpec spec, int value) {
|
||||
Preconditions.checkArgument(spec.concurrencyLevel == null, "concurrency level was already set to ", spec.concurrencyLevel);
|
||||
spec.concurrencyLevel = value;
|
||||
}
|
||||
}
|
||||
|
||||
static class MaximumWeightParser extends CacheBuilderSpec.LongParser {
|
||||
protected void parseLong(CacheBuilderSpec spec, long value) {
|
||||
Preconditions.checkArgument(spec.maximumWeight == null, "maximum weight was already set to ", spec.maximumWeight);
|
||||
Preconditions.checkArgument(spec.maximumSize == null, "maximum size was already set to ", spec.maximumSize);
|
||||
spec.maximumWeight = value;
|
||||
}
|
||||
}
|
||||
|
||||
static class MaximumSizeParser extends CacheBuilderSpec.LongParser {
|
||||
protected void parseLong(CacheBuilderSpec spec, long value) {
|
||||
Preconditions.checkArgument(spec.maximumSize == null, "maximum size was already set to ", spec.maximumSize);
|
||||
Preconditions.checkArgument(spec.maximumWeight == null, "maximum weight was already set to ", spec.maximumWeight);
|
||||
spec.maximumSize = value;
|
||||
}
|
||||
}
|
||||
|
||||
static class InitialCapacityParser extends CacheBuilderSpec.IntegerParser {
|
||||
protected void parseInteger(CacheBuilderSpec spec, int value) {
|
||||
Preconditions.checkArgument(spec.initialCapacity == null, "initial capacity was already set to ", spec.initialCapacity);
|
||||
spec.initialCapacity = value;
|
||||
}
|
||||
}
|
||||
|
||||
abstract static class LongParser implements CacheBuilderSpec.ValueParser {
|
||||
protected abstract void parseLong(CacheBuilderSpec var1, long var2);
|
||||
|
||||
public void parse(CacheBuilderSpec spec, String key, String value) {
|
||||
Preconditions.checkArgument(value != null && !value.isEmpty(), "value of key %s omitted", key);
|
||||
|
||||
try {
|
||||
this.parseLong(spec, Long.parseLong(value));
|
||||
} catch (NumberFormatException var5) {
|
||||
throw new IllegalArgumentException(String.format("key %s value set to %s, must be integer", key, value), var5);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
abstract static class IntegerParser implements CacheBuilderSpec.ValueParser {
|
||||
protected abstract void parseInteger(CacheBuilderSpec var1, int var2);
|
||||
|
||||
public void parse(CacheBuilderSpec spec, String key, String value) {
|
||||
Preconditions.checkArgument(value != null && !value.isEmpty(), "value of key %s omitted", key);
|
||||
|
||||
try {
|
||||
this.parseInteger(spec, Integer.parseInt(value));
|
||||
} catch (NumberFormatException var5) {
|
||||
throw new IllegalArgumentException(String.format("key %s value set to %s, must be integer", key, value), var5);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private interface ValueParser {
|
||||
void parse(CacheBuilderSpec var1, String var2, @Nullable String var3);
|
||||
}
|
||||
}
|
108
src/main/com/google/common/cache/CacheLoader.java
vendored
Normal file
108
src/main/com/google/common/cache/CacheLoader.java
vendored
Normal file
|
@ -0,0 +1,108 @@
|
|||
package com.google.common.cache;
|
||||
|
||||
import com.google.common.annotations.Beta;
|
||||
import com.google.common.annotations.GwtCompatible;
|
||||
import com.google.common.annotations.GwtIncompatible;
|
||||
import com.google.common.base.Function;
|
||||
import com.google.common.base.Preconditions;
|
||||
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;
|
||||
|
||||
@GwtCompatible(
|
||||
emulated = true
|
||||
)
|
||||
public abstract class CacheLoader<K, V> {
|
||||
protected CacheLoader() {
|
||||
}
|
||||
|
||||
public abstract V load(K var1) throws Exception;
|
||||
|
||||
@GwtIncompatible("Futures")
|
||||
public ListenableFuture<V> reload(K key, V oldValue) throws Exception {
|
||||
Preconditions.checkNotNull(key);
|
||||
Preconditions.checkNotNull(oldValue);
|
||||
return Futures.immediateFuture(this.load(key));
|
||||
}
|
||||
|
||||
public Map<K, V> loadAll(Iterable<? extends K> keys) throws Exception {
|
||||
throw new CacheLoader.UnsupportedLoadingOperationException();
|
||||
}
|
||||
|
||||
@Beta
|
||||
public static <K, V> CacheLoader<K, V> from(Function<K, V> function) {
|
||||
return new CacheLoader.FunctionToCacheLoader(function);
|
||||
}
|
||||
|
||||
@Beta
|
||||
public static <V> CacheLoader<Object, V> from(Supplier<V> supplier) {
|
||||
return new CacheLoader.SupplierToCacheLoader(supplier);
|
||||
}
|
||||
|
||||
@Beta
|
||||
@GwtIncompatible("Executor + Futures")
|
||||
public static <K, V> CacheLoader<K, V> asyncReloading(final CacheLoader<K, V> loader, final Executor executor) {
|
||||
Preconditions.checkNotNull(loader);
|
||||
Preconditions.checkNotNull(executor);
|
||||
return new CacheLoader<K, V>() {
|
||||
public V load(K key) throws Exception {
|
||||
return loader.load(key);
|
||||
}
|
||||
|
||||
public ListenableFuture<V> reload(final K key, final V oldValue) throws Exception {
|
||||
ListenableFutureTask<V> task = ListenableFutureTask.create(new Callable<V>() {
|
||||
public V call() throws Exception {
|
||||
return loader.reload(key, oldValue).get();
|
||||
}
|
||||
});
|
||||
executor.execute(task);
|
||||
return task;
|
||||
}
|
||||
|
||||
public Map<K, V> loadAll(Iterable<? extends K> keys) throws Exception {
|
||||
return loader.loadAll(keys);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public static final class InvalidCacheLoadException extends RuntimeException {
|
||||
public InvalidCacheLoadException(String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
||||
|
||||
static final class UnsupportedLoadingOperationException extends UnsupportedOperationException {
|
||||
}
|
||||
|
||||
private static final class SupplierToCacheLoader<V> extends CacheLoader<Object, V> implements Serializable {
|
||||
private final Supplier<V> computingSupplier;
|
||||
private static final long serialVersionUID = 0L;
|
||||
|
||||
public SupplierToCacheLoader(Supplier<V> computingSupplier) {
|
||||
this.computingSupplier = (Supplier)Preconditions.checkNotNull(computingSupplier);
|
||||
}
|
||||
|
||||
public V load(Object key) {
|
||||
Preconditions.checkNotNull(key);
|
||||
return this.computingSupplier.get();
|
||||
}
|
||||
}
|
||||
|
||||
private static final class FunctionToCacheLoader<K, V> extends CacheLoader<K, V> implements Serializable {
|
||||
private final Function<K, V> computingFunction;
|
||||
private static final long serialVersionUID = 0L;
|
||||
|
||||
public FunctionToCacheLoader(Function<K, V> computingFunction) {
|
||||
this.computingFunction = (Function)Preconditions.checkNotNull(computingFunction);
|
||||
}
|
||||
|
||||
public V load(K key) {
|
||||
return this.computingFunction.apply(Preconditions.checkNotNull(key));
|
||||
}
|
||||
}
|
||||
}
|
111
src/main/com/google/common/cache/CacheStats.java
vendored
Normal file
111
src/main/com/google/common/cache/CacheStats.java
vendored
Normal file
|
@ -0,0 +1,111 @@
|
|||
package com.google.common.cache;
|
||||
|
||||
import com.google.common.annotations.Beta;
|
||||
import com.google.common.annotations.GwtCompatible;
|
||||
import com.google.common.base.MoreObjects;
|
||||
import com.google.common.base.Objects;
|
||||
import com.google.common.base.Preconditions;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
@Beta
|
||||
@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;
|
||||
|
||||
public CacheStats(long hitCount, long missCount, long loadSuccessCount, long loadExceptionCount, long totalLoadTime, long evictionCount) {
|
||||
Preconditions.checkArgument(hitCount >= 0L);
|
||||
Preconditions.checkArgument(missCount >= 0L);
|
||||
Preconditions.checkArgument(loadSuccessCount >= 0L);
|
||||
Preconditions.checkArgument(loadExceptionCount >= 0L);
|
||||
Preconditions.checkArgument(totalLoadTime >= 0L);
|
||||
Preconditions.checkArgument(evictionCount >= 0L);
|
||||
this.hitCount = hitCount;
|
||||
this.missCount = missCount;
|
||||
this.loadSuccessCount = loadSuccessCount;
|
||||
this.loadExceptionCount = loadExceptionCount;
|
||||
this.totalLoadTime = totalLoadTime;
|
||||
this.evictionCount = evictionCount;
|
||||
}
|
||||
|
||||
public long requestCount() {
|
||||
return this.hitCount + this.missCount;
|
||||
}
|
||||
|
||||
public long hitCount() {
|
||||
return this.hitCount;
|
||||
}
|
||||
|
||||
public double hitRate() {
|
||||
long requestCount = this.requestCount();
|
||||
return requestCount == 0L ? 1.0D : (double)this.hitCount / (double)requestCount;
|
||||
}
|
||||
|
||||
public long missCount() {
|
||||
return this.missCount;
|
||||
}
|
||||
|
||||
public double missRate() {
|
||||
long requestCount = this.requestCount();
|
||||
return requestCount == 0L ? 0.0D : (double)this.missCount / (double)requestCount;
|
||||
}
|
||||
|
||||
public long loadCount() {
|
||||
return this.loadSuccessCount + this.loadExceptionCount;
|
||||
}
|
||||
|
||||
public long loadSuccessCount() {
|
||||
return this.loadSuccessCount;
|
||||
}
|
||||
|
||||
public long loadExceptionCount() {
|
||||
return this.loadExceptionCount;
|
||||
}
|
||||
|
||||
public double loadExceptionRate() {
|
||||
long totalLoadCount = this.loadSuccessCount + this.loadExceptionCount;
|
||||
return totalLoadCount == 0L ? 0.0D : (double)this.loadExceptionCount / (double)totalLoadCount;
|
||||
}
|
||||
|
||||
public long totalLoadTime() {
|
||||
return this.totalLoadTime;
|
||||
}
|
||||
|
||||
public double averageLoadPenalty() {
|
||||
long totalLoadCount = this.loadSuccessCount + this.loadExceptionCount;
|
||||
return totalLoadCount == 0L ? 0.0D : (double)this.totalLoadTime / (double)totalLoadCount;
|
||||
}
|
||||
|
||||
public long evictionCount() {
|
||||
return this.evictionCount;
|
||||
}
|
||||
|
||||
public CacheStats minus(CacheStats other) {
|
||||
return new CacheStats(Math.max(0L, this.hitCount - other.hitCount), Math.max(0L, this.missCount - other.missCount), Math.max(0L, this.loadSuccessCount - other.loadSuccessCount), Math.max(0L, this.loadExceptionCount - other.loadExceptionCount), Math.max(0L, this.totalLoadTime - other.totalLoadTime), Math.max(0L, this.evictionCount - other.evictionCount));
|
||||
}
|
||||
|
||||
public CacheStats plus(CacheStats other) {
|
||||
return new CacheStats(this.hitCount + other.hitCount, this.missCount + other.missCount, this.loadSuccessCount + other.loadSuccessCount, this.loadExceptionCount + other.loadExceptionCount, this.totalLoadTime + other.totalLoadTime, this.evictionCount + other.evictionCount);
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
return Objects.hashCode(this.hitCount, this.missCount, this.loadSuccessCount, this.loadExceptionCount, this.totalLoadTime, this.evictionCount);
|
||||
}
|
||||
|
||||
public boolean equals(@Nullable Object object) {
|
||||
if (!(object instanceof CacheStats)) {
|
||||
return false;
|
||||
} else {
|
||||
CacheStats other = (CacheStats)object;
|
||||
return this.hitCount == other.hitCount && this.missCount == other.missCount && this.loadSuccessCount == other.loadSuccessCount && this.loadExceptionCount == other.loadExceptionCount && this.totalLoadTime == other.totalLoadTime && this.evictionCount == other.evictionCount;
|
||||
}
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return MoreObjects.toStringHelper((Object)this).add("hitCount", this.hitCount).add("missCount", this.missCount).add("loadSuccessCount", this.loadSuccessCount).add("loadExceptionCount", this.loadExceptionCount).add("totalLoadTime", this.totalLoadTime).add("evictionCount", this.evictionCount).toString();
|
||||
}
|
||||
}
|
81
src/main/com/google/common/cache/ForwardingCache.java
vendored
Normal file
81
src/main/com/google/common/cache/ForwardingCache.java
vendored
Normal file
|
@ -0,0 +1,81 @@
|
|||
package com.google.common.cache;
|
||||
|
||||
import com.google.common.annotations.Beta;
|
||||
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;
|
||||
|
||||
@Beta
|
||||
public abstract class ForwardingCache<K, V> extends ForwardingObject implements Cache<K, V> {
|
||||
protected ForwardingCache() {
|
||||
}
|
||||
|
||||
protected abstract Cache<K, V> delegate();
|
||||
|
||||
@Nullable
|
||||
public V getIfPresent(Object key) {
|
||||
return this.delegate().getIfPresent(key);
|
||||
}
|
||||
|
||||
public V get(K key, Callable<? extends V> valueLoader) throws ExecutionException {
|
||||
return this.delegate().get(key, valueLoader);
|
||||
}
|
||||
|
||||
public ImmutableMap<K, V> getAllPresent(Iterable<?> keys) {
|
||||
return this.delegate().getAllPresent(keys);
|
||||
}
|
||||
|
||||
public void put(K key, V value) {
|
||||
this.delegate().put(key, value);
|
||||
}
|
||||
|
||||
public void putAll(Map<? extends K, ? extends V> m) {
|
||||
this.delegate().putAll(m);
|
||||
}
|
||||
|
||||
public void invalidate(Object key) {
|
||||
this.delegate().invalidate(key);
|
||||
}
|
||||
|
||||
public void invalidateAll(Iterable<?> keys) {
|
||||
this.delegate().invalidateAll(keys);
|
||||
}
|
||||
|
||||
public void invalidateAll() {
|
||||
this.delegate().invalidateAll();
|
||||
}
|
||||
|
||||
public long size() {
|
||||
return this.delegate().size();
|
||||
}
|
||||
|
||||
public CacheStats stats() {
|
||||
return this.delegate().stats();
|
||||
}
|
||||
|
||||
public ConcurrentMap<K, V> asMap() {
|
||||
return this.delegate().asMap();
|
||||
}
|
||||
|
||||
public void cleanUp() {
|
||||
this.delegate().cleanUp();
|
||||
}
|
||||
|
||||
@Beta
|
||||
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 = (Cache)Preconditions.checkNotNull(delegate);
|
||||
}
|
||||
|
||||
protected final Cache<K, V> delegate() {
|
||||
return this.delegate;
|
||||
}
|
||||
}
|
||||
}
|
47
src/main/com/google/common/cache/ForwardingLoadingCache.java
vendored
Normal file
47
src/main/com/google/common/cache/ForwardingLoadingCache.java
vendored
Normal file
|
@ -0,0 +1,47 @@
|
|||
package com.google.common.cache;
|
||||
|
||||
import com.google.common.annotations.Beta;
|
||||
import com.google.common.base.Preconditions;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
|
||||
@Beta
|
||||
public abstract class ForwardingLoadingCache<K, V> extends ForwardingCache<K, V> implements LoadingCache<K, V> {
|
||||
protected ForwardingLoadingCache() {
|
||||
}
|
||||
|
||||
protected abstract LoadingCache<K, V> delegate();
|
||||
|
||||
public V get(K key) throws ExecutionException {
|
||||
return this.delegate().get(key);
|
||||
}
|
||||
|
||||
public V getUnchecked(K key) {
|
||||
return this.delegate().getUnchecked(key);
|
||||
}
|
||||
|
||||
public ImmutableMap<K, V> getAll(Iterable<? extends K> keys) throws ExecutionException {
|
||||
return this.delegate().getAll(keys);
|
||||
}
|
||||
|
||||
public V apply(K key) {
|
||||
return this.delegate().apply(key);
|
||||
}
|
||||
|
||||
public void refresh(K key) {
|
||||
this.delegate().refresh(key);
|
||||
}
|
||||
|
||||
@Beta
|
||||
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 = (LoadingCache)Preconditions.checkNotNull(delegate);
|
||||
}
|
||||
|
||||
protected final LoadingCache<K, V> delegate() {
|
||||
return this.delegate;
|
||||
}
|
||||
}
|
||||
}
|
26
src/main/com/google/common/cache/LoadingCache.java
vendored
Normal file
26
src/main/com/google/common/cache/LoadingCache.java
vendored
Normal file
|
@ -0,0 +1,26 @@
|
|||
package com.google.common.cache;
|
||||
|
||||
import com.google.common.annotations.Beta;
|
||||
import com.google.common.annotations.GwtCompatible;
|
||||
import com.google.common.base.Function;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
|
||||
@Beta
|
||||
@GwtCompatible
|
||||
public interface LoadingCache<K, V> extends Cache<K, V>, Function<K, V> {
|
||||
V get(K var1) throws ExecutionException;
|
||||
|
||||
V getUnchecked(K var1);
|
||||
|
||||
ImmutableMap<K, V> getAll(Iterable<? extends K> var1) throws ExecutionException;
|
||||
|
||||
/** @deprecated */
|
||||
@Deprecated
|
||||
V apply(K var1);
|
||||
|
||||
void refresh(K var1);
|
||||
|
||||
ConcurrentMap<K, V> asMap();
|
||||
}
|
3792
src/main/com/google/common/cache/LocalCache.java
vendored
Normal file
3792
src/main/com/google/common/cache/LocalCache.java
vendored
Normal file
File diff suppressed because it is too large
Load diff
12
src/main/com/google/common/cache/LongAddable.java
vendored
Normal file
12
src/main/com/google/common/cache/LongAddable.java
vendored
Normal file
|
@ -0,0 +1,12 @@
|
|||
package com.google.common.cache;
|
||||
|
||||
import com.google.common.annotations.GwtCompatible;
|
||||
|
||||
@GwtCompatible
|
||||
interface LongAddable {
|
||||
void increment();
|
||||
|
||||
void add(long var1);
|
||||
|
||||
long sum();
|
||||
}
|
58
src/main/com/google/common/cache/LongAddables.java
vendored
Normal file
58
src/main/com/google/common/cache/LongAddables.java
vendored
Normal file
|
@ -0,0 +1,58 @@
|
|||
package com.google.common.cache;
|
||||
|
||||
import com.google.common.annotations.GwtCompatible;
|
||||
import com.google.common.base.Supplier;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
|
||||
@GwtCompatible(
|
||||
emulated = true
|
||||
)
|
||||
final class LongAddables {
|
||||
private static final Supplier<LongAddable> SUPPLIER;
|
||||
|
||||
public static LongAddable create() {
|
||||
return (LongAddable)SUPPLIER.get();
|
||||
}
|
||||
|
||||
static {
|
||||
Supplier supplier;
|
||||
try {
|
||||
new LongAdder();
|
||||
supplier = new Supplier<LongAddable>() {
|
||||
public LongAddable get() {
|
||||
return new LongAdder();
|
||||
}
|
||||
};
|
||||
} catch (Throwable var2) {
|
||||
supplier = new Supplier<LongAddable>() {
|
||||
public LongAddable get() {
|
||||
return new LongAddables.PureJavaLongAddable();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
SUPPLIER = supplier;
|
||||
}
|
||||
|
||||
private static final class PureJavaLongAddable extends AtomicLong implements LongAddable {
|
||||
private PureJavaLongAddable() {
|
||||
}
|
||||
|
||||
public void increment() {
|
||||
this.getAndIncrement();
|
||||
}
|
||||
|
||||
public void add(long x) {
|
||||
this.getAndAdd(x);
|
||||
}
|
||||
|
||||
public long sum() {
|
||||
return this.get();
|
||||
}
|
||||
|
||||
// $FF: synthetic method
|
||||
PureJavaLongAddable(Object x0) {
|
||||
this();
|
||||
}
|
||||
}
|
||||
}
|
117
src/main/com/google/common/cache/LongAdder.java
vendored
Normal file
117
src/main/com/google/common/cache/LongAdder.java
vendored
Normal file
|
@ -0,0 +1,117 @@
|
|||
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;
|
||||
|
||||
@GwtCompatible(
|
||||
emulated = true
|
||||
)
|
||||
final class LongAdder extends Striped64 implements Serializable, LongAddable {
|
||||
private static final long serialVersionUID = 7249069246863182397L;
|
||||
|
||||
final long fn(long v, long x) {
|
||||
return v + x;
|
||||
}
|
||||
|
||||
public LongAdder() {
|
||||
}
|
||||
|
||||
public void add(long x) {
|
||||
Striped64.Cell[] as;
|
||||
long b;
|
||||
if ((as = this.cells) != null || !this.casBase(b = this.base, b + x)) {
|
||||
boolean uncontended = true;
|
||||
long v;
|
||||
int[] hc;
|
||||
Striped64.Cell a;
|
||||
int n;
|
||||
if ((hc = (int[])threadHashCode.get()) == null || as == null || (n = as.length) < 1 || (a = as[n - 1 & hc[0]]) == null || !(uncontended = a.cas(v = a.value, v + x))) {
|
||||
this.retryUpdate(x, hc, uncontended);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void increment() {
|
||||
this.add(1L);
|
||||
}
|
||||
|
||||
public void decrement() {
|
||||
this.add(-1L);
|
||||
}
|
||||
|
||||
public long sum() {
|
||||
long sum = this.base;
|
||||
Striped64.Cell[] as = this.cells;
|
||||
if (as != null) {
|
||||
int n = as.length;
|
||||
|
||||
for(int i = 0; i < n; ++i) {
|
||||
Striped64.Cell a = as[i];
|
||||
if (a != null) {
|
||||
sum += a.value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return sum;
|
||||
}
|
||||
|
||||
public void reset() {
|
||||
this.internalReset(0L);
|
||||
}
|
||||
|
||||
public long sumThenReset() {
|
||||
long sum = this.base;
|
||||
Striped64.Cell[] as = this.cells;
|
||||
this.base = 0L;
|
||||
if (as != null) {
|
||||
int n = as.length;
|
||||
|
||||
for(int i = 0; i < n; ++i) {
|
||||
Striped64.Cell a = as[i];
|
||||
if (a != null) {
|
||||
sum += a.value;
|
||||
a.value = 0L;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return sum;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return Long.toString(this.sum());
|
||||
}
|
||||
|
||||
public long longValue() {
|
||||
return this.sum();
|
||||
}
|
||||
|
||||
public int intValue() {
|
||||
return (int)this.sum();
|
||||
}
|
||||
|
||||
public float floatValue() {
|
||||
return (float)this.sum();
|
||||
}
|
||||
|
||||
public double doubleValue() {
|
||||
return (double)this.sum();
|
||||
}
|
||||
|
||||
private void writeObject(ObjectOutputStream s) throws IOException {
|
||||
s.defaultWriteObject();
|
||||
s.writeLong(this.sum());
|
||||
}
|
||||
|
||||
private void readObject(ObjectInputStream s) throws IOException, ClassNotFoundException {
|
||||
s.defaultReadObject();
|
||||
this.busy = 0;
|
||||
this.cells = null;
|
||||
this.base = s.readLong();
|
||||
}
|
||||
}
|
44
src/main/com/google/common/cache/RemovalCause.java
vendored
Normal file
44
src/main/com/google/common/cache/RemovalCause.java
vendored
Normal file
|
@ -0,0 +1,44 @@
|
|||
package com.google.common.cache;
|
||||
|
||||
import com.google.common.annotations.Beta;
|
||||
import com.google.common.annotations.GwtCompatible;
|
||||
|
||||
@Beta
|
||||
@GwtCompatible
|
||||
public enum RemovalCause {
|
||||
EXPLICIT {
|
||||
boolean wasEvicted() {
|
||||
return false;
|
||||
}
|
||||
},
|
||||
REPLACED {
|
||||
boolean wasEvicted() {
|
||||
return false;
|
||||
}
|
||||
},
|
||||
COLLECTED {
|
||||
boolean wasEvicted() {
|
||||
return true;
|
||||
}
|
||||
},
|
||||
EXPIRED {
|
||||
boolean wasEvicted() {
|
||||
return true;
|
||||
}
|
||||
},
|
||||
SIZE {
|
||||
boolean wasEvicted() {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
private RemovalCause() {
|
||||
}
|
||||
|
||||
abstract boolean wasEvicted();
|
||||
|
||||
// $FF: synthetic method
|
||||
RemovalCause(Object x2) {
|
||||
this();
|
||||
}
|
||||
}
|
10
src/main/com/google/common/cache/RemovalListener.java
vendored
Normal file
10
src/main/com/google/common/cache/RemovalListener.java
vendored
Normal file
|
@ -0,0 +1,10 @@
|
|||
package com.google.common.cache;
|
||||
|
||||
import com.google.common.annotations.Beta;
|
||||
import com.google.common.annotations.GwtCompatible;
|
||||
|
||||
@Beta
|
||||
@GwtCompatible
|
||||
public interface RemovalListener<K, V> {
|
||||
void onRemoval(RemovalNotification<K, V> var1);
|
||||
}
|
25
src/main/com/google/common/cache/RemovalListeners.java
vendored
Normal file
25
src/main/com/google/common/cache/RemovalListeners.java
vendored
Normal file
|
@ -0,0 +1,25 @@
|
|||
package com.google.common.cache;
|
||||
|
||||
import com.google.common.annotations.Beta;
|
||||
import com.google.common.base.Preconditions;
|
||||
import java.util.concurrent.Executor;
|
||||
|
||||
@Beta
|
||||
public final class RemovalListeners {
|
||||
private RemovalListeners() {
|
||||
}
|
||||
|
||||
public static <K, V> RemovalListener<K, V> asynchronous(final RemovalListener<K, V> listener, final Executor executor) {
|
||||
Preconditions.checkNotNull(listener);
|
||||
Preconditions.checkNotNull(executor);
|
||||
return new RemovalListener<K, V>() {
|
||||
public void onRemoval(final RemovalNotification<K, V> notification) {
|
||||
executor.execute(new Runnable() {
|
||||
public void run() {
|
||||
listener.onRemoval(notification);
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
68
src/main/com/google/common/cache/RemovalNotification.java
vendored
Normal file
68
src/main/com/google/common/cache/RemovalNotification.java
vendored
Normal file
|
@ -0,0 +1,68 @@
|
|||
package com.google.common.cache;
|
||||
|
||||
import com.google.common.annotations.Beta;
|
||||
import com.google.common.annotations.GwtCompatible;
|
||||
import com.google.common.base.Objects;
|
||||
import com.google.common.base.Preconditions;
|
||||
import java.util.Map.Entry;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
@Beta
|
||||
@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;
|
||||
private static final long serialVersionUID = 0L;
|
||||
|
||||
RemovalNotification(@Nullable K key, @Nullable V value, RemovalCause cause) {
|
||||
this.key = key;
|
||||
this.value = value;
|
||||
this.cause = (RemovalCause)Preconditions.checkNotNull(cause);
|
||||
}
|
||||
|
||||
public RemovalCause getCause() {
|
||||
return this.cause;
|
||||
}
|
||||
|
||||
public boolean wasEvicted() {
|
||||
return this.cause.wasEvicted();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public K getKey() {
|
||||
return this.key;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public V getValue() {
|
||||
return this.value;
|
||||
}
|
||||
|
||||
public final V setValue(V value) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public boolean equals(@Nullable Object object) {
|
||||
if (!(object instanceof Entry)) {
|
||||
return false;
|
||||
} else {
|
||||
Entry<?, ?> that = (Entry)object;
|
||||
return Objects.equal(this.getKey(), that.getKey()) && Objects.equal(this.getValue(), that.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
K k = this.getKey();
|
||||
V v = this.getValue();
|
||||
return (k == null ? 0 : k.hashCode()) ^ (v == null ? 0 : v.hashCode());
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
String var1 = String.valueOf(String.valueOf(this.getKey()));
|
||||
String var2 = String.valueOf(String.valueOf(this.getValue()));
|
||||
return (new StringBuilder(1 + var1.length() + var2.length())).append(var1).append("=").append(var2).toString();
|
||||
}
|
||||
}
|
229
src/main/com/google/common/cache/Striped64.java
vendored
Normal file
229
src/main/com/google/common/cache/Striped64.java
vendored
Normal file
|
@ -0,0 +1,229 @@
|
|||
package com.google.common.cache;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.security.AccessController;
|
||||
import java.security.PrivilegedActionException;
|
||||
import java.security.PrivilegedExceptionAction;
|
||||
import java.util.Random;
|
||||
import sun.misc.Unsafe;
|
||||
|
||||
abstract class Striped64 extends Number {
|
||||
static final ThreadLocal<int[]> threadHashCode = new ThreadLocal();
|
||||
static final Random rng = new Random();
|
||||
static final int NCPU = Runtime.getRuntime().availableProcessors();
|
||||
transient volatile Striped64.Cell[] cells;
|
||||
transient volatile long base;
|
||||
transient volatile int busy;
|
||||
private static final Unsafe UNSAFE;
|
||||
private static final long baseOffset;
|
||||
private static final long busyOffset;
|
||||
|
||||
final boolean casBase(long cmp, long val) {
|
||||
return UNSAFE.compareAndSwapLong(this, baseOffset, cmp, val);
|
||||
}
|
||||
|
||||
final boolean casBusy() {
|
||||
return UNSAFE.compareAndSwapInt(this, busyOffset, 0, 1);
|
||||
}
|
||||
|
||||
abstract long fn(long var1, long var3);
|
||||
|
||||
final void retryUpdate(long x, int[] hc, boolean wasUncontended) {
|
||||
int h;
|
||||
if (hc == null) {
|
||||
threadHashCode.set(hc = new int[1]);
|
||||
int r = rng.nextInt();
|
||||
h = hc[0] = r == 0 ? 1 : r;
|
||||
} else {
|
||||
h = hc[0];
|
||||
}
|
||||
|
||||
boolean collide = false;
|
||||
|
||||
while(true) {
|
||||
Striped64.Cell[] as;
|
||||
int n;
|
||||
long v;
|
||||
if ((as = this.cells) != null && (n = as.length) > 0) {
|
||||
Striped64.Cell a;
|
||||
if ((a = as[n - 1 & h]) == null) {
|
||||
if (this.busy == 0) {
|
||||
Striped64.Cell r = new Striped64.Cell(x);
|
||||
if (this.busy == 0 && this.casBusy()) {
|
||||
boolean created = false;
|
||||
|
||||
try {
|
||||
Striped64.Cell[] rs;
|
||||
int m;
|
||||
int j;
|
||||
if ((rs = this.cells) != null && (m = rs.length) > 0 && rs[j = m - 1 & h] == null) {
|
||||
rs[j] = r;
|
||||
created = true;
|
||||
}
|
||||
} finally {
|
||||
this.busy = 0;
|
||||
}
|
||||
|
||||
if (created) {
|
||||
break;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
collide = false;
|
||||
} else if (!wasUncontended) {
|
||||
wasUncontended = true;
|
||||
} else {
|
||||
if (a.cas(v = a.value, this.fn(v, x))) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (n < NCPU && this.cells == as) {
|
||||
if (!collide) {
|
||||
collide = true;
|
||||
} else if (this.busy == 0 && this.casBusy()) {
|
||||
try {
|
||||
if (this.cells == as) {
|
||||
Striped64.Cell[] rs = new Striped64.Cell[n << 1];
|
||||
|
||||
for(int i = 0; i < n; ++i) {
|
||||
rs[i] = as[i];
|
||||
}
|
||||
|
||||
this.cells = rs;
|
||||
}
|
||||
} finally {
|
||||
this.busy = 0;
|
||||
}
|
||||
|
||||
collide = false;
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
collide = false;
|
||||
}
|
||||
}
|
||||
|
||||
h ^= h << 13;
|
||||
h ^= h >>> 17;
|
||||
h ^= h << 5;
|
||||
hc[0] = h;
|
||||
} else if (this.busy == 0 && this.cells == as && this.casBusy()) {
|
||||
boolean init = false;
|
||||
|
||||
try {
|
||||
if (this.cells == as) {
|
||||
Striped64.Cell[] rs = new Striped64.Cell[2];
|
||||
rs[h & 1] = new Striped64.Cell(x);
|
||||
this.cells = rs;
|
||||
init = true;
|
||||
}
|
||||
} finally {
|
||||
this.busy = 0;
|
||||
}
|
||||
|
||||
if (init) {
|
||||
break;
|
||||
}
|
||||
} else if (this.casBase(v = this.base, this.fn(v, x))) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
final void internalReset(long initialValue) {
|
||||
Striped64.Cell[] as = this.cells;
|
||||
this.base = initialValue;
|
||||
if (as != null) {
|
||||
int n = as.length;
|
||||
|
||||
for(int i = 0; i < n; ++i) {
|
||||
Striped64.Cell a = as[i];
|
||||
if (a != null) {
|
||||
a.value = initialValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static Unsafe getUnsafe() {
|
||||
try {
|
||||
return Unsafe.getUnsafe();
|
||||
} catch (SecurityException var2) {
|
||||
try {
|
||||
return (Unsafe)AccessController.doPrivileged(new PrivilegedExceptionAction<Unsafe>() {
|
||||
public Unsafe run() throws Exception {
|
||||
Class<Unsafe> k = Unsafe.class;
|
||||
Field[] arr$ = k.getDeclaredFields();
|
||||
int len$ = arr$.length;
|
||||
|
||||
for(int i$ = 0; i$ < len$; ++i$) {
|
||||
Field f = arr$[i$];
|
||||
f.setAccessible(true);
|
||||
Object x = f.get((Object)null);
|
||||
if (k.isInstance(x)) {
|
||||
return (Unsafe)k.cast(x);
|
||||
}
|
||||
}
|
||||
|
||||
throw new NoSuchFieldError("the Unsafe");
|
||||
}
|
||||
});
|
||||
} catch (PrivilegedActionException var1) {
|
||||
throw new RuntimeException("Could not initialize intrinsics", var1.getCause());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static {
|
||||
try {
|
||||
UNSAFE = getUnsafe();
|
||||
Class<?> sk = Striped64.class;
|
||||
baseOffset = UNSAFE.objectFieldOffset(sk.getDeclaredField("base"));
|
||||
busyOffset = UNSAFE.objectFieldOffset(sk.getDeclaredField("busy"));
|
||||
} catch (Exception var1) {
|
||||
throw new Error(var1);
|
||||
}
|
||||
}
|
||||
|
||||
static final class Cell {
|
||||
volatile long p0;
|
||||
volatile long p1;
|
||||
volatile long p2;
|
||||
volatile long p3;
|
||||
volatile long p4;
|
||||
volatile long p5;
|
||||
volatile long p6;
|
||||
volatile long value;
|
||||
volatile long q0;
|
||||
volatile long q1;
|
||||
volatile long q2;
|
||||
volatile long q3;
|
||||
volatile long q4;
|
||||
volatile long q5;
|
||||
volatile long q6;
|
||||
private static final Unsafe UNSAFE;
|
||||
private static final long valueOffset;
|
||||
|
||||
Cell(long x) {
|
||||
this.value = x;
|
||||
}
|
||||
|
||||
final boolean cas(long cmp, long val) {
|
||||
return UNSAFE.compareAndSwapLong(this, valueOffset, cmp, val);
|
||||
}
|
||||
|
||||
static {
|
||||
try {
|
||||
UNSAFE = Striped64.getUnsafe();
|
||||
Class<?> ak = Striped64.Cell.class;
|
||||
valueOffset = UNSAFE.objectFieldOffset(ak.getDeclaredField("value"));
|
||||
} catch (Exception var1) {
|
||||
throw new Error(var1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
10
src/main/com/google/common/cache/Weigher.java
vendored
Normal file
10
src/main/com/google/common/cache/Weigher.java
vendored
Normal file
|
@ -0,0 +1,10 @@
|
|||
package com.google.common.cache;
|
||||
|
||||
import com.google.common.annotations.Beta;
|
||||
import com.google.common.annotations.GwtCompatible;
|
||||
|
||||
@Beta
|
||||
@GwtCompatible
|
||||
public interface Weigher<K, V> {
|
||||
int weigh(K var1, V var2);
|
||||
}
|
8
src/main/com/google/common/cache/package-info.java
vendored
Normal file
8
src/main/com/google/common/cache/package-info.java
vendored
Normal file
|
@ -0,0 +1,8 @@
|
|||
package com.google.common.cache;
|
||||
|
||||
import javax.annotation.ParametersAreNonnullByDefault;
|
||||
|
||||
// $FF: synthetic class
|
||||
@ParametersAreNonnullByDefault
|
||||
interface package-info {
|
||||
}
|
364
src/main/com/google/common/collect/AbstractBiMap.java
Normal file
364
src/main/com/google/common/collect/AbstractBiMap.java
Normal file
|
@ -0,0 +1,364 @@
|
|||
package com.google.common.collect;
|
||||
|
||||
import com.google.common.annotations.GwtCompatible;
|
||||
import com.google.common.annotations.GwtIncompatible;
|
||||
import com.google.common.base.Objects;
|
||||
import com.google.common.base.Preconditions;
|
||||
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 java.util.Map.Entry;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
@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;
|
||||
private transient Set<K> keySet;
|
||||
private transient Set<V> valueSet;
|
||||
private transient Set<Entry<K, V>> entrySet;
|
||||
@GwtIncompatible("Not needed in emulated source.")
|
||||
private static final long serialVersionUID = 0L;
|
||||
|
||||
AbstractBiMap(Map<K, V> forward, Map<V, K> backward) {
|
||||
this.setDelegates(forward, backward);
|
||||
}
|
||||
|
||||
private AbstractBiMap(Map<K, V> backward, AbstractBiMap<V, K> forward) {
|
||||
this.delegate = backward;
|
||||
this.inverse = forward;
|
||||
}
|
||||
|
||||
protected Map<K, V> delegate() {
|
||||
return this.delegate;
|
||||
}
|
||||
|
||||
K checkKey(@Nullable K key) {
|
||||
return key;
|
||||
}
|
||||
|
||||
V checkValue(@Nullable V value) {
|
||||
return value;
|
||||
}
|
||||
|
||||
void setDelegates(Map<K, V> forward, Map<V, K> backward) {
|
||||
Preconditions.checkState(this.delegate == null);
|
||||
Preconditions.checkState(this.inverse == null);
|
||||
Preconditions.checkArgument(forward.isEmpty());
|
||||
Preconditions.checkArgument(backward.isEmpty());
|
||||
Preconditions.checkArgument(forward != backward);
|
||||
this.delegate = forward;
|
||||
this.inverse = new AbstractBiMap.Inverse(backward, this);
|
||||
}
|
||||
|
||||
void setInverse(AbstractBiMap<V, K> inverse) {
|
||||
this.inverse = inverse;
|
||||
}
|
||||
|
||||
public boolean containsValue(@Nullable Object value) {
|
||||
return this.inverse.containsKey(value);
|
||||
}
|
||||
|
||||
public V put(@Nullable K key, @Nullable V value) {
|
||||
return this.putInBothMaps(key, value, false);
|
||||
}
|
||||
|
||||
public V forcePut(@Nullable K key, @Nullable V value) {
|
||||
return this.putInBothMaps(key, value, true);
|
||||
}
|
||||
|
||||
private V putInBothMaps(@Nullable K key, @Nullable V value, boolean force) {
|
||||
this.checkKey(key);
|
||||
this.checkValue(value);
|
||||
boolean containedKey = this.containsKey(key);
|
||||
if (containedKey && Objects.equal(value, this.get(key))) {
|
||||
return value;
|
||||
} else {
|
||||
if (force) {
|
||||
this.inverse().remove(value);
|
||||
} else {
|
||||
Preconditions.checkArgument(!this.containsValue(value), "value already present: %s", value);
|
||||
}
|
||||
|
||||
V oldValue = this.delegate.put(key, value);
|
||||
this.updateInverseMap(key, containedKey, oldValue, value);
|
||||
return oldValue;
|
||||
}
|
||||
}
|
||||
|
||||
private void updateInverseMap(K key, boolean containedKey, V oldValue, V newValue) {
|
||||
if (containedKey) {
|
||||
this.removeFromInverseMap(oldValue);
|
||||
}
|
||||
|
||||
this.inverse.delegate.put(newValue, key);
|
||||
}
|
||||
|
||||
public V remove(@Nullable Object key) {
|
||||
return this.containsKey(key) ? this.removeFromBothMaps(key) : null;
|
||||
}
|
||||
|
||||
private V removeFromBothMaps(Object key) {
|
||||
V oldValue = this.delegate.remove(key);
|
||||
this.removeFromInverseMap(oldValue);
|
||||
return oldValue;
|
||||
}
|
||||
|
||||
private void removeFromInverseMap(V oldValue) {
|
||||
this.inverse.delegate.remove(oldValue);
|
||||
}
|
||||
|
||||
public void putAll(Map<? extends K, ? extends V> map) {
|
||||
Iterator i$ = map.entrySet().iterator();
|
||||
|
||||
while(i$.hasNext()) {
|
||||
Entry<? extends K, ? extends V> entry = (Entry)i$.next();
|
||||
this.put(entry.getKey(), entry.getValue());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
this.delegate.clear();
|
||||
this.inverse.delegate.clear();
|
||||
}
|
||||
|
||||
public BiMap<V, K> inverse() {
|
||||
return this.inverse;
|
||||
}
|
||||
|
||||
public Set<K> keySet() {
|
||||
Set<K> result = this.keySet;
|
||||
return result == null ? (this.keySet = new AbstractBiMap.KeySet()) : result;
|
||||
}
|
||||
|
||||
public Set<V> values() {
|
||||
Set<V> result = this.valueSet;
|
||||
return result == null ? (this.valueSet = new AbstractBiMap.ValueSet()) : result;
|
||||
}
|
||||
|
||||
public Set<Entry<K, V>> entrySet() {
|
||||
Set<Entry<K, V>> result = this.entrySet;
|
||||
return result == null ? (this.entrySet = new AbstractBiMap.EntrySet()) : result;
|
||||
}
|
||||
|
||||
// $FF: synthetic method
|
||||
AbstractBiMap(Map x0, AbstractBiMap x1, Object x2) {
|
||||
this(x0, x1);
|
||||
}
|
||||
|
||||
private static class Inverse<K, V> extends AbstractBiMap<K, V> {
|
||||
@GwtIncompatible("Not needed in emulated source.")
|
||||
private static final long serialVersionUID = 0L;
|
||||
|
||||
private Inverse(Map<K, V> backward, AbstractBiMap<V, K> forward) {
|
||||
super(backward, forward, null);
|
||||
}
|
||||
|
||||
K checkKey(K key) {
|
||||
return this.inverse.checkValue(key);
|
||||
}
|
||||
|
||||
V checkValue(V value) {
|
||||
return this.inverse.checkKey(value);
|
||||
}
|
||||
|
||||
@GwtIncompatible("java.io.ObjectOuputStream")
|
||||
private void writeObject(ObjectOutputStream stream) throws IOException {
|
||||
stream.defaultWriteObject();
|
||||
stream.writeObject(this.inverse());
|
||||
}
|
||||
|
||||
@GwtIncompatible("java.io.ObjectInputStream")
|
||||
private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException {
|
||||
stream.defaultReadObject();
|
||||
this.setInverse((AbstractBiMap)stream.readObject());
|
||||
}
|
||||
|
||||
@GwtIncompatible("Not needed in the emulated source.")
|
||||
Object readResolve() {
|
||||
return this.inverse().inverse();
|
||||
}
|
||||
|
||||
// $FF: synthetic method
|
||||
Inverse(Map x0, AbstractBiMap x1, Object x2) {
|
||||
this(x0, x1);
|
||||
}
|
||||
}
|
||||
|
||||
private class EntrySet extends ForwardingSet<Entry<K, V>> {
|
||||
final Set<Entry<K, V>> esDelegate;
|
||||
|
||||
private EntrySet() {
|
||||
this.esDelegate = AbstractBiMap.this.delegate.entrySet();
|
||||
}
|
||||
|
||||
protected Set<Entry<K, V>> delegate() {
|
||||
return this.esDelegate;
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
AbstractBiMap.this.clear();
|
||||
}
|
||||
|
||||
public boolean remove(Object object) {
|
||||
if (!this.esDelegate.contains(object)) {
|
||||
return false;
|
||||
} else {
|
||||
Entry<?, ?> entry = (Entry)object;
|
||||
AbstractBiMap.this.inverse.delegate.remove(entry.getValue());
|
||||
this.esDelegate.remove(entry);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public Iterator<Entry<K, V>> iterator() {
|
||||
final Iterator<Entry<K, V>> iterator = this.esDelegate.iterator();
|
||||
return new Iterator<Entry<K, V>>() {
|
||||
Entry<K, V> entry;
|
||||
|
||||
public boolean hasNext() {
|
||||
return iterator.hasNext();
|
||||
}
|
||||
|
||||
public Entry<K, V> next() {
|
||||
this.entry = (Entry)iterator.next();
|
||||
final Entry<K, V> finalEntry = this.entry;
|
||||
return new ForwardingMapEntry<K, V>() {
|
||||
protected Entry<K, V> delegate() {
|
||||
return finalEntry;
|
||||
}
|
||||
|
||||
public V setValue(V value) {
|
||||
Preconditions.checkState(EntrySet.this.contains(this), "entry no longer in map");
|
||||
if (Objects.equal(value, this.getValue())) {
|
||||
return value;
|
||||
} else {
|
||||
Preconditions.checkArgument(!AbstractBiMap.this.containsValue(value), "value already present: %s", value);
|
||||
V oldValue = finalEntry.setValue(value);
|
||||
Preconditions.checkState(Objects.equal(value, AbstractBiMap.this.get(this.getKey())), "entry no longer in map");
|
||||
AbstractBiMap.this.updateInverseMap(this.getKey(), true, oldValue, value);
|
||||
return oldValue;
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public void remove() {
|
||||
CollectPreconditions.checkRemove(this.entry != null);
|
||||
V value = this.entry.getValue();
|
||||
iterator.remove();
|
||||
AbstractBiMap.this.removeFromInverseMap(value);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public Object[] toArray() {
|
||||
return this.standardToArray();
|
||||
}
|
||||
|
||||
public <T> T[] toArray(T[] array) {
|
||||
return this.standardToArray(array);
|
||||
}
|
||||
|
||||
public boolean contains(Object o) {
|
||||
return Maps.containsEntryImpl(this.delegate(), o);
|
||||
}
|
||||
|
||||
public boolean containsAll(Collection<?> c) {
|
||||
return this.standardContainsAll(c);
|
||||
}
|
||||
|
||||
public boolean removeAll(Collection<?> c) {
|
||||
return this.standardRemoveAll(c);
|
||||
}
|
||||
|
||||
public boolean retainAll(Collection<?> c) {
|
||||
return this.standardRetainAll(c);
|
||||
}
|
||||
|
||||
// $FF: synthetic method
|
||||
EntrySet(Object x1) {
|
||||
this();
|
||||
}
|
||||
}
|
||||
|
||||
private class ValueSet extends ForwardingSet<V> {
|
||||
final Set<V> valuesDelegate;
|
||||
|
||||
private ValueSet() {
|
||||
this.valuesDelegate = AbstractBiMap.this.inverse.keySet();
|
||||
}
|
||||
|
||||
protected Set<V> delegate() {
|
||||
return this.valuesDelegate;
|
||||
}
|
||||
|
||||
public Iterator<V> iterator() {
|
||||
return Maps.valueIterator(AbstractBiMap.this.entrySet().iterator());
|
||||
}
|
||||
|
||||
public Object[] toArray() {
|
||||
return this.standardToArray();
|
||||
}
|
||||
|
||||
public <T> T[] toArray(T[] array) {
|
||||
return this.standardToArray(array);
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return this.standardToString();
|
||||
}
|
||||
|
||||
// $FF: synthetic method
|
||||
ValueSet(Object x1) {
|
||||
this();
|
||||
}
|
||||
}
|
||||
|
||||
private class KeySet extends ForwardingSet<K> {
|
||||
private KeySet() {
|
||||
}
|
||||
|
||||
protected Set<K> delegate() {
|
||||
return AbstractBiMap.this.delegate.keySet();
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
AbstractBiMap.this.clear();
|
||||
}
|
||||
|
||||
public boolean remove(Object key) {
|
||||
if (!this.contains(key)) {
|
||||
return false;
|
||||
} else {
|
||||
AbstractBiMap.this.removeFromBothMaps(key);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean removeAll(Collection<?> keysToRemove) {
|
||||
return this.standardRemoveAll(keysToRemove);
|
||||
}
|
||||
|
||||
public boolean retainAll(Collection<?> keysToRetain) {
|
||||
return this.standardRetainAll(keysToRetain);
|
||||
}
|
||||
|
||||
public Iterator<K> iterator() {
|
||||
return Maps.keyIterator(AbstractBiMap.this.entrySet().iterator());
|
||||
}
|
||||
|
||||
// $FF: synthetic method
|
||||
KeySet(Object x1) {
|
||||
this();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,55 @@
|
|||
package com.google.common.collect;
|
||||
|
||||
import com.google.common.annotations.GwtCompatible;
|
||||
import com.google.common.base.Preconditions;
|
||||
import java.util.NoSuchElementException;
|
||||
|
||||
@GwtCompatible
|
||||
abstract class AbstractIndexedListIterator<E> extends UnmodifiableListIterator<E> {
|
||||
private final int size;
|
||||
private int position;
|
||||
|
||||
protected abstract E get(int var1);
|
||||
|
||||
protected AbstractIndexedListIterator(int size) {
|
||||
this(size, 0);
|
||||
}
|
||||
|
||||
protected AbstractIndexedListIterator(int size, int position) {
|
||||
Preconditions.checkPositionIndex(position, size);
|
||||
this.size = size;
|
||||
this.position = position;
|
||||
}
|
||||
|
||||
public final boolean hasNext() {
|
||||
return this.position < this.size;
|
||||
}
|
||||
|
||||
public final E next() {
|
||||
if (!this.hasNext()) {
|
||||
throw new NoSuchElementException();
|
||||
} else {
|
||||
return this.get(this.position++);
|
||||
}
|
||||
}
|
||||
|
||||
public final int nextIndex() {
|
||||
return this.position;
|
||||
}
|
||||
|
||||
public final boolean hasPrevious() {
|
||||
return this.position > 0;
|
||||
}
|
||||
|
||||
public final E previous() {
|
||||
if (!this.hasPrevious()) {
|
||||
throw new NoSuchElementException();
|
||||
} else {
|
||||
return this.get(--this.position);
|
||||
}
|
||||
}
|
||||
|
||||
public final int previousIndex() {
|
||||
return this.position - 1;
|
||||
}
|
||||
}
|
71
src/main/com/google/common/collect/AbstractIterator.java
Normal file
71
src/main/com/google/common/collect/AbstractIterator.java
Normal file
|
@ -0,0 +1,71 @@
|
|||
package com.google.common.collect;
|
||||
|
||||
import com.google.common.annotations.GwtCompatible;
|
||||
import com.google.common.base.Preconditions;
|
||||
import java.util.NoSuchElementException;
|
||||
|
||||
@GwtCompatible
|
||||
public abstract class AbstractIterator<T> extends UnmodifiableIterator<T> {
|
||||
private AbstractIterator.State state;
|
||||
private T next;
|
||||
|
||||
protected AbstractIterator() {
|
||||
this.state = AbstractIterator.State.NOT_READY;
|
||||
}
|
||||
|
||||
protected abstract T computeNext();
|
||||
|
||||
protected final T endOfData() {
|
||||
this.state = AbstractIterator.State.DONE;
|
||||
return null;
|
||||
}
|
||||
|
||||
public final boolean hasNext() {
|
||||
Preconditions.checkState(this.state != AbstractIterator.State.FAILED);
|
||||
switch(this.state) {
|
||||
case DONE:
|
||||
return false;
|
||||
case READY:
|
||||
return true;
|
||||
default:
|
||||
return this.tryToComputeNext();
|
||||
}
|
||||
}
|
||||
|
||||
private boolean tryToComputeNext() {
|
||||
this.state = AbstractIterator.State.FAILED;
|
||||
this.next = this.computeNext();
|
||||
if (this.state != AbstractIterator.State.DONE) {
|
||||
this.state = AbstractIterator.State.READY;
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public final T next() {
|
||||
if (!this.hasNext()) {
|
||||
throw new NoSuchElementException();
|
||||
} else {
|
||||
this.state = AbstractIterator.State.NOT_READY;
|
||||
T result = this.next;
|
||||
this.next = null;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
public final T peek() {
|
||||
if (!this.hasNext()) {
|
||||
throw new NoSuchElementException();
|
||||
} else {
|
||||
return this.next;
|
||||
}
|
||||
}
|
||||
|
||||
private static enum State {
|
||||
READY,
|
||||
NOT_READY,
|
||||
DONE,
|
||||
FAILED;
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue