Browse Source
Merge in CORE/base-third from ~ROCK/base-third:feature/x to feature/x * commit 'fc8ffd63c5c666a0c2cbc10e5a02cabc4f30af82': REPORT-98514 feat:websocket cbb——移除third下socketio REPORT-98514 feat:websocket cbb——移除third下socketiofeature/x
Rock-刘经诚
1 year ago
1002 changed files with 2 additions and 149026 deletions
@ -1,6 +0,0 @@
|
||||
*.iml |
||||
.idea/ |
||||
.DS_Store |
||||
.project |
||||
.classpath |
||||
*.gradle |
@ -1,18 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?> |
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" |
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" |
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> |
||||
<modelVersion>4.0.0</modelVersion> |
||||
|
||||
<parent> |
||||
<groupId>com.fr.third</groupId> |
||||
<artifactId>step1</artifactId> |
||||
<version>${revision}</version> |
||||
<relativePath>../base-third-project/base-third-step1</relativePath> |
||||
</parent> |
||||
|
||||
<artifactId>fine-jodd</artifactId> |
||||
<version>${revision}</version> |
||||
|
||||
|
||||
</project> |
@ -1,5 +0,0 @@
|
||||
## jodd |
||||
|
||||
版本:3.7.1 |
||||
|
||||
github地址:https://github.com/oblac/jodd/tree/v3.7.1 |
@ -1,43 +0,0 @@
|
||||
// Copyright (c) 2003-present, Jodd Team (http://jodd.org)
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
package com.fr.third.jodd; |
||||
|
||||
/** |
||||
* Jodd! |
||||
*/ |
||||
public class Jodd { |
||||
|
||||
/** |
||||
* Ascii art of Jodds name. Every serious framework needs one:) |
||||
*/ |
||||
public static String JODD = "\n" + |
||||
" __ __ __\n" + |
||||
" / /___ ____/ /___/ /\n" + |
||||
" __ / / __ \\/ __ / __ / \n" + |
||||
" / /_/ / /_/ / /_/ / /_/ / \n" + |
||||
" \\____/\\____/\\__,_/\\__,_/ \n"; |
||||
|
||||
} |
@ -1,188 +0,0 @@
|
||||
// Copyright (c) 2003-present, Jodd Team (http://jodd.org)
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
package com.fr.third.jodd.bean; |
||||
|
||||
import java.util.Map; |
||||
|
||||
import static com.fr.third.jodd.util.StringPool.LEFT_SQ_BRACKET; |
||||
import static com.fr.third.jodd.util.StringPool.RIGHT_SQ_BRACKET; |
||||
|
||||
/** |
||||
* Powerful tool for copying properties from one bean into another. |
||||
* <code>BeanCopy</code> works with POJO beans, but also with <code>Map</code>. |
||||
* |
||||
* @see BeanVisitor |
||||
*/ |
||||
public class BeanCopy extends BeanVisitorImplBase<BeanCopy> { |
||||
|
||||
protected Object destination; |
||||
protected boolean forced; |
||||
protected boolean declaredTarget; |
||||
protected boolean isTargetMap; |
||||
|
||||
// ---------------------------------------------------------------- ctor
|
||||
|
||||
/** |
||||
* Creates new BeanCopy process between the source and the destination. |
||||
* Both source and destination can be a POJO object or a <code>Map</code>. |
||||
*/ |
||||
public BeanCopy(final Object source, final Object destination) { |
||||
this.source = source; |
||||
this.destination = destination; |
||||
} |
||||
|
||||
private BeanCopy(final Object source) { |
||||
this.source = source; |
||||
} |
||||
|
||||
/** |
||||
* Simple static factory for <code>BeanCopy</code>. |
||||
* @see #BeanCopy(Object, Object) |
||||
*/ |
||||
public static BeanCopy beans(final Object source, final Object destination) { |
||||
return new BeanCopy(source, destination); |
||||
} |
||||
|
||||
/** |
||||
* Creates <code>BeanCopy</code> with given POJO bean as a source. |
||||
*/ |
||||
public static BeanCopy fromBean(final Object source) { |
||||
return new BeanCopy(source); |
||||
} |
||||
|
||||
/** |
||||
* Creates <code>BeanCopy</code> with given <code>Map</code> as a source. |
||||
*/ |
||||
public static BeanCopy fromMap(final Map source) { |
||||
BeanCopy beanCopy = new BeanCopy(source); |
||||
|
||||
beanCopy.isSourceMap = true; |
||||
|
||||
return beanCopy; |
||||
} |
||||
|
||||
/** |
||||
* Defines source, detects a map. |
||||
*/ |
||||
public static BeanCopy from(final Object source) { |
||||
BeanCopy beanCopy = new BeanCopy(source); |
||||
|
||||
beanCopy.isSourceMap = source instanceof Map; |
||||
|
||||
return beanCopy; |
||||
} |
||||
|
||||
// ---------------------------------------------------------------- destination
|
||||
|
||||
/** |
||||
* Defines destination bean. |
||||
*/ |
||||
public BeanCopy toBean(final Object destination) { |
||||
this.destination = destination; |
||||
return this; |
||||
} |
||||
|
||||
/** |
||||
* Defines destination map. |
||||
*/ |
||||
public BeanCopy toMap(final Map destination) { |
||||
this.destination = destination; |
||||
|
||||
isTargetMap = true; |
||||
|
||||
return this; |
||||
} |
||||
|
||||
/** |
||||
* Defines destination, detects a map. |
||||
*/ |
||||
public BeanCopy to(final Object destination) { |
||||
this.destination = destination; |
||||
|
||||
this.isTargetMap = destination instanceof Map; |
||||
|
||||
return this; |
||||
} |
||||
|
||||
// ---------------------------------------------------------------- properties
|
||||
|
||||
/** |
||||
* Defines if all properties should be copied (when set to <code>true</code>) |
||||
* or only public (when set to <code>false</code>, default). |
||||
*/ |
||||
@Override |
||||
public BeanCopy declared(final boolean declared) { |
||||
this.declared = declared; |
||||
this.declaredTarget = declared; |
||||
return this; |
||||
} |
||||
|
||||
/** |
||||
* Fine-tuning of the declared behaviour. |
||||
*/ |
||||
public BeanCopy declared(final boolean declaredSource, final boolean declaredTarget) { |
||||
this.declared = declaredSource; |
||||
this.declaredTarget = declaredTarget; |
||||
return this; |
||||
} |
||||
|
||||
public BeanCopy forced(final boolean forced) { |
||||
this.forced = forced; |
||||
return this; |
||||
} |
||||
|
||||
// ---------------------------------------------------------------- visitor
|
||||
|
||||
protected BeanUtil beanUtil; |
||||
|
||||
/** |
||||
* Performs the copying. |
||||
*/ |
||||
public void copy() { |
||||
beanUtil = new BeanUtilBean() |
||||
.declared(declared) |
||||
.forced(forced) |
||||
.silent(true); |
||||
visit(); |
||||
} |
||||
|
||||
/** |
||||
* Copies single property to the destination. |
||||
* Exceptions are ignored, so copying continues if |
||||
* destination does not have some of the sources properties. |
||||
*/ |
||||
@Override |
||||
protected boolean visitProperty(String name, final Object value) { |
||||
if (isTargetMap) { |
||||
name = LEFT_SQ_BRACKET + name + RIGHT_SQ_BRACKET; |
||||
} |
||||
|
||||
beanUtil.setProperty(destination, name, value); |
||||
|
||||
return true; |
||||
} |
||||
|
||||
} |
@ -1,55 +0,0 @@
|
||||
// Copyright (c) 2003-present, Jodd Team (http://jodd.org)
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
package com.fr.third.jodd.bean; |
||||
|
||||
import com.fr.third.jodd.exception.UncheckedException; |
||||
|
||||
/** |
||||
* Unchecked bean exception. |
||||
*/ |
||||
public class BeanException extends UncheckedException { |
||||
|
||||
public BeanException(final Throwable t) { |
||||
super(t); |
||||
} |
||||
|
||||
public BeanException(final String message) { |
||||
super(message); |
||||
} |
||||
|
||||
public BeanException(final String message, final BeanProperty bp) { |
||||
super(message + ". Invalid property: " + bp); |
||||
} |
||||
|
||||
public BeanException(final String message, final Throwable t) { |
||||
super(message, t); |
||||
} |
||||
|
||||
public BeanException(final String message, final BeanProperty bp, final Throwable t) { |
||||
super(message + ". Invalid property: " + bp, t); |
||||
} |
||||
|
||||
} |
@ -1,150 +0,0 @@
|
||||
// Copyright (c) 2003-present, Jodd Team (http://jodd.org)
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
package com.fr.third.jodd.bean; |
||||
|
||||
import com.fr.third.jodd.introspector.ClassDescriptor; |
||||
import com.fr.third.jodd.introspector.ClassIntrospector; |
||||
import com.fr.third.jodd.introspector.Getter; |
||||
import com.fr.third.jodd.introspector.PropertyDescriptor; |
||||
import com.fr.third.jodd.introspector.Setter; |
||||
|
||||
import java.util.function.Supplier; |
||||
|
||||
/** |
||||
* Represents a bean named property. Contains two information: |
||||
* <ol> |
||||
* <li>Bean instance (and cached class descriptor)</li> |
||||
* <li>Property name</li> |
||||
* </ol> |
||||
* Used only internally by {@link BeanUtil} and similar utils. |
||||
*/ |
||||
class BeanProperty { |
||||
|
||||
BeanProperty(final BeanUtilBean beanUtilBean, final Object bean, final String propertyName) { |
||||
this.introspector = beanUtilBean.introspector; |
||||
setName(propertyName); |
||||
updateBean(bean); |
||||
this.last = true; |
||||
this.first = true; |
||||
this.fullName = bean.getClass().getSimpleName() + '#' + propertyName; |
||||
} |
||||
|
||||
// ---------------------------------------------------------------- bean and descriptor
|
||||
|
||||
final String fullName; // initial name
|
||||
final ClassIntrospector introspector; |
||||
Object bean; |
||||
private ClassDescriptor cd; |
||||
String name; // property name
|
||||
boolean last; // is it a last property (when nested)
|
||||
boolean first; // is it first property (when nested)
|
||||
String indexString; // indexString for index property
|
||||
|
||||
/** |
||||
* Sets current property name. |
||||
*/ |
||||
public void setName(final String name) { |
||||
this.name = name; |
||||
this.updateProperty = true; |
||||
} |
||||
|
||||
/** |
||||
* Sets new bean instance. |
||||
*/ |
||||
private void setBean(final Object bean) { |
||||
this.bean = bean; |
||||
this.cd = (bean == null ? null : introspector.lookup(bean.getClass())); |
||||
this.first = false; |
||||
this.updateProperty = true; |
||||
} |
||||
|
||||
/** |
||||
* Updates the bean. Detects special case of suppliers. |
||||
*/ |
||||
public void updateBean(final Object bean) { |
||||
this.setBean(bean); |
||||
|
||||
if (this.cd != null && this.cd.isSupplier()) { |
||||
final Object newBean = ((Supplier)this.bean).get(); |
||||
setBean(newBean); |
||||
} |
||||
} |
||||
|
||||
// ---------------------------------------------------------------- simple properties
|
||||
|
||||
// indicates that property descriptor has to be updated
|
||||
// since there was some property-related change of BeanProperty state
|
||||
private boolean updateProperty = true; |
||||
|
||||
// most recent property descriptor
|
||||
private PropertyDescriptor propertyDescriptor; |
||||
|
||||
/** |
||||
* Loads property descriptor, if property was updated. |
||||
*/ |
||||
private void loadPropertyDescriptor() { |
||||
if (updateProperty) { |
||||
if (cd == null) { |
||||
propertyDescriptor = null; |
||||
} else { |
||||
propertyDescriptor = cd.getPropertyDescriptor(name, true); |
||||
} |
||||
updateProperty = false; |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Returns getter. |
||||
*/ |
||||
public Getter getGetter(final boolean declared) { |
||||
loadPropertyDescriptor(); |
||||
return propertyDescriptor != null ? propertyDescriptor.getGetter(declared) : null; |
||||
} |
||||
|
||||
/** |
||||
* Returns setter. |
||||
*/ |
||||
public Setter getSetter(final boolean declared) { |
||||
loadPropertyDescriptor(); |
||||
return propertyDescriptor != null ? propertyDescriptor.getSetter(declared) : null; |
||||
} |
||||
|
||||
/** |
||||
* Returns <code>true</code> if class is a map. |
||||
*/ |
||||
public boolean isMap() { |
||||
return cd != null && cd.isMap(); |
||||
} |
||||
|
||||
String index; |
||||
|
||||
// ---------------------------------------------------------------- toString
|
||||
|
||||
@Override |
||||
public String toString() { |
||||
return fullName + " (" + (bean != null ? bean.getClass().getSimpleName() : "?") + '#' + name + ')'; |
||||
} |
||||
} |
@ -1,60 +0,0 @@
|
||||
// Copyright (c) 2003-present, Jodd Team (http://jodd.org)
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
package com.fr.third.jodd.bean; |
||||
|
||||
import com.fr.third.jodd.template.ContextTemplateParser; |
||||
import com.fr.third.jodd.template.StringTemplateParser; |
||||
|
||||
/** |
||||
* Bean template is a string template with JSP-alike |
||||
* macros for injecting context values. |
||||
* This is a parser for such bean templates. |
||||
* <p> |
||||
* Once set, <code>BeanTemplateParser</code> instance is reusable |
||||
* as it doesn't store any parsing state. |
||||
* <p> |
||||
* Based on {@link StringTemplateParser}. |
||||
*/ |
||||
public class BeanTemplateParser extends StringTemplateParser { |
||||
|
||||
/** |
||||
* Creates bean-backed <code>MacroResolver</code>. |
||||
*/ |
||||
public ContextTemplateParser of(final Object context) { |
||||
return template -> parseWithBean(template, context); |
||||
} |
||||
|
||||
public String parseWithBean(final String template, final Object context) { |
||||
return super.parse(template, macroName -> { |
||||
Object value = BeanUtil.declaredSilent.getProperty(context, macroName); |
||||
|
||||
if (value == null) { |
||||
return null; |
||||
} |
||||
return value.toString(); |
||||
}); |
||||
} |
||||
} |
@ -1,154 +0,0 @@
|
||||
// Copyright (c) 2003-present, Jodd Team (http://jodd.org)
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
package com.fr.third.jodd.bean; |
||||
|
||||
/** |
||||
* Supreme utility for reading and writing bean properties. However, this one is the fastest available. |
||||
* Although it provides various methods, the whole thing can be easily extended to match most needs. |
||||
* <p> |
||||
* BeanUtil supports: |
||||
* <ul> |
||||
* <li>Nested properties: separated by a dot ('.')</li> |
||||
* <li>Indexed properties: arrays or Lists</li> |
||||
* <li>Simple properties: accessor or Map</li> |
||||
* </ul> |
||||
* |
||||
* <p> |
||||
* Variants includes combinations of forced, declared and silent writing. |
||||
* <ul> |
||||
* <li><i>Forced</i> setting property tries to create destination property so it can be set correctly.</li> |
||||
* <li><i>Silent</i> doesn't throw an exception if destination doesn't exist or if conversion fails.</li> |
||||
* <li><i>Declared</i> includes only declared (public) properties.</li> |
||||
* </ul> |
||||
* <p> |
||||
* This utility considers both bean property methods (set and get accessors), and bean fields. |
||||
* This is done because of several reasons: often there is no need for both set/get accessors, since |
||||
* bean logic requires just one functionality (e.g. just reading). In such case, other bean manipulation |
||||
* libraries still requires to have both accessors in order to set or get value. |
||||
* Another reason is that most common usage is to work with public accessors, and in that case |
||||
* private fields are ignored. |
||||
*/ |
||||
public interface BeanUtil { |
||||
|
||||
/** |
||||
* Default instance of {@link BeanUtilBean}. |
||||
*/ |
||||
BeanUtil pojo = new BeanUtilBean(); |
||||
|
||||
BeanUtil declared = new BeanUtilBean().declared(true); |
||||
|
||||
BeanUtil silent = new BeanUtilBean().silent(true); |
||||
|
||||
BeanUtil forced = new BeanUtilBean().forced(true); |
||||
|
||||
BeanUtil declaredSilent = new BeanUtilBean().declared(true).silent(true); |
||||
|
||||
BeanUtil declaredForced = new BeanUtilBean().declared(true).forced(true); |
||||
|
||||
BeanUtil declaredForcedSilent = new BeanUtilBean().declared(true).forced(true).silent(true); |
||||
|
||||
BeanUtil forcedSilent = new BeanUtilBean().forced(true).silent(true); |
||||
|
||||
// ---------------------------------------------------------------- SET
|
||||
|
||||
/** |
||||
* Sets Java Bean property. |
||||
* @param bean Java POJO bean or a Map |
||||
* @param name property name |
||||
* @param value property value |
||||
*/ |
||||
void setProperty(Object bean, String name, Object value); |
||||
|
||||
/** |
||||
* Sets indexed property. |
||||
*/ |
||||
void setIndexProperty(Object bean, String property, int index, Object value); |
||||
|
||||
/** |
||||
* Sets simple property. |
||||
*/ |
||||
void setSimpleProperty(Object bean, String property, Object value); |
||||
|
||||
|
||||
// ---------------------------------------------------------------- GET
|
||||
|
||||
/** |
||||
* Returns value of bean's property. |
||||
* <p> |
||||
* In silent mode, returning of <code>null</code> is ambiguous: it may means that property name |
||||
* is valid and property value is <code>null</code> or that property name is invalid. |
||||
* <p> |
||||
* Using forced mode does not have any influence on the result. |
||||
*/ |
||||
<T> T getProperty(Object bean, String name); |
||||
|
||||
/** |
||||
* Returns value of indexed property. |
||||
*/ |
||||
<T> T getIndexProperty(Object bean, String property, int index); |
||||
|
||||
/** |
||||
* Reads simple property. |
||||
*/ |
||||
<T> T getSimpleProperty(Object bean, String property); |
||||
|
||||
|
||||
// ---------------------------------------------------------------- HAS
|
||||
|
||||
/** |
||||
* Returns <code>true</code> if bean has a property. |
||||
*/ |
||||
boolean hasProperty(Object bean, String name); |
||||
|
||||
/** |
||||
* Returns <code>true</code> if bean has only a root property. |
||||
* If yes, this means that property may be injected into the bean. |
||||
* If not, bean does not contain the property. |
||||
*/ |
||||
boolean hasRootProperty(Object bean, String name); |
||||
|
||||
/** |
||||
* Returns <code>true</code> if simple property exist. |
||||
*/ |
||||
boolean hasSimpleProperty(Object bean, String property); |
||||
|
||||
|
||||
// ---------------------------------------------------------------- type
|
||||
|
||||
/** |
||||
* Returns property type. |
||||
*/ |
||||
Class<?> getPropertyType(Object bean, String name); |
||||
|
||||
|
||||
// ---------------------------------------------------------------- misc
|
||||
|
||||
/** |
||||
* Returns the very first name chunk of the property. |
||||
*/ |
||||
public String extractThisReference(String propertyName); |
||||
|
||||
} |
@ -1,559 +0,0 @@
|
||||
// Copyright (c) 2003-present, Jodd Team (http://jodd.org)
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
package com.fr.third.jodd.bean; |
||||
|
||||
import com.fr.third.jodd.introspector.Getter; |
||||
import com.fr.third.jodd.introspector.Setter; |
||||
import com.fr.third.jodd.util.ClassUtil; |
||||
import com.fr.third.jodd.util.StringUtil; |
||||
|
||||
import java.lang.reflect.Array; |
||||
import java.util.HashMap; |
||||
import java.util.List; |
||||
import java.util.Map; |
||||
|
||||
/** |
||||
* Instantiable version of {@link BeanUtil}. |
||||
*/ |
||||
public class BeanUtilBean extends BeanUtilUtil implements BeanUtil { |
||||
|
||||
/** |
||||
* Sets the declared flag. |
||||
*/ |
||||
public BeanUtilBean declared(final boolean declared) { |
||||
this.isDeclared = declared; |
||||
return this; |
||||
} |
||||
|
||||
/** |
||||
* Sets the forced flag. |
||||
*/ |
||||
public BeanUtilBean forced(final boolean forced) { |
||||
this.isForced = forced; |
||||
return this; |
||||
} |
||||
|
||||
/** |
||||
* Sets the silent flag. |
||||
*/ |
||||
public BeanUtilBean silent(final boolean silent) { |
||||
this.isSilent = silent; |
||||
return this; |
||||
} |
||||
|
||||
// ---------------------------------------------------------------- internal resolver
|
||||
|
||||
/** |
||||
* Resolves nested property name to the very last indexed property. |
||||
* If forced, <code>null</code> or non-existing properties will be created. |
||||
*/ |
||||
protected void resolveNestedProperties(final BeanProperty bp) { |
||||
String name = bp.name; |
||||
int dotNdx; |
||||
while ((dotNdx = indexOfDot(name)) != -1) { |
||||
bp.last = false; |
||||
bp.setName(name.substring(0, dotNdx)); |
||||
bp.updateBean(getIndexProperty(bp)); |
||||
name = name.substring(dotNdx + 1); |
||||
} |
||||
bp.last = true; |
||||
bp.setName(name); |
||||
} |
||||
|
||||
protected boolean resolveExistingNestedProperties(final BeanProperty bp) { |
||||
String name = bp.name; |
||||
int dotNdx; |
||||
while ((dotNdx = indexOfDot(name)) != -1) { |
||||
bp.last = false; |
||||
bp.setName(name.substring(0, dotNdx)); |
||||
final String temp = bp.name; |
||||
if (!hasIndexProperty(bp)) { |
||||
return false; |
||||
} |
||||
bp.setName(temp); |
||||
bp.updateBean(getIndexProperty(bp)); |
||||
name = name.substring(dotNdx + 1); |
||||
} |
||||
bp.last = true; |
||||
bp.setName(name); |
||||
return true; |
||||
} |
||||
|
||||
|
||||
// ---------------------------------------------------------------- simple property
|
||||
|
||||
@Override |
||||
public boolean hasSimpleProperty(final Object bean, final String property) { |
||||
return hasSimpleProperty(new BeanProperty(this, bean, property)); |
||||
} |
||||
|
||||
protected boolean hasSimpleProperty(final BeanProperty bp) { |
||||
if (bp.bean == null) { |
||||
return false; |
||||
} |
||||
|
||||
// try: getter
|
||||
final Getter getter = bp.getGetter(isDeclared); |
||||
if (getter != null) { |
||||
return true; |
||||
} |
||||
|
||||
// try: (Map) get("property")
|
||||
if (bp.isMap()) { |
||||
Map map = (Map) bp.bean; |
||||
if (map.containsKey(bp.name)) { |
||||
return true; |
||||
} |
||||
} |
||||
|
||||
return false; |
||||
} |
||||
|
||||
@Override |
||||
public <T> T getSimpleProperty(final Object bean, final String property) { |
||||
return (T) getSimpleProperty(new BeanProperty(this, bean, property)); |
||||
} |
||||
|
||||
protected Object getSimpleProperty(final BeanProperty bp) { |
||||
|
||||
if (bp.name.length() == 0) { |
||||
if (bp.indexString != null) { |
||||
// index string exist, but property name is missing
|
||||
return bp.bean; |
||||
} |
||||
throw new BeanException("Invalid property", bp); |
||||
} |
||||
|
||||
Getter getter = bp.getGetter(isDeclared); |
||||
|
||||
if (getter != null) { |
||||
Object result; |
||||
try { |
||||
result = getter.invokeGetter(bp.bean); |
||||
} catch (Exception ex) { |
||||
if (isSilent) { |
||||
return null; |
||||
} |
||||
throw new BeanException("Getter failed: " + getter, ex); |
||||
} |
||||
|
||||
if ((result == null) && (isForced)) { |
||||
result = createBeanProperty(bp); |
||||
} |
||||
return result; |
||||
} |
||||
|
||||
// try: (Map) get("property")
|
||||
if (bp.isMap()) { |
||||
Map map = (Map) bp.bean; |
||||
Object key = convertIndexToMapKey(getter, bp.name); |
||||
|
||||
if (!map.containsKey(key)) { |
||||
if (!isForced) { |
||||
if (isSilent) { |
||||
return null; |
||||
} |
||||
throw new BeanException("Map key not found: " + bp.name, bp); |
||||
} |
||||
Map value = new HashMap(); |
||||
//noinspection unchecked
|
||||
map.put(key, value); |
||||
return value; |
||||
} |
||||
return map.get(key); |
||||
} |
||||
|
||||
// failed
|
||||
if (isSilent) { |
||||
return null; |
||||
} |
||||
throw new BeanException("Simple property not found: " + bp.name, bp); |
||||
} |
||||
|
||||
@Override |
||||
public void setSimpleProperty(final Object bean, final String property, final Object value) { |
||||
setSimpleProperty(new BeanProperty(this, bean, property), value); |
||||
} |
||||
|
||||
/** |
||||
* Sets a value of simple property. |
||||
*/ |
||||
@SuppressWarnings({"unchecked"}) |
||||
protected void setSimpleProperty(final BeanProperty bp, final Object value) { |
||||
Setter setter = bp.getSetter(isDeclared); |
||||
|
||||
// try: setter
|
||||
if (setter != null) { |
||||
invokeSetter(setter, bp, value); |
||||
return; |
||||
} |
||||
|
||||
// try: put("property", value)
|
||||
if (bp.isMap()) { |
||||
((Map) bp.bean).put(bp.name, value); |
||||
return; |
||||
} |
||||
if (isSilent) { |
||||
return; |
||||
} |
||||
throw new BeanException("Simple property not found: " + bp.name, bp); |
||||
} |
||||
|
||||
// ---------------------------------------------------------------- indexed property
|
||||
|
||||
protected boolean hasIndexProperty(final BeanProperty bp) { |
||||
|
||||
if (bp.bean == null) { |
||||
return false; |
||||
} |
||||
String indexString = extractIndex(bp); |
||||
|
||||
if (indexString == null) { |
||||
return hasSimpleProperty(bp); |
||||
} |
||||
|
||||
Object resultBean = getSimpleProperty(bp); |
||||
|
||||
if (resultBean == null) { |
||||
return false; |
||||
} |
||||
|
||||
// try: property[index]
|
||||
if (resultBean.getClass().isArray()) { |
||||
int index = parseInt(indexString, bp); |
||||
return (index >= 0) && (index < Array.getLength(resultBean)); |
||||
} |
||||
|
||||
// try: list.get(index)
|
||||
if (resultBean instanceof List) { |
||||
int index = parseInt(indexString, bp); |
||||
return (index >= 0) && (index < ((List)resultBean).size()); |
||||
} |
||||
if (resultBean instanceof Map) { |
||||
return ((Map)resultBean).containsKey(indexString); |
||||
} |
||||
|
||||
// failed
|
||||
return false; |
||||
} |
||||
|
||||
@Override |
||||
public <T> T getIndexProperty(final Object bean, final String property, final int index) { |
||||
BeanProperty bp = new BeanProperty(this, bean, property); |
||||
|
||||
bp.indexString = bp.index = String.valueOf(index); |
||||
|
||||
Object value = _getIndexProperty(bp); |
||||
|
||||
bp.indexString = null; |
||||
|
||||
return (T) value; |
||||
} |
||||
|
||||
/** |
||||
* Get non-nested property value: either simple or indexed property. |
||||
* If forced, missing bean will be created if possible. |
||||
*/ |
||||
protected Object getIndexProperty(final BeanProperty bp) { |
||||
bp.indexString = extractIndex(bp); |
||||
|
||||
Object value = _getIndexProperty(bp); |
||||
|
||||
bp.indexString = null; |
||||
|
||||
return value; |
||||
} |
||||
|
||||
private Object _getIndexProperty(final BeanProperty bp) { |
||||
Object resultBean = getSimpleProperty(bp); |
||||
Getter getter = bp.getGetter(isDeclared); |
||||
|
||||
if (bp.indexString == null) { |
||||
return resultBean; // no index, just simple bean
|
||||
} |
||||
if (resultBean == null) { |
||||
if (isSilent) { |
||||
return null; |
||||
} |
||||
throw new BeanException("Index property is null: " + bp.name, bp); |
||||
} |
||||
|
||||
// try: property[index]
|
||||
if (resultBean.getClass().isArray()) { |
||||
int index = parseInt(bp.indexString, bp); |
||||
if (isForced) { |
||||
return arrayForcedGet(bp, resultBean, index); |
||||
} else { |
||||
return Array.get(resultBean, index); |
||||
} |
||||
} |
||||
|
||||
// try: list.get(index)
|
||||
if (resultBean instanceof List) { |
||||
int index = parseInt(bp.indexString, bp); |
||||
List list = (List) resultBean; |
||||
if (!isForced) { |
||||
return list.get(index); |
||||
} |
||||
if (!bp.last) { |
||||
ensureListSize(list, index); |
||||
} |
||||
Object value = list.get(index); |
||||
if (value == null) { |
||||
Class listComponentType = extractGenericComponentType(getter); |
||||
if (listComponentType == Object.class) { |
||||
// not an error: when component type is unknown, use Map as generic bean
|
||||
listComponentType = Map.class; |
||||
} |
||||
try { |
||||
value = ClassUtil.newInstance(listComponentType); |
||||
} catch (Exception ex) { |
||||
if (isSilent) { |
||||
return null; |
||||
} |
||||
throw new BeanException("Invalid list element: " + bp.name + '[' + index + ']', bp, ex); |
||||
} |
||||
//noinspection unchecked
|
||||
list.set(index, value); |
||||
} |
||||
return value; |
||||
} |
||||
|
||||
// try: map.get('index')
|
||||
if (resultBean instanceof Map) { |
||||
Map map = (Map) resultBean; |
||||
Object key = convertIndexToMapKey(getter, bp.indexString); |
||||
|
||||
if (!isForced) { |
||||
return map.get(key); |
||||
} |
||||
Object value = map.get(key); |
||||
if (!bp.last) { |
||||
if (value == null) { |
||||
Class mapComponentType = extractGenericComponentType(getter); |
||||
if (mapComponentType == Object.class) { |
||||
mapComponentType = Map.class; |
||||
} |
||||
try { |
||||
value = ClassUtil.newInstance(mapComponentType); |
||||
} catch (Exception ex) { |
||||
if (isSilent) { |
||||
return null; |
||||
} |
||||
throw new BeanException("Invalid map element: " + bp.name + '[' + bp.indexString + ']', bp, ex); |
||||
} |
||||
|
||||
//noinspection unchecked
|
||||
map.put(key, value); |
||||
} |
||||
} |
||||
return value; |
||||
} |
||||
|
||||
// failed
|
||||
if (isSilent) { |
||||
return null; |
||||
} |
||||
throw new BeanException("Index property is not an array, list or map: " + bp.name, bp); |
||||
} |
||||
|
||||
@Override |
||||
public void setIndexProperty(final Object bean, final String property, final int index, final Object value) { |
||||
BeanProperty bp = new BeanProperty(this, bean, property); |
||||
|
||||
bp.indexString = bp.index = String.valueOf(index); |
||||
|
||||
_setIndexProperty(bp, value); |
||||
|
||||
bp.indexString = null; |
||||
} |
||||
|
||||
/** |
||||
* Sets indexed or regular properties (no nested!). |
||||
*/ |
||||
protected void setIndexProperty(final BeanProperty bp, final Object value) { |
||||
bp.indexString = extractIndex(bp); |
||||
|
||||
_setIndexProperty(bp, value); |
||||
|
||||
bp.indexString = null; |
||||
} |
||||
|
||||
@SuppressWarnings({"unchecked"}) |
||||
private void _setIndexProperty(final BeanProperty bp, Object value) { |
||||
if (bp.indexString == null) { |
||||
setSimpleProperty(bp, value); |
||||
return; |
||||
} |
||||
|
||||
// try: getInner()
|
||||
Object nextBean = getSimpleProperty(bp); |
||||
Getter getter = bp.getGetter(isDeclared); |
||||
|
||||
if (nextBean == null) { |
||||
if (isSilent) { |
||||
return; |
||||
} |
||||
throw new BeanException("Index property is null:" + bp.name, bp); |
||||
} |
||||
|
||||
// inner bean found
|
||||
if (nextBean.getClass().isArray()) { |
||||
int index = parseInt(bp.indexString, bp); |
||||
if (isForced) { |
||||
arrayForcedSet(bp, nextBean, index, value); |
||||
} else { |
||||
Array.set(nextBean, index, value); |
||||
} |
||||
return; |
||||
} |
||||
|
||||
if (nextBean instanceof List) { |
||||
int index = parseInt(bp.indexString, bp); |
||||
Class listComponentType = extractGenericComponentType(getter); |
||||
if (listComponentType != Object.class) { |
||||
value = convertType(value, listComponentType); |
||||
} |
||||
List list = (List) nextBean; |
||||
if (isForced) { |
||||
ensureListSize(list, index); |
||||
} |
||||
list.set(index, value); |
||||
return; |
||||
} |
||||
if (nextBean instanceof Map) { |
||||
Map map = (Map) nextBean; |
||||
Object key = convertIndexToMapKey(getter, bp.indexString); |
||||
|
||||
Class mapComponentType = extractGenericComponentType(getter); |
||||
if (mapComponentType != Object.class) { |
||||
value = convertType(value, mapComponentType); |
||||
} |
||||
map.put(key, value); |
||||
return; |
||||
} |
||||
|
||||
// failed
|
||||
if (isSilent) { |
||||
return; |
||||
} |
||||
throw new BeanException("Index property is not an array, list or map: " + bp.name, bp); |
||||
} |
||||
|
||||
|
||||
// ---------------------------------------------------------------- SET
|
||||
|
||||
@Override |
||||
public void setProperty(final Object bean, final String name, final Object value) { |
||||
BeanProperty beanProperty = new BeanProperty(this, bean, name); |
||||
|
||||
if (!isSilent) { |
||||
resolveNestedProperties(beanProperty); |
||||
setIndexProperty(beanProperty, value); |
||||
} |
||||
else { |
||||
try { |
||||
resolveNestedProperties(beanProperty); |
||||
setIndexProperty(beanProperty, value); |
||||
} |
||||
catch (Exception ignore) {} |
||||
} |
||||
} |
||||
|
||||
// ---------------------------------------------------------------- GET
|
||||
|
||||
/** |
||||
* Returns value of bean's property. |
||||
*/ |
||||
@Override |
||||
public <T> T getProperty(final Object bean, final String name) { |
||||
BeanProperty beanProperty = new BeanProperty(this, bean, name); |
||||
if (!isSilent) { |
||||
resolveNestedProperties(beanProperty); |
||||
return (T) getIndexProperty(beanProperty); |
||||
} |
||||
else { |
||||
try { |
||||
resolveNestedProperties(beanProperty); |
||||
return (T) getIndexProperty(beanProperty); |
||||
} |
||||
catch (Exception ignore) { |
||||
return null; |
||||
} |
||||
} |
||||
} |
||||
|
||||
// ---------------------------------------------------------------- HAS
|
||||
|
||||
@Override |
||||
public boolean hasProperty(final Object bean, final String name) { |
||||
BeanProperty beanProperty = new BeanProperty(this, bean, name); |
||||
if (!resolveExistingNestedProperties(beanProperty)) { |
||||
return false; |
||||
} |
||||
return hasIndexProperty(beanProperty); |
||||
} |
||||
|
||||
@Override |
||||
public boolean hasRootProperty(final Object bean, String name) { |
||||
int dotNdx = indexOfDot(name); |
||||
if (dotNdx != -1) { |
||||
name = name.substring(0, dotNdx); |
||||
} |
||||
BeanProperty beanProperty = new BeanProperty(this, bean, name); |
||||
extractIndex(beanProperty); |
||||
return hasSimpleProperty(beanProperty); |
||||
} |
||||
|
||||
// ---------------------------------------------------------------- type
|
||||
|
||||
@Override |
||||
public Class<?> getPropertyType(final Object bean, final String name) { |
||||
BeanProperty beanProperty = new BeanProperty(this, bean, name); |
||||
if (!resolveExistingNestedProperties(beanProperty)) { |
||||
return null; |
||||
} |
||||
hasIndexProperty(beanProperty); |
||||
return extractType(beanProperty); |
||||
} |
||||
|
||||
// ---------------------------------------------------------------- utilities
|
||||
|
||||
private static final char[] INDEX_CHARS = new char[] {'.', '['}; |
||||
|
||||
/** |
||||
* Extract the first name of this reference. |
||||
*/ |
||||
@Override |
||||
public String extractThisReference(final String propertyName) { |
||||
int ndx = StringUtil.indexOfChars(propertyName, INDEX_CHARS); |
||||
if (ndx == -1) { |
||||
return propertyName; |
||||
} |
||||
return propertyName.substring(0, ndx); |
||||
} |
||||
|
||||
} |
@ -1,346 +0,0 @@
|
||||
// Copyright (c) 2003-present, Jodd Team (http://jodd.org)
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
package com.fr.third.jodd.bean; |
||||
|
||||
import com.fr.third.jodd.introspector.ClassIntrospector; |
||||
import com.fr.third.jodd.introspector.Getter; |
||||
import com.fr.third.jodd.introspector.MapperFunction; |
||||
import com.fr.third.jodd.introspector.Setter; |
||||
import com.fr.third.jodd.typeconverter.TypeConverterManager; |
||||
import com.fr.third.jodd.util.ClassUtil; |
||||
|
||||
import java.lang.reflect.Array; |
||||
import java.util.Collection; |
||||
import java.util.List; |
||||
|
||||
/** |
||||
* Various bean property utilities that makes writings of {@link BeanUtil} classes easy. |
||||
*/ |
||||
abstract class BeanUtilUtil implements BeanUtil { |
||||
|
||||
// ---------------------------------------------------------------- flags
|
||||
|
||||
protected boolean isDeclared = false; |
||||
protected boolean isForced = false; |
||||
protected boolean isSilent = false; |
||||
|
||||
// ---------------------------------------------------------------- introspector
|
||||
|
||||
protected ClassIntrospector introspector = ClassIntrospector.get(); |
||||
protected TypeConverterManager typeConverterManager = TypeConverterManager.get(); |
||||
|
||||
/** |
||||
* Sets {@link ClassIntrospector introspector} implementation. |
||||
*/ |
||||
public void setIntrospector(final ClassIntrospector introspector) { |
||||
this.introspector = introspector; |
||||
} |
||||
|
||||
/** |
||||
* Sets {@link TypeConverterManager type converter manager} implementation. |
||||
*/ |
||||
public void setTypeConverterManager(final TypeConverterManager typeConverterManager) { |
||||
this.typeConverterManager = typeConverterManager; |
||||
} |
||||
|
||||
/** |
||||
* Converts object to destination type. Invoked before the |
||||
* value is set into destination. Throws <code>TypeConversionException</code> |
||||
* if conversion fails. |
||||
*/ |
||||
@SuppressWarnings("unchecked") |
||||
protected Object convertType(final Object value, final Class type) { |
||||
return typeConverterManager.convertType(value, type); |
||||
} |
||||
|
||||
/** |
||||
* Converter to collection. |
||||
*/ |
||||
@SuppressWarnings("unchecked") |
||||
protected Object convertToCollection(final Object value, final Class destinationType, final Class componentType) { |
||||
return typeConverterManager.convertToCollection(value, destinationType, componentType); |
||||
} |
||||
|
||||
|
||||
// ---------------------------------------------------------------- accessors
|
||||
|
||||
/** |
||||
* Invokes setter, but first converts type to match the setter type. |
||||
*/ |
||||
protected Object invokeSetter(final Setter setter, final BeanProperty bp, Object value) { |
||||
try { |
||||
|
||||
final MapperFunction setterMapperFunction = setter.getMapperFunction(); |
||||
|
||||
if (setterMapperFunction != null) { |
||||
value = setterMapperFunction.apply(value); |
||||
} |
||||
|
||||
final Class type = setter.getSetterRawType(); |
||||
|
||||
if (ClassUtil.isTypeOf(type, Collection.class)) { |
||||
Class componentType = setter.getSetterRawComponentType(); |
||||
|
||||
value = convertToCollection(value, type, componentType); |
||||
} else { |
||||
// no collections
|
||||
value = convertType(value, type); |
||||
} |
||||
|
||||
setter.invokeSetter(bp.bean, value); |
||||
} catch (Exception ex) { |
||||
if (isSilent) { |
||||
return null; |
||||
} |
||||
throw new BeanException("Setter failed: " + setter, ex); |
||||
} |
||||
return value; |
||||
} |
||||
|
||||
// ---------------------------------------------------------------- forced
|
||||
|
||||
/** |
||||
* Returns the element of an array forced. If value is <code>null</code>, it will be instantiated. |
||||
* If not the last part of indexed bean property, array will be expanded to the index if necessary. |
||||
*/ |
||||
protected Object arrayForcedGet(final BeanProperty bp, Object array, final int index) { |
||||
Class componentType = array.getClass().getComponentType(); |
||||
if (!bp.last) { |
||||
array = ensureArraySize(bp, array, componentType, index); |
||||
} |
||||
Object value = Array.get(array, index); |
||||
if (value == null) { |
||||
try { |
||||
//noinspection unchecked
|
||||
value = ClassUtil.newInstance(componentType); |
||||
} catch (Exception ex) { |
||||
if (isSilent) { |
||||
return null; |
||||
} |
||||
throw new BeanException("Invalid array element: " + bp.name + '[' + index + ']', bp, ex); |
||||
} |
||||
Array.set(array, index, value); |
||||
} |
||||
return value; |
||||
} |
||||
|
||||
/** |
||||
* Sets the array element forced. If index is greater then arrays length, array will be expanded to the index. |
||||
* If speed is critical, it is better to allocate an array with proper size before using this method. |
||||
*/ |
||||
protected void arrayForcedSet(final BeanProperty bp, Object array, final int index, Object value) { |
||||
Class componentType = array.getClass().getComponentType(); |
||||
array = ensureArraySize(bp, array, componentType, index); |
||||
value = convertType(value, componentType); |
||||
Array.set(array, index, value); |
||||
} |
||||
|
||||
|
||||
@SuppressWarnings({"SuspiciousSystemArraycopy"}) |
||||
protected Object ensureArraySize(final BeanProperty bp, Object array, final Class componentType, final int index) { |
||||
int len = Array.getLength(array); |
||||
if (index >= len) { |
||||
Object newArray = Array.newInstance(componentType, index + 1); |
||||
System.arraycopy(array, 0, newArray, 0, len); |
||||
|
||||
Setter setter = bp.getSetter(true); |
||||
if (setter == null) { |
||||
// no point to check for bp.silent, throws NPE later
|
||||
throw new BeanException("Setter or field not found: " + bp.name, bp); |
||||
} |
||||
|
||||
newArray = invokeSetter(setter, bp, newArray); |
||||
|
||||
array = newArray; |
||||
} |
||||
return array; |
||||
} |
||||
|
||||
@SuppressWarnings({"unchecked"}) |
||||
protected void ensureListSize(final List list, final int size) { |
||||
int len = list.size(); |
||||
while (size >= len) { |
||||
list.add(null); |
||||
len++; |
||||
} |
||||
} |
||||
|
||||
// ---------------------------------------------------------------- index
|
||||
|
||||
/** |
||||
* Finds the very first next dot. Ignores dots between index brackets. |
||||
* Returns <code>-1</code> when dot is not found. |
||||
*/ |
||||
protected int indexOfDot(final String name) { |
||||
int ndx = 0; |
||||
int len = name.length(); |
||||
|
||||
boolean insideBracket = false; |
||||
|
||||
while (ndx < len) { |
||||
char c = name.charAt(ndx); |
||||
|
||||
if (insideBracket) { |
||||
if (c == ']') { |
||||
insideBracket = false; |
||||
} |
||||
} else { |
||||
if (c == '.') { |
||||
return ndx; |
||||
} |
||||
if (c == '[') { |
||||
insideBracket = true; |
||||
} |
||||
} |
||||
ndx++; |
||||
} |
||||
return -1; |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Extract index string from non-nested property name. |
||||
* If index is found, it is stripped from bean property name. |
||||
* If no index is found, it returns <code>null</code>. |
||||
*/ |
||||
protected String extractIndex(final BeanProperty bp) { |
||||
bp.index = null; |
||||
String name = bp.name; |
||||
int lastNdx = name.length() - 1; |
||||
if (lastNdx < 0) { |
||||
return null; |
||||
} |
||||
if (name.charAt(lastNdx) == ']') { |
||||
int leftBracketNdx = name.lastIndexOf('['); |
||||
if (leftBracketNdx != -1) { |
||||
bp.setName(name.substring(0, leftBracketNdx)); |
||||
bp.index = name.substring(leftBracketNdx + 1, lastNdx); |
||||
return bp.index; |
||||
} |
||||
} |
||||
return null; |
||||
} |
||||
|
||||
protected int parseInt(final String indexString, final BeanProperty bp) { |
||||
try { |
||||
return Integer.parseInt(indexString); |
||||
} catch (NumberFormatException nfex) { |
||||
// no point to use bp.silent, as will throw exception
|
||||
throw new BeanException("Invalid index: " + indexString, bp, nfex); |
||||
} |
||||
} |
||||
|
||||
// ---------------------------------------------------------------- create property
|
||||
|
||||
/** |
||||
* Creates new instance for current property name through its setter. |
||||
* It uses default constructor! |
||||
*/ |
||||
protected Object createBeanProperty(final BeanProperty bp) { |
||||
Setter setter = bp.getSetter(true); |
||||
if (setter == null) { |
||||
return null; |
||||
} |
||||
|
||||
Class type = setter.getSetterRawType(); |
||||
|
||||
Object newInstance; |
||||
try { |
||||
newInstance = ClassUtil.newInstance(type); |
||||
} catch (Exception ex) { |
||||
if (isSilent) { |
||||
return null; |
||||
} |
||||
throw new BeanException("Invalid property: " + bp.name, bp, ex); |
||||
} |
||||
|
||||
newInstance = invokeSetter(setter, bp, newInstance); |
||||
|
||||
return newInstance; |
||||
} |
||||
|
||||
// ---------------------------------------------------------------- generic and type
|
||||
|
||||
/** |
||||
* Extracts generic component type of a property. Returns <code>Object.class</code> |
||||
* when property does not have component. |
||||
*/ |
||||
protected Class extractGenericComponentType(final Getter getter) { |
||||
Class componentType = null; |
||||
|
||||
if (getter != null) { |
||||
componentType = getter.getGetterRawComponentType(); |
||||
} |
||||
|
||||
if (componentType == null) { |
||||
componentType = Object.class; |
||||
} |
||||
return componentType; |
||||
} |
||||
|
||||
/** |
||||
* Converts <b>Map</b> index to key type. If conversion fails, original value will be returned. |
||||
*/ |
||||
protected Object convertIndexToMapKey(final Getter getter, final Object index) { |
||||
Class indexType = null; |
||||
|
||||
if (getter != null) { |
||||
indexType = getter.getGetterRawKeyComponentType(); |
||||
} |
||||
|
||||
// check if set
|
||||
if (indexType == null) { |
||||
indexType = Object.class; // marker for no generic type
|
||||
} |
||||
|
||||
if (indexType == Object.class) { |
||||
return index; |
||||
} |
||||
|
||||
try { |
||||
return convertType(index, indexType); |
||||
} catch (Exception ignore) { |
||||
return index; |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Extracts type of current property. |
||||
*/ |
||||
protected Class extractType(final BeanProperty bp) { |
||||
Getter getter = bp.getGetter(isDeclared); |
||||
if (getter != null) { |
||||
if (bp.index != null) { |
||||
Class type = getter.getGetterRawComponentType(); |
||||
return type == null ? Object.class : type; |
||||
} |
||||
return getter.getGetterRawType(); |
||||
} |
||||
|
||||
return null; // this should not happens
|
||||
} |
||||
|
||||
} |
@ -1,194 +0,0 @@
|
||||
// Copyright (c) 2003-present, Jodd Team (http://jodd.org)
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
package com.fr.third.jodd.bean; |
||||
|
||||
import com.fr.third.jodd.inex.InExRuleMatcher; |
||||
import com.fr.third.jodd.inex.InExRules; |
||||
import com.fr.third.jodd.introspector.ClassDescriptor; |
||||
import com.fr.third.jodd.introspector.ClassIntrospector; |
||||
import com.fr.third.jodd.introspector.FieldDescriptor; |
||||
import com.fr.third.jodd.introspector.MethodDescriptor; |
||||
import com.fr.third.jodd.introspector.PropertyDescriptor; |
||||
import com.fr.third.jodd.util.StringUtil; |
||||
|
||||
import java.util.ArrayList; |
||||
import java.util.Map; |
||||
import java.util.Set; |
||||
|
||||
import static com.fr.third.jodd.util.StringPool.LEFT_SQ_BRACKET; |
||||
import static com.fr.third.jodd.util.StringPool.RIGHT_SQ_BRACKET; |
||||
|
||||
/** |
||||
* Visitor for bean properties. It extracts properties names |
||||
* from the source bean and then visits one by one. |
||||
* |
||||
* @see BeanVisitorImplBase |
||||
*/ |
||||
public abstract class BeanVisitor implements InExRuleMatcher<String, String> { |
||||
|
||||
/** |
||||
* Source bean. |
||||
*/ |
||||
protected Object source; |
||||
/** |
||||
* Include/exclude rules. |
||||
*/ |
||||
protected InExRules<String, String, String> rules = new InExRules<>(this); |
||||
/** |
||||
* Flag for enabling declared properties, or just public ones. |
||||
*/ |
||||
protected boolean declared; |
||||
/** |
||||
* Defines if null values should be ignored. |
||||
*/ |
||||
protected boolean ignoreNullValues; |
||||
/** |
||||
* Defines if empty string should be ignored. |
||||
*/ |
||||
protected boolean ignoreEmptyString; |
||||
/** |
||||
* Defines if fields should be included. |
||||
*/ |
||||
protected boolean includeFields; |
||||
/** |
||||
* Initial matching mode. |
||||
*/ |
||||
protected boolean blacklist = true; |
||||
/** |
||||
* Indicates the the source is a Map. |
||||
*/ |
||||
protected boolean isSourceMap = false; |
||||
|
||||
// ---------------------------------------------------------------- util
|
||||
|
||||
/** |
||||
* Returns all bean property names. |
||||
*/ |
||||
protected String[] getAllBeanPropertyNames(final Class type, final boolean declared) { |
||||
final ClassDescriptor classDescriptor = ClassIntrospector.get().lookup(type); |
||||
|
||||
final PropertyDescriptor[] propertyDescriptors = classDescriptor.getAllPropertyDescriptors(); |
||||
|
||||
final ArrayList<String> names = new ArrayList<>(propertyDescriptors.length); |
||||
|
||||
for (final PropertyDescriptor propertyDescriptor : propertyDescriptors) { |
||||
final MethodDescriptor getter = propertyDescriptor.getReadMethodDescriptor(); |
||||
if (getter != null) { |
||||
if (getter.matchDeclared(declared)) { |
||||
names.add(propertyDescriptor.getName()); |
||||
} |
||||
} |
||||
else if (includeFields) { |
||||
final FieldDescriptor field = propertyDescriptor.getFieldDescriptor(); |
||||
if (field != null) { |
||||
if (field.matchDeclared(declared)) { |
||||
names.add(field.getName()); |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
return names.toArray(new String[0]); |
||||
} |
||||
|
||||
/** |
||||
* Returns an array of bean properties. If bean is a <code>Map</code>, |
||||
* all its keys will be returned. |
||||
*/ |
||||
protected String[] resolveProperties(final Object bean, final boolean declared) { |
||||
final String[] properties; |
||||
|
||||
if (bean instanceof Map) { |
||||
final Set keys = ((Map) bean).keySet(); |
||||
|
||||
properties = new String[keys.size()]; |
||||
int ndx = 0; |
||||
for (final Object key : keys) { |
||||
properties[ndx] = key.toString(); |
||||
ndx++; |
||||
} |
||||
} else { |
||||
properties = getAllBeanPropertyNames(bean.getClass(), declared); |
||||
} |
||||
|
||||
return properties; |
||||
} |
||||
|
||||
/** |
||||
* Starts visiting properties. |
||||
*/ |
||||
public void visit() { |
||||
final String[] properties = resolveProperties(source, declared); |
||||
|
||||
for (final String name : properties) { |
||||
if (name == null) { |
||||
continue; |
||||
} |
||||
|
||||
if (!rules.match(name, blacklist)) { |
||||
continue; |
||||
} |
||||
|
||||
final Object value; |
||||
|
||||
String propertyName = name; |
||||
|
||||
if (isSourceMap) { |
||||
propertyName = LEFT_SQ_BRACKET + name + RIGHT_SQ_BRACKET; |
||||
} |
||||
|
||||
if (declared) { |
||||
value = BeanUtil.declared.getProperty(source, propertyName); |
||||
} else { |
||||
value = BeanUtil.pojo.getProperty(source, propertyName); |
||||
} |
||||
|
||||
if (value == null && ignoreNullValues) { |
||||
continue; |
||||
} |
||||
|
||||
if (ignoreEmptyString && value instanceof String && StringUtil.isEmpty((String) value)) { |
||||
continue; |
||||
} |
||||
|
||||
visitProperty(name, value); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Invoked for each visited property. Returns <code>true</code> if |
||||
* visiting should continue, otherwise <code>false</code> to stop. |
||||
*/ |
||||
protected abstract boolean visitProperty(String name, Object value); |
||||
|
||||
/** |
||||
* Compares property name to the rules. |
||||
*/ |
||||
@Override |
||||
public boolean accept(final String propertyName, final String rule, final boolean include) { |
||||
return propertyName.equals(rule); |
||||
} |
||||
} |
@ -1,131 +0,0 @@
|
||||
// Copyright (c) 2003-present, Jodd Team (http://jodd.org)
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
package com.fr.third.jodd.bean; |
||||
|
||||
/** |
||||
* Default implementation of {@link BeanVisitor} for just setting |
||||
* the properties in fluent way. |
||||
*/ |
||||
public abstract class BeanVisitorImplBase<T> extends BeanVisitor { |
||||
|
||||
@SuppressWarnings("unchecked") |
||||
protected T _this() { |
||||
return (T) this; |
||||
} |
||||
|
||||
/** |
||||
* Excludes all properties, i.e. enables blacklist mode. |
||||
*/ |
||||
public T excludeAll() { |
||||
blacklist = false; |
||||
return _this(); |
||||
} |
||||
|
||||
/** |
||||
* Defines excluded property names. |
||||
*/ |
||||
public T exclude(final String... excludes) { |
||||
for (String ex : excludes) { |
||||
rules.exclude(ex); |
||||
} |
||||
return _this(); |
||||
} |
||||
|
||||
/** |
||||
* Exclude a property. |
||||
*/ |
||||
public T exclude(final String exclude) { |
||||
rules.exclude(exclude); |
||||
return _this(); |
||||
} |
||||
|
||||
/** |
||||
* Defines included property names. |
||||
*/ |
||||
public T include(final String... includes) { |
||||
for (String in : includes) { |
||||
rules.include(in); |
||||
} |
||||
return _this(); |
||||
} |
||||
|
||||
/** |
||||
* Include a property. |
||||
*/ |
||||
public T include(final String include) { |
||||
rules.include(include); |
||||
return _this(); |
||||
} |
||||
|
||||
/** |
||||
* Defines included property names as public properties |
||||
* of given template class. Sets to black list mode. |
||||
*/ |
||||
public T includeAs(final Class template) { |
||||
blacklist = false; |
||||
|
||||
String[] properties = getAllBeanPropertyNames(template, false); |
||||
|
||||
include(properties); |
||||
|
||||
return _this(); |
||||
} |
||||
|
||||
/** |
||||
* Defines if <code>null</code> values should be ignored. |
||||
*/ |
||||
public T ignoreNulls(final boolean ignoreNulls) { |
||||
this.ignoreNullValues = ignoreNulls; |
||||
|
||||
return _this(); |
||||
} |
||||
|
||||
/** |
||||
* Defines if <code>empty string</code> should be ignored. |
||||
*/ |
||||
public T ignoreEmptyString(final boolean ignoreEmptyString) { |
||||
this.ignoreEmptyString = ignoreEmptyString; |
||||
return _this(); |
||||
} |
||||
|
||||
/** |
||||
* Defines if all properties should be copied (when set to <code>true</code>) |
||||
* or only public (when set to <code>false</code>, default). |
||||
*/ |
||||
public T declared(final boolean declared) { |
||||
this.declared = declared; |
||||
return _this(); |
||||
} |
||||
|
||||
/** |
||||
* Defines if fields without getters should be copied too. |
||||
*/ |
||||
public T includeFields(final boolean includeFields) { |
||||
this.includeFields = includeFields; |
||||
return _this(); |
||||
} |
||||
|
||||
} |
@ -1,83 +0,0 @@
|
||||
// Copyright (c) 2003-present, Jodd Team (http://jodd.org)
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
package com.fr.third.jodd.bean; |
||||
|
||||
import java.util.Map; |
||||
|
||||
/** |
||||
* Walker over bean properties. |
||||
*/ |
||||
public class BeanWalker extends BeanVisitorImplBase<BeanWalker> { |
||||
|
||||
private final BeanWalkerCallback callback; |
||||
|
||||
/** |
||||
* Functional callback for walking. |
||||
*/ |
||||
public interface BeanWalkerCallback { |
||||
void visitProperty(String name, Object value); |
||||
} |
||||
|
||||
public BeanWalker(final BeanWalkerCallback callback) { |
||||
this.callback = callback; |
||||
} |
||||
|
||||
/** |
||||
* Static ctor. |
||||
*/ |
||||
public static BeanWalker walk(final BeanWalkerCallback callback) { |
||||
return new BeanWalker(callback); |
||||
} |
||||
|
||||
public void source(final Object source) { |
||||
this.source = source; |
||||
|
||||
isSourceMap = (source instanceof Map); |
||||
|
||||
visit(); |
||||
} |
||||
|
||||
public void bean(final Object bean) { |
||||
this.source = bean; |
||||
|
||||
visit(); |
||||
} |
||||
|
||||
public void map(final Map map) { |
||||
this.source = map; |
||||
|
||||
this.isSourceMap = true; |
||||
|
||||
visit(); |
||||
} |
||||
|
||||
@Override |
||||
protected boolean visitProperty(final String name, final Object value) { |
||||
callback.visitProperty(name, value); |
||||
return true; |
||||
} |
||||
|
||||
} |
@ -1,29 +0,0 @@
|
||||
// Copyright (c) 2003-present, Jodd Team (http://jodd.org)
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
/** |
||||
* Java Bean utilities, provides <em>the fastest</em> bean manipulation. |
||||
*/ |
||||
package com.fr.third.jodd.bean; |
@ -1,166 +0,0 @@
|
||||
// Copyright (c) 2003-present, Jodd Team (http://jodd.org)
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
package com.fr.third.jodd.buffer; |
||||
|
||||
import java.util.Arrays; |
||||
|
||||
/** |
||||
* Faster {@code boolean} buffer. |
||||
*/ |
||||
public class FastBooleanBuffer { |
||||
|
||||
private boolean[] buffer; |
||||
private int offset; |
||||
|
||||
/** |
||||
* Creates a new {@code boolean} buffer. The buffer capacity is |
||||
* initially 64 booleans, though its size increases if necessary. |
||||
*/ |
||||
public FastBooleanBuffer() { |
||||
this.buffer = new boolean[64]; |
||||
} |
||||
|
||||
/** |
||||
* Creates a new {@code boolean} buffer, with a buffer capacity of |
||||
* the specified size. |
||||
* |
||||
* @param size the initial size. |
||||
* @throws IllegalArgumentException if size is negative. |
||||
*/ |
||||
public FastBooleanBuffer(final int size) { |
||||
this.buffer = new boolean[size]; |
||||
} |
||||
|
||||
/** |
||||
* Grows the buffer. |
||||
*/ |
||||
private void grow(final int minCapacity) { |
||||
final int oldCapacity = buffer.length; |
||||
int newCapacity = oldCapacity << 1; |
||||
if (newCapacity - minCapacity < 0) { |
||||
// special case, min capacity is larger then a grow
|
||||
newCapacity = minCapacity + 512; |
||||
} |
||||
buffer = Arrays.copyOf(buffer, newCapacity); |
||||
} |
||||
|
||||
/** |
||||
* Appends single {@code boolean} to buffer. |
||||
*/ |
||||
public void append(final boolean element) { |
||||
if (offset - buffer.length >= 0) { |
||||
grow(offset); |
||||
} |
||||
|
||||
buffer[offset++] = element; |
||||
} |
||||
|
||||
/** |
||||
* Appends {@code boolean} array to buffer. |
||||
*/ |
||||
public FastBooleanBuffer append(final boolean[] array, final int off, final int len) { |
||||
if (offset + len - buffer.length > 0) { |
||||
grow(offset + len); |
||||
} |
||||
|
||||
System.arraycopy(array, off, buffer, offset, len); |
||||
offset += len; |
||||
return this; |
||||
} |
||||
|
||||
/** |
||||
* Appends {@code boolean} array to buffer. |
||||
*/ |
||||
public FastBooleanBuffer append(final boolean[] array) { |
||||
return append(array, 0, array.length); |
||||
} |
||||
|
||||
/** |
||||
* Appends another fast buffer to this one. |
||||
*/ |
||||
public FastBooleanBuffer append(final FastBooleanBuffer buff) { |
||||
if (buff.offset == 0) { |
||||
return this; |
||||
} |
||||
append(buff.buffer, 0, buff.offset); |
||||
return this; |
||||
} |
||||
|
||||
/** |
||||
* Returns buffer size. |
||||
*/ |
||||
public int size() { |
||||
return offset; |
||||
} |
||||
|
||||
/** |
||||
* Tests if this buffer has no elements. |
||||
*/ |
||||
public boolean isEmpty() { |
||||
return offset == 0; |
||||
} |
||||
|
||||
/** |
||||
* Resets the buffer content. |
||||
*/ |
||||
public void clear() { |
||||
offset = 0; |
||||
} |
||||
|
||||
/** |
||||
* Creates {@code boolean} array from buffered content. |
||||
*/ |
||||
public boolean[] toArray() { |
||||
return Arrays.copyOf(buffer, offset); |
||||
} |
||||
|
||||
/** |
||||
* Creates {@code boolean} subarray from buffered content. |
||||
*/ |
||||
public boolean[] toArray(final int start, final int len) { |
||||
final boolean[] array = new boolean[len]; |
||||
|
||||
if (len == 0) { |
||||
return array; |
||||
} |
||||
|
||||
System.arraycopy(buffer, start, array, 0, len); |
||||
|
||||
return array; |
||||
} |
||||
|
||||
/** |
||||
* Returns {@code boolean} element at given index. |
||||
*/ |
||||
public boolean get(final int index) { |
||||
if (index >= offset) { |
||||
throw new IndexOutOfBoundsException(); |
||||
} |
||||
return buffer[index]; |
||||
} |
||||
|
||||
|
||||
} |
@ -1,166 +0,0 @@
|
||||
// Copyright (c) 2003-present, Jodd Team (http://jodd.org)
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
package com.fr.third.jodd.buffer; |
||||
|
||||
import java.util.Arrays; |
||||
|
||||
/** |
||||
* Faster {@code byte} buffer. Works faster for smaller buffer sizes. |
||||
* After eg. length of 2048 the performances are practically the same. |
||||
*/ |
||||
public class FastByteBuffer { |
||||
|
||||
private byte[] buffer; |
||||
private int offset; |
||||
|
||||
/** |
||||
* Creates a new {@code byte} buffer. The buffer capacity is |
||||
* initially 64 bytes, though its size increases if necessary. |
||||
*/ |
||||
public FastByteBuffer() { |
||||
this.buffer = new byte[64]; |
||||
} |
||||
|
||||
/** |
||||
* Creates a new {@code byte} buffer, with a buffer capacity of |
||||
* the specified size. |
||||
* |
||||
* @param size the initial size. |
||||
* @throws IllegalArgumentException if size is negative. |
||||
*/ |
||||
public FastByteBuffer(final int size) { |
||||
this.buffer = new byte[size]; |
||||
} |
||||
|
||||
/** |
||||
* Grows the buffer. |
||||
*/ |
||||
private void grow(final int minCapacity) { |
||||
final int oldCapacity = buffer.length; |
||||
int newCapacity = oldCapacity << 1; |
||||
if (newCapacity - minCapacity < 0) { |
||||
// special case, min capacity is larger then a grow
|
||||
newCapacity = minCapacity + 512; |
||||
} |
||||
buffer = Arrays.copyOf(buffer, newCapacity); |
||||
} |
||||
|
||||
/** |
||||
* Appends single {@code byte} to buffer. |
||||
*/ |
||||
public void append(final byte element) { |
||||
if (offset - buffer.length >= 0) { |
||||
grow(offset); |
||||
} |
||||
|
||||
buffer[offset++] = element; |
||||
} |
||||
|
||||
/** |
||||
* Appends {@code byte} array to buffer. |
||||
*/ |
||||
public FastByteBuffer append(final byte[] array, final int off, final int len) { |
||||
if (offset + len - buffer.length > 0) { |
||||
grow(offset + len); |
||||
} |
||||
|
||||
System.arraycopy(array, off, buffer, offset, len); |
||||
offset += len; |
||||
return this; |
||||
} |
||||
|
||||
/** |
||||
* Appends {@code byte} array to buffer. |
||||
*/ |
||||
public FastByteBuffer append(final byte[] array) { |
||||
return append(array, 0, array.length); |
||||
} |
||||
|
||||
/** |
||||
* Appends another fast buffer to this one. |
||||
*/ |
||||
public FastByteBuffer append(final FastByteBuffer buff) { |
||||
if (buff.offset == 0) { |
||||
return this; |
||||
} |
||||
append(buff.buffer, 0, buff.offset); |
||||
return this; |
||||
} |
||||
|
||||
/** |
||||
* Returns buffer size. |
||||
*/ |
||||
public int size() { |
||||
return offset; |
||||
} |
||||
|
||||
/** |
||||
* Tests if this buffer has no elements. |
||||
*/ |
||||
public boolean isEmpty() { |
||||
return offset == 0; |
||||
} |
||||
|
||||
/** |
||||
* Resets the buffer content. |
||||
*/ |
||||
public void clear() { |
||||
offset = 0; |
||||
} |
||||
|
||||
/** |
||||
* Creates {@code byte} array from buffered content. |
||||
*/ |
||||
public byte[] toArray() { |
||||
return Arrays.copyOf(buffer, offset); |
||||
} |
||||
|
||||
/** |
||||
* Creates {@code byte} subarray from buffered content. |
||||
*/ |
||||
public byte[] toArray(final int start, final int len) { |
||||
final byte[] array = new byte[len]; |
||||
|
||||
if (len == 0) { |
||||
return array; |
||||
} |
||||
|
||||
System.arraycopy(buffer, start, array, 0, len); |
||||
|
||||
return array; |
||||
} |
||||
|
||||
/** |
||||
* Returns {@code byte} element at given index. |
||||
*/ |
||||
public byte get(final int index) { |
||||
if (index >= offset) { |
||||
throw new IndexOutOfBoundsException(); |
||||
} |
||||
return buffer[index]; |
||||
} |
||||
|
||||
} |
@ -1,211 +0,0 @@
|
||||
// Copyright (c) 2003-present, Jodd Team (http://jodd.org)
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
package com.fr.third.jodd.buffer; |
||||
|
||||
import com.fr.third.jodd.util.CharArraySequence; |
||||
|
||||
import java.util.Arrays; |
||||
|
||||
/** |
||||
* Faster {@code char} buffer. |
||||
*/ |
||||
public class FastCharBuffer implements CharSequence, Appendable { |
||||
|
||||
private char[] buffer; |
||||
private int offset; |
||||
|
||||
/** |
||||
* Creates a new {@code char} buffer. The buffer capacity is |
||||
* initially 64 chars, though its size increases if necessary. |
||||
*/ |
||||
public FastCharBuffer() { |
||||
this.buffer = new char[64]; |
||||
} |
||||
|
||||
/** |
||||
* Creates a new {@code char} buffer, with a buffer capacity of |
||||
* the specified size, in chars. |
||||
* |
||||
* @param size the initial size. |
||||
* @throws IllegalArgumentException if size is negative. |
||||
*/ |
||||
public FastCharBuffer(final int size) { |
||||
this.buffer = new char[size]; |
||||
} |
||||
|
||||
/** |
||||
* Grows the buffer. |
||||
*/ |
||||
private void grow(final int minCapacity) { |
||||
final int oldCapacity = buffer.length; |
||||
int newCapacity = oldCapacity << 1; |
||||
if (newCapacity - minCapacity < 0) { |
||||
// special case, min capacity is larger then a grow
|
||||
newCapacity = minCapacity + 512; |
||||
} |
||||
buffer = Arrays.copyOf(buffer, newCapacity); |
||||
} |
||||
|
||||
/** |
||||
* Appends single {@code char} to buffer. |
||||
*/ |
||||
@Override |
||||
public FastCharBuffer append(final char element) { |
||||
if (offset - buffer.length >= 0) { |
||||
grow(offset); |
||||
} |
||||
|
||||
buffer[offset++] = element; |
||||
return this; |
||||
} |
||||
|
||||
/** |
||||
* Appends {@code char} array to buffer. |
||||
*/ |
||||
public FastCharBuffer append(final char[] array, final int off, final int len) { |
||||
if (offset + len - buffer.length > 0) { |
||||
grow(offset + len); |
||||
} |
||||
|
||||
System.arraycopy(array, off, buffer, offset, len); |
||||
offset += len; |
||||
return this; |
||||
} |
||||
|
||||
/** |
||||
* Appends {@code char} array to buffer. |
||||
*/ |
||||
public FastCharBuffer append(final char[] array) { |
||||
return append(array, 0, array.length); |
||||
} |
||||
|
||||
/** |
||||
* Appends another fast buffer to this one. |
||||
*/ |
||||
public FastCharBuffer append(final FastCharBuffer buff) { |
||||
if (buff.offset == 0) { |
||||
return this; |
||||
} |
||||
append(buff.buffer, 0, buff.offset); |
||||
return this; |
||||
} |
||||
|
||||
/** |
||||
* Returns buffer size. |
||||
*/ |
||||
public int size() { |
||||
return offset; |
||||
} |
||||
|
||||
@Override |
||||
public int length() { |
||||
return offset; |
||||
} |
||||
|
||||
/** |
||||
* Tests if this buffer has no elements. |
||||
*/ |
||||
public boolean isEmpty() { |
||||
return offset == 0; |
||||
} |
||||
|
||||
/** |
||||
* Resets the buffer content. |
||||
*/ |
||||
public void clear() { |
||||
offset = 0; |
||||
} |
||||
|
||||
/** |
||||
* Creates {@code char} array from buffered content. |
||||
*/ |
||||
public char[] toArray() { |
||||
return Arrays.copyOf(buffer, offset); |
||||
} |
||||
|
||||
/** |
||||
* Creates {@code char} subarray from buffered content. |
||||
*/ |
||||
public char[] toArray(final int start, final int len) { |
||||
final char[] array = new char[len]; |
||||
|
||||
if (len == 0) { |
||||
return array; |
||||
} |
||||
|
||||
System.arraycopy(buffer, start, array, 0, len); |
||||
|
||||
return array; |
||||
} |
||||
|
||||
/** |
||||
* Returns {@code char} element at given index. |
||||
*/ |
||||
public char get(final int index) { |
||||
if (index >= offset) { |
||||
throw new IndexOutOfBoundsException(); |
||||
} |
||||
return buffer[index]; |
||||
} |
||||
|
||||
/** |
||||
* Appends character sequence to buffer. |
||||
*/ |
||||
@Override |
||||
public FastCharBuffer append(final CharSequence csq) { |
||||
append(csq, 0, csq.length()); |
||||
return this; |
||||
} |
||||
|
||||
/** |
||||
* Appends character sequence to buffer. |
||||
*/ |
||||
@Override |
||||
public FastCharBuffer append(final CharSequence csq, final int start, final int end) { |
||||
for (int i = start; i < end; i++) { |
||||
append(csq.charAt(i)); |
||||
} |
||||
return this; |
||||
} |
||||
@Override |
||||
public char charAt(final int index) { |
||||
return get(index); |
||||
} |
||||
|
||||
@Override |
||||
public CharSequence subSequence(final int start, final int end) { |
||||
return new CharArraySequence(buffer, start, end - start); |
||||
} |
||||
|
||||
/** |
||||
* Returns a String of the char buffer. |
||||
* Please use {@code StringBuilder} instead, it is faster. |
||||
*/ |
||||
@Override |
||||
public String toString() { |
||||
return new String(toArray()); |
||||
} |
||||
} |
@ -1,166 +0,0 @@
|
||||
// Copyright (c) 2003-present, Jodd Team (http://jodd.org)
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
package com.fr.third.jodd.buffer; |
||||
|
||||
import java.util.Arrays; |
||||
|
||||
/** |
||||
* Faster {@code double} buffer. |
||||
*/ |
||||
public class FastDoubleBuffer { |
||||
|
||||
private double[] buffer; |
||||
private int offset; |
||||
|
||||
/** |
||||
* Creates a new {@code double} buffer. The buffer capacity is |
||||
* initially 64 doubles, though its size increases if necessary. |
||||
*/ |
||||
public FastDoubleBuffer() { |
||||
this.buffer = new double[64]; |
||||
} |
||||
|
||||
/** |
||||
* Creates a new {@code double} buffer, with a buffer capacity of |
||||
* the specified size. |
||||
* |
||||
* @param size the initial size. |
||||
* @throws IllegalArgumentException if size is negative. |
||||
*/ |
||||
public FastDoubleBuffer(final int size) { |
||||
this.buffer = new double[size]; |
||||
} |
||||
|
||||
/** |
||||
* Grows the buffer. |
||||
*/ |
||||
private void grow(final int minCapacity) { |
||||
final int oldCapacity = buffer.length; |
||||
int newCapacity = oldCapacity << 1; |
||||
if (newCapacity - minCapacity < 0) { |
||||
// special case, min capacity is larger then a grow
|
||||
newCapacity = minCapacity + 512; |
||||
} |
||||
buffer = Arrays.copyOf(buffer, newCapacity); |
||||
} |
||||
|
||||
/** |
||||
* Appends single {@code double} to buffer. |
||||
*/ |
||||
public void append(final double element) { |
||||
if (offset - buffer.length >= 0) { |
||||
grow(offset); |
||||
} |
||||
|
||||
buffer[offset++] = element; |
||||
} |
||||
|
||||
/** |
||||
* Appends {@code double} array to buffer. |
||||
*/ |
||||
public FastDoubleBuffer append(final double[] array, final int off, final int len) { |
||||
if (offset + len - buffer.length > 0) { |
||||
grow(offset + len); |
||||
} |
||||
|
||||
System.arraycopy(array, off, buffer, offset, len); |
||||
offset += len; |
||||
return this; |
||||
} |
||||
|
||||
/** |
||||
* Appends {@code double} array to buffer. |
||||
*/ |
||||
public FastDoubleBuffer append(final double[] array) { |
||||
return append(array, 0, array.length); |
||||
} |
||||
|
||||
/** |
||||
* Appends another fast buffer to this one. |
||||
*/ |
||||
public FastDoubleBuffer append(final FastDoubleBuffer buff) { |
||||
if (buff.offset == 0) { |
||||
return this; |
||||
} |
||||
append(buff.buffer, 0, buff.offset); |
||||
return this; |
||||
} |
||||
|
||||
/** |
||||
* Returns buffer size. |
||||
*/ |
||||
public int size() { |
||||
return offset; |
||||
} |
||||
|
||||
/** |
||||
* Tests if this buffer has no elements. |
||||
*/ |
||||
public boolean isEmpty() { |
||||
return offset == 0; |
||||
} |
||||
|
||||
/** |
||||
* Resets the buffer content. |
||||
*/ |
||||
public void clear() { |
||||
offset = 0; |
||||
} |
||||
|
||||
/** |
||||
* Creates {@code double} array from buffered content. |
||||
*/ |
||||
public double[] toArray() { |
||||
return Arrays.copyOf(buffer, offset); |
||||
} |
||||
|
||||
/** |
||||
* Creates {@code double} subarray from buffered content. |
||||
*/ |
||||
public double[] toArray(final int start, final int len) { |
||||
final double[] array = new double[len]; |
||||
|
||||
if (len == 0) { |
||||
return array; |
||||
} |
||||
|
||||
System.arraycopy(buffer, start, array, 0, len); |
||||
|
||||
return array; |
||||
} |
||||
|
||||
/** |
||||
* Returns {@code double} element at given index. |
||||
*/ |
||||
public double get(final int index) { |
||||
if (index >= offset) { |
||||
throw new IndexOutOfBoundsException(); |
||||
} |
||||
return buffer[index]; |
||||
} |
||||
|
||||
|
||||
} |
@ -1,165 +0,0 @@
|
||||
// Copyright (c) 2003-present, Jodd Team (http://jodd.org)
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
package com.fr.third.jodd.buffer; |
||||
|
||||
import java.util.Arrays; |
||||
|
||||
/** |
||||
* Faster {@code float} buffer. |
||||
*/ |
||||
public class FastFloatBuffer { |
||||
|
||||
private float[] buffer; |
||||
private int offset; |
||||
|
||||
/** |
||||
* Creates a new {@code float} buffer. The buffer capacity is |
||||
* initially 64 floats, though its size increases if necessary. |
||||
*/ |
||||
public FastFloatBuffer() { |
||||
this.buffer = new float[64]; |
||||
} |
||||
|
||||
/** |
||||
* Creates a new {@code float} buffer, with a buffer capacity of |
||||
* the specified size. |
||||
* |
||||
* @param size the initial size. |
||||
* @throws IllegalArgumentException if size is negative. |
||||
*/ |
||||
public FastFloatBuffer(final int size) { |
||||
this.buffer = new float[size]; |
||||
} |
||||
|
||||
/** |
||||
* Grows the buffer. |
||||
*/ |
||||
private void grow(final int minCapacity) { |
||||
final int oldCapacity = buffer.length; |
||||
int newCapacity = oldCapacity << 1; |
||||
if (newCapacity - minCapacity < 0) { |
||||
// special case, min capacity is larger then a grow
|
||||
newCapacity = minCapacity + 512; |
||||
} |
||||
buffer = Arrays.copyOf(buffer, newCapacity); |
||||
} |
||||
|
||||
/** |
||||
* Appends single {@code float} to buffer. |
||||
*/ |
||||
public void append(final float element) { |
||||
if (offset - buffer.length >= 0) { |
||||
grow(offset); |
||||
} |
||||
|
||||
buffer[offset++] = element; |
||||
} |
||||
|
||||
/** |
||||
* Appends {@code float} array to buffer. |
||||
*/ |
||||
public FastFloatBuffer append(final float[] array, final int off, final int len) { |
||||
if (offset + len - buffer.length > 0) { |
||||
grow(offset + len); |
||||
} |
||||
|
||||
System.arraycopy(array, off, buffer, offset, len); |
||||
offset += len; |
||||
return this; |
||||
} |
||||
|
||||
/** |
||||
* Appends {@code float} array to buffer. |
||||
*/ |
||||
public FastFloatBuffer append(final float[] array) { |
||||
return append(array, 0, array.length); |
||||
} |
||||
|
||||
/** |
||||
* Appends another fast buffer to this one. |
||||
*/ |
||||
public FastFloatBuffer append(final FastFloatBuffer buff) { |
||||
if (buff.offset == 0) { |
||||
return this; |
||||
} |
||||
append(buff.buffer, 0, buff.offset); |
||||
return this; |
||||
} |
||||
|
||||
/** |
||||
* Returns buffer size. |
||||
*/ |
||||
public int size() { |
||||
return offset; |
||||
} |
||||
|
||||
/** |
||||
* Tests if this buffer has no elements. |
||||
*/ |
||||
public boolean isEmpty() { |
||||
return offset == 0; |
||||
} |
||||
|
||||
/** |
||||
* Resets the buffer content. |
||||
*/ |
||||
public void clear() { |
||||
offset = 0; |
||||
} |
||||
|
||||
/** |
||||
* Creates {@code float} array from buffered content. |
||||
*/ |
||||
public float[] toArray() { |
||||
return Arrays.copyOf(buffer, offset); |
||||
} |
||||
|
||||
/** |
||||
* Creates {@code float} subarray from buffered content. |
||||
*/ |
||||
public float[] toArray(final int start, final int len) { |
||||
final float[] array = new float[len]; |
||||
|
||||
if (len == 0) { |
||||
return array; |
||||
} |
||||
|
||||
System.arraycopy(buffer, start, array, 0, len); |
||||
|
||||
return array; |
||||
} |
||||
|
||||
/** |
||||
* Returns {@code float} element at given index. |
||||
*/ |
||||
public float get(final int index) { |
||||
if (index >= offset) { |
||||
throw new IndexOutOfBoundsException(); |
||||
} |
||||
return buffer[index]; |
||||
} |
||||
|
||||
} |
@ -1,166 +0,0 @@
|
||||
// Copyright (c) 2003-present, Jodd Team (http://jodd.org)
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
package com.fr.third.jodd.buffer; |
||||
|
||||
import java.util.Arrays; |
||||
|
||||
/** |
||||
* Faster {@code int} buffer. |
||||
*/ |
||||
public class FastIntBuffer { |
||||
|
||||
private int[] buffer; |
||||
private int offset; |
||||
|
||||
/** |
||||
* Creates a new {@code int} buffer. The buffer capacity is |
||||
* initially 64 ints, though its size increases if necessary. |
||||
*/ |
||||
public FastIntBuffer() { |
||||
this.buffer = new int[64]; |
||||
} |
||||
|
||||
/** |
||||
* Creates a new {@code int} buffer, with a buffer capacity of |
||||
* the specified size. |
||||
* |
||||
* @param size the initial size. |
||||
* @throws IllegalArgumentException if size is negative. |
||||
*/ |
||||
public FastIntBuffer(final int size) { |
||||
this.buffer = new int[size]; |
||||
} |
||||
|
||||
/** |
||||
* Grows the buffer. |
||||
*/ |
||||
private void grow(final int minCapacity) { |
||||
final int oldCapacity = buffer.length; |
||||
int newCapacity = oldCapacity << 1; |
||||
if (newCapacity - minCapacity < 0) { |
||||
// special case, min capacity is larger then a grow
|
||||
newCapacity = minCapacity + 512; |
||||
} |
||||
buffer = Arrays.copyOf(buffer, newCapacity); |
||||
} |
||||
|
||||
/** |
||||
* Appends single {@code int} to buffer. |
||||
*/ |
||||
public void append(final int element) { |
||||
if (offset - buffer.length >= 0) { |
||||
grow(offset); |
||||
} |
||||
|
||||
buffer[offset++] = element; |
||||
} |
||||
|
||||
/** |
||||
* Appends {@code int} array to buffer. |
||||
*/ |
||||
public FastIntBuffer append(final int[] array, final int off, final int len) { |
||||
if (offset + len - buffer.length > 0) { |
||||
grow(offset + len); |
||||
} |
||||
|
||||
System.arraycopy(array, off, buffer, offset, len); |
||||
offset += len; |
||||
return this; |
||||
} |
||||
|
||||
/** |
||||
* Appends {@code int} array to buffer. |
||||
*/ |
||||
public FastIntBuffer append(final int[] array) { |
||||
return append(array, 0, array.length); |
||||
} |
||||
|
||||
/** |
||||
* Appends another fast buffer to this one. |
||||
*/ |
||||
public FastIntBuffer append(final FastIntBuffer buff) { |
||||
if (buff.offset == 0) { |
||||
return this; |
||||
} |
||||
append(buff.buffer, 0, buff.offset); |
||||
return this; |
||||
} |
||||
|
||||
/** |
||||
* Returns buffer size. |
||||
*/ |
||||
public int size() { |
||||
return offset; |
||||
} |
||||
|
||||
/** |
||||
* Tests if this buffer has no elements. |
||||
*/ |
||||
public boolean isEmpty() { |
||||
return offset == 0; |
||||
} |
||||
|
||||
/** |
||||
* Resets the buffer content. |
||||
*/ |
||||
public void clear() { |
||||
offset = 0; |
||||
} |
||||
|
||||
/** |
||||
* Creates {@code int} array from buffered content. |
||||
*/ |
||||
public int[] toArray() { |
||||
return Arrays.copyOf(buffer, offset); |
||||
} |
||||
|
||||
/** |
||||
* Creates {@code int} subarray from buffered content. |
||||
*/ |
||||
public int[] toArray(final int start, final int len) { |
||||
final int[] array = new int[len]; |
||||
|
||||
if (len == 0) { |
||||
return array; |
||||
} |
||||
|
||||
System.arraycopy(buffer, start, array, 0, len); |
||||
|
||||
return array; |
||||
} |
||||
|
||||
/** |
||||
* Returns {@code int} element at given index. |
||||
*/ |
||||
public int get(final int index) { |
||||
if (index >= offset) { |
||||
throw new IndexOutOfBoundsException(); |
||||
} |
||||
return buffer[index]; |
||||
} |
||||
|
||||
|
||||
} |
@ -1,166 +0,0 @@
|
||||
// Copyright (c) 2003-present, Jodd Team (http://jodd.org)
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
package com.fr.third.jodd.buffer; |
||||
|
||||
import java.util.Arrays; |
||||
|
||||
/** |
||||
* Faster {@code long} buffer. |
||||
*/ |
||||
public class FastLongBuffer { |
||||
|
||||
private long[] buffer; |
||||
private int offset; |
||||
|
||||
/** |
||||
* Creates a new {@code long} buffer. The buffer capacity is |
||||
* initially 64 longs, though its size increases if necessary. |
||||
*/ |
||||
public FastLongBuffer() { |
||||
this.buffer = new long[64]; |
||||
} |
||||
|
||||
/** |
||||
* Creates a new {@code long} buffer, with a buffer capacity of |
||||
* the specified size. |
||||
* |
||||
* @param size the initial size. |
||||
* @throws IllegalArgumentException if size is negative. |
||||
*/ |
||||
public FastLongBuffer(final int size) { |
||||
this.buffer = new long[size]; |
||||
} |
||||
|
||||
/** |
||||
* Grows the buffer. |
||||
*/ |
||||
private void grow(final int minCapacity) { |
||||
final int oldCapacity = buffer.length; |
||||
int newCapacity = oldCapacity << 1; |
||||
if (newCapacity - minCapacity < 0) { |
||||
// special case, min capacity is larger then a grow
|
||||
newCapacity = minCapacity + 512; |
||||
} |
||||
buffer = Arrays.copyOf(buffer, newCapacity); |
||||
} |
||||
|
||||
/** |
||||
* Appends single {@code long} to buffer. |
||||
*/ |
||||
public void append(final long element) { |
||||
if (offset - buffer.length >= 0) { |
||||
grow(offset); |
||||
} |
||||
|
||||
buffer[offset++] = element; |
||||
} |
||||
|
||||
/** |
||||
* Appends {@code long} array to buffer. |
||||
*/ |
||||
public FastLongBuffer append(final long[] array, final int off, final int len) { |
||||
if (offset + len - buffer.length > 0) { |
||||
grow(offset + len); |
||||
} |
||||
|
||||
System.arraycopy(array, off, buffer, offset, len); |
||||
offset += len; |
||||
return this; |
||||
} |
||||
|
||||
/** |
||||
* Appends {@code long} array to buffer. |
||||
*/ |
||||
public FastLongBuffer append(final long[] array) { |
||||
return append(array, 0, array.length); |
||||
} |
||||
|
||||
/** |
||||
* Appends another fast buffer to this one. |
||||
*/ |
||||
public FastLongBuffer append(final FastLongBuffer buff) { |
||||
if (buff.offset == 0) { |
||||
return this; |
||||
} |
||||
append(buff.buffer, 0, buff.offset); |
||||
return this; |
||||
} |
||||
|
||||
/** |
||||
* Returns buffer size. |
||||
*/ |
||||
public int size() { |
||||
return offset; |
||||
} |
||||
|
||||
/** |
||||
* Tests if this buffer has no elements. |
||||
*/ |
||||
public boolean isEmpty() { |
||||
return offset == 0; |
||||
} |
||||
|
||||
/** |
||||
* Resets the buffer content. |
||||
*/ |
||||
public void clear() { |
||||
offset = 0; |
||||
} |
||||
|
||||
/** |
||||
* Creates {@code long} array from buffered content. |
||||
*/ |
||||
public long[] toArray() { |
||||
return Arrays.copyOf(buffer, offset); |
||||
} |
||||
|
||||
/** |
||||
* Creates {@code long} subarray from buffered content. |
||||
*/ |
||||
public long[] toArray(final int start, final int len) { |
||||
final long[] array = new long[len]; |
||||
|
||||
if (len == 0) { |
||||
return array; |
||||
} |
||||
|
||||
System.arraycopy(buffer, start, array, 0, len); |
||||
|
||||
return array; |
||||
} |
||||
|
||||
/** |
||||
* Returns {@code long} element at given index. |
||||
*/ |
||||
public long get(final int index) { |
||||
if (index >= offset) { |
||||
throw new IndexOutOfBoundsException(); |
||||
} |
||||
return buffer[index]; |
||||
} |
||||
|
||||
|
||||
} |
@ -1,165 +0,0 @@
|
||||
// Copyright (c) 2003-present, Jodd Team (http://jodd.org)
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
package com.fr.third.jodd.buffer; |
||||
|
||||
import java.util.Arrays; |
||||
|
||||
/** |
||||
* Faster {@code short} buffer. |
||||
*/ |
||||
public class FastShortBuffer { |
||||
|
||||
private short[] buffer; |
||||
private int offset; |
||||
|
||||
/** |
||||
* Creates a new {@code short} buffer. The buffer capacity is |
||||
* initially 64 shorts, though its size increases if necessary. |
||||
*/ |
||||
public FastShortBuffer() { |
||||
this.buffer = new short[64]; |
||||
} |
||||
|
||||
/** |
||||
* Creates a new {@code short} buffer, with a buffer capacity of |
||||
* the specified size. |
||||
* |
||||
* @param size the initial size. |
||||
* @throws IllegalArgumentException if size is negative. |
||||
*/ |
||||
public FastShortBuffer(final int size) { |
||||
this.buffer = new short[size]; |
||||
} |
||||
|
||||
/** |
||||
* Grows the buffer. |
||||
*/ |
||||
private void grow(final int minCapacity) { |
||||
final int oldCapacity = buffer.length; |
||||
int newCapacity = oldCapacity << 1; |
||||
if (newCapacity - minCapacity < 0) { |
||||
// special case, min capacity is larger then a grow
|
||||
newCapacity = minCapacity + 512; |
||||
} |
||||
buffer = Arrays.copyOf(buffer, newCapacity); |
||||
} |
||||
|
||||
/** |
||||
* Appends single {@code short} to buffer. |
||||
*/ |
||||
public void append(final short element) { |
||||
if (offset - buffer.length >= 0) { |
||||
grow(offset); |
||||
} |
||||
|
||||
buffer[offset++] = element; |
||||
} |
||||
|
||||
/** |
||||
* Appends {@code short} array to buffer. |
||||
*/ |
||||
public FastShortBuffer append(final short[] array, final int off, final int len) { |
||||
if (offset + len - buffer.length > 0) { |
||||
grow(offset + len); |
||||
} |
||||
|
||||
System.arraycopy(array, off, buffer, offset, len); |
||||
offset += len; |
||||
return this; |
||||
} |
||||
|
||||
/** |
||||
* Appends {@code short} array to buffer. |
||||
*/ |
||||
public FastShortBuffer append(final short[] array) { |
||||
return append(array, 0, array.length); |
||||
} |
||||
|
||||
/** |
||||
* Appends another fast buffer to this one. |
||||
*/ |
||||
public FastShortBuffer append(final FastShortBuffer buff) { |
||||
if (buff.offset == 0) { |
||||
return this; |
||||
} |
||||
append(buff.buffer, 0, buff.offset); |
||||
return this; |
||||
} |
||||
|
||||
/** |
||||
* Returns buffer size. |
||||
*/ |
||||
public int size() { |
||||
return offset; |
||||
} |
||||
|
||||
/** |
||||
* Tests if this buffer has no elements. |
||||
*/ |
||||
public boolean isEmpty() { |
||||
return offset == 0; |
||||
} |
||||
|
||||
/** |
||||
* Resets the buffer content. |
||||
*/ |
||||
public void clear() { |
||||
offset = 0; |
||||
} |
||||
|
||||
/** |
||||
* Creates {@code short} array from buffered content. |
||||
*/ |
||||
public short[] toArray() { |
||||
return Arrays.copyOf(buffer, offset); |
||||
} |
||||
|
||||
/** |
||||
* Creates {@code short} subarray from buffered content. |
||||
*/ |
||||
public short[] toArray(final int start, final int len) { |
||||
final short[] array = new short[len]; |
||||
|
||||
if (len == 0) { |
||||
return array; |
||||
} |
||||
|
||||
System.arraycopy(buffer, start, array, 0, len); |
||||
|
||||
return array; |
||||
} |
||||
|
||||
/** |
||||
* Returns {@code short} element at given index. |
||||
*/ |
||||
public short get(final int index) { |
||||
if (index >= offset) { |
||||
throw new IndexOutOfBoundsException(); |
||||
} |
||||
return buffer[index]; |
||||
} |
||||
|
||||
} |
@ -1,29 +0,0 @@
|
||||
// Copyright (c) 2003-present, Jodd Team (http://jodd.org)
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
/** |
||||
* Faster primitive buffers, a simple wrappers over an array. |
||||
*/ |
||||
package com.fr.third.jodd.buffer; |
@ -1,344 +0,0 @@
|
||||
// Copyright (c) 2003-present, Jodd Team (http://jodd.org)
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
package com.fr.third.jodd.cache; |
||||
|
||||
import java.util.HashMap; |
||||
import java.util.Map; |
||||
import java.util.Objects; |
||||
import java.util.concurrent.locks.StampedLock; |
||||
|
||||
/** |
||||
* Default implementation of timed and size cache map. |
||||
* Implementations should: |
||||
* <ul> |
||||
* <li>create a new cache map</li> |
||||
* <li>implements own <code>prune</code> strategy</li> |
||||
* </ul> |
||||
* Uses <code>ReentrantReadWriteLock</code> to synchronize access. |
||||
* Since upgrading from a read lock to the write lock is not possible, |
||||
* be careful withing {@link #get(Object)} method. |
||||
*/ |
||||
public abstract class AbstractCacheMap<K,V> implements Cache<K,V> { |
||||
|
||||
static class CacheObject<K2,V2> { |
||||
CacheObject(final K2 key, final V2 object, final long ttl) { |
||||
this.key = key; |
||||
this.cachedObject = object; |
||||
this.ttl = ttl; |
||||
this.lastAccess = System.currentTimeMillis(); |
||||
} |
||||
|
||||
final K2 key; |
||||
final V2 cachedObject; |
||||
long lastAccess; // time of last access
|
||||
long accessCount; // number of accesses
|
||||
long ttl; // objects timeout (time-to-live), 0 = no timeout
|
||||
|
||||
boolean isExpired() { |
||||
if (ttl == 0) { |
||||
return false; |
||||
} |
||||
return lastAccess + ttl < System.currentTimeMillis(); |
||||
} |
||||
V2 getObject() { |
||||
lastAccess = System.currentTimeMillis(); |
||||
accessCount++; |
||||
return cachedObject; |
||||
} |
||||
V2 peekObject() { |
||||
return cachedObject; |
||||
} |
||||
} |
||||
|
||||
protected Map<K,CacheObject<K,V>> cacheMap; |
||||
private final StampedLock lock = new StampedLock(); |
||||
|
||||
// ---------------------------------------------------------------- properties
|
||||
|
||||
protected int cacheSize; // max cache size, 0 = no limit
|
||||
|
||||
/** |
||||
* {@inheritDoc} |
||||
*/ |
||||
@Override |
||||
public int limit() { |
||||
return cacheSize; |
||||
} |
||||
|
||||
protected long timeout; // default timeout, 0 = no timeout
|
||||
|
||||
/** |
||||
* Returns default cache timeout or <code>0</code> if it is not set. |
||||
* Timeout can be set individually for each object. |
||||
*/ |
||||
@Override |
||||
public long timeout() { |
||||
return timeout; |
||||
} |
||||
|
||||
/** |
||||
* Identifies if objects has custom timeouts. |
||||
* Should be used to determine if prune for existing objects is needed. |
||||
*/ |
||||
protected boolean existCustomTimeout; |
||||
|
||||
/** |
||||
* Returns <code>true</code> if prune of expired objects should be invoked. |
||||
* For internal use. |
||||
*/ |
||||
protected boolean isPruneExpiredActive() { |
||||
return (timeout != 0) || existCustomTimeout; |
||||
} |
||||
|
||||
|
||||
// ---------------------------------------------------------------- put
|
||||
|
||||
|
||||
/** |
||||
* {@inheritDoc} |
||||
*/ |
||||
@Override |
||||
public void put(final K key, final V object) { |
||||
put(key, object, timeout); |
||||
} |
||||
|
||||
|
||||
/** |
||||
* {@inheritDoc} |
||||
*/ |
||||
@Override |
||||
public void put(final K key, final V object, final long timeout) { |
||||
Objects.requireNonNull(object); |
||||
|
||||
final long stamp = lock.writeLock(); |
||||
|
||||
try { |
||||
final CacheObject<K,V> co = createCacheObject(key, object, timeout); |
||||
if (timeout != 0) { |
||||
existCustomTimeout = true; |
||||
} |
||||
if (isReallyFull(key)) { |
||||
pruneCache(); |
||||
} |
||||
cacheMap.put(key, co); |
||||
} |
||||
finally { |
||||
lock.unlockWrite(stamp); |
||||
} |
||||
} |
||||
|
||||
protected CacheObject<K, V> createCacheObject(K key, V object, long timeout) { |
||||
return new CacheObject<>(key, object, timeout); |
||||
} |
||||
|
||||
// ---------------------------------------------------------------- get
|
||||
|
||||
protected int hitCount; |
||||
protected int missCount; |
||||
|
||||
/** |
||||
* Returns hit count. |
||||
*/ |
||||
public int getHitCount() { |
||||
return hitCount; |
||||
} |
||||
|
||||
/** |
||||
* Returns miss count. |
||||
*/ |
||||
public int getMissCount() { |
||||
return missCount; |
||||
} |
||||
|
||||
/** |
||||
* {@inheritDoc} |
||||
*/ |
||||
@Override |
||||
public V get(final K key) { |
||||
long stamp = lock.readLock(); |
||||
|
||||
try { |
||||
final CacheObject<K,V> co = cacheMap.get(key); |
||||
if (co == null) { |
||||
missCount++; |
||||
return null; |
||||
} |
||||
if (co.isExpired()) { |
||||
final long newStamp = lock.tryConvertToWriteLock(stamp); |
||||
|
||||
if (newStamp != 0L) { |
||||
stamp = newStamp; |
||||
// lock is upgraded to write lock
|
||||
} |
||||
else { |
||||
// manually upgrade lock to write lock
|
||||
lock.unlockRead(stamp); |
||||
stamp = lock.writeLock(); |
||||
} |
||||
|
||||
final CacheObject<K,V> removedCo = cacheMap.remove(key); |
||||
if (removedCo != null) { |
||||
onRemove(removedCo.key, removedCo.cachedObject); |
||||
} |
||||
|
||||
missCount++; |
||||
return null; |
||||
} |
||||
|
||||
hitCount++; |
||||
return co.getObject(); |
||||
} |
||||
finally { |
||||
lock.unlock(stamp); |
||||
} |
||||
} |
||||
|
||||
// ---------------------------------------------------------------- prune
|
||||
|
||||
/** |
||||
* Prune implementation. |
||||
*/ |
||||
protected abstract int pruneCache(); |
||||
|
||||
/** |
||||
* {@inheritDoc} |
||||
*/ |
||||
@Override |
||||
public final int prune() { |
||||
final long stamp = lock.writeLock(); |
||||
try { |
||||
return pruneCache(); |
||||
} |
||||
finally { |
||||
lock.unlockWrite(stamp); |
||||
} |
||||
} |
||||
|
||||
// ---------------------------------------------------------------- common
|
||||
|
||||
/** |
||||
* {@inheritDoc} |
||||
*/ |
||||
@Override |
||||
public boolean isFull() { |
||||
if (cacheSize == 0) { |
||||
return false; |
||||
} |
||||
return cacheMap.size() >= cacheSize; |
||||
} |
||||
|
||||
protected boolean isReallyFull(final K key) { |
||||
if (cacheSize == 0) { |
||||
return false; |
||||
} |
||||
if (cacheMap.size() >= cacheSize) { |
||||
return !cacheMap.containsKey(key); |
||||
} |
||||
else { |
||||
return false; |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* {@inheritDoc} |
||||
*/ |
||||
@Override |
||||
public V remove(final K key) { |
||||
V removedValue = null; |
||||
final long stamp = lock.writeLock(); |
||||
try { |
||||
final CacheObject<K,V> co = cacheMap.remove(key); |
||||
|
||||
if (co != null) { |
||||
onRemove(co.key, co.cachedObject); |
||||
removedValue = co.cachedObject; |
||||
} |
||||
} |
||||
finally { |
||||
lock.unlockWrite(stamp); |
||||
} |
||||
return removedValue; |
||||
} |
||||
|
||||
/** |
||||
* {@inheritDoc} |
||||
*/ |
||||
@Override |
||||
public void clear() { |
||||
final long stamp = lock.writeLock(); |
||||
try { |
||||
cacheMap.clear(); |
||||
} |
||||
finally { |
||||
lock.unlockWrite(stamp); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* {@inheritDoc} |
||||
*/ |
||||
@Override |
||||
public int size() { |
||||
return cacheMap.size(); |
||||
} |
||||
|
||||
/** |
||||
* {@inheritDoc} |
||||
*/ |
||||
@Override |
||||
public boolean isEmpty() { |
||||
return size() == 0; |
||||
} |
||||
|
||||
/** |
||||
* {@inheritDoc} |
||||
*/ |
||||
@Override |
||||
public Map<K, V> snapshot(final boolean peek) { |
||||
final long stamp = lock.writeLock(); |
||||
try { |
||||
final Map<K, V> map = new HashMap<>(cacheMap.size()); |
||||
cacheMap.forEach((key, cacheValue) -> { |
||||
if (!cacheValue.isExpired()) { |
||||
map.put(key, peek ? cacheValue.peekObject() : cacheValue.getObject()); |
||||
} |
||||
}); |
||||
return map; |
||||
} |
||||
finally { |
||||
lock.unlockWrite(stamp); |
||||
} |
||||
} |
||||
|
||||
// ---------------------------------------------------------------- protected
|
||||
|
||||
/** |
||||
* Callback called on item removal. The cache is still locked. |
||||
*/ |
||||
protected void onRemove(final K key, final V cachedObject) { |
||||
} |
||||
|
||||
} |
@ -1,108 +0,0 @@
|
||||
// Copyright (c) 2003-present, Jodd Team (http://jodd.org)
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
package com.fr.third.jodd.cache; |
||||
|
||||
import java.util.Map; |
||||
|
||||
/** |
||||
* Cache interface. |
||||
*/ |
||||
public interface Cache<K, V> { |
||||
|
||||
/** |
||||
* Returns cache size or <code>0</code> if there is no size limit. |
||||
*/ |
||||
int limit(); |
||||
|
||||
/** |
||||
* Returns default timeout or <code>0</code> if it is not set. |
||||
*/ |
||||
long timeout(); |
||||
|
||||
/** |
||||
* Adds an object to the cache with default timeout. |
||||
* @see Cache#put(Object, Object, long) |
||||
*/ |
||||
void put(K key, V object); |
||||
|
||||
/** |
||||
* Adds an object to the cache with specified timeout after which it becomes expired. |
||||
* If cache is full, {@link #prune()} is invoked to make room for new object. |
||||
* Cached value must be non-null. |
||||
*/ |
||||
void put(K key, V object, long timeout); |
||||
|
||||
/** |
||||
* Retrieves an object from the cache. Returns <code>null</code> if object |
||||
* is not longer in cache or if it is expired. |
||||
*/ |
||||
V get(K key); |
||||
|
||||
/** |
||||
* Prunes objects from cache and returns the number of removed objects. |
||||
* Used strategy depends on cache implementation. |
||||
*/ |
||||
int prune(); |
||||
|
||||
/** |
||||
* Returns <code>true</code> if max cache capacity has been reached |
||||
* only if cache is size limited. |
||||
*/ |
||||
boolean isFull(); |
||||
|
||||
/** |
||||
* Removes an object from the cache and returns removed value of {@code null} |
||||
* if object was not in the cache or was expired. |
||||
*/ |
||||
V remove(K key); |
||||
|
||||
/** |
||||
* Clears current cache. |
||||
*/ |
||||
void clear(); |
||||
|
||||
/** |
||||
* Returns current cache size. |
||||
*/ |
||||
int size(); |
||||
|
||||
/** |
||||
* Returns <code>true</code> if cache is empty. |
||||
*/ |
||||
boolean isEmpty(); |
||||
|
||||
/** |
||||
* Creates a snapshot from current cache values. Returned values may not |
||||
* longer be valid or they might be already expired! Cache is locked during |
||||
* the snapshot creation. |
||||
* @param peek if set, snapshot will just peek the object and not get them (and modify last access) |
||||
*/ |
||||
Map<K, V> snapshot(boolean peek); |
||||
|
||||
default Map<K, V> snapshot() { |
||||
return this.snapshot(false); |
||||
} |
||||
} |
@ -1,89 +0,0 @@
|
||||
// Copyright (c) 2003-present, Jodd Team (http://jodd.org)
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
package com.fr.third.jodd.cache; |
||||
|
||||
import java.util.Iterator; |
||||
import java.util.LinkedHashMap; |
||||
|
||||
/** |
||||
* FIFO (first in first out) cache. |
||||
* |
||||
* <p> |
||||
* FIFO (first in first out): just adds items to the cache as they are accessed, putting them in a queue or buffer and |
||||
* not changing their location in the buffer; when the cache is full, items are ejected in the order they were |
||||
* added. Cache access overhead is constant time regardless of the size of the cache. The advantage of this algorithm |
||||
* is that it's simple and fast; it can be implemented using a simple array and an index. The disadvantage is that |
||||
* it's not very smart; it doesn't make any effort to keep more commonly used items in cache. |
||||
* <p> |
||||
* Summary for FIFO: fast, not adaptive, not scan resistant. |
||||
*/ |
||||
public class FIFOCache<K, V> extends AbstractCacheMap<K, V> { |
||||
|
||||
public FIFOCache(final int cacheSize) { |
||||
this(cacheSize, 0); |
||||
} |
||||
|
||||
/** |
||||
* Creates a new LRU cache. |
||||
*/ |
||||
public FIFOCache(final int cacheSize, final long timeout) { |
||||
this.cacheSize = cacheSize; |
||||
this.timeout = timeout; |
||||
cacheMap = new LinkedHashMap<>(cacheSize + 1, 1.0f, false); |
||||
} |
||||
|
||||
|
||||
// ---------------------------------------------------------------- prune
|
||||
|
||||
/** |
||||
* Prune expired objects and, if cache is still full, the first one. |
||||
*/ |
||||
@Override |
||||
protected int pruneCache() { |
||||
int count = 0; |
||||
CacheObject<K,V> first = null; |
||||
Iterator<CacheObject<K,V>> values = cacheMap.values().iterator(); |
||||
while (values.hasNext()) { |
||||
CacheObject<K,V> co = values.next(); |
||||
if (co.isExpired()) { |
||||
values.remove(); |
||||
onRemove(co.key, co.cachedObject); |
||||
count++; |
||||
} |
||||
if (first == null) { |
||||
first = co; |
||||
} |
||||
} |
||||
if (isFull()) { |
||||
if (first != null) { |
||||
cacheMap.remove(first.key); |
||||
onRemove(first.key, first.cachedObject); |
||||
count++; |
||||
} |
||||
} |
||||
return count; |
||||
} |
||||
} |
@ -1,153 +0,0 @@
|
||||
// Copyright (c) 2003-present, Jodd Team (http://jodd.org)
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
package com.fr.third.jodd.cache; |
||||
|
||||
import com.fr.third.jodd.io.FileUtil; |
||||
|
||||
import java.io.File; |
||||
import java.io.IOException; |
||||
|
||||
/** |
||||
* Base in-memory files cache. |
||||
*/ |
||||
public abstract class FileCache { |
||||
|
||||
protected final Cache<File, byte[]> cache; |
||||
protected final int maxSize; |
||||
protected final int maxFileSize; |
||||
protected final long timeout; |
||||
|
||||
protected int usedSize; |
||||
|
||||
/** |
||||
* Creates new File LFU cache. |
||||
* @param maxSize total cache size in bytes |
||||
* @param maxFileSize max available file size in bytes, may be 0 |
||||
* @param timeout timeout, may be 0 |
||||
*/ |
||||
protected FileCache(final int maxSize, final int maxFileSize, final long timeout) { |
||||
this.maxSize = maxSize; |
||||
this.maxFileSize = maxFileSize; |
||||
this.timeout = timeout; |
||||
this.cache = createCache(); |
||||
} |
||||
|
||||
/** |
||||
* Creates new cache instance for files content. |
||||
*/ |
||||
protected abstract Cache<File, byte[]> createCache(); |
||||
|
||||
/** |
||||
* Creates CacheObject that updates last access time based on files last modification. |
||||
*/ |
||||
protected AbstractCacheMap.CacheObject<File, byte[]> createFileCacheObject(File fileKey, byte[] object, long timeout) { |
||||
return new AbstractCacheMap.CacheObject<File, byte[]>(fileKey, object, timeout) { |
||||
@Override |
||||
boolean isExpired() { |
||||
if (fileKey.lastModified() > this.lastAccess) { |
||||
this.lastAccess = fileKey.lastModified(); |
||||
} |
||||
return super.isExpired(); |
||||
} |
||||
}; |
||||
} |
||||
|
||||
// ---------------------------------------------------------------- get
|
||||
|
||||
/** |
||||
* Returns max cache size in bytes. |
||||
*/ |
||||
public int maxSize() { |
||||
return maxSize; |
||||
} |
||||
|
||||
/** |
||||
* Returns actually used size in bytes. |
||||
*/ |
||||
public int usedSize() { |
||||
return usedSize; |
||||
} |
||||
|
||||
/** |
||||
* Returns maximum allowed file size that can be added to the cache. |
||||
* Files larger than this value will be not added, even if there is |
||||
* enough room. |
||||
*/ |
||||
public int maxFileSize() { |
||||
return maxFileSize; |
||||
} |
||||
|
||||
/** |
||||
* Returns number of cached files. |
||||
*/ |
||||
public int cachedFilesCount() { |
||||
return cache.size(); |
||||
} |
||||
|
||||
/** |
||||
* Returns timeout. |
||||
*/ |
||||
public long cacheTimeout() { |
||||
return cache.timeout(); |
||||
} |
||||
|
||||
/** |
||||
* Clears the cache. |
||||
*/ |
||||
public void clear() { |
||||
cache.clear(); |
||||
usedSize = 0; |
||||
} |
||||
|
||||
// ---------------------------------------------------------------- get
|
||||
|
||||
/** |
||||
* Returns cached file bytes. If file is not cached it will be |
||||
* read and put in the cache (if all the rules are satisfied). |
||||
*/ |
||||
public byte[] getFileBytes(final File file) throws IOException { |
||||
byte[] bytes = cache.get(file); |
||||
if (bytes != null) { |
||||
return bytes; |
||||
} |
||||
|
||||
// add file
|
||||
bytes = FileUtil.readBytes(file); |
||||
|
||||
if ((maxFileSize != 0) && (file.length() > maxFileSize)) { |
||||
// don't cache files that size exceed max allowed file size
|
||||
return bytes; |
||||
} |
||||
|
||||
usedSize += bytes.length; |
||||
|
||||
// put file into cache
|
||||
// if used size > total, purge() will be invoked
|
||||
cache.put(file, bytes); |
||||
|
||||
return bytes; |
||||
} |
||||
|
||||
} |
@ -1,82 +0,0 @@
|
||||
// Copyright (c) 2003-present, Jodd Team (http://jodd.org)
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
package com.fr.third.jodd.cache; |
||||
|
||||
import java.io.File; |
||||
|
||||
/** |
||||
* Files LFU cache stores files content in memory to dramatically |
||||
* speed up performances for frequently read files. |
||||
*/ |
||||
public class FileLFUCache extends FileCache { |
||||
|
||||
/** |
||||
* Creates file LFU cache with specified size. Sets |
||||
* {@link #maxFileSize max available file size} to half of this value. |
||||
*/ |
||||
public FileLFUCache(final int maxSize) { |
||||
this(maxSize, maxSize / 2, 0); |
||||
} |
||||
|
||||
public FileLFUCache(final int maxSize, final int maxFileSize) { |
||||
this(maxSize, maxFileSize, 0); |
||||
} |
||||
|
||||
/** |
||||
* Creates new File LFU cache. |
||||
* @param maxSize total cache size in bytes |
||||
* @param maxFileSize max available file size in bytes, may be 0 |
||||
* @param timeout timeout, may be 0 |
||||
*/ |
||||
public FileLFUCache(final int maxSize, final int maxFileSize, final long timeout) { |
||||
super(maxSize, maxFileSize, timeout); |
||||
} |
||||
|
||||
@Override |
||||
protected Cache<File, byte[]> createCache() { |
||||
return new LFUCache<File, byte[]>(0, timeout) { |
||||
@Override |
||||
public boolean isFull() { |
||||
return usedSize > FileLFUCache.this.maxSize; |
||||
} |
||||
|
||||
@Override |
||||
protected boolean isReallyFull(final File file) { |
||||
return isFull(); |
||||
} |
||||
|
||||
@Override |
||||
protected void onRemove(final File key, final byte[] cachedObject) { |
||||
usedSize -= cachedObject.length; |
||||
} |
||||
|
||||
@Override |
||||
protected CacheObject<File, byte[]> createCacheObject(File key, byte[] object, long timeout) { |
||||
return createFileCacheObject(key, object, timeout); |
||||
} |
||||
}; |
||||
} |
||||
} |
@ -1,81 +0,0 @@
|
||||
// Copyright (c) 2003-present, Jodd Team (http://jodd.org)
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
package com.fr.third.jodd.cache; |
||||
|
||||
import java.io.File; |
||||
|
||||
/** |
||||
* Cache of recently used files. |
||||
*/ |
||||
public class FileLRUCache extends FileCache { |
||||
|
||||
/** |
||||
* Creates file LRU cache with specified size. Sets |
||||
* {@link #maxFileSize max available file size} to half of this value. |
||||
*/ |
||||
public FileLRUCache(final int maxSize) { |
||||
this(maxSize, maxSize / 2, 0); |
||||
} |
||||
|
||||
public FileLRUCache(final int maxSize, final int maxFileSize) { |
||||
this(maxSize, maxFileSize, 0); |
||||
} |
||||
|
||||
/** |
||||
* Creates new File LRU cache. |
||||
* @param maxSize total cache size in bytes |
||||
* @param maxFileSize max available file size in bytes, may be 0 |
||||
* @param timeout timeout, may be 0 |
||||
*/ |
||||
public FileLRUCache(final int maxSize, final int maxFileSize, final long timeout) { |
||||
super(maxSize, maxFileSize, timeout); |
||||
} |
||||
|
||||
@Override |
||||
protected Cache<File, byte[]> createCache() { |
||||
return new LRUCache<File, byte[]>(0, timeout) { |
||||
@Override |
||||
public boolean isFull() { |
||||
return usedSize > FileLRUCache.this.maxSize; |
||||
} |
||||
|
||||
@Override |
||||
protected boolean isReallyFull(final File file) { |
||||
return isFull(); |
||||
} |
||||
|
||||
@Override |
||||
protected void onRemove(final File key, final byte[] cachedObject) { |
||||
usedSize -= cachedObject.length; |
||||
} |
||||
|
||||
@Override |
||||
protected CacheObject<File, byte[]> createCacheObject(File key, byte[] object, long timeout) { |
||||
return createFileCacheObject(key, object, timeout); |
||||
} |
||||
|
||||
}; |
||||
} |
||||
} |
@ -1,111 +0,0 @@
|
||||
// Copyright (c) 2003-present, Jodd Team (http://jodd.org)
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
package com.fr.third.jodd.cache; |
||||
|
||||
import java.util.HashMap; |
||||
import java.util.Iterator; |
||||
|
||||
/** |
||||
* LFU (least frequently used) cache. Frequency is calculated as access count. This cache |
||||
* is resistant on 'new usages scenario': when some object is removed from the cache, |
||||
* access count of all items in cache is decreased by access count of removed value. |
||||
* This allows new frequent elements to come into the cache. |
||||
* <p> |
||||
* Frequency of use data is kept on all items. The most frequently used items are kept in the cache. |
||||
* Because of the bookkeeping requirements, cache access overhead increases logarithmically with cache size. |
||||
* The advantage is that long term usage patterns are captured well, incidentally making the algorithm scan resistant; |
||||
* the disadvantage, besides the larger access overhead, is that the algorithm doesn't adapt quickly to changing |
||||
* usage patterns, and in particular doesn't help with temporally clustered accesses. |
||||
* <p> |
||||
* Summary for LFU: not fast, captures frequency of use, scan resistant. |
||||
*/ |
||||
public class LFUCache<K,V> extends AbstractCacheMap<K,V> { |
||||
|
||||
public LFUCache(final int maxSize) { |
||||
this(maxSize, 0); |
||||
} |
||||
|
||||
public LFUCache(final int maxSize, final long timeout) { |
||||
this.cacheSize = maxSize; |
||||
this.timeout = timeout; |
||||
cacheMap = new HashMap<>(maxSize + 1); |
||||
} |
||||
|
||||
// ---------------------------------------------------------------- prune
|
||||
|
||||
/** |
||||
* Prunes expired and, if cache is still full, the LFU element(s) from the cache. |
||||
* On LFU removal, access count is normalized to value which had removed object. |
||||
* Returns the number of removed objects. |
||||
*/ |
||||
@Override |
||||
protected int pruneCache() { |
||||
int count = 0; |
||||
CacheObject<K,V> comin = null; |
||||
|
||||
// remove expired items and find cached object with minimal access count
|
||||
Iterator<CacheObject<K,V>> values = cacheMap.values().iterator(); |
||||
while (values.hasNext()) { |
||||
CacheObject<K,V> co = values.next(); |
||||
if (co.isExpired()) { |
||||
values.remove(); |
||||
onRemove(co.key, co.cachedObject); |
||||
count++; |
||||
continue; |
||||
} |
||||
|
||||
if (comin == null) { |
||||
comin = co; |
||||
} else { |
||||
if (co.accessCount < comin.accessCount) { |
||||
comin = co; |
||||
} |
||||
} |
||||
} |
||||
|
||||
if (!isFull()) { |
||||
return count; |
||||
} |
||||
|
||||
// decrease access count to all cached objects
|
||||
if (comin != null) { |
||||
long minAccessCount = comin.accessCount; |
||||
|
||||
values = cacheMap.values().iterator(); |
||||
while (values.hasNext()) { |
||||
CacheObject<K, V> co = values.next(); |
||||
co.accessCount -= minAccessCount; |
||||
if (co.accessCount <= 0) { |
||||
values.remove(); |
||||
onRemove(co.key, co.cachedObject); |
||||
count++; |
||||
} |
||||
} |
||||
} |
||||
return count; |
||||
} |
||||
|
||||
} |
@ -1,103 +0,0 @@
|
||||
// Copyright (c) 2003-present, Jodd Team (http://jodd.org)
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
package com.fr.third.jodd.cache; |
||||
|
||||
import java.util.LinkedHashMap; |
||||
import java.util.Map; |
||||
import java.util.Iterator; |
||||
|
||||
|
||||
/** |
||||
* LRU (least recently used) cache. |
||||
* |
||||
* <p> |
||||
* Items are added to the cache as they are accessed; when the cache is full, the least recently used item is ejected. |
||||
* This type of cache is typically implemented as a linked list, so that an item in cache, when it is accessed again, |
||||
* can be moved back up to the head of the queue; items are ejected from the tail of the queue. Cache access overhead |
||||
* is again constant time. This algorithm is simple and fast, and it has a significant advantage over FIFO in being |
||||
* able to adapt somewhat to the data access pattern; frequently used items are less likely to be |
||||
* ejected from the cache. The main disadvantage is that it can still get filled up with items that are |
||||
* unlikely to be reaccessed soon; in particular, it can become useless in the face of scanning type accesses. |
||||
* Nonetheless, this is by far the most frequently used caching algorithm. |
||||
* <p> |
||||
* Implementation note: unfortunately, it was not possible to have <code>onRemove</code> callback method, |
||||
* since <code>LinkedHashMap</code> has its removal methods private. |
||||
* <p> |
||||
* Summary for LRU: fast, adaptive, not scan resistant. |
||||
*/ |
||||
public class LRUCache<K, V> extends AbstractCacheMap<K, V> { |
||||
|
||||
public LRUCache(final int cacheSize) { |
||||
this(cacheSize, 0); |
||||
} |
||||
|
||||
/** |
||||
* Creates a new LRU cache. |
||||
*/ |
||||
public LRUCache(final int cacheSize, final long timeout) { |
||||
this.cacheSize = cacheSize; |
||||
this.timeout = timeout; |
||||
cacheMap = new LinkedHashMap<K, CacheObject<K,V>>(cacheSize + 1, 1.0f, true) { |
||||
@Override |
||||
protected boolean removeEldestEntry(final Map.Entry eldest) { |
||||
return LRUCache.this.removeEldestEntry(size()); |
||||
} |
||||
}; |
||||
} |
||||
|
||||
/** |
||||
* Removes the eldest entry if current cache size exceed cache size. |
||||
*/ |
||||
protected boolean removeEldestEntry(final int currentSize) { |
||||
if (cacheSize == 0) { |
||||
return false; |
||||
} |
||||
return currentSize > cacheSize; |
||||
} |
||||
|
||||
// ---------------------------------------------------------------- prune
|
||||
|
||||
/** |
||||
* Prune only expired objects, <code>LinkedHashMap</code> will take care of LRU if needed. |
||||
*/ |
||||
@Override |
||||
protected int pruneCache() { |
||||
if (!isPruneExpiredActive()) { |
||||
return 0; |
||||
} |
||||
int count = 0; |
||||
Iterator<CacheObject<K,V>> values = cacheMap.values().iterator(); |
||||
while (values.hasNext()) { |
||||
CacheObject<K,V> co = values.next(); |
||||
if (co.isExpired()) { |
||||
values.remove(); |
||||
onRemove(co.key, co.cachedObject); |
||||
count++; |
||||
} |
||||
} |
||||
return count; |
||||
} |
||||
} |
@ -1,96 +0,0 @@
|
||||
// Copyright (c) 2003-present, Jodd Team (http://jodd.org)
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
package com.fr.third.jodd.cache; |
||||
|
||||
import java.util.Collections; |
||||
import java.util.Map; |
||||
|
||||
/** |
||||
* Simple no-cache implementations of {@link Cache} for situation when cache |
||||
* needs to be quickly turned-off. |
||||
*/ |
||||
public class NoCache<K, V> implements Cache<K, V> { |
||||
|
||||
@Override |
||||
public int limit() { |
||||
return 0; |
||||
} |
||||
|
||||
@Override |
||||
public long timeout() { |
||||
return 0; |
||||
} |
||||
|
||||
@Override |
||||
public void put(final K key, final V object) { |
||||
// ignore
|
||||
} |
||||
|
||||
@Override |
||||
public void put(final K key, final V object, final long timeout) { |
||||
// ignore
|
||||
} |
||||
|
||||
@Override |
||||
public V get(final K key) { |
||||
return null; |
||||
} |
||||
|
||||
@Override |
||||
public int prune() { |
||||
return 0; |
||||
} |
||||
|
||||
@Override |
||||
public boolean isFull() { |
||||
return true; |
||||
} |
||||
|
||||
@Override |
||||
public V remove(final K key) { |
||||
return null; |
||||
} |
||||
|
||||
@Override |
||||
public void clear() { |
||||
// ignore
|
||||
} |
||||
|
||||
@Override |
||||
public int size() { |
||||
return 0; |
||||
} |
||||
|
||||
@Override |
||||
public boolean isEmpty() { |
||||
return true; |
||||
} |
||||
|
||||
@Override |
||||
public Map<K, V> snapshot(final boolean peek) { |
||||
return Collections.emptyMap(); |
||||
} |
||||
} |
@ -1,98 +0,0 @@
|
||||
// Copyright (c) 2003-present, Jodd Team (http://jodd.org)
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
package com.fr.third.jodd.cache; |
||||
|
||||
import java.util.HashMap; |
||||
import java.util.Iterator; |
||||
import java.util.Timer; |
||||
import java.util.TimerTask; |
||||
|
||||
/** |
||||
* Timed cache. Not limited by size, objects are removed only when they are expired. |
||||
* Prune is not invoked explicitly by standard {@link Cache} methods, however, |
||||
* it is possible to schedule prunes on fined-rate delays. |
||||
*/ |
||||
public class TimedCache<K, V> extends AbstractCacheMap<K, V> { |
||||
|
||||
public TimedCache(final long timeout) { |
||||
this.cacheSize = 0; |
||||
this.timeout = timeout; |
||||
cacheMap = new HashMap<>(); |
||||
} |
||||
|
||||
// ---------------------------------------------------------------- prune
|
||||
|
||||
/** |
||||
* Prunes expired elements from the cache. Returns the number of removed objects. |
||||
*/ |
||||
@Override |
||||
protected int pruneCache() { |
||||
int count = 0; |
||||
Iterator<CacheObject<K,V>> values = cacheMap.values().iterator(); |
||||
while (values.hasNext()) { |
||||
CacheObject co = values.next(); |
||||
if (co.isExpired()) { |
||||
values.remove(); |
||||
count++; |
||||
} |
||||
} |
||||
return count; |
||||
} |
||||
|
||||
|
||||
// ---------------------------------------------------------------- auto prune
|
||||
|
||||
protected Timer pruneTimer; |
||||
|
||||
/** |
||||
* Schedules prune. |
||||
*/ |
||||
public void schedulePrune(final long delay) { |
||||
if (pruneTimer != null) { |
||||
pruneTimer.cancel(); |
||||
} |
||||
pruneTimer = new Timer(); |
||||
pruneTimer.schedule( |
||||
new TimerTask() { |
||||
@Override |
||||
public void run() { |
||||
prune(); |
||||
} |
||||
}, delay, delay |
||||
); |
||||
} |
||||
|
||||
/** |
||||
* Cancels prune schedules. |
||||
*/ |
||||
public void cancelPruneSchedule() { |
||||
if (pruneTimer != null) { |
||||
pruneTimer.cancel(); |
||||
pruneTimer = null; |
||||
} |
||||
} |
||||
|
||||
} |
@ -1,205 +0,0 @@
|
||||
// Copyright (c) 2003-present, Jodd Team (http://jodd.org)
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
package com.fr.third.jodd.cache; |
||||
|
||||
import java.util.AbstractMap; |
||||
import java.util.Collections; |
||||
import java.util.IdentityHashMap; |
||||
import java.util.Map; |
||||
import java.util.Set; |
||||
import java.util.WeakHashMap; |
||||
import java.util.concurrent.ConcurrentHashMap; |
||||
import java.util.function.Consumer; |
||||
import java.util.function.Function; |
||||
|
||||
/** |
||||
* Types cache. Provides several implementations depending on what you need to be addressed. |
||||
* There are two things you should take care off: |
||||
* <ul> |
||||
* <li>synchronization - especially on storing items. If not synchronized, one instance of an item may be put |
||||
* more then once into the map. This is usually fine, as it happens only during the initialization and makes not |
||||
* harm if something is created twice</li> |
||||
* <li>weak - if your key classes are replaced during the runtime, you should use weak map, in order to automatically |
||||
* remove obsolete keys.</li> |
||||
* </ul> |
||||
*/ |
||||
public class TypeCache<T> { |
||||
|
||||
// ---------------------------------------------------------------- builder
|
||||
|
||||
/** |
||||
* Creates a type cache by using a builder. |
||||
*/ |
||||
public static <A> Builder<A> create() { |
||||
return new Builder<>(); |
||||
} |
||||
|
||||
/** |
||||
* Creates default implementation of the type cache. |
||||
*/ |
||||
@SuppressWarnings("unchecked") |
||||
public static <A> TypeCache<A> createDefault() { |
||||
return TypeCache.<A>create().get(); |
||||
} |
||||
|
||||
public static class Builder<A> { |
||||
private boolean threadsafe; |
||||
private boolean weak; |
||||
private boolean none; |
||||
|
||||
/** |
||||
* No cache will be used. |
||||
* Setting other properties will not have any affect. |
||||
*/ |
||||
public Builder<A> noCache() { |
||||
none = true; |
||||
return this; |
||||
} |
||||
|
||||
/** |
||||
* Cache keys will be weak. |
||||
*/ |
||||
public Builder<A> weak(final boolean weak) { |
||||
this.weak = weak; |
||||
return this; |
||||
} |
||||
/** |
||||
* Cache will be thread-safe. |
||||
*/ |
||||
public Builder<A> threadsafe(final boolean threadsafe) { |
||||
this.threadsafe = threadsafe; |
||||
return this; |
||||
} |
||||
|
||||
/** |
||||
* Builds a type cache. |
||||
*/ |
||||
public TypeCache<A> get() { |
||||
final Map<Class<?>, A> map; |
||||
if (none) { |
||||
map = new AbstractMap<Class<?>, A>() { |
||||
@Override |
||||
public A put(final Class<?> key, final A value) { |
||||
return null; |
||||
} |
||||
|
||||
@Override |
||||
public A get(final Object key) { |
||||
return null; |
||||
} |
||||
|
||||
@Override |
||||
public Set<Entry<Class<?>, A>> entrySet() { |
||||
return Collections.emptySet(); |
||||
} |
||||
}; |
||||
} |
||||
else if (weak) { |
||||
if (threadsafe) { |
||||
map = Collections.synchronizedMap(new WeakHashMap<>()); |
||||
} else { |
||||
map = new WeakHashMap<>(); |
||||
} |
||||
} else { |
||||
if (threadsafe) { |
||||
map = new ConcurrentHashMap<>(); |
||||
} else { |
||||
map = new IdentityHashMap<>(); |
||||
} |
||||
} |
||||
|
||||
return new TypeCache<>(map); |
||||
} |
||||
} |
||||
|
||||
// ---------------------------------------------------------------- map
|
||||
|
||||
private final Map<Class<?>, T> map; |
||||
|
||||
private TypeCache(final Map<Class<?>, T> backedMap) { |
||||
this.map = backedMap; |
||||
} |
||||
|
||||
/** |
||||
* Add values to the map. |
||||
*/ |
||||
public T put(final Class<?> type, final T value) { |
||||
return map.put(type, value); |
||||
} |
||||
|
||||
/** |
||||
* Returns value from the map or {@code null} if value does not exist. |
||||
*/ |
||||
public T get(final Class<?> key) { |
||||
return map.get(key); |
||||
} |
||||
|
||||
/** |
||||
* Returns existing value or add default supplied one. |
||||
* Use this method instead of {@code get-nullcheck-put} block when |
||||
* thread-safety is of importance. |
||||
*/ |
||||
@SuppressWarnings("unchecked") |
||||
public <K> T get(final Class<K> key, final Function<Class<K>, ? extends T> mappingFunction) { |
||||
return map.computeIfAbsent(key, aClass -> mappingFunction.apply((Class<K>) aClass)); |
||||
} |
||||
|
||||
/** |
||||
* Removes element from the type cache. |
||||
*/ |
||||
public T remove(final Class<?> type) { |
||||
return map.remove(type); |
||||
} |
||||
|
||||
/** |
||||
* Clears complete cache. |
||||
*/ |
||||
public void clear() { |
||||
map.clear(); |
||||
} |
||||
|
||||
/** |
||||
* Returns cache size. |
||||
*/ |
||||
public int size() { |
||||
return map.size(); |
||||
} |
||||
|
||||
/** |
||||
* Returns {@code true} if cache is empty. |
||||
*/ |
||||
public boolean isEmpty() { |
||||
return map.isEmpty(); |
||||
} |
||||
|
||||
/** |
||||
* Iterates all cached values. |
||||
*/ |
||||
public void forEachValue(final Consumer<? super T> valueConsumer) { |
||||
map.values().forEach(valueConsumer); |
||||
} |
||||
|
||||
} |
@ -1,29 +0,0 @@
|
||||
// Copyright (c) 2003-present, Jodd Team (http://jodd.org)
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
/** |
||||
* Some useful caches: LRU, LFU, FIFO. |
||||
*/ |
||||
package com.fr.third.jodd.cache; |
@ -1,298 +0,0 @@
|
||||
// Copyright (c) 2003-present, Jodd Team (http://jodd.org)
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
package com.fr.third.jodd.chalk; |
||||
|
||||
import com.fr.third.jodd.util.StringPool; |
||||
|
||||
/** |
||||
* Chalk allows you to color output going to console. |
||||
* @see Chalk256 |
||||
*/ |
||||
public class Chalk<T extends Chalk<T>> { |
||||
|
||||
/** |
||||
* Global flag that disables all the chalks. |
||||
* Useful for windows platforms :) |
||||
*/ |
||||
public static boolean enabled = true; |
||||
|
||||
protected static final String RESET = "0"; |
||||
|
||||
protected static final String BOLD = "1"; |
||||
protected static final String UNBOLD = "22"; // 21 isn't widely supported and 22 does the same thing
|
||||
protected static final String DIM = "2"; |
||||
protected static final String UNDIM = "22"; |
||||
protected static final String ITALIC = "3"; |
||||
protected static final String UNITALIC = "23"; |
||||
protected static final String UNDERLINE = "4"; |
||||
protected static final String UNUNDERLINE = "24"; |
||||
protected static final String INVERSE = "7"; |
||||
protected static final String UNINVERSE = "27"; |
||||
protected static final String HIDDEN = "8"; |
||||
protected static final String UNHIDDEN = "28"; |
||||
protected static final String STRIKETHROUGH = "9"; |
||||
protected static final String UNSTRIKETHROUGH = "29"; |
||||
|
||||
protected static final String COLOR_RESET = "39"; |
||||
protected static final String BLACK = "30"; |
||||
protected static final String RED = "31"; |
||||
protected static final String GREEN = "32"; |
||||
protected static final String YELLOW = "33"; |
||||
protected static final String BLUE = "34"; |
||||
protected static final String MAGENTA = "35"; |
||||
protected static final String CYAN = "36"; |
||||
protected static final String WHITE = "37"; |
||||
protected static final String GRAY = "90"; |
||||
|
||||
protected static final String BGCOLOR_RESET = "49"; |
||||
protected static final String BGBLACK = "40"; |
||||
protected static final String BGRED = "41"; |
||||
protected static final String BGGREEN = "42"; |
||||
protected static final String BGYELLOW = "43"; |
||||
protected static final String BGBLUE = "44"; |
||||
protected static final String BGMAGENTA = "45"; |
||||
protected static final String BGCYAN = "46"; |
||||
protected static final String BGWHITE = "47"; |
||||
|
||||
protected StringBuilder prefix; |
||||
protected StringBuilder suffix; |
||||
protected String text; |
||||
|
||||
/** |
||||
* Creates new chalk. |
||||
*/ |
||||
public static Chalk chalk() { |
||||
return new Chalk(); |
||||
} |
||||
|
||||
@SuppressWarnings("unchecked") |
||||
protected T _this() { |
||||
return (T) this; |
||||
} |
||||
|
||||
// ---------------------------------------------------------------- style
|
||||
|
||||
public T bold() { |
||||
startSequence(BOLD); |
||||
endSequence(UNBOLD); |
||||
return _this(); |
||||
} |
||||
|
||||
public T italic() { |
||||
startSequence(ITALIC); |
||||
endSequence(UNITALIC); |
||||
return _this(); |
||||
} |
||||
|
||||
public T dim() { |
||||
startSequence(DIM); |
||||
endSequence(UNDIM); |
||||
return _this(); |
||||
} |
||||
|
||||
public T underline() { |
||||
startSequence(UNDERLINE); |
||||
endSequence(UNUNDERLINE); |
||||
return _this(); |
||||
} |
||||
|
||||
public T inverse() { |
||||
startSequence(INVERSE); |
||||
endSequence(UNINVERSE); |
||||
return _this(); |
||||
} |
||||
|
||||
public T hidden() { |
||||
startSequence(HIDDEN); |
||||
endSequence(UNHIDDEN); |
||||
return _this(); |
||||
} |
||||
public T strikeThrough() { |
||||
startSequence(STRIKETHROUGH); |
||||
endSequence(UNSTRIKETHROUGH); |
||||
return _this(); |
||||
} |
||||
|
||||
// ---------------------------------------------------------------- colors
|
||||
|
||||
public T black() { |
||||
startSequence(BLACK); |
||||
endSequence(COLOR_RESET); |
||||
return _this(); |
||||
} |
||||
public T red() { |
||||
startSequence(RED); |
||||
endSequence(COLOR_RESET); |
||||
return _this(); |
||||
} |
||||
public T green() { |
||||
startSequence(GREEN); |
||||
endSequence(COLOR_RESET); |
||||
return _this(); |
||||
} |
||||
public T yellow() { |
||||
startSequence(YELLOW); |
||||
endSequence(COLOR_RESET); |
||||
return _this(); |
||||
} |
||||
public T blue() { |
||||
startSequence(BLUE); |
||||
endSequence(COLOR_RESET); |
||||
return _this(); |
||||
} |
||||
public T magenta() { |
||||
startSequence(MAGENTA); |
||||
endSequence(COLOR_RESET); |
||||
return _this(); |
||||
} |
||||
public T cyan() { |
||||
startSequence(CYAN); |
||||
endSequence(COLOR_RESET); |
||||
return _this(); |
||||
} |
||||
public T white() { |
||||
startSequence(WHITE); |
||||
endSequence(COLOR_RESET); |
||||
return _this(); |
||||
} |
||||
public T gray() { |
||||
startSequence(GRAY); |
||||
endSequence(COLOR_RESET); |
||||
return _this(); |
||||
} |
||||
public T grey() { |
||||
return gray(); |
||||
} |
||||
|
||||
// ---------------------------------------------------------------- bg colors
|
||||
|
||||
public T bgBlack() { |
||||
startSequence(BGBLACK); |
||||
endSequence(BGCOLOR_RESET); |
||||
return _this(); |
||||
} |
||||
public T bgRed() { |
||||
startSequence(BGRED); |
||||
endSequence(BGCOLOR_RESET); |
||||
return _this(); |
||||
} |
||||
public T bgGreen() { |
||||
startSequence(BGGREEN); |
||||
endSequence(BGCOLOR_RESET); |
||||
return _this(); |
||||
} |
||||
public T bgYellow() { |
||||
startSequence(BGYELLOW); |
||||
endSequence(BGCOLOR_RESET); |
||||
return _this(); |
||||
} |
||||
public T bgBlue() { |
||||
startSequence(BGBLUE); |
||||
endSequence(BGCOLOR_RESET); |
||||
return _this(); |
||||
} |
||||
public T bgMagenta() { |
||||
startSequence(BGMAGENTA); |
||||
endSequence(BGCOLOR_RESET); |
||||
return _this(); |
||||
} |
||||
public T bgCyan() { |
||||
startSequence(BGCYAN); |
||||
endSequence(BGCOLOR_RESET); |
||||
return _this(); |
||||
} |
||||
public T bgWhite() { |
||||
startSequence(BGWHITE); |
||||
endSequence(BGCOLOR_RESET); |
||||
return _this(); |
||||
} |
||||
|
||||
// ---------------------------------------------------------------- internal
|
||||
|
||||
protected void startSequence(final String value) { |
||||
if (prefix == null) { |
||||
prefix = new StringBuilder(); |
||||
prefix.append("\u001B["); |
||||
} |
||||
else { |
||||
prefix.append(StringPool.SEMICOLON); |
||||
} |
||||
|
||||
prefix.append(value); |
||||
} |
||||
|
||||
protected void endSequence(final String value) { |
||||
if (suffix == null) { |
||||
suffix = new StringBuilder(); |
||||
suffix |
||||
.append("\u001B[") |
||||
.append(value); |
||||
} |
||||
else { |
||||
suffix.insert(2, value + StringPool.SEMICOLON); |
||||
} |
||||
} |
||||
|
||||
// ---------------------------------------------------------------- out
|
||||
|
||||
/** |
||||
* Returns chalked string. |
||||
*/ |
||||
public String on(final String string) { |
||||
if (!enabled) { |
||||
return string; |
||||
} |
||||
|
||||
final StringBuilder sb = new StringBuilder(); |
||||
|
||||
if (prefix != null) { |
||||
sb.append(prefix).append("m"); |
||||
} |
||||
|
||||
sb.append(string); |
||||
|
||||
if (suffix != null) { |
||||
sb.append(suffix).append("m"); |
||||
} |
||||
|
||||
return sb.toString(); |
||||
} |
||||
|
||||
/** |
||||
* Prints chalked string to system output. |
||||
*/ |
||||
public void print(final String string) { |
||||
System.out.print(on(string)); |
||||
} |
||||
|
||||
/** |
||||
* Prints chalked string to system output. |
||||
*/ |
||||
public void println(final String string) { |
||||
System.out.println(on(string)); |
||||
} |
||||
|
||||
} |
@ -1,123 +0,0 @@
|
||||
// Copyright (c) 2003-present, Jodd Team (http://jodd.org)
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
package com.fr.third.jodd.chalk; |
||||
|
||||
/** |
||||
* Chalk256 allows you to color output going to ansi-256 console. |
||||
* @see Chalk |
||||
*/ |
||||
public class Chalk256 extends Chalk<Chalk256> { |
||||
|
||||
private static final String[] FG_CODES = new String[256]; |
||||
private static final String[] BG_CODES = new String[256]; |
||||
|
||||
static { |
||||
for (int i = 0; i < FG_CODES.length; i++) { |
||||
FG_CODES[i] = "38;5;" + i; |
||||
} |
||||
for (int i = 0; i < BG_CODES.length; i++) { |
||||
BG_CODES[i] = "48;5;" + i; |
||||
} |
||||
} |
||||
|
||||
public static Chalk256 chalk() { |
||||
return new Chalk256(); |
||||
} |
||||
|
||||
// ---------------------------------------------------------------- fg codes
|
||||
|
||||
public Chalk256 standard(final int index) { |
||||
startSequence(FG_CODES[index(index, 0, 8)]); |
||||
endSequence(RESET); |
||||
return _this(); |
||||
} |
||||
public Chalk256 bright(final int index) { |
||||
startSequence(FG_CODES[index(index, 8, 16)]); |
||||
endSequence(RESET); |
||||
return _this(); |
||||
} |
||||
public Chalk256 rgb(final int index) { |
||||
startSequence(FG_CODES[index(index, 16, 232)]); |
||||
endSequence(RESET); |
||||
return _this(); |
||||
} |
||||
|
||||
/** |
||||
* Colors with red-green-blue value, in the range 0 to 6. |
||||
*/ |
||||
public Chalk256 rgb(final int r, final int b, final int g) { |
||||
startSequence(FG_CODES[index(36*r + 6*g + b,16, 232)]); |
||||
endSequence(RESET); |
||||
return _this(); |
||||
} |
||||
public Chalk256 grayscale(final int index) { |
||||
startSequence(FG_CODES[index(index, 232, 256)]); |
||||
endSequence(RESET); |
||||
return _this(); |
||||
} |
||||
// ---------------------------------------------------------------- bg codes
|
||||
|
||||
public Chalk256 bgStandard(final int index) { |
||||
startSequence(BG_CODES[index(index, 0, 8)]); |
||||
endSequence(RESET); |
||||
return _this(); |
||||
} |
||||
public Chalk256 bgBright(final int index) { |
||||
startSequence(BG_CODES[index(index, 8, 16)]); |
||||
endSequence(RESET); |
||||
return _this(); |
||||
} |
||||
public Chalk256 bgRgb(final int index) { |
||||
startSequence(BG_CODES[index(index, 16, 232)]); |
||||
endSequence(RESET); |
||||
return _this(); |
||||
} |
||||
|
||||
/** |
||||
* Colors with red-green-blue value, in the range 0 to 6. |
||||
*/ |
||||
public Chalk256 bgRgb(final int r, final int b, final int g) { |
||||
startSequence(BG_CODES[index(36*r + 6*g + b,16, 232)]); |
||||
endSequence(RESET); |
||||
return _this(); |
||||
} |
||||
public Chalk256 bgGrayscale(final int index) { |
||||
startSequence(BG_CODES[index(index, 232, 256)]); |
||||
endSequence(RESET); |
||||
return _this(); |
||||
} |
||||
|
||||
// ---------------------------------------------------------------- bgcolors
|
||||
|
||||
private int index(int index, final int from, final int to) { |
||||
index += from; |
||||
if ((index < from) || (index >= to)) { |
||||
throw new IllegalArgumentException("Color index not in range: [0, " + (to - from) + "]"); |
||||
} |
||||
return index; |
||||
} |
||||
|
||||
} |
@ -1,29 +0,0 @@
|
||||
// Copyright (c) 2003-present, Jodd Team (http://jodd.org)
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
/** |
||||
* Little tool for coloring the console output. |
||||
*/ |
||||
package com.fr.third.jodd.chalk; |
@ -1,233 +0,0 @@
|
||||
// Copyright (c) 2003-present, Jodd Team (http://jodd.org)
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
package com.fr.third.jodd.cli; |
||||
|
||||
import java.util.ArrayList; |
||||
import java.util.List; |
||||
import java.util.function.Consumer; |
||||
|
||||
public class Cli implements Consumer<String[]> { |
||||
|
||||
private final List<Option> options = new ArrayList<>(); |
||||
private final List<Param> params = new ArrayList<>(); |
||||
|
||||
public Option option() { |
||||
final Option option = new Option(); |
||||
options.add(option); |
||||
return option; |
||||
} |
||||
|
||||
public Param param() { |
||||
final Param param = new Param(); |
||||
params.add(param); |
||||
return param; |
||||
} |
||||
|
||||
private boolean consumeOptionWithLongName(final String input, final String valueToConsume) { |
||||
for (final Option option : options) { |
||||
if (input.equals(option.longName)) { |
||||
if (option.hasArg && valueToConsume == null) { |
||||
throw new CliException("Option value not provided for: " + input); |
||||
} |
||||
option.consumer.accept(option.hasArg ? valueToConsume : input); |
||||
return option.hasArg; |
||||
} |
||||
|
||||
if (option.longName != null && input.startsWith(option.longName + "=")) { |
||||
option.consumer.accept(input.substring(option.longName.length() + 1)); |
||||
return false; |
||||
} |
||||
} |
||||
|
||||
throw new CliException("Unknown option: " + input); |
||||
} |
||||
|
||||
private boolean consumeOptionWithShortName(final String input, final String valueToConsume) { |
||||
for (final Option option : options) { |
||||
if (input.equals(option.shortName)) { |
||||
if (option.hasArg) { |
||||
if (valueToConsume == null) { |
||||
throw new CliException("Option value not provided for: " + input); |
||||
} |
||||
option.consumer.accept(valueToConsume); |
||||
return true; |
||||
} |
||||
else { |
||||
option.consumer.accept(input); |
||||
return false; |
||||
} |
||||
} |
||||
|
||||
if (option.shortName != null && input.startsWith(option.shortName + "=")) { |
||||
option.consumer.accept(input.substring(option.shortName.length() + 1)); |
||||
return false; |
||||
} |
||||
} |
||||
throw new CliException("Unknown option: " + input); |
||||
} |
||||
|
||||
private void consumeOptionWithShortNameAndNoArguments(final String shortName) { |
||||
for (final Option option : options) { |
||||
if (shortName.equals(option.shortName) && !option.hasArg) { |
||||
option.consumer.accept(shortName); |
||||
return; |
||||
} |
||||
} |
||||
throw new CliException("Unknown option: " + shortName); |
||||
} |
||||
|
||||
@Override |
||||
public void accept(final String... args) { |
||||
assertConfigurationIsValid(); |
||||
|
||||
boolean dontParseOptionsAnyMore = false; |
||||
int i; |
||||
int paramsIndex = 0; |
||||
|
||||
for (i = 0; i < args.length; i++) { |
||||
final String arg = args[i]; |
||||
if (arg.isEmpty()) { |
||||
continue; |
||||
} |
||||
final String value = (i + 1 < args.length) ? args[i + 1] : null; |
||||
|
||||
if (arg.equals("--")) { |
||||
dontParseOptionsAnyMore = true; |
||||
continue; |
||||
} |
||||
|
||||
if (!dontParseOptionsAnyMore) { |
||||
// long names
|
||||
if (arg.startsWith("--")) { |
||||
final String argLongName = arg.substring(2); |
||||
|
||||
consumeOptionWithLongName(argLongName, value); |
||||
|
||||
args[i] = null; |
||||
continue; |
||||
} |
||||
|
||||
// short names
|
||||
if (arg.startsWith("-")) { |
||||
final String argShortName = arg.substring(1); |
||||
|
||||
if (argShortName.length() > 1 && argShortName.charAt(1) != '=') { |
||||
// compressed options
|
||||
final char[] allShortNames = argShortName.toCharArray(); |
||||
for (final char c : allShortNames) { |
||||
final String argName = String.valueOf(c); |
||||
consumeOptionWithShortNameAndNoArguments(argName); |
||||
} |
||||
args[i] = null; |
||||
continue; |
||||
} |
||||
|
||||
final boolean valueConsumed = consumeOptionWithShortName(argShortName, value); |
||||
|
||||
// mark argument as consumed
|
||||
args[i] = null; |
||||
if (valueConsumed) { |
||||
// mark value as consumed, too
|
||||
i++; |
||||
args[i] = null; |
||||
} |
||||
continue; |
||||
} |
||||
} |
||||
|
||||
// params
|
||||
|
||||
if (paramsIndex == params.size()) { |
||||
// we are done here
|
||||
break; |
||||
} |
||||
final Param param = params.get(paramsIndex++); |
||||
|
||||
final List<String> paramArguments = new ArrayList<>(); |
||||
|
||||
int from = 0; |
||||
final int to = param.required + param.optional; |
||||
|
||||
for (; from < to; from++, i++) { |
||||
final String paramValue = (i < args.length) ? args[i] : null; |
||||
if (paramValue == null) { |
||||
break; |
||||
} |
||||
paramArguments.add(paramValue); |
||||
} |
||||
i--; |
||||
|
||||
if (paramArguments.size() < param.required) { |
||||
throw new CliException("Parameter required: " + param.label); |
||||
} |
||||
|
||||
if (paramArguments.isEmpty()) { |
||||
// parameter not found
|
||||
continue; |
||||
} |
||||
|
||||
param.consumer.accept(paramArguments.toArray(new String[0])); |
||||
} |
||||
|
||||
// must check if remaining parameters are not satisfied
|
||||
while (paramsIndex < params.size()) { |
||||
final Param param = params.get(paramsIndex++); |
||||
if (param.required > 0) { |
||||
throw new CliException("Parameter required: " + param.label); |
||||
} |
||||
} |
||||
} |
||||
|
||||
private void assertConfigurationIsValid() { |
||||
for (final Option option : options) { |
||||
if (option.consumer == null) { |
||||
throw new CliException("Option has no registered consumer: " + option); |
||||
} |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Prints the usage line. |
||||
*/ |
||||
public void printUsage(final String commandName) { |
||||
final StringBuilder usage = new StringBuilder(commandName); |
||||
|
||||
for (final Option option : options) { |
||||
if (option.shortName != null) { |
||||
usage.append(" [-").append(option.shortName).append("]"); |
||||
} else if (option.longName != null) { |
||||
usage.append(" [--").append(option.longName).append("]"); |
||||
} |
||||
} |
||||
|
||||
for (final Param param : params) { |
||||
usage.append(" ").append(param.label); |
||||
} |
||||
|
||||
System.out.println(usage); |
||||
} |
||||
|
||||
} |
@ -1,37 +0,0 @@
|
||||
// Copyright (c) 2003-present, Jodd Team (http://jodd.org)
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
package com.fr.third.jodd.cli; |
||||
|
||||
import com.fr.third.jodd.exception.UncheckedException; |
||||
|
||||
/** |
||||
* CLI exception. |
||||
*/ |
||||
public class CliException extends UncheckedException { |
||||
public CliException(final String message) { |
||||
super(message); |
||||
} |
||||
} |
@ -1,96 +0,0 @@
|
||||
// Copyright (c) 2003-present, Jodd Team (http://jodd.org)
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
package com.fr.third.jodd.cli; |
||||
|
||||
import java.util.function.Consumer; |
||||
|
||||
public class Option { |
||||
|
||||
String label; |
||||
String shortName; |
||||
String longName; |
||||
String description; |
||||
boolean hasArg; |
||||
String argLabel; |
||||
Consumer<String> consumer; |
||||
|
||||
public Option shortName(final String shortName) { |
||||
this.shortName = shortName; |
||||
return this; |
||||
} |
||||
|
||||
public Option longName(final String longName) { |
||||
this.longName = longName; |
||||
return this; |
||||
} |
||||
|
||||
public Option names(final String shortName, final String longName) { |
||||
this.shortName = shortName; |
||||
this.longName = longName; |
||||
return this; |
||||
} |
||||
|
||||
public Option description(final String description) { |
||||
this.description = description; |
||||
return this; |
||||
} |
||||
|
||||
public Option hasArg() { |
||||
this.hasArg = true; |
||||
return this; |
||||
} |
||||
|
||||
public Option hasArg(final String argLabel) { |
||||
this.hasArg = true; |
||||
this.argLabel = argLabel; |
||||
return this; |
||||
} |
||||
|
||||
public Option label(final String label) { |
||||
this.label = label; |
||||
return this; |
||||
} |
||||
|
||||
public Option with(final Consumer<String> consumer) { |
||||
this.consumer = consumer; |
||||
return this; |
||||
} |
||||
|
||||
@Override |
||||
public String toString() { |
||||
String out = ""; |
||||
if (shortName != null) { |
||||
out += "-" + shortName; |
||||
} |
||||
if (longName != null) { |
||||
if (!out.isEmpty()) { |
||||
out += " | "; |
||||
} |
||||
out += "--" + longName; |
||||
} |
||||
return out; |
||||
} |
||||
} |
@ -1,84 +0,0 @@
|
||||
// Copyright (c) 2003-present, Jodd Team (http://jodd.org)
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
package com.fr.third.jodd.cli; |
||||
|
||||
import java.util.function.Consumer; |
||||
|
||||
public class Param { |
||||
String label; |
||||
int required = 0; |
||||
int optional = 1; |
||||
String description; |
||||
Consumer<String[]> consumer; |
||||
|
||||
public Param required(final int required) { |
||||
this.required = required; |
||||
return this; |
||||
} |
||||
|
||||
public Param optional(final int optional) { |
||||
this.optional = optional; |
||||
return this; |
||||
} |
||||
|
||||
public Param required() { |
||||
this.required = 1; |
||||
this.optional = 0; |
||||
return this; |
||||
} |
||||
|
||||
public Param optional() { |
||||
this.required = 0; |
||||
this.optional = 1; |
||||
return this; |
||||
} |
||||
|
||||
public Param all() { |
||||
this.optional = 1_000_000; // magic number indicating *ALL* parameters
|
||||
return this; |
||||
} |
||||
|
||||
public Param range(final int required, final int max) { |
||||
this.required = required; |
||||
this.optional = max - required; |
||||
return this; |
||||
} |
||||
|
||||
public Param label(final String label) { |
||||
this.label = label; |
||||
return this; |
||||
} |
||||
|
||||
public Param description(final String description) { |
||||
this.description = description; |
||||
return this; |
||||
} |
||||
|
||||
public Param with(final Consumer<String[]> consumer) { |
||||
this.consumer = consumer; |
||||
return this; |
||||
} |
||||
} |
@ -1,29 +0,0 @@
|
||||
// Copyright (c) 2003-present, Jodd Team (http://jodd.org)
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
/** |
||||
* Small parser for command line arguments. |
||||
*/ |
||||
package com.fr.third.jodd.cli; |
@ -1,65 +0,0 @@
|
||||
// Copyright (c) 2003-present, Jodd Team (http://jodd.org)
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
package com.fr.third.jodd.core; |
||||
|
||||
import com.fr.third.jodd.util.StringPool; |
||||
|
||||
import java.security.Security; |
||||
|
||||
/** |
||||
* Jodd library-wide properties. |
||||
*/ |
||||
public class JoddCore { |
||||
|
||||
static { |
||||
// Starting from Java8 u151, the `Unlimited Strength Jurisdiction Policy Files`
|
||||
// are included with Java, but has to be enabled.
|
||||
// They are enabled on Java9 by default.
|
||||
Security.setProperty("crypto.policy", "unlimited"); |
||||
} |
||||
|
||||
// ---------------------------------------------------------------- settings
|
||||
|
||||
/** |
||||
* Default prefix for temporary files. |
||||
*/ |
||||
public static String tempFilePrefix = "jodd-"; |
||||
|
||||
/** |
||||
* The encoding used across the Jodd classes, "UTF-8" by default. |
||||
*/ |
||||
public static String encoding = StringPool.UTF_8; |
||||
|
||||
/** |
||||
* Buffer size for various I/O operations. |
||||
*/ |
||||
public static int ioBufferSize = 16384; |
||||
/** |
||||
* Flag that controls the {@code Unsafe} usage (if system detects it). Enabled by default. |
||||
*/ |
||||
public static boolean unsafeUsageEnabled = true; |
||||
|
||||
} |
@ -1,29 +0,0 @@
|
||||
// Copyright (c) 2003-present, Jodd Team (http://jodd.org)
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
/** |
||||
* Jodd Core module. |
||||
*/ |
||||
package com.fr.third.jodd.core; |
@ -1,303 +0,0 @@
|
||||
// Copyright (c) 2003-present, Jodd Team (http://jodd.org)
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
package com.fr.third.jodd.datetime; |
||||
|
||||
import com.fr.third.jodd.util.HashCode; |
||||
import static com.fr.third.jodd.util.HashCode.hash; |
||||
|
||||
import java.io.Serializable; |
||||
|
||||
/** |
||||
* Generic date time stamp just stores and holds date and time information. |
||||
* This class does not contain any date/time logic, neither guarantees |
||||
* that date is valid. |
||||
* |
||||
* @see JDateTime |
||||
* @see JulianDateStamp |
||||
* @deprecated jodd目前版本为5.1.6, 此版本已移除此类, 兼容问题暂不删除此类 |
||||
*/ |
||||
@Deprecated |
||||
public class DateTimeStamp implements Comparable, Serializable, Cloneable { |
||||
|
||||
/** |
||||
* Default empty constructor. |
||||
*/ |
||||
public DateTimeStamp() { |
||||
} |
||||
|
||||
/** |
||||
* Constructor that sets date and time. |
||||
*/ |
||||
public DateTimeStamp(int year, int month, int day, int hour, int minute, int second, int millisecond) { |
||||
this.year = year; |
||||
this.month = month; |
||||
this.day = day; |
||||
this.hour = hour; |
||||
this.minute = minute; |
||||
this.second = second; |
||||
this.millisecond = millisecond; |
||||
} |
||||
|
||||
/** |
||||
* Constructor that sets just date. Time is set to zeros. |
||||
*/ |
||||
public DateTimeStamp(int year, int month, int day) { |
||||
this(year, month, day, 0, 0, 0, 0); |
||||
} |
||||
|
||||
/** |
||||
* Year. |
||||
*/ |
||||
public int year; |
||||
|
||||
/** |
||||
* Month, range: [1 - 12] |
||||
*/ |
||||
public int month = 1; |
||||
|
||||
/** |
||||
* Day, range: [1 - 31] |
||||
*/ |
||||
public int day = 1; |
||||
|
||||
/** |
||||
* Hour, range: [0 - 23] |
||||
*/ |
||||
public int hour; |
||||
|
||||
/** |
||||
* Minute, range [0 - 59] |
||||
*/ |
||||
public int minute; |
||||
|
||||
/** |
||||
* Second, range: [0 - 59] |
||||
*/ |
||||
public int second; |
||||
|
||||
/** |
||||
* Millisecond, range: [0 - 1000] |
||||
*/ |
||||
public int millisecond; |
||||
|
||||
|
||||
// ---------------------------------------------------------------- get/set
|
||||
|
||||
public int getYear() { |
||||
return year; |
||||
} |
||||
|
||||
public void setYear(int year) { |
||||
this.year = year; |
||||
} |
||||
|
||||
public int getMonth() { |
||||
return month; |
||||
} |
||||
|
||||
public void setMonth(int month) { |
||||
this.month = month; |
||||
} |
||||
|
||||
public int getDay() { |
||||
return day; |
||||
} |
||||
|
||||
public void setDay(int day) { |
||||
this.day = day; |
||||
} |
||||
|
||||
public int getHour() { |
||||
return hour; |
||||
} |
||||
|
||||
public void setHour(int hour) { |
||||
this.hour = hour; |
||||
} |
||||
|
||||
public int getMinute() { |
||||
return minute; |
||||
} |
||||
|
||||
public void setMinute(int minute) { |
||||
this.minute = minute; |
||||
} |
||||
|
||||
public int getSecond() { |
||||
return second; |
||||
} |
||||
|
||||
public void setSecond(int second) { |
||||
this.second = second; |
||||
} |
||||
|
||||
public int getMillisecond() { |
||||
return millisecond; |
||||
} |
||||
|
||||
public void setMillisecond(int millisecond) { |
||||
this.millisecond = millisecond; |
||||
} |
||||
|
||||
// ---------------------------------------------------------------- compare
|
||||
|
||||
/** |
||||
* Compares this object with the specified object for order. Returns a |
||||
* negative integer, zero, or a positive integer as this object is less |
||||
* than, equal to, or greater than the specified object. |
||||
* |
||||
* @param o the Object to be compared. |
||||
* @return a negative integer, zero, or a positive integer as this object |
||||
* is less than, equal to, or greater than the specified object. |
||||
* |
||||
* @throws ClassCastException if the specified object's type prevents it |
||||
* from being compared to this Object. |
||||
*/ |
||||
public int compareTo(Object o) { |
||||
DateTimeStamp dts = (DateTimeStamp) o; |
||||
|
||||
int date1 = year * 10000 + month * 100 + day; |
||||
int date2 = dts.year * 10000 + dts.month * 100 + dts.day; |
||||
|
||||
if (date1 < date2) { |
||||
return -1; |
||||
} |
||||
if (date1 > date2) { |
||||
return 1; |
||||
} |
||||
|
||||
date1 = (hour * 10000000) + (minute * 100000) + (second * 1000) + millisecond; |
||||
date2 = (dts.hour * 10000000) + (dts.minute * 100000) + (dts.second * 1000) + dts.millisecond; |
||||
|
||||
if (date1 < date2) { |
||||
return -1; |
||||
} |
||||
if (date1 > date2) { |
||||
return 1; |
||||
} |
||||
return 0; |
||||
} |
||||
|
||||
/** |
||||
* Compares just date component of two date time stamps. |
||||
*/ |
||||
public int compareDateTo(Object o) { |
||||
DateTimeStamp dts = (DateTimeStamp) o; |
||||
|
||||
int date1 = year * 10000 + month * 100 + day; |
||||
int date2 = dts.year * 10000 + dts.month * 100 + dts.day; |
||||
|
||||
if (date1 < date2) { |
||||
return -1; |
||||
} |
||||
if (date1 > date2) { |
||||
return 1; |
||||
} |
||||
return 0; |
||||
} |
||||
|
||||
|
||||
// ---------------------------------------------------------------- toString
|
||||
|
||||
/** |
||||
* Simple to string conversion. |
||||
* |
||||
* @return date/time string in 'y-m-d h:m:m.s' format |
||||
*/ |
||||
@Override |
||||
public String toString() { |
||||
return new StringBuilder(25).append(year).append('-').append(month) |
||||
.append('-').append(day).append(' ').append(hour).append(':') |
||||
.append(minute).append(':').append(second).append('.') |
||||
.append(millisecond).toString(); |
||||
} |
||||
|
||||
// ---------------------------------------------------------------- equals & hashCode
|
||||
|
||||
@Override |
||||
public boolean equals(Object object) { |
||||
if (this == object) { |
||||
return true; |
||||
} |
||||
if (this.getClass() != object.getClass()) { |
||||
return false; |
||||
} |
||||
DateTimeStamp stamp = (DateTimeStamp) object; |
||||
return (stamp.year == this.year) && |
||||
(stamp.month == this.month) && |
||||
(stamp.day == this.day) && |
||||
(stamp.hour == this.hour) && |
||||
(stamp.minute == this.minute) && |
||||
(stamp.second == this.second) && |
||||
(stamp.millisecond == this.millisecond); |
||||
} |
||||
|
||||
@Override |
||||
public int hashCode() { |
||||
int result = HashCode.SEED; |
||||
result = hash(result, year); |
||||
result = hash(result, month); |
||||
result = hash(result, day); |
||||
result = hash(result, hour); |
||||
result = hash(result, minute); |
||||
result = hash(result, second); |
||||
result = hash(result, millisecond); |
||||
return result; |
||||
} |
||||
|
||||
// ---------------------------------------------------------------- clone
|
||||
|
||||
|
||||
@Override |
||||
protected DateTimeStamp clone() { |
||||
DateTimeStamp dts = new DateTimeStamp(); |
||||
dts.year = this.year; |
||||
dts.month = this.month; |
||||
dts.day = this.day; |
||||
dts.hour = this.hour; |
||||
dts.minute = this.minute; |
||||
dts.second = this.second; |
||||
dts.millisecond = this.millisecond; |
||||
return dts; |
||||
} |
||||
|
||||
// ---------------------------------------------------------------- equals
|
||||
|
||||
public boolean isEqualDate(DateTimeStamp date) { |
||||
return date.day == this.day |
||||
&& date.month == this.month |
||||
&& date.year == this.year; |
||||
} |
||||
|
||||
public boolean isEqualTime(DateTimeStamp time) { |
||||
return time.hour == this.hour |
||||
&& time.minute == this.minute |
||||
&& time.second == this.second |
||||
&& time.millisecond == this.millisecond; |
||||
} |
||||
|
||||
|
||||
} |
File diff suppressed because it is too large
Load Diff
@ -1,88 +0,0 @@
|
||||
// Copyright (c) 2003-present, Jodd Team (http://jodd.org)
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
package com.fr.third.jodd.datetime; |
||||
|
||||
import com.fr.third.jodd.datetime.format.Iso8601JdtFormatter; |
||||
import com.fr.third.jodd.datetime.format.JdtFormatter; |
||||
|
||||
import java.util.TimeZone; |
||||
import java.util.Locale; |
||||
|
||||
/** |
||||
* Defaults for {@link JDateTime}. |
||||
* @deprecated jodd目前版本为5.1.6, 此版本已移除此类, 兼容问题暂不删除此类 |
||||
*/ |
||||
@Deprecated |
||||
@SuppressWarnings({"RedundantFieldInitialization"}) |
||||
public class JDateTimeDefault { |
||||
|
||||
/** |
||||
* Default value for month fix. |
||||
*/ |
||||
public static boolean monthFix = true; |
||||
|
||||
/** |
||||
* Default time zone. Set it to <code>null</code> |
||||
* for system default timezone. |
||||
*/ |
||||
public static TimeZone timeZone = null; // system default
|
||||
|
||||
/** |
||||
* Default locale for date names. Set it to <code>null</code> |
||||
* for system default locale. |
||||
*/ |
||||
public static Locale locale = null; // system default
|
||||
|
||||
/** |
||||
* Default format template. |
||||
*/ |
||||
public static String format = JDateTime.DEFAULT_FORMAT; |
||||
|
||||
/** |
||||
* Default formatter. |
||||
*/ |
||||
public static JdtFormatter formatter = new Iso8601JdtFormatter(); |
||||
|
||||
/** |
||||
* Default definition of first day of week. |
||||
*/ |
||||
public static int firstDayOfWeek = JDateTime.MONDAY; |
||||
|
||||
/** |
||||
* Default number of days first week of year must have. |
||||
*/ |
||||
public static int mustHaveDayOfFirstWeek = 4; |
||||
|
||||
/** |
||||
* Default minimal number of days firs week of year must have. |
||||
*/ |
||||
public static int minDaysInFirstWeek = 4; |
||||
|
||||
/** |
||||
* Default value for tracking DST. |
||||
*/ |
||||
public static boolean trackDST = false; |
||||
} |
@ -1,302 +0,0 @@
|
||||
// Copyright (c) 2003-present, Jodd Team (http://jodd.org)
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
package com.fr.third.jodd.datetime; |
||||
|
||||
import java.util.List; |
||||
import java.util.ArrayList; |
||||
|
||||
/** |
||||
* Nice thread-aware stopwatch that supports time spans, cumulative times and laps. |
||||
* Useful for all kind of profiling, time measurements etc. |
||||
* |
||||
* @deprecated jodd目前版本为5.1.6, 此版本已移除此类, 兼容问题暂不删除此类 |
||||
*/ |
||||
@Deprecated |
||||
public class JStopWatch { |
||||
|
||||
/** |
||||
* Optional stopwatch name. |
||||
*/ |
||||
protected String name; |
||||
/** |
||||
* Last start time. |
||||
*/ |
||||
protected long startTime; |
||||
/** |
||||
* Last stop time. |
||||
*/ |
||||
protected long stopTime; |
||||
/** |
||||
* Last elapsed time. |
||||
*/ |
||||
protected long spanTime; |
||||
/** |
||||
* Cumulative elapsed time. |
||||
*/ |
||||
protected long totalTime; |
||||
/** |
||||
* Running flag. |
||||
*/ |
||||
protected boolean running; |
||||
|
||||
// ---------------------------------------------------------------- ctors
|
||||
|
||||
/** |
||||
* Starts the stopwatch. |
||||
*/ |
||||
public JStopWatch() { |
||||
this("#jStopWatch"); |
||||
} |
||||
|
||||
/** |
||||
* Starts the named stopwatch. |
||||
*/ |
||||
public JStopWatch(String name) { |
||||
this.name = name; |
||||
start(); |
||||
} |
||||
|
||||
/** |
||||
* Returns stopwatch name. |
||||
*/ |
||||
public String getName() { |
||||
return name; |
||||
} |
||||
|
||||
/** |
||||
* Returns <code>true</code> if stopwatch is running. |
||||
*/ |
||||
public boolean isRunning() { |
||||
return running; |
||||
} |
||||
|
||||
// ---------------------------------------------------------------- basic
|
||||
|
||||
/** |
||||
* Starts the stopwatch. {@link #stop()} must be called prior to restart. |
||||
* Returns starting time in milliseconds. |
||||
*/ |
||||
public long start() { |
||||
if (!running) { |
||||
startTime = System.currentTimeMillis(); |
||||
running = true; |
||||
} |
||||
return startTime; |
||||
} |
||||
|
||||
/** |
||||
* Restarts the stopwatch. |
||||
*/ |
||||
public long restart() { |
||||
startTime = System.currentTimeMillis(); |
||||
running = true; |
||||
return startTime; |
||||
} |
||||
|
||||
/** |
||||
* Stops the stopwatch if running. Returns span time. |
||||
* If laps are used, marks the last lap. |
||||
*/ |
||||
public long stop() { |
||||
if (running) { |
||||
stopTime = System.currentTimeMillis(); |
||||
if (laps != null) { |
||||
lap(stopTime); |
||||
} |
||||
spanTime = stopTime - startTime; |
||||
totalTime += stopTime - startTime; |
||||
running = false; |
||||
} |
||||
return spanTime; |
||||
} |
||||
|
||||
/** |
||||
* Returns total elapsed time from the {@link #start()} in ms. |
||||
*/ |
||||
public long elapsed() { |
||||
return System.currentTimeMillis() - startTime; |
||||
} |
||||
|
||||
/** |
||||
* Stops the stopwatch and returns total cumulative time in ms. |
||||
*/ |
||||
public long total() { |
||||
stop(); |
||||
return totalTime; |
||||
} |
||||
|
||||
/** |
||||
* Stops the stopwatch and returns total time span for last |
||||
* start-stop sequence. |
||||
*/ |
||||
public long span() { |
||||
stop(); |
||||
return spanTime; |
||||
} |
||||
|
||||
|
||||
// ---------------------------------------------------------------- laps
|
||||
|
||||
/** |
||||
* List of all laps. Contains long arrays in following format: |
||||
* <ul> |
||||
* <li>lap time - current lap time,</li> |
||||
* <li>lap span time - elapsed time from start,</li> |
||||
* <li>lap millis - lap milliseconds. |
||||
* </ul> |
||||
*/ |
||||
protected List<long[]> laps; |
||||
|
||||
/** |
||||
* Marks a lap and returns its length. May be called only while stop watch is running. |
||||
*/ |
||||
public long lap() { |
||||
return lap(System.currentTimeMillis()); |
||||
} |
||||
|
||||
protected long lap(long lap) { |
||||
if (!running) { |
||||
return 0; |
||||
} |
||||
long lapSpanTime = lap - startTime; |
||||
long lapTime; |
||||
if (laps == null) { |
||||
lapTime = lapSpanTime; |
||||
laps = new ArrayList<long[]>(); |
||||
} else { |
||||
long[] previous = laps.get(laps.size() - 1); |
||||
lapTime = lap - previous[2]; |
||||
} |
||||
laps.add(new long[] {lapTime, lapSpanTime, lap}); |
||||
return lapTime; |
||||
} |
||||
|
||||
/** |
||||
* Returns the total number of laps up to this moment. |
||||
*/ |
||||
public int totalLaps() { |
||||
if (laps == null) { |
||||
return 0; |
||||
} |
||||
return laps.size(); |
||||
} |
||||
|
||||
/** |
||||
* Returns lap times for 1-based lap index. |
||||
* Returns <code>null</code> if laps are not used or if index is invalid. |
||||
*/ |
||||
public long[] getLapTimes(int index) { |
||||
if (laps == null) { |
||||
return null; |
||||
} |
||||
if ((index <= 0) || (index > laps.size())) { |
||||
return null; |
||||
} |
||||
return laps.get(index - 1); |
||||
} |
||||
|
||||
// ---------------------------------------------------------------- output
|
||||
|
||||
/** |
||||
* Returns total elapsed time as formatted string from the last start. |
||||
*/ |
||||
@Override |
||||
public String toString() { |
||||
long elapsed = elapsed(); |
||||
StringBuilder sb = new StringBuilder(); |
||||
sb.append("JStopWatch ").append(name).append(running ? " is running." : "").append('\n'); |
||||
if (running) { |
||||
sb.append("elapsed: ").append(formatTimeSpan(elapsed)); |
||||
} else { |
||||
if (spanTime != totalTime) { |
||||
sb.append("span: ").append(formatTimeSpan(spanTime)).append('\n'); |
||||
} |
||||
sb.append("\ntotal: ").append(formatTimeSpan(totalTime)); |
||||
} |
||||
if (laps != null) { |
||||
if (!laps.isEmpty()) { |
||||
sb.append('\n'); |
||||
sb.append("\n\t\t\tlap\t\telapsed\n"); |
||||
} |
||||
for (int i = 0; i < laps.size(); i++) { |
||||
long[] longs = laps.get(i); |
||||
sb.append(" lap #").append(i + 1).append(':').append('\t'); |
||||
sb.append(formatTimeSpan(longs[0])).append('\t'); |
||||
sb.append(formatTimeSpan(longs[1])).append('\n'); |
||||
} |
||||
} |
||||
return sb.toString(); |
||||
} |
||||
|
||||
/** |
||||
* Formats time spans. |
||||
*/ |
||||
public static String formatTimeSpan(long millis) { |
||||
long seconds = 0; |
||||
long minutes = 0; |
||||
long hours = 0; |
||||
|
||||
if (millis > 1000) { |
||||
seconds = millis / 1000; |
||||
millis %= 1000; |
||||
} |
||||
if (seconds > 60) { |
||||
minutes = seconds / 60; |
||||
seconds %= 60; |
||||
} |
||||
if (minutes > 60) { |
||||
hours = minutes / 60; |
||||
minutes %= 60; |
||||
} |
||||
|
||||
StringBuilder result = new StringBuilder(20); |
||||
boolean out = false; |
||||
if (hours > 0) { |
||||
result.append(hours).append(':'); |
||||
out = true; |
||||
} |
||||
if (out || (minutes > 0)) { |
||||
if (minutes < 10) { |
||||
result.append('0'); |
||||
} |
||||
result.append(minutes).append(':'); |
||||
} |
||||
|
||||
if (seconds < 10) { |
||||
result.append('0'); |
||||
} |
||||
result.append(seconds).append('.'); |
||||
|
||||
if (millis < 10) { |
||||
result.append('0'); |
||||
} |
||||
if (millis < 100) { |
||||
result.append('0'); |
||||
} |
||||
result.append(millis); |
||||
return result.toString(); |
||||
} |
||||
} |
@ -1,337 +0,0 @@
|
||||
// Copyright (c) 2003-present, Jodd Team (http://jodd.org)
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
package com.fr.third.jodd.datetime; |
||||
|
||||
import com.fr.third.jodd.util.HashCode; |
||||
import static com.fr.third.jodd.util.HashCode.hash; |
||||
|
||||
import java.math.BigDecimal; |
||||
import java.io.Serializable; |
||||
|
||||
/** |
||||
* Julian Date stamp, for high precision calculations. Julian date is a real |
||||
* number and it basically consist of two parts: integer and fraction. Integer |
||||
* part carries date information, fraction carries time information. |
||||
* |
||||
* <p> |
||||
* The Julian day or Julian day number (JDN) is the (integer) number of days that |
||||
* have elapsed since Monday, January 1, 4713 BC in the proleptic Julian calendar 1. |
||||
* That day is counted as Julian day zero. Thus the multiples of 7 are Mondays. |
||||
* Negative values can also be used. |
||||
* |
||||
* <p> |
||||
* The Julian Date (JD) is the number of days (with decimal fraction of the day) that |
||||
* have elapsed since 12 noon Greenwich Mean Time (UT or TT) of that day. |
||||
* Rounding to the nearest integer gives the Julian day number. |
||||
* <p> |
||||
* For calculations that will have time precision of 1e-3 seconds, both |
||||
* fraction and integer part must have enough digits in it. The problem is |
||||
* that integer part is big and, on the other hand fractional is small, and |
||||
* since final julian date is a sum of this two values, some fraction |
||||
* numerals may be lost. Therefore, for higher precision both |
||||
* fractional and integer part of julian date real number has to be |
||||
* preserved. |
||||
* <p> |
||||
* This class stores the unmodified fraction part, but not all digits |
||||
* are significant! For 1e-3 seconds precision, only 8 digits after |
||||
* the decimal point are significant. |
||||
* |
||||
* @see TimeUtil |
||||
* @see JDateTime |
||||
* @see DateTimeStamp |
||||
* @deprecated jodd目前版本为5.1.6, 此版本已移除此类, 兼容问题暂不删除此类 |
||||
*/ |
||||
@Deprecated |
||||
public class JulianDateStamp implements Serializable, Cloneable { |
||||
|
||||
/** |
||||
* Integer part of the Julian Date (JD). |
||||
*/ |
||||
protected int integer; |
||||
|
||||
/** |
||||
* Returns integer part of the Julian Date (JD). |
||||
*/ |
||||
public int getInteger() { |
||||
return integer; |
||||
} |
||||
|
||||
/** |
||||
* Fraction part of the Julian Date (JD). |
||||
* Should be always in [0.0, 1.0) range. |
||||
*/ |
||||
protected double fraction; |
||||
|
||||
/** |
||||
* Returns the fraction part of Julian Date (JD). |
||||
* Returned value is always in [0.0, 1.0) range. |
||||
*/ |
||||
public double getFraction() { |
||||
return fraction; |
||||
} |
||||
|
||||
/** |
||||
* Calculates and returns significant fraction only as an int. |
||||
*/ |
||||
public int getSignificantFraction() { |
||||
return (int) (fraction * 100000000); |
||||
} |
||||
|
||||
/** |
||||
* Returns JDN. Note that JDN is not equal to {@link #integer}. It is calculated by |
||||
* rounding to the nearest integer. |
||||
*/ |
||||
public int getJulianDayNumber() { |
||||
if (fraction >= 0.5) { |
||||
return integer + 1; |
||||
} |
||||
return integer; |
||||
} |
||||
|
||||
// ---------------------------------------------------------------- ctors
|
||||
|
||||
/** |
||||
* Default empty constructor. |
||||
*/ |
||||
public JulianDateStamp() { |
||||
} |
||||
|
||||
/** |
||||
* Creates JD from a <code>double</code>. |
||||
*/ |
||||
public JulianDateStamp(double jd) { |
||||
set(jd); |
||||
} |
||||
|
||||
/** |
||||
* Creates JD from both integer and fractional part using normalization. |
||||
* Normalization occurs when fractional part is out of range. |
||||
* |
||||
* @see #set(int, double) |
||||
* |
||||
* @param i integer part |
||||
* @param f fractional part should be in range [0.0, 1.0) |
||||
*/ |
||||
public JulianDateStamp(int i, double f) { |
||||
set(i, f); |
||||
} |
||||
|
||||
/** |
||||
* Creates JD from <code>BigDecimal</code>. |
||||
*/ |
||||
public JulianDateStamp(BigDecimal bd) { |
||||
double d = bd.doubleValue(); |
||||
integer = (int) d; |
||||
bd = bd.subtract(new BigDecimal(integer)); |
||||
fraction = bd.doubleValue(); |
||||
} |
||||
|
||||
|
||||
// ---------------------------------------------------------------- conversion
|
||||
|
||||
|
||||
/** |
||||
* Returns <code>double</code> value of JD. |
||||
* <b>CAUTION</b>: double values may not be suit for precision math due to |
||||
* loss of precision. |
||||
*/ |
||||
public double doubleValue() { |
||||
return (double)integer + fraction; |
||||
} |
||||
|
||||
/** |
||||
* Returns <code>BigDecimal</code> value of JD. |
||||
*/ |
||||
@SuppressWarnings({"UnpredictableBigDecimalConstructorCall"}) |
||||
public BigDecimal toBigDecimal() { |
||||
BigDecimal bd = new BigDecimal(integer); |
||||
return bd.add(new BigDecimal(fraction)); |
||||
} |
||||
|
||||
/** |
||||
* Returns string representation of JD. |
||||
* |
||||
* @return julian integer as string |
||||
*/ |
||||
@Override |
||||
public String toString() { |
||||
String s = Double.toString(fraction); |
||||
int i = s.indexOf('.'); |
||||
s = s.substring(i); |
||||
return integer + s; |
||||
} |
||||
|
||||
|
||||
// ---------------------------------------------------------------- math
|
||||
|
||||
/** |
||||
* Adds a JD to current instance. |
||||
*/ |
||||
public JulianDateStamp add(JulianDateStamp jds) { |
||||
int i = this.integer + jds.integer; |
||||
double f = this.fraction + jds.fraction; |
||||
set(i, f); |
||||
return this; |
||||
} |
||||
|
||||
/** |
||||
* Adds a double to current instance. |
||||
*/ |
||||
public JulianDateStamp add(double delta) { |
||||
set(this.integer, this.fraction + delta); |
||||
return this; |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Subtracts a JD from current instance. |
||||
*/ |
||||
public JulianDateStamp sub(JulianDateStamp jds) { |
||||
int i = this.integer - jds.integer; |
||||
double f = this.fraction -jds.fraction; |
||||
set(i, f); |
||||
return this; |
||||
} |
||||
|
||||
/** |
||||
* Subtracts a double from current instance. |
||||
*/ |
||||
public JulianDateStamp sub(double delta) { |
||||
set(this.integer, this.fraction - delta); |
||||
return this; |
||||
} |
||||
|
||||
/** |
||||
* Sets integer and fractional part with normalization. |
||||
* Normalization means that if double is out of range, |
||||
* values will be correctly fixed. |
||||
*/ |
||||
public void set(int i, double f) { |
||||
integer = i; |
||||
int fi = (int) f; |
||||
f -= fi; |
||||
integer += fi; |
||||
if (f < 0) { |
||||
f += 1; |
||||
integer--; |
||||
} |
||||
this.fraction = f; |
||||
} |
||||
|
||||
public void set(double jd) { |
||||
integer = (int)jd; |
||||
fraction = jd - (double)integer; |
||||
} |
||||
|
||||
|
||||
// ---------------------------------------------------------------- between
|
||||
|
||||
/** |
||||
* Calculates the number of days between two dates. Returned value is always positive. |
||||
*/ |
||||
public int daysBetween(JulianDateStamp otherDate) { |
||||
int difference = daysSpan(otherDate); |
||||
return difference >= 0 ? difference : -difference; |
||||
} |
||||
|
||||
/** |
||||
* Returns span between two days. Returned value may be positive (when this date |
||||
* is after the provided one) or negative (when comparing to future date). |
||||
*/ |
||||
public int daysSpan(JulianDateStamp otherDate) { |
||||
int now = getJulianDayNumber(); |
||||
int then = otherDate.getJulianDayNumber(); |
||||
return now - then; |
||||
} |
||||
|
||||
// ---------------------------------------------------------------- equals & hashCode
|
||||
|
||||
@Override |
||||
public boolean equals(Object object) { |
||||
if (this == object) { |
||||
return true; |
||||
} |
||||
if (this.getClass() != object.getClass()) { |
||||
return false; |
||||
} |
||||
JulianDateStamp stamp = (JulianDateStamp) object; |
||||
return (stamp.integer == this.integer) && |
||||
(Double.compare(stamp.fraction, this.fraction) == 0); |
||||
} |
||||
|
||||
@Override |
||||
public int hashCode() { |
||||
int result = HashCode.SEED; |
||||
result = hash(result, integer); |
||||
result = hash(result, fraction); |
||||
return result; |
||||
} |
||||
|
||||
// ---------------------------------------------------------------- clone
|
||||
|
||||
@Override |
||||
protected JulianDateStamp clone() { |
||||
return new JulianDateStamp(this.integer, this.fraction); |
||||
} |
||||
|
||||
// ---------------------------------------------------------------- conversion
|
||||
|
||||
/** |
||||
* Returns Reduced Julian Date (RJD), used by astronomers. |
||||
* RJD = JD − 2400000 |
||||
*/ |
||||
public JulianDateStamp getReducedJulianDate() { |
||||
return new JulianDateStamp(integer - 2400000, fraction); |
||||
} |
||||
|
||||
public void setReducedJulianDate(double rjd) { |
||||
set(rjd + 2400000); |
||||
} |
||||
|
||||
/** |
||||
* Returns Modified Julian Date (MJD), where date starts from midnight rather than noon. |
||||
* RJD = JD − 2400000.5 |
||||
*/ |
||||
public JulianDateStamp getModifiedJulianDate() { |
||||
return new JulianDateStamp(integer - 2400000, fraction - 0.5); |
||||
} |
||||
|
||||
public void setModifiedJulianDate(double mjd) { |
||||
set(mjd + 2400000.5); |
||||
} |
||||
|
||||
/** |
||||
* Returns Truncated Julian Day (TJD), introduced by NASA for the space program. |
||||
* TJD began at midnight at the beginning of May 24, 1968 (Friday). |
||||
*/ |
||||
public JulianDateStamp getTruncatedJulianDate() { |
||||
return new JulianDateStamp(integer - 2440000, fraction - 0.5); |
||||
} |
||||
|
||||
public void setTruncatedJulianDate(double tjd) { |
||||
set(tjd + 2440000.5); |
||||
} |
||||
} |
@ -1,118 +0,0 @@
|
||||
// Copyright (c) 2003-present, Jodd Team (http://jodd.org)
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
package com.fr.third.jodd.datetime; |
||||
|
||||
/** |
||||
* Holds a time period. With julian dates and {@link JDateTime} it is quite |
||||
* easy to calculate period in days - just by subtracting two julian day numbers. |
||||
* However, calculating hours, minutes and seconds would require more calculation |
||||
* and this class provides simple and faster period calculation. |
||||
* |
||||
* @deprecated jodd目前版本为5.1.6, 此版本已移除此类, 兼容问题暂不删除此类 |
||||
*/ |
||||
@Deprecated |
||||
public class Period { |
||||
|
||||
protected final long days; |
||||
protected final int hours; |
||||
protected final int minutes; |
||||
protected final int seconds; |
||||
protected final int milliseconds; |
||||
|
||||
public Period(JDateTime jdt1, JDateTime jdt2) { |
||||
if (jdt2.isBefore(jdt1)) { |
||||
JDateTime temp = jdt1; |
||||
jdt1 = jdt2; |
||||
jdt2 = temp; |
||||
} |
||||
long julian2 = jdt2.getJulianDayNumber(); |
||||
long julian1 = jdt1.getJulianDayNumber(); |
||||
|
||||
long days = julian2 - julian1; |
||||
int milliseconds = jdt2.getMillisecond() - jdt1.getMillisecond(); |
||||
int seconds = jdt2.getSecond() - jdt1.getSecond(); |
||||
int minutes = jdt2.getMinute() - jdt1.getMinute(); |
||||
int hours = jdt2.getHour() - jdt1.getHour(); |
||||
|
||||
if (milliseconds < 0) { |
||||
seconds--; |
||||
milliseconds += 1000; |
||||
} |
||||
if (seconds < 0) { |
||||
minutes--; |
||||
seconds += 60; |
||||
} |
||||
if (minutes < 0) { |
||||
hours--; |
||||
minutes += 60; |
||||
} |
||||
if (hours < 0) { |
||||
days--; |
||||
hours += 24; |
||||
} |
||||
|
||||
this.days = days; |
||||
this.hours = hours; |
||||
this.minutes = minutes; |
||||
this.seconds = seconds; |
||||
this.milliseconds = milliseconds; |
||||
} |
||||
|
||||
/** |
||||
* Returns number of days in period. |
||||
*/ |
||||
public long getDays() { |
||||
return days; |
||||
} |
||||
|
||||
/** |
||||
* Returns hours in period. |
||||
*/ |
||||
public int getHours() { |
||||
return hours; |
||||
} |
||||
|
||||
/** |
||||
* Returns minutes in period. |
||||
*/ |
||||
public int getMinutes() { |
||||
return minutes; |
||||
} |
||||
|
||||
/** |
||||
* Returns seconds in period. |
||||
*/ |
||||
public int getSeconds() { |
||||
return seconds; |
||||
} |
||||
|
||||
/** |
||||
* Returns milliseconds in period. |
||||
*/ |
||||
public int getMilliseconds() { |
||||
return milliseconds; |
||||
} |
||||
} |
@ -1,398 +0,0 @@
|
||||
// Copyright (c) 2003-present, Jodd Team (http://jodd.org)
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
package com.fr.third.jodd.datetime; |
||||
|
||||
import java.text.ParseException; |
||||
import java.text.SimpleDateFormat; |
||||
import java.util.Date; |
||||
import java.util.Locale; |
||||
|
||||
/** |
||||
* Date time calculations and utilities. <code>TimeUtil</code> is used by |
||||
* {@link JDateTime} and it contains few utilities that may be used |
||||
* elsewhere, although {@link JDateTime} is recommended for all time |
||||
* manipulation. |
||||
* |
||||
* @deprecated jodd目前版本为5.1.6, 此版本已移除此类, 兼容问题暂不删除此类 |
||||
*/ |
||||
@Deprecated |
||||
public class TimeUtil { |
||||
|
||||
public static final int SECONDS_IN_DAY = 60 * 60 * 24; |
||||
|
||||
public static final long MILLIS_IN_DAY = 1000L * SECONDS_IN_DAY; |
||||
|
||||
// ---------------------------------------------------------------- misc calc
|
||||
|
||||
/** |
||||
* Calculates day of year from given time stamp. |
||||
* It may not work for some dates in 1582. |
||||
* |
||||
* @return day of year in range: [1-366] |
||||
*/ |
||||
public static int dayOfYear(int year, int month, int day) { |
||||
int day_of_year; |
||||
if (isLeapYear(year)) { |
||||
day_of_year = ((275 * month) / 9) - ((month + 9) / 12) + day - 30; |
||||
} else { |
||||
day_of_year = ((275 * month) / 9) - (((month + 9) / 12) << 1) + day - 30; |
||||
} |
||||
return day_of_year; |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Check if the given year is leap year. |
||||
* |
||||
* @return <code>true</code> if the year is a leap year |
||||
*/ |
||||
public static boolean isLeapYear(int y) { |
||||
boolean result = false; |
||||
|
||||
if (((y % 4) == 0) && // must be divisible by 4...
|
||||
((y < 1582) || // and either before reform year...
|
||||
((y % 100) != 0) || // or not a century...
|
||||
((y % 400) == 0))) { // or a multiple of 400...
|
||||
result = true; // for leap year.
|
||||
} |
||||
return result; |
||||
} |
||||
|
||||
static final int[] MONTH_LENGTH = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; |
||||
|
||||
/** |
||||
* Returns the length of the specified month in days. Month is 1 for January |
||||
* and 12 for December. |
||||
* |
||||
* @return length of the specified month in days |
||||
*/ |
||||
public static int getMonthLength(int year, int month) { |
||||
return getMonthLength(year, month, isLeapYear(year)); |
||||
} |
||||
|
||||
static int getMonthLength(int year, int month, boolean leap) { |
||||
if ((month < 1) || (month > 12)) { |
||||
throw new IllegalArgumentException("Invalid month: " + month); |
||||
} |
||||
if (month == 2) { |
||||
return leap ? 29 : 28; |
||||
} |
||||
if ((year == 1582) && (month == 10)) { |
||||
return 21; |
||||
} |
||||
return MONTH_LENGTH[month]; |
||||
} |
||||
|
||||
|
||||
// ---------------------------------------------------------------- valid
|
||||
|
||||
/** |
||||
* Checks if date is valid. |
||||
* |
||||
* @return <code>true</code> if date is valid, otherwise <code>false</code> |
||||
*/ |
||||
public static boolean isValidDate(int year, int month, int day) { |
||||
if ((month < 1) || (month > 12)) { |
||||
return false; |
||||
} |
||||
int ml = getMonthLength(year, month); |
||||
//noinspection RedundantIfStatement
|
||||
if ((day < 1) || (day > ml)) { |
||||
return false; |
||||
} |
||||
return true; |
||||
} |
||||
|
||||
/** |
||||
* Checks if time is valid. |
||||
* |
||||
* @param hour hour to check |
||||
* @param minute minute to check |
||||
* @param second second to check |
||||
* |
||||
* @return <code>true</code> if time is valid, otherwise <code>false</code> |
||||
*/ |
||||
public static boolean isValidTime(int hour, int minute, int second, int millisecond) { |
||||
if ((hour < 0) || (hour >= 24)) { |
||||
return false; |
||||
} |
||||
if ((minute < 0) || (minute >= 60)) { |
||||
return false; |
||||
} |
||||
if ((second < 0) || (second >= 60)) { |
||||
return false; |
||||
} |
||||
//noinspection RedundantIfStatement
|
||||
if ((millisecond < 0) || (millisecond >= 1000)) { |
||||
return false; |
||||
} |
||||
return true; |
||||
} |
||||
|
||||
/** |
||||
* Checks if date and time are valid. |
||||
* |
||||
* @param year year to check |
||||
* @param month month to check |
||||
* @param day day to check |
||||
* @param hour hour to check |
||||
* @param minute minute to check |
||||
* @param second second to check |
||||
* |
||||
* @return <code>true</code> if date and time are valid, otherwise <code>false</code> |
||||
*/ |
||||
public static boolean isValidDateTime(int year, int month, int day, int hour, int minute, int second, int millisecond) { |
||||
return (isValidDate(year, month, day) && isValidTime(hour, minute, second, millisecond)); |
||||
} |
||||
|
||||
/** |
||||
* Checks if date and time are valid. |
||||
* |
||||
* @param dts date/time stamp |
||||
* |
||||
* @return <code>true</code> if date and time are valid, otherwise <code>false</code> |
||||
*/ |
||||
public static boolean isValidDateTime(DateTimeStamp dts) { |
||||
return (isValidDate(dts.year, dts.month, dts.day) && isValidTime(dts.hour, dts.minute, dts.second, dts.millisecond)); |
||||
} |
||||
|
||||
|
||||
// ---------------------------------------------------------------- julian date
|
||||
|
||||
/** |
||||
* Calculates Astronomical Julian Date from given time stamp. |
||||
* |
||||
* @return Julian Date stamp |
||||
*/ |
||||
public static JulianDateStamp toJulianDate(DateTimeStamp time) { |
||||
return toJulianDate(time.year, time.month, time.day, time.hour, time.minute, time.second, time.millisecond); |
||||
} |
||||
|
||||
/** |
||||
* Calculates Astronomical Julian Date from given time.<p> |
||||
* |
||||
* Astronomical Julian Dates are counting from noon of the January 1st, -4712 |
||||
* (julian date 0 is -4712/01/01 12:00:00). Zero year exist. Julian Date |
||||
* is always GMT, there are no timezones. |
||||
* <p> |
||||
* |
||||
* Algorithm based on Numerical Recipesin C, 2nd ed., Cambridge University |
||||
* Press 1992, modified and enhanced by Igor Spasic. |
||||
* |
||||
* @param year year |
||||
* @param month month |
||||
* @param day day |
||||
* @param hour hour |
||||
* @param minute minute |
||||
* @param second second |
||||
* |
||||
* @return julian time stamp |
||||
*/ |
||||
public static JulianDateStamp toJulianDate(int year, int month, int day, int hour, int minute, int second, int millisecond) { |
||||
|
||||
// month range fix
|
||||
if ((month > 12) || (month < -12)) { |
||||
month--; |
||||
int delta = month / 12; |
||||
year += delta; |
||||
month -= delta * 12; |
||||
month++; |
||||
} |
||||
if (month < 0) { |
||||
year--; |
||||
month += 12; |
||||
} |
||||
|
||||
// decimal day fraction
|
||||
double frac = (hour / 24.0) + (minute / 1440.0) + (second / 86400.0) + (millisecond / 86400000.0); |
||||
if (frac < 0) { // negative time fix
|
||||
int delta = ((int)(-frac)) + 1; |
||||
frac += delta; |
||||
day -= delta; |
||||
} |
||||
//double gyr = year + (0.01 * month) + (0.0001 * day) + (0.0001 * frac) + 1.0e-9;
|
||||
double gyr = year + (0.01 * month) + (0.0001 * (day + frac)) + 1.0e-9; |
||||
|
||||
// conversion factors
|
||||
int iy0; |
||||
int im0; |
||||
if (month <= 2) { |
||||
iy0 = year - 1; |
||||
im0 = month + 12; |
||||
} else { |
||||
iy0 = year; |
||||
im0 = month; |
||||
} |
||||
int ia = iy0 / 100; |
||||
int ib = 2 - ia + (ia >> 2); |
||||
|
||||
// calculate julian date
|
||||
int jd; |
||||
if (year <= 0) { |
||||
jd = (int)((365.25 * iy0) - 0.75) + (int)(30.6001 * (im0 + 1)) + day + 1720994; |
||||
} else { |
||||
jd = (int)(365.25 * iy0) + (int)(30.6001 * (im0 + 1)) + day + 1720994; |
||||
} |
||||
if (gyr >= 1582.1015) { // on or after 15 October 1582
|
||||
jd += ib; |
||||
} |
||||
//return jd + frac + 0.5;
|
||||
|
||||
return new JulianDateStamp(jd, frac + 0.5); |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Calculates time stamp from Astronomical Julian Date. |
||||
* |
||||
* @param JD julian date |
||||
* |
||||
* @return time stamp |
||||
*/ |
||||
public static DateTimeStamp fromJulianDate(double JD) { |
||||
return fromJulianDate(new JulianDateStamp(JD)); |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Calculates time stamp from Astronomical Julian Date. |
||||
* Algorithm based on Numerical Recipesin C, 2nd ed., Cambridge University |
||||
* Press 1992. |
||||
* |
||||
* @param jds julian date stamp |
||||
* |
||||
* @return time stamp |
||||
*/ |
||||
public static DateTimeStamp fromJulianDate(JulianDateStamp jds) { |
||||
DateTimeStamp time = new DateTimeStamp(); |
||||
int year, month, day; |
||||
double frac; |
||||
int jd, ka, kb, kc, kd, ke, ialp; |
||||
|
||||
//double JD = jds.doubleValue();//jdate;
|
||||
//jd = (int)(JD + 0.5); // integer julian date
|
||||
//frac = JD + 0.5 - (double)jd + 1.0e-10; // day fraction
|
||||
|
||||
ka = (int)(jds.fraction + 0.5); |
||||
jd = jds.integer + ka; |
||||
frac = jds.fraction + 0.5 - ka + 1.0e-10; |
||||
|
||||
ka = jd; |
||||
if (jd >= 2299161) { |
||||
ialp = (int)(((double)jd - 1867216.25) / (36524.25)); |
||||
ka = jd + 1 + ialp - (ialp >> 2); |
||||
} |
||||
kb = ka + 1524; |
||||
kc = (int)(((double)kb - 122.1) / 365.25); |
||||
kd = (int)((double)kc * 365.25); |
||||
ke = (int)((double)(kb - kd) / 30.6001); |
||||
day = kb - kd - ((int)((double)ke * 30.6001)); |
||||
if (ke > 13) { |
||||
month = ke - 13; |
||||
} else { |
||||
month = ke - 1; |
||||
} |
||||
if ((month == 2) && (day > 28)){ |
||||
day = 29; |
||||
} |
||||
if ((month == 2) && (day == 29) && (ke == 3)) { |
||||
year = kc - 4716; |
||||
} else if (month > 2) { |
||||
year = kc - 4716; |
||||
} else { |
||||
year = kc - 4715; |
||||
} |
||||
time.year = year; |
||||
time.month = month; |
||||
time.day = day; |
||||
|
||||
// hour with minute and second included as fraction
|
||||
double d_hour = frac * 24.0; |
||||
time.hour = (int) d_hour; // integer hour
|
||||
|
||||
// minute with second included as a fraction
|
||||
double d_minute = (d_hour - (double)time.hour) * 60.0; |
||||
time.minute = (int) d_minute; // integer minute
|
||||
|
||||
double d_second = (d_minute - (double)time.minute) * 60.0; |
||||
time.second = (int) d_second; // integer seconds
|
||||
|
||||
double d_millis = (d_second - (double)time.second) * 1000.0; |
||||
|
||||
// fix calculation errors
|
||||
time.millisecond = (int) (((d_millis * 10) + 0.5) / 10); |
||||
|
||||
return time; |
||||
} |
||||
|
||||
// ---------------------------------------------------------------- gc
|
||||
|
||||
/** |
||||
* Returns Calendar month from provided JDateTime month. |
||||
*/ |
||||
public static int toCalendarMonth(int month) { |
||||
return month - 1; |
||||
} |
||||
|
||||
/** |
||||
* Returns Calendar day-of-week from provided JDateTime. |
||||
*/ |
||||
public static int toCalendarDayOfWeek(int dayOfWeek) { |
||||
return (dayOfWeek % 7) + 1; |
||||
} |
||||
|
||||
|
||||
// ---------------------------------------------------------------- format
|
||||
|
||||
public static final SimpleDateFormat HTTP_DATE_FORMAT = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss z", Locale.US); |
||||
|
||||
/** |
||||
* Formats time to HTTP date/time format. Note that number of milliseconds |
||||
* is lost. |
||||
*/ |
||||
public static String formatHttpDate(long millis) { |
||||
Date date = new Date(millis); |
||||
return HTTP_DATE_FORMAT.format(date); |
||||
} |
||||
|
||||
/** |
||||
* Parses the HTTP date/time format. Returns <code>-1</code> if given string |
||||
* is invalid. |
||||
*/ |
||||
public static long parseHttpTime(String time) { |
||||
if (time == null) { |
||||
return -1; |
||||
} |
||||
|
||||
try { |
||||
return TimeUtil.HTTP_DATE_FORMAT.parse(time).getTime(); |
||||
} |
||||
catch (ParseException e) { |
||||
return -1; |
||||
} |
||||
} |
||||
|
||||
} |
@ -1,75 +0,0 @@
|
||||
// Copyright (c) 2003-present, Jodd Team (http://jodd.org)
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
package com.fr.third.jodd.datetime; |
||||
|
||||
import java.util.TimeZone; |
||||
|
||||
/** |
||||
* Misc timezone utilities. |
||||
* |
||||
* @deprecated jodd目前版本为5.1.6, 此版本已移除此类, 兼容问题暂不删除此类 |
||||
*/ |
||||
@Deprecated |
||||
public class TimeZoneUtil { |
||||
|
||||
/** |
||||
* Returns raw offset difference in milliseconds. |
||||
*/ |
||||
public static int getRawOffsetDifference(TimeZone from, TimeZone to) { |
||||
int offsetBefore = from.getRawOffset(); |
||||
int offsetAfter = to.getRawOffset(); |
||||
return offsetAfter - offsetBefore; |
||||
} |
||||
|
||||
/** |
||||
* Returns offset difference in milliseconds for given time. |
||||
*/ |
||||
public static int getOffsetDifference(long now, TimeZone from, TimeZone to) { |
||||
int offsetBefore = from.getOffset(now); |
||||
int offsetAfter = to.getOffset(now); |
||||
return offsetAfter - offsetBefore; |
||||
} |
||||
|
||||
/** |
||||
* Get offset difference in milliseconds for given jdatetime. |
||||
*/ |
||||
public static int getOffset(JDateTime jdt, TimeZone tz) { |
||||
return tz.getOffset( |
||||
jdt.getEra(), |
||||
jdt.getYear(), |
||||
jdt.getMonth() - 1, |
||||
jdt.getDay(), |
||||
TimeUtil.toCalendarDayOfWeek(jdt.getDayOfWeek()), |
||||
jdt.getMillisOfDay() |
||||
); |
||||
} |
||||
|
||||
public static int getOffsetDifference(JDateTime jdt, TimeZone from, TimeZone to) { |
||||
int offsetBefore = getOffset(jdt, from); |
||||
int offsetAfter = getOffset(jdt, to); |
||||
return offsetAfter - offsetBefore; |
||||
} |
||||
} |
@ -1,330 +0,0 @@
|
||||
// Copyright (c) 2003-present, Jodd Team (http://jodd.org)
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
package com.fr.third.jodd.datetime.format; |
||||
|
||||
import com.fr.third.jodd.datetime.DateTimeStamp; |
||||
import com.fr.third.jodd.datetime.JDateTime; |
||||
import com.fr.third.jodd.util.CharUtil; |
||||
|
||||
/** |
||||
* Abstract formatter for easier {@link JdtFormatter} implementations. |
||||
* <p> |
||||
* For setting date and time, default formatter parses input String against |
||||
* specified format. It extracts parts of input string upon patterns |
||||
* and then each part is converted to a number for a date/time information. |
||||
* It doesn't ignore any non-number character. If conversion fails, |
||||
* <code>null</code> is returned. |
||||
* |
||||
* <p> |
||||
* Getting date time is also user friendly. Specified format may not only |
||||
* contains patterns but also any text. To remove errors in decoding when |
||||
* text may be recognize as one of patterns, format text may be quoted |
||||
* with the special escape sign. Double quote in the text will be decoded |
||||
* as a single quote, of course. |
||||
* <p> |
||||
* |
||||
* It is not necessary to have parsers for all patterns. |
||||
* |
||||
* @deprecated jodd目前版本为5.1.6, 此版本已移除此类, 兼容问题暂不删除此类 |
||||
*/ |
||||
@Deprecated |
||||
public abstract class AbstractFormatter implements JdtFormatter { |
||||
|
||||
/** |
||||
* Available patterns list. Used by {@link #findPattern(char[], int)} |
||||
* when parsing date time format. Each formatter will have its own set of |
||||
* patterns, in strictly defined order. |
||||
*/ |
||||
protected char[][] patterns; |
||||
|
||||
/** |
||||
* Escape character. |
||||
*/ |
||||
protected char escapeChar = '\''; |
||||
|
||||
|
||||
/** |
||||
* Converts String array of patterns to char arrays. |
||||
*/ |
||||
protected void preparePatterns(String[] spat) { |
||||
patterns = new char[spat.length][]; |
||||
for (int i = 0; i < spat.length; i++) { |
||||
patterns[i] = spat[i].toCharArray(); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Finds the longest pattern in provided format starting from specified position. |
||||
* All available patterns are stored in {@link #patterns}. |
||||
* |
||||
* @param format date time format to examine |
||||
* @param i starting index |
||||
* |
||||
* @return 0-based index of founded pattern, or <code>-1</code> if pattern not found |
||||
*/ |
||||
protected int findPattern(char[] format, int i) { |
||||
int frmtc_len = format.length; |
||||
boolean match; |
||||
int n, lastn = -1; |
||||
int maxLen = 0; |
||||
for (n = 0; n < patterns.length; n++) { |
||||
char[] curr = patterns[n]; // current pattern from the pattern list
|
||||
if (i > frmtc_len - curr.length) { |
||||
continue; |
||||
} |
||||
match = true; |
||||
int delta = 0; |
||||
while (delta < curr.length) { // match given pattern
|
||||
if (curr[delta] != format[i + delta]) { |
||||
match = false; // no match, go to next
|
||||
break; |
||||
} |
||||
delta++; |
||||
} |
||||
if (match) { // match
|
||||
if (patterns[n].length > maxLen) { // find longest match
|
||||
lastn = n; |
||||
maxLen = patterns[n].length; |
||||
} |
||||
} |
||||
} |
||||
return lastn; |
||||
} |
||||
|
||||
// ---------------------------------------------------------------- convert
|
||||
|
||||
/** |
||||
* Creates a date-time string for founded pattern. Founded patterns |
||||
* is identified by its {@link #patterns} index. |
||||
* |
||||
* @param patternIndex index of founded pattern |
||||
* @param jdt date time information |
||||
*/ |
||||
protected abstract String convertPattern(int patternIndex, JDateTime jdt); |
||||
|
||||
/** |
||||
* {@inheritDoc} |
||||
* @see JdtFormatter#convert(JDateTime, String) |
||||
*/ |
||||
public String convert(JDateTime jdt, String format) { |
||||
char[] fmtc = format.toCharArray(); |
||||
int fmtc_len = fmtc.length; |
||||
StringBuilder result = new StringBuilder(fmtc_len); |
||||
|
||||
int i = 0; |
||||
while (i < fmtc_len) { |
||||
if (fmtc[i] == escapeChar) { // quote founded
|
||||
int end = i + 1; |
||||
while (end < fmtc_len) { |
||||
if (fmtc[end] == escapeChar) { // second quote founded
|
||||
if (end + 1 < fmtc_len) { |
||||
end++; |
||||
if (fmtc[end] == escapeChar) { // skip double quotes
|
||||
result.append(escapeChar); // and continue
|
||||
} else { |
||||
break; |
||||
} |
||||
} |
||||
} else { |
||||
result.append(fmtc[end]); |
||||
} |
||||
end++; |
||||
} |
||||
i = end; |
||||
continue; // end of quoted string, continue the main loop
|
||||
} |
||||
|
||||
int n = findPattern(fmtc, i); |
||||
if (n != -1) { // pattern founded
|
||||
result.append(convertPattern(n, jdt)); |
||||
i += patterns[n].length; |
||||
} else { |
||||
result.append(fmtc[i]); |
||||
i++; |
||||
} |
||||
} |
||||
return result.toString(); |
||||
} |
||||
|
||||
// ---------------------------------------------------------------- parse
|
||||
|
||||
/** |
||||
* Parses value for matched pattern. Founded patterns |
||||
* is identified by its {@link #patterns} index. |
||||
* Note that value may represent both integer and decimals. |
||||
* May throw {@link NumberFormatException}. |
||||
* |
||||
* @param patternIndex index of founded pattern |
||||
* @param value value to parse, no spaces or tabs |
||||
* @param destination destination to modify |
||||
*/ |
||||
protected abstract void parseValue(int patternIndex, String value, DateTimeStamp destination); |
||||
|
||||
/** |
||||
* {@inheritDoc} |
||||
* @see JdtFormatter#parse(String, String) |
||||
*/ |
||||
public DateTimeStamp parse(String value, String format) { |
||||
char[] valueChars = value.toCharArray(); |
||||
char[] formatChars = format.toCharArray(); |
||||
|
||||
int i = 0, j = 0; |
||||
int valueLen = valueChars.length; |
||||
int formatLen = formatChars.length; |
||||
|
||||
// detect if separators are used
|
||||
boolean useSeparators = true; |
||||
|
||||
if (valueLen == formatLen) { |
||||
useSeparators = false; |
||||
|
||||
for (char valueChar : valueChars) { |
||||
if (!CharUtil.isDigit(valueChar)) { |
||||
useSeparators = true; |
||||
break; |
||||
} |
||||
} |
||||
} |
||||
|
||||
DateTimeStamp time = new DateTimeStamp(); |
||||
StringBuilder sb = new StringBuilder(); |
||||
while (true) { |
||||
int n = findPattern(formatChars, i); |
||||
if (n != -1) { // pattern founded
|
||||
int patternLen = patterns[n].length; |
||||
i += patternLen; |
||||
sb.setLength(0); |
||||
if (!useSeparators) { |
||||
for (int k = 0; k < patternLen; k++) { |
||||
sb.append(valueChars[j++]); |
||||
} |
||||
} else { |
||||
char next = 0xFFFF; |
||||
if (i < formatLen) { |
||||
next = formatChars[i]; // next = delimiter
|
||||
} |
||||
while ((j < valueLen) && (valueChars[j] != next)) { |
||||
char scj = valueChars[j]; |
||||
if ((scj != ' ') && (scj != '\t')) { // ignore surrounding whitespaces
|
||||
sb.append(valueChars[j]); |
||||
} |
||||
j++; |
||||
} |
||||
} |
||||
|
||||
parseValue(n, sb.toString(), time); |
||||
} else { |
||||
if (!useSeparators) { |
||||
throw new IllegalArgumentException("Invalid value: " + value); |
||||
} |
||||
if (formatChars[i] == valueChars[j]) { |
||||
j++; |
||||
} |
||||
i++; |
||||
} |
||||
if ((i == formatLen) || (j == valueLen)) { |
||||
break; |
||||
} |
||||
} |
||||
return time; |
||||
} |
||||
|
||||
|
||||
// ---------------------------------------------------------------- util
|
||||
|
||||
/** |
||||
* Prints values 00 - 99. |
||||
*/ |
||||
protected String print2(int value) { |
||||
if (value < 0) { |
||||
throw new IllegalArgumentException("Value must be positive: " + value); |
||||
} |
||||
if (value < 10) { |
||||
return '0' + Integer.toString(value); |
||||
} |
||||
if (value < 100) { |
||||
return Integer.toString(value); |
||||
} |
||||
throw new IllegalArgumentException("Value too big: " + value); |
||||
} |
||||
|
||||
/** |
||||
* Prints values 00 - 999. |
||||
*/ |
||||
protected String print3(int value) { |
||||
if (value < 0) { |
||||
throw new IllegalArgumentException("Value must be positive: " + value); |
||||
} |
||||
if (value < 10) { |
||||
return "00" + Integer.toString(value); |
||||
} |
||||
if (value < 100) { |
||||
return '0' + Integer.toString(value); |
||||
} |
||||
if (value < 1000) { |
||||
return Integer.toString(value); |
||||
} |
||||
throw new IllegalArgumentException("Value too big: " + value); |
||||
} |
||||
|
||||
/** |
||||
* Prints 4 digits and optional minus sign. |
||||
*/ |
||||
protected String printPad4(int value) { |
||||
char[] result = new char[4]; |
||||
int count = 0; |
||||
|
||||
if (value < 0) { |
||||
result[count++] = '-'; |
||||
value = -value; |
||||
} |
||||
|
||||
String str = Integer.toString(value); |
||||
|
||||
if (value < 10) { |
||||
result[count++] = '0'; |
||||
result[count++] = '0'; |
||||
result[count++] = '0'; |
||||
result[count++] = str.charAt(0); |
||||
} else if (value < 100) { |
||||
result[count++] = '0'; |
||||
result[count++] = '0'; |
||||
result[count++] = str.charAt(0); |
||||
result[count++] = str.charAt(1); |
||||
} else if (value < 1000) { |
||||
result[count++] = '0'; |
||||
result[count++] = str.charAt(0); |
||||
result[count++] = str.charAt(1); |
||||
result[count++] = str.charAt(2); |
||||
} else { |
||||
if (count > 0) { |
||||
return '-' + str; |
||||
} |
||||
return str; |
||||
} |
||||
return new String(result, 0, count); |
||||
} |
||||
} |
@ -1,170 +0,0 @@
|
||||
// Copyright (c) 2003-present, Jodd Team (http://jodd.org)
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
package com.fr.third.jodd.datetime.format; |
||||
|
||||
import com.fr.third.jodd.datetime.DateTimeStamp; |
||||
import com.fr.third.jodd.datetime.JDateTime; |
||||
import com.fr.third.jodd.datetime.DateTimeStamp; |
||||
import com.fr.third.jodd.datetime.JDateTime; |
||||
import com.fr.third.jodd.util.LocaleUtil; |
||||
import com.fr.third.jodd.util.DateFormatSymbolsEx; |
||||
|
||||
import java.util.TimeZone; |
||||
|
||||
/** |
||||
* Default {@link JdtFormatter} uses <b>ISO 8601</b> specification, enhanced by some |
||||
* custom patterns. For more information see: |
||||
* <a href="http://en.wikipedia.org/wiki/ISO_8601">ISO 8601 on Wikipedia</a> |
||||
* |
||||
* <p> |
||||
* Patterns list: |
||||
* |
||||
* <ul> |
||||
* <li>YYYY + year</li> |
||||
* <li>MM + month</li> |
||||
* <li>DD + day of month</li> |
||||
* <li>D - day of week</li> |
||||
* <li>MML - month name (add-on)</li> |
||||
* <li>MMS - month abbreviation (add-on)</li> |
||||
* <li>DL - day of week name (add-on)</li> |
||||
* <li>DS - day of week abbreviation (add-on)</li> |
||||
* <li>hh + hour</li> |
||||
* <li>mm + minute</li> |
||||
* <li>ss + seconds (no milliseconds)</li> |
||||
* <li>mss + milliseconds (add-on)</li> |
||||
* <li>DDD - day of year</li> |
||||
* <li>WW - week of year</li> |
||||
* <li>WWW - week of year with 'W' prefix</li> |
||||
* <li>W - week of month (add-on)</li> |
||||
* <li>E - era</li> |
||||
* <li>TLZ - time zone long</li> |
||||
* <li>TLS - time zone short</li> |
||||
* </ul> |
||||
* |
||||
* <p> |
||||
* Patterns noted with + sign are used both for conversion and parsing. |
||||
* All patterns are used for conversion. |
||||
* |
||||
* @deprecated jodd目前版本为5.1.6, 此版本已移除此类, 兼容问题暂不删除此类 |
||||
*/ |
||||
@Deprecated |
||||
public class Iso8601JdtFormatter extends AbstractFormatter { |
||||
|
||||
public Iso8601JdtFormatter() { |
||||
preparePatterns( |
||||
new String[] { |
||||
"YYYY", // 0 + year
|
||||
"MM", // 1 + month
|
||||
"DD", // 2 + day of month
|
||||
"D", // 3 - day of week
|
||||
"MML", // 4 - month long name
|
||||
"MMS", // 5 - month short name
|
||||
"DL", // 6 - day of week long name
|
||||
"DS", // 7 - day of week short name
|
||||
"hh", // 8 + hour
|
||||
"mm", // 9 + minute
|
||||
"ss", // 10 + seconds
|
||||
"mss", // 11 + milliseconds
|
||||
"DDD", // 12 - day of year
|
||||
"WW", // 13 - week of year
|
||||
"WWW", // 14 - week of year with 'W' prefix
|
||||
"W", // 15 - week of month
|
||||
"E", // 16 - era
|
||||
"TZL", // 17 - timezone long name
|
||||
"TZS", // 18 - timezone short name
|
||||
} |
||||
); |
||||
} |
||||
|
||||
@Override |
||||
protected String convertPattern(int patternIndex, JDateTime jdt) { |
||||
DateFormatSymbolsEx dfs = LocaleUtil.getDateFormatSymbols(jdt.getLocale()); |
||||
switch (patternIndex) { |
||||
case 0: |
||||
return printPad4(jdt.getYear()); |
||||
case 1: |
||||
return print2(jdt.getMonth()); |
||||
case 2: |
||||
return print2(jdt.getDay()); |
||||
case 3: |
||||
return Integer.toString(jdt.getDayOfWeek()); |
||||
case 4: |
||||
return dfs.getMonth(jdt.getMonth() - 1); |
||||
case 5: |
||||
return dfs.getShortMonth(jdt.getMonth() - 1); |
||||
case 6: |
||||
return dfs.getWeekday((jdt.getDayOfWeek() % 7) + 1); |
||||
case 7: |
||||
return dfs.getShortWeekday((jdt.getDayOfWeek() % 7) + 1); |
||||
case 8: |
||||
return print2(jdt.getHour()); |
||||
case 9: |
||||
return print2(jdt.getMinute()); |
||||
case 10: |
||||
return print2(jdt.getSecond()); |
||||
case 11: |
||||
return print3(jdt.getMillisecond()); |
||||
case 12: |
||||
return print3(jdt.getDayOfYear()); |
||||
case 13: |
||||
return print2(jdt.getWeekOfYear()); |
||||
case 14: |
||||
return 'W' + print2(jdt.getWeekOfYear()); |
||||
case 15: |
||||
return Integer.toString(jdt.getWeekOfMonth()); |
||||
case 16: |
||||
return jdt.getEra() == 1 ? dfs.getAdEra() : dfs.getBcEra(); |
||||
case 17: |
||||
return jdt.getTimeZone().getDisplayName( |
||||
jdt.isInDaylightTime(), |
||||
TimeZone.LONG, |
||||
jdt.getLocale()); |
||||
case 18: |
||||
return jdt.getTimeZone().getDisplayName( |
||||
jdt.isInDaylightTime(), |
||||
TimeZone.SHORT, |
||||
jdt.getLocale()); |
||||
default: |
||||
return new String(patterns[patternIndex]); |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
protected void parseValue(int patternIndex, String value, DateTimeStamp destination) { |
||||
int v = Integer.parseInt(value); |
||||
switch (patternIndex) { |
||||
case 0: destination.year = v; break; |
||||
case 1: destination.month = v; break; |
||||
case 2: destination.day = v; break; |
||||
case 8: destination.hour = v; break; |
||||
case 9: destination.minute = v; break; |
||||
case 10: destination.second = v; break; |
||||
case 11: destination.millisecond = v; break; |
||||
default: |
||||
throw new IllegalArgumentException("Invalid template: " + new String(patterns[patternIndex])); |
||||
} |
||||
} |
||||
} |
@ -1,75 +0,0 @@
|
||||
// Copyright (c) 2003-present, Jodd Team (http://jodd.org)
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
package com.fr.third.jodd.datetime.format; |
||||
|
||||
import com.fr.third.jodd.datetime.DateTimeStamp; |
||||
import com.fr.third.jodd.datetime.JDateTime; |
||||
|
||||
/** |
||||
* Immutable format-formatter pair. |
||||
* |
||||
* @deprecated jodd目前版本为5.1.6, 此版本已移除此类, 兼容问题暂不删除此类 |
||||
*/ |
||||
@Deprecated |
||||
public class JdtFormat { |
||||
|
||||
protected final String format; |
||||
protected final JdtFormatter formatter; |
||||
|
||||
public JdtFormat(JdtFormatter formatter, String format) { |
||||
this.format = format; |
||||
this.formatter = formatter; |
||||
} |
||||
|
||||
/** |
||||
* Returns format. |
||||
*/ |
||||
public String getFormat() { |
||||
return format; |
||||
} |
||||
|
||||
/** |
||||
* Returns formatter. |
||||
*/ |
||||
public JdtFormatter getFormatter() { |
||||
return formatter; |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Delegates for {@link JdtFormatter#convert(JDateTime, String)}. |
||||
*/ |
||||
public String convert(JDateTime jdt) { |
||||
return formatter.convert(jdt, format); |
||||
} |
||||
|
||||
/** |
||||
* Delegates for {@link JdtFormatter#parse(String, String)}. |
||||
*/ |
||||
public DateTimeStamp parse(String value) { |
||||
return formatter.parse(value, format); |
||||
} |
||||
} |
@ -1,62 +0,0 @@
|
||||
// Copyright (c) 2003-present, Jodd Team (http://jodd.org)
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
package com.fr.third.jodd.datetime.format; |
||||
|
||||
import com.fr.third.jodd.datetime.DateTimeStamp; |
||||
import com.fr.third.jodd.datetime.JDateTime; |
||||
|
||||
import java.io.Serializable; |
||||
|
||||
/** |
||||
* Date time formatter performs conversion both from and to string representation of time. |
||||
* |
||||
* @see AbstractFormatter |
||||
* @deprecated jodd目前版本为5.1.6, 此版本已移除此类, 兼容问题暂不删除此类 |
||||
*/ |
||||
@Deprecated |
||||
public interface JdtFormatter extends Serializable { |
||||
|
||||
/** |
||||
* Converts date time to a string using specified format. |
||||
* |
||||
* @param jdt JDateTime to read from |
||||
* @param format format |
||||
* |
||||
* @return formatted string with date time information |
||||
*/ |
||||
String convert(JDateTime jdt, String format); |
||||
|
||||
/** |
||||
* Parses string given in specified format and extracts time information. |
||||
* It returns a new instance of <code>DateTimeStamp</code> or <code>null</code> if error occurs. |
||||
* |
||||
* @param value string containing date time values |
||||
* @param format format |
||||
* |
||||
* @return DateTimeStamp instance with populated data |
||||
*/ |
||||
DateTimeStamp parse(String value, String format); |
||||
} |
@ -1,29 +0,0 @@
|
||||
// Copyright (c) 2003-present, Jodd Team (http://jodd.org)
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
/** |
||||
* JDateTime formatters for converting date/time informations to/from strings. |
||||
*/ |
||||
package com.fr.third.jodd.datetime.format; |
@ -1,29 +0,0 @@
|
||||
// Copyright (c) 2003-present, Jodd Team (http://jodd.org)
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
/** |
||||
* Finally, easy manipulation of date and time! |
||||
*/ |
||||
package com.fr.third.jodd.datetime; |
@ -1,301 +0,0 @@
|
||||
// Copyright (c) 2003-present, Jodd Team (http://jodd.org)
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
package com.fr.third.jodd.exception; |
||||
|
||||
import com.fr.third.jodd.io.StreamUtil; |
||||
import com.fr.third.jodd.util.StringUtil; |
||||
|
||||
import java.io.PrintWriter; |
||||
import java.io.StringWriter; |
||||
import java.lang.reflect.InvocationTargetException; |
||||
import java.lang.reflect.UndeclaredThrowableException; |
||||
import java.sql.SQLException; |
||||
import java.util.ArrayList; |
||||
import java.util.Collection; |
||||
|
||||
/** |
||||
* Few exception utilities. |
||||
*/ |
||||
public class ExceptionUtil { |
||||
|
||||
/** |
||||
* Returns current stack trace in form of array of stack trace elements. |
||||
* First stack trace element is removed. |
||||
* Since an exception is thrown internally, this method is slow. |
||||
*/ |
||||
@SuppressWarnings({"ThrowCaughtLocally"}) |
||||
public static StackTraceElement[] getCurrentStackTrace() { |
||||
StackTraceElement[] ste = new Exception().getStackTrace(); |
||||
if (ste.length > 1) { |
||||
StackTraceElement[] result = new StackTraceElement[ste.length - 1]; |
||||
System.arraycopy(ste, 1, result, 0, ste.length - 1); |
||||
return result; |
||||
} else { |
||||
return ste; |
||||
} |
||||
} |
||||
|
||||
// ---------------------------------------------------------------- exception stack trace
|
||||
|
||||
/** |
||||
* Returns stack trace filtered by class names. |
||||
*/ |
||||
public static StackTraceElement[] getStackTrace(final Throwable t, final String[] allow, final String[] deny) { |
||||
StackTraceElement[] st = t.getStackTrace(); |
||||
ArrayList<StackTraceElement> result = new ArrayList<>(st.length); |
||||
|
||||
elementLoop: |
||||
for (StackTraceElement element : st) { |
||||
String className = element.getClassName(); |
||||
if (allow != null) { |
||||
boolean validElemenet = false; |
||||
for (String filter : allow) { |
||||
if (className.contains(filter)) { |
||||
validElemenet = true; |
||||
break; |
||||
} |
||||
} |
||||
if (!validElemenet) { |
||||
continue; |
||||
} |
||||
} |
||||
if (deny != null) { |
||||
for (String filter : deny) { |
||||
if (className.contains(filter)) { |
||||
continue elementLoop; |
||||
} |
||||
} |
||||
} |
||||
result.add(element); |
||||
} |
||||
st = new StackTraceElement[result.size()]; |
||||
return result.toArray(st); |
||||
} |
||||
|
||||
/** |
||||
* Returns stack trace chain filtered by class names. |
||||
*/ |
||||
public static StackTraceElement[][] getStackTraceChain(Throwable t, final String[] allow, final String[] deny) { |
||||
ArrayList<StackTraceElement[]> result = new ArrayList<>(); |
||||
while (t != null) { |
||||
StackTraceElement[] stack = getStackTrace(t, allow, deny); |
||||
result.add(stack); |
||||
t = t.getCause(); |
||||
} |
||||
StackTraceElement[][] allStacks = new StackTraceElement[result.size()][]; |
||||
for (int i = 0; i < allStacks.length; i++) { |
||||
allStacks[i] = result.get(i); |
||||
} |
||||
return allStacks; |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Returns exception chain starting from top up to root cause. |
||||
*/ |
||||
public static Throwable[] getExceptionChain(Throwable throwable) { |
||||
ArrayList<Throwable> list = new ArrayList<>(); |
||||
list.add(throwable); |
||||
while ((throwable = throwable.getCause()) != null) { |
||||
list.add(throwable); |
||||
} |
||||
Throwable[] result = new Throwable[list.size()]; |
||||
return list.toArray(result); |
||||
} |
||||
|
||||
|
||||
// ---------------------------------------------------------------- exception to string
|
||||
|
||||
|
||||
/** |
||||
* Prints stack trace into a String. |
||||
*/ |
||||
public static String exceptionStackTraceToString(final Throwable t) { |
||||
StringWriter sw = new StringWriter(); |
||||
PrintWriter pw = new PrintWriter(sw, true); |
||||
|
||||
t.printStackTrace(pw); |
||||
|
||||
StreamUtil.close(pw); |
||||
StreamUtil.close(sw); |
||||
|
||||
return sw.toString(); |
||||
} |
||||
|
||||
/** |
||||
* Prints full exception stack trace, from top to root cause, into a String. |
||||
*/ |
||||
public static String exceptionChainToString(Throwable t) { |
||||
StringWriter sw = new StringWriter(); |
||||
PrintWriter pw = new PrintWriter(sw, true); |
||||
while (t != null) { |
||||
t.printStackTrace(pw); |
||||
t = t.getCause(); |
||||
} |
||||
|
||||
StreamUtil.close(pw); |
||||
StreamUtil.close(sw); |
||||
|
||||
return sw.toString(); |
||||
} |
||||
|
||||
/** |
||||
* Build a message for the given base message and its cause. |
||||
*/ |
||||
public static String buildMessage(final String message, Throwable cause) { |
||||
if (cause != null) { |
||||
cause = getRootCause(cause); |
||||
StringBuilder buf = new StringBuilder(); |
||||
if (message != null) { |
||||
buf.append(message).append("; "); |
||||
} |
||||
buf.append("<--- ").append(cause); |
||||
return buf.toString(); |
||||
} else { |
||||
return message; |
||||
} |
||||
} |
||||
|
||||
// ---------------------------------------------------------------- root cause
|
||||
|
||||
/** |
||||
* Introspects the <code>Throwable</code> to obtain the root cause. |
||||
* <p> |
||||
* This method walks through the exception chain to the last element, |
||||
* "root" of the tree, and returns that exception. If no root cause found |
||||
* returns provided throwable. |
||||
*/ |
||||
public static Throwable getRootCause(final Throwable throwable) { |
||||
Throwable cause = throwable.getCause(); |
||||
if (cause == null) { |
||||
return throwable; |
||||
} |
||||
|
||||
Throwable t = throwable; |
||||
|
||||
// defend against (malicious?) circularity
|
||||
for (int i = 0; i < 1000; i++) { |
||||
cause = t.getCause(); |
||||
if (cause == null) { |
||||
return t; |
||||
} |
||||
t = cause; |
||||
} |
||||
|
||||
return throwable; |
||||
} |
||||
|
||||
/** |
||||
* Finds throwing cause in exception stack. Returns throwable object if cause class is matched. |
||||
* Otherwise, returns <code>null</code>. |
||||
*/ |
||||
@SuppressWarnings({"unchecked"}) |
||||
public static <T extends Throwable> T findCause(Throwable throwable, final Class<T> cause) { |
||||
while (throwable != null) { |
||||
if (throwable.getClass().equals(cause)) { |
||||
return (T) throwable; |
||||
} |
||||
throwable = throwable.getCause(); |
||||
} |
||||
return null; |
||||
} |
||||
|
||||
|
||||
// ---------------------------------------------------------------- sql
|
||||
|
||||
/** |
||||
* Rolls up SQL exceptions by taking each proceeding exception |
||||
* and making it a child of the previous using the <code>setNextException</code> |
||||
* method of SQLException. |
||||
*/ |
||||
public static SQLException rollupSqlExceptions(final Collection<SQLException> exceptions) { |
||||
SQLException parent = null; |
||||
for (SQLException exception : exceptions) { |
||||
if (parent != null) { |
||||
exception.setNextException(parent); |
||||
} |
||||
parent = exception; |
||||
} |
||||
return parent; |
||||
} |
||||
|
||||
// ---------------------------------------------------------------- misc
|
||||
|
||||
/** |
||||
* Throws checked exceptions in un-checked manner. |
||||
*/ |
||||
public static void throwRuntimeException(final Throwable throwable) { |
||||
throw wrapToRuntimeException(throwable); |
||||
} |
||||
|
||||
/** |
||||
* Returns <code>non-null</code> message for a throwable. |
||||
*/ |
||||
public static String message(final Throwable throwable) { |
||||
String message = throwable.getMessage(); |
||||
|
||||
if (StringUtil.isBlank(message)) { |
||||
message = throwable.toString(); |
||||
} |
||||
|
||||
return message; |
||||
} |
||||
|
||||
/** |
||||
* Wraps exception to {@code RuntimeException}. |
||||
*/ |
||||
public static RuntimeException wrapToRuntimeException(final Throwable throwable) { |
||||
if (throwable instanceof RuntimeException) { |
||||
return (RuntimeException) throwable; |
||||
} |
||||
return new RuntimeException(throwable); |
||||
} |
||||
public static Exception wrapToException(final Throwable throwable) { |
||||
if (throwable instanceof Exception) { |
||||
return (Exception) throwable; |
||||
} |
||||
return new RuntimeException(throwable); |
||||
} |
||||
|
||||
/** |
||||
* Unwraps invocation and undeclared exceptions to real cause. |
||||
*/ |
||||
public static Throwable unwrapThrowable(final Throwable wrappedThrowable) { |
||||
Throwable unwrapped = wrappedThrowable; |
||||
while (true) { |
||||
if (unwrapped instanceof InvocationTargetException) { |
||||
unwrapped = ((InvocationTargetException) unwrapped).getTargetException(); |
||||
} |
||||
else if (unwrapped instanceof UndeclaredThrowableException) { |
||||
unwrapped = ((UndeclaredThrowableException) unwrapped).getUndeclaredThrowable(); |
||||
} |
||||
else { |
||||
return unwrapped; |
||||
} |
||||
} |
||||
} |
||||
|
||||
} |
@ -1,212 +0,0 @@
|
||||
// Copyright (c) 2003-present, Jodd Team (http://jodd.org)
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
package com.fr.third.jodd.exception; |
||||
|
||||
import java.io.IOException; |
||||
import java.io.PrintStream; |
||||
import java.io.PrintWriter; |
||||
import java.io.UncheckedIOException; |
||||
import java.util.concurrent.Callable; |
||||
|
||||
/** |
||||
* Unchecked exception and also a wrapper for checked exceptions. |
||||
*/ |
||||
@SuppressWarnings({"SynchronizationOnLocalVariableOrMethodParameter"}) |
||||
public class UncheckedException extends RuntimeException { |
||||
|
||||
protected final Throwable cause; |
||||
|
||||
/** |
||||
* Divider between causes printouts. |
||||
*/ |
||||
protected static final String CAUSE_DIV = "---[cause]------------------------------------------------------------------------"; |
||||
|
||||
/** |
||||
* If set to <code>true</code> stack trace will be enhanced with cause's stack traces. |
||||
*/ |
||||
protected final boolean showCauseDetails; |
||||
|
||||
// ---------------------------------------------------------------- constructors
|
||||
|
||||
public UncheckedException(final Throwable t) { |
||||
super(t.getMessage()); |
||||
cause = t; |
||||
this.showCauseDetails = true; |
||||
} |
||||
|
||||
public UncheckedException(final Throwable t, final boolean showCauseDetails) { |
||||
super(t.getMessage()); |
||||
cause = t; |
||||
this.showCauseDetails = showCauseDetails; |
||||
} |
||||
|
||||
public UncheckedException() { |
||||
super(); |
||||
cause = null; |
||||
this.showCauseDetails = false; |
||||
} |
||||
|
||||
public UncheckedException(final String message) { |
||||
super(message); |
||||
cause = null; |
||||
this.showCauseDetails = false; |
||||
} |
||||
|
||||
public UncheckedException(final String message, final Throwable t) { |
||||
super(message, t); |
||||
cause = t; |
||||
this.showCauseDetails = true; |
||||
} |
||||
|
||||
public UncheckedException(final String message, final Throwable t, final boolean showCauseDetails) { |
||||
super(message, t); |
||||
cause = t; |
||||
this.showCauseDetails = showCauseDetails; |
||||
} |
||||
|
||||
// ---------------------------------------------------------------- stack trace
|
||||
|
||||
@Override |
||||
public void printStackTrace() { |
||||
printStackTrace(System.err); |
||||
} |
||||
|
||||
@Override |
||||
public void printStackTrace(final PrintStream ps) { |
||||
synchronized (ps) { |
||||
super.printStackTrace(ps); |
||||
if ((cause != null) && showCauseDetails) { |
||||
Throwable rootCause = ExceptionUtil.getRootCause(cause); |
||||
ps.println(CAUSE_DIV); |
||||
rootCause.printStackTrace(ps); |
||||
} |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
public void printStackTrace(final PrintWriter pw) { |
||||
synchronized (pw) { |
||||
super.printStackTrace(pw); |
||||
if ((cause != null) && showCauseDetails) { |
||||
Throwable rootCause = ExceptionUtil.getRootCause(cause); |
||||
pw.println(CAUSE_DIV); |
||||
rootCause.printStackTrace(pw); |
||||
} |
||||
} |
||||
} |
||||
|
||||
// ---------------------------------------------------------------- txt
|
||||
|
||||
/** |
||||
* Returns the detail message, including the message from the nested exception if there is one. |
||||
*/ |
||||
@Override |
||||
public String getMessage() { |
||||
return ExceptionUtil.buildMessage(super.getMessage(), cause); |
||||
} |
||||
|
||||
// ---------------------------------------------------------------- wrap
|
||||
|
||||
/** |
||||
* Wraps checked exceptions in a <code>UncheckedException</code>. |
||||
* Unchecked exceptions are not wrapped. |
||||
*/ |
||||
public static <V> V callAndWrapException(final Callable<V> callable) { |
||||
try { |
||||
return callable.call(); |
||||
} |
||||
catch (IOException ioex) { |
||||
throw new UncheckedIOException(ioex); |
||||
} |
||||
catch (RuntimeException rtex) { |
||||
throw rtex; |
||||
} |
||||
catch (Exception t) { |
||||
throw new UncheckedException(t); |
||||
} |
||||
} |
||||
|
||||
@FunctionalInterface |
||||
public interface CallableVoid { |
||||
public void call() throws Exception; |
||||
} |
||||
|
||||
/** |
||||
* Wraps checked exceptions in a <code>UncheckedException</code>. |
||||
* Unchecked exceptions are not wrapped. |
||||
*/ |
||||
public static void runAndWrapException(final CallableVoid callable) { |
||||
try { |
||||
callable.call(); |
||||
} |
||||
catch (IOException ioex) { |
||||
throw new UncheckedIOException(ioex); |
||||
} |
||||
catch (RuntimeException rtex) { |
||||
throw rtex; |
||||
} |
||||
catch (Exception t) { |
||||
throw new UncheckedException(t); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Wraps all exceptions in a <code>UncheckedException</code> |
||||
*/ |
||||
public static RuntimeException wrap(final Throwable t) { |
||||
return new UncheckedException(t); |
||||
} |
||||
|
||||
/** |
||||
* Wraps all exceptions in a <code>UncheckedException</code> |
||||
*/ |
||||
public static RuntimeException wrap(final Throwable t, final String message) { |
||||
return new UncheckedException(message, t); |
||||
} |
||||
|
||||
|
||||
// ---------------------------------------------------------------- cause
|
||||
|
||||
/** |
||||
* Re-throws cause if exists. |
||||
*/ |
||||
public void rethrow() throws Throwable { |
||||
if (cause == null) { |
||||
return; |
||||
} |
||||
throw cause; |
||||
} |
||||
|
||||
/** |
||||
* Returns exception cause. |
||||
*/ |
||||
@Override |
||||
public Throwable getCause() { |
||||
return cause; |
||||
} |
||||
|
||||
|
||||
} |
@ -1,29 +0,0 @@
|
||||
// Copyright (c) 2003-present, Jodd Team (http://jodd.org)
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
/** |
||||
* Jodds exceptions. |
||||
*/ |
||||
package com.fr.third.jodd.exception; |
@ -1,52 +0,0 @@
|
||||
// Copyright (c) 2003-present, Jodd Team (http://jodd.org)
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
package com.fr.third.jodd.inex; |
||||
|
||||
import com.fr.third.jodd.util.Wildcard; |
||||
|
||||
/** |
||||
* Rule matcher. |
||||
*/ |
||||
@FunctionalInterface |
||||
public interface InExRuleMatcher<T, R> { |
||||
|
||||
/** |
||||
* {@link com.fr.third.jodd.util.Wildcard#match(CharSequence, CharSequence) Wilcard} rule matcher. |
||||
*/ |
||||
InExRuleMatcher<String, String> WILDCARD_RULE_MATCHER = |
||||
(value, rule, include) -> Wildcard.match(value, rule); |
||||
/** |
||||
* {@link com.fr.third.jodd.util.Wildcard#matchPath(String, String) Wilcard path} rule matcher. |
||||
*/ |
||||
InExRuleMatcher<String, String> WILDCARD_PATH_RULE_MATCHER = |
||||
(value, rule, include) -> Wildcard.matchPath(value, rule); |
||||
|
||||
/** |
||||
* Matches the value against the rule. |
||||
*/ |
||||
boolean accept(T value, R rule, boolean include); |
||||
|
||||
} |
@ -1,381 +0,0 @@
|
||||
// Copyright (c) 2003-present, Jodd Team (http://jodd.org)
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
package com.fr.third.jodd.inex; |
||||
|
||||
import java.util.ArrayList; |
||||
import java.util.List; |
||||
|
||||
/** |
||||
* A single-class rule engine for includes/excludes filtering logic. It can be used when |
||||
* set of objects has to filtered using includes and excludes rules. |
||||
* For example, when filtering files by file name etc. |
||||
* <p> |
||||
* Rule engine works in one of two modes: |
||||
* <ul> |
||||
* <li><i>blacklist</i> - when any input is allowed by default and when you specify |
||||
* explicit excludes. |
||||
* </li> |
||||
* <li><i>whitelist</i> - when any input is disabled by default and when you specify |
||||
* explicit includes. |
||||
* </li> |
||||
* </ul> |
||||
* <p> |
||||
* The logic of this rule engine depends on the current mode. In both cases, |
||||
* always the inverse rules are considered first. For example, for <i>blacklist</i> |
||||
* mode, engine first examine excludes, and then includes. This way you can |
||||
* set any filter combination. |
||||
* <p> |
||||
* All Jodd classes that filters something uses this class to unify the |
||||
* behavior across the Jodd library. |
||||
* <p> |
||||
* About generics: rule engine examine Values (V). Rules are defined as Definitions (D). |
||||
* They are stored internally as R, that is used with Values. |
||||
*/ |
||||
public class InExRules<V, D, R> implements InExRuleMatcher<V, R> { |
||||
|
||||
public InExRules<String, String, String> create() { |
||||
return new InExRules<>(); |
||||
} |
||||
|
||||
protected List<Rule<R>> rules; |
||||
protected final InExRuleMatcher<V, R> inExRuleMatcher; |
||||
protected int includesCount; |
||||
protected int excludesCount; |
||||
protected boolean blacklist = true; |
||||
|
||||
/** |
||||
* Creates default instance. |
||||
*/ |
||||
public InExRules() { |
||||
this.inExRuleMatcher = this; |
||||
} |
||||
|
||||
/** |
||||
* Creates instance that uses provided matcher. |
||||
*/ |
||||
public InExRules(final InExRuleMatcher<V, R> inExRuleMatcher) { |
||||
this.inExRuleMatcher = inExRuleMatcher; |
||||
} |
||||
|
||||
/** |
||||
* Returns total number of all rules. |
||||
*/ |
||||
public int totalRules() { |
||||
if (rules == null) { |
||||
return 0; |
||||
} |
||||
return rules.size(); |
||||
} |
||||
|
||||
/** |
||||
* Returns total number of include rules. |
||||
*/ |
||||
public int totalIncludeRules() { |
||||
return includesCount; |
||||
} |
||||
|
||||
/** |
||||
* Returns total number of exclude rules. |
||||
*/ |
||||
public int totalExcludeRules() { |
||||
return excludesCount; |
||||
} |
||||
|
||||
/** |
||||
* Returns <code>true</code> if rule engine has at least one rule set. |
||||
*/ |
||||
public boolean hasRules() { |
||||
if (rules == null) { |
||||
return false; |
||||
} |
||||
return !rules.isEmpty(); |
||||
} |
||||
|
||||
/** |
||||
* Rule definition. |
||||
*/ |
||||
public static class Rule<R> { |
||||
public final R value; |
||||
public final boolean include; |
||||
|
||||
public Rule(final R value, final boolean include) { |
||||
this.value = value; |
||||
this.include = include; |
||||
} |
||||
|
||||
@Override |
||||
public String toString() { |
||||
return (include ? "+" : "-") + value.toString(); |
||||
} |
||||
|
||||
@Override |
||||
public boolean equals(final Object o) { |
||||
if (this == o) { |
||||
return true; |
||||
} |
||||
if (o == null || getClass() != o.getClass()) { |
||||
return false; |
||||
} |
||||
|
||||
Rule rule = (Rule) o; |
||||
|
||||
if (include != rule.include) { |
||||
return false; |
||||
} |
||||
if (!value.equals(rule.value)) { |
||||
return false; |
||||
} |
||||
|
||||
return true; |
||||
} |
||||
|
||||
@Override |
||||
public int hashCode() { |
||||
int result = value.hashCode(); |
||||
result = 31 * result + (include ? 1 : 0); |
||||
return result; |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Returns rule's value on given index. |
||||
*/ |
||||
public R getRule(final int index) { |
||||
return rules.get(index).value; |
||||
} |
||||
|
||||
/** |
||||
* Resets all the rules in this rule engine. |
||||
*/ |
||||
public void reset() { |
||||
if (rules != null) { |
||||
rules.clear(); |
||||
} |
||||
includesCount = excludesCount = 0; |
||||
blacklist = true; |
||||
} |
||||
|
||||
/** |
||||
* Enables <i>blacklist</i> mode - everything is <b>included</b> by default, |
||||
* and user sets explicit excludes. |
||||
*/ |
||||
public void blacklist() { |
||||
blacklist = true; |
||||
} |
||||
|
||||
/** |
||||
* Returns <code>true</code> if blacklist mode is set. |
||||
*/ |
||||
public boolean isBlacklist() { |
||||
return blacklist; |
||||
} |
||||
|
||||
/** |
||||
* Enables <i>whitelist</i> mode - everything is <b>excluded</b> by default, |
||||
* and user set explicit includes. |
||||
*/ |
||||
public void whitelist() { |
||||
blacklist = false; |
||||
} |
||||
|
||||
/** |
||||
* Returns <code>true</code> if whitelist mode is set. |
||||
*/ |
||||
public boolean isWhitelist() { |
||||
return !blacklist; |
||||
} |
||||
|
||||
/** |
||||
* Sets blacklist or whitelist mode depending on rules. Smart mode |
||||
* determines the following: |
||||
* <ul> |
||||
* <li>If there are only include rules, then the {@link #whitelist() whitelist} mode is set.</li> |
||||
* <li>If there are only excluded rules, then the {@link #blacklist() blacklist} mode is set.</li> |
||||
* <li>In any other case (both type of rules exist or no rules are set), then mode is not changed.</li> |
||||
* </ul> |
||||
* Should be called <b>after</b> all the rules are set, before matching starts. |
||||
*/ |
||||
public void detectMode() { |
||||
if (excludesCount == 0 && includesCount > 0) { |
||||
whitelist(); |
||||
} |
||||
else if (excludesCount > 0 && includesCount == 0) { |
||||
blacklist(); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Adds include rule. |
||||
*/ |
||||
public void include(final D rule) { |
||||
addRule(rule, true); |
||||
} |
||||
|
||||
/** |
||||
* Adds exclude rule. |
||||
*/ |
||||
public void exclude(final D rule) { |
||||
addRule(rule, false); |
||||
} |
||||
|
||||
/** |
||||
* Adds a rule. Duplicates are not allowed and will be ignored. |
||||
*/ |
||||
protected void addRule(final D ruleDefinition, final boolean include) { |
||||
if (rules == null) { |
||||
rules = new ArrayList<>(); |
||||
} |
||||
|
||||
if (include) { |
||||
includesCount++; |
||||
} else { |
||||
excludesCount++; |
||||
} |
||||
|
||||
Rule<R> newRule = new Rule<>(makeRule(ruleDefinition), include); |
||||
|
||||
if (rules.contains(newRule)) { |
||||
return; |
||||
} |
||||
|
||||
rules.add(newRule); |
||||
} |
||||
|
||||
protected R makeRule(final D rule) { |
||||
return (R) rule; |
||||
} |
||||
|
||||
/** |
||||
* Matches value against the set of rules using current white/black list mode. |
||||
*/ |
||||
public boolean match(final V value) { |
||||
return match(value, blacklist); |
||||
} |
||||
/** |
||||
* Matches value against the set of rules using provided white/black list mode. |
||||
*/ |
||||
public boolean match(final V value, final boolean blacklist) { |
||||
if (rules == null) { |
||||
return blacklist; |
||||
} |
||||
|
||||
boolean include = blacklist; |
||||
|
||||
if (include) { |
||||
include = processExcludes(value, true); |
||||
include = processIncludes(value, include); |
||||
} |
||||
else { |
||||
include = processIncludes(value, false); |
||||
include = processExcludes(value, include); |
||||
} |
||||
|
||||
return include; |
||||
} |
||||
|
||||
/** |
||||
* Applies rules on given flag using current black/white list mode. |
||||
* @see #apply(Object, boolean, boolean) |
||||
*/ |
||||
public boolean apply(final V value, final boolean flag) { |
||||
return apply(value, blacklist, flag); |
||||
} |
||||
|
||||
/** |
||||
* Applies rules on given flag. Flag is only changed if at least one rule |
||||
* matched. Otherwise, the same value is returned. This way you can |
||||
* chain several rules and have the rule engine change the flag |
||||
* only when a rule is matched. |
||||
*/ |
||||
public boolean apply(final V value, final boolean blacklist, boolean flag) { |
||||
if (rules == null) { |
||||
return flag; |
||||
} |
||||
|
||||
if (blacklist) { |
||||
flag = processExcludes(value, flag); |
||||
flag = processIncludes(value, flag); |
||||
} |
||||
else { |
||||
flag = processIncludes(value, flag); |
||||
flag = processExcludes(value, flag); |
||||
} |
||||
|
||||
return flag; |
||||
} |
||||
|
||||
/** |
||||
* Process includes rules. |
||||
*/ |
||||
protected boolean processIncludes(final V value, boolean include) { |
||||
if (includesCount > 0) { |
||||
if (!include) { |
||||
for (Rule<R> rule : rules) { |
||||
if (!rule.include) { |
||||
continue; |
||||
} |
||||
|
||||
if (inExRuleMatcher.accept(value, rule.value, true)) { |
||||
include = true; |
||||
break; |
||||
} |
||||
} |
||||
} |
||||
} |
||||
return include; |
||||
} |
||||
|
||||
/** |
||||
* Process excludes rules. |
||||
*/ |
||||
protected boolean processExcludes(final V value, boolean include) { |
||||
if (excludesCount > 0) { |
||||
if (include) { |
||||
for (Rule<R> rule : rules) { |
||||
if (rule.include) { |
||||
continue; |
||||
} |
||||
|
||||
if (inExRuleMatcher.accept(value, rule.value, false)) { |
||||
include = false; |
||||
break; |
||||
} |
||||
} |
||||
} |
||||
} |
||||
return include; |
||||
} |
||||
|
||||
/** |
||||
* Matches value against single rule. By default performs <code>equals</code> on value |
||||
* against the rule. |
||||
*/ |
||||
@Override |
||||
public boolean accept(final V value, final R rule, final boolean include) { |
||||
return value.equals(rule); |
||||
} |
||||
|
||||
} |
@ -1,29 +0,0 @@
|
||||
// Copyright (c) 2003-present, Jodd Team (http://jodd.org)
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
/** |
||||
* Include-Exclude rules engine. |
||||
*/ |
||||
package com.fr.third.jodd.inex; |
@ -1,86 +0,0 @@
|
||||
// Copyright (c) 2003-present, Jodd Team (http://jodd.org)
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
package com.fr.third.jodd.introspector; |
||||
|
||||
import com.fr.third.jodd.cache.TypeCache; |
||||
|
||||
/** |
||||
* Default {@link com.fr.third.jodd.introspector.ClassIntrospector introspector} that caches all class descriptors. |
||||
* It can examine either <b>accessible</b> or <b>supported</b> fields/methods/constructors. |
||||
* <p> |
||||
* It simply caches <b>all</b> class descriptors. |
||||
*/ |
||||
public class CachingIntrospector implements ClassIntrospector { |
||||
|
||||
protected final TypeCache<ClassDescriptor> cache; |
||||
protected final boolean scanAccessible; |
||||
protected final boolean enhancedProperties; |
||||
protected final boolean includeFieldsAsProperties; |
||||
protected final String[] propertyFieldPrefix; |
||||
|
||||
/** |
||||
* Default constructor. |
||||
*/ |
||||
public CachingIntrospector() { |
||||
this(true, true, true, null); |
||||
} |
||||
|
||||
/** |
||||
* Creates new caching {@link ClassIntrospector}. It may scan |
||||
* <b>accessible</b> or <b>supported</b> fields, methods or |
||||
* constructors. |
||||
*/ |
||||
public CachingIntrospector(final boolean scanAccessible, final boolean enhancedProperties, final boolean includeFieldsAsProperties, final String[] propertyFieldPrefix) { |
||||
this.cache = TypeCache.createDefault(); |
||||
this.scanAccessible = scanAccessible; |
||||
this.enhancedProperties = enhancedProperties; |
||||
this.includeFieldsAsProperties = includeFieldsAsProperties; |
||||
this.propertyFieldPrefix = propertyFieldPrefix; |
||||
} |
||||
|
||||
/** |
||||
* {@inheritDoc} |
||||
*/ |
||||
@Override |
||||
public ClassDescriptor lookup(final Class type) { |
||||
return cache.get(type, (t) -> |
||||
new ClassDescriptor( |
||||
t, |
||||
scanAccessible, |
||||
enhancedProperties, |
||||
includeFieldsAsProperties, |
||||
propertyFieldPrefix)); |
||||
} |
||||
|
||||
/** |
||||
* {@inheritDoc} |
||||
*/ |
||||
@Override |
||||
public void reset() { |
||||
cache.clear(); |
||||
} |
||||
|
||||
} |
@ -1,378 +0,0 @@
|
||||
// Copyright (c) 2003-present, Jodd Team (http://jodd.org)
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
package com.fr.third.jodd.introspector; |
||||
|
||||
import com.fr.third.jodd.util.ClassUtil; |
||||
|
||||
import java.util.Collection; |
||||
import java.util.List; |
||||
import java.util.Map; |
||||
import java.util.Set; |
||||
import java.util.function.Supplier; |
||||
|
||||
/** |
||||
* A descriptor class for all methods/fields/properties/constructors of a class. |
||||
* Static methods/fields are ignored. |
||||
* <p> |
||||
* Descriptors are 'lazy': various internal caches are created on first request. |
||||
* <p> |
||||
* Throughout this class, public members are defined as members |
||||
* defined with "public" keyword and declared in a public type. |
||||
* Public members declared by a non-public class is considered non-public |
||||
* because access to it from outside is prohibited by the java access control |
||||
* anyway. |
||||
* <p> |
||||
* Public members defined in public classes are always preferred even |
||||
* when we allow private/protected members and types to be visible. |
||||
* So if a non-public subtype and a public super type both have a field |
||||
* with the same name, the field in the public super type is always used. |
||||
*/ |
||||
public class ClassDescriptor { |
||||
|
||||
protected final Class type; |
||||
protected final boolean scanAccessible; |
||||
protected final boolean extendedProperties; |
||||
protected final boolean includeFieldsAsProperties; |
||||
protected final String[] propertyFieldPrefix; |
||||
protected final Class[] interfaces; |
||||
protected final Class[] superclasses; |
||||
|
||||
public ClassDescriptor(final Class type, final boolean scanAccessible, final boolean extendedProperties, final boolean includeFieldsAsProperties, final String[] propertyFieldPrefix) { |
||||
this.type = type; |
||||
this.scanAccessible = scanAccessible; |
||||
this.extendedProperties = extendedProperties; |
||||
this.includeFieldsAsProperties = includeFieldsAsProperties; |
||||
this.propertyFieldPrefix = propertyFieldPrefix; |
||||
|
||||
isArray = type.isArray(); |
||||
isMap = ClassUtil.isTypeOf(type, Map.class); |
||||
isList = ClassUtil.isTypeOf(type, List.class); |
||||
isSet = ClassUtil.isTypeOf(type, Set.class); |
||||
isCollection = ClassUtil.isTypeOf(type, Collection.class); |
||||
isSupplier = ClassUtil.isTypeOf(type, Supplier.class); |
||||
|
||||
interfaces = ClassUtil.resolveAllInterfaces(type); |
||||
superclasses = ClassUtil.resolveAllSuperclasses(type); |
||||
|
||||
isSystemClass = type.getName().startsWith("java.") && |
||||
!type.getName().startsWith("java.awt.geom."); |
||||
} |
||||
|
||||
/** |
||||
* Get the class object that this descriptor describes. |
||||
*/ |
||||
public Class getType() { |
||||
return type; |
||||
} |
||||
|
||||
/** |
||||
* Returns <code>true</code> if this class descriptor |
||||
* works with accessible fields/methods/constructors or with |
||||
* all supported. |
||||
*/ |
||||
public boolean isScanAccessible() { |
||||
return scanAccessible; |
||||
} |
||||
|
||||
/** |
||||
* Returns <code>true</code> if properties in this class descriptor |
||||
* are extended and include field description. |
||||
*/ |
||||
public boolean isExtendedProperties() { |
||||
return extendedProperties; |
||||
} |
||||
|
||||
/** |
||||
* Include fields as properties. |
||||
*/ |
||||
public boolean isIncludeFieldsAsProperties() { |
||||
return includeFieldsAsProperties; |
||||
} |
||||
|
||||
/** |
||||
* Returns property field prefixes. May be <code>null</code> |
||||
* if prefixes are not set. If you need to access both prefixed |
||||
* and non-prefixed fields, use empty string as one of the prefixes. |
||||
*/ |
||||
public String[] getPropertyFieldPrefix() { |
||||
return propertyFieldPrefix; |
||||
} |
||||
|
||||
// ---------------------------------------------------------------- special
|
||||
|
||||
private final boolean isArray; |
||||
/** |
||||
* Returns <code>true</code> if class is an array. |
||||
*/ |
||||
public boolean isArray() { |
||||
return isArray; |
||||
} |
||||
|
||||
private final boolean isMap; |
||||
/** |
||||
* Returns <code>true</code> if class is a <code>Map</code>. |
||||
*/ |
||||
public boolean isMap() { |
||||
return isMap; |
||||
} |
||||
|
||||
private final boolean isList; |
||||
/** |
||||
* Returns <code>true</code> if class is a <code>List</code>. |
||||
*/ |
||||
public boolean isList() { |
||||
return isList; |
||||
} |
||||
|
||||
private final boolean isSet; |
||||
/** |
||||
* Returns <code>true</code> if type is a <code>Set</code>. |
||||
*/ |
||||
public boolean isSet() { |
||||
return isSet; |
||||
} |
||||
|
||||
private final boolean isCollection; |
||||
/** |
||||
* Returns <code>true</code> if type is a collection. |
||||
*/ |
||||
public boolean isCollection() { |
||||
return isCollection; |
||||
} |
||||
|
||||
private final boolean isSupplier; |
||||
|
||||
/** |
||||
* Returns <code>true</code> if type is a supplier. |
||||
*/ |
||||
public boolean isSupplier() { |
||||
return isSupplier; |
||||
} |
||||
|
||||
private boolean isSystemClass; |
||||
|
||||
/** |
||||
* Returns <code>true</code> is class is a system class and should not |
||||
* expose fields or declared methods. |
||||
*/ |
||||
public boolean isSystemClass() { |
||||
return isSystemClass; |
||||
} |
||||
|
||||
// ---------------------------------------------------------------- fields
|
||||
|
||||
private Fields fields; |
||||
|
||||
/** |
||||
* Returns {@link Fields fields collection}. |
||||
* Creates new fields collection on first usage. |
||||
*/ |
||||
protected Fields getFields() { |
||||
if (fields == null) { |
||||
fields = new Fields(this); |
||||
} |
||||
return fields; |
||||
} |
||||
|
||||
/** |
||||
* Returns field descriptor. |
||||
*/ |
||||
public FieldDescriptor getFieldDescriptor(final String name, final boolean declared) { |
||||
final FieldDescriptor fieldDescriptor = getFields().getFieldDescriptor(name); |
||||
|
||||
if (fieldDescriptor != null) { |
||||
if (!fieldDescriptor.matchDeclared(declared)) { |
||||
return null; |
||||
} |
||||
} |
||||
|
||||
return fieldDescriptor; |
||||
} |
||||
|
||||
/** |
||||
* Returns all field descriptors, including declared ones. |
||||
*/ |
||||
public FieldDescriptor[] getAllFieldDescriptors() { |
||||
return getFields().getAllFieldDescriptors(); |
||||
} |
||||
|
||||
// ---------------------------------------------------------------- methods
|
||||
|
||||
private Methods methods; |
||||
|
||||
/** |
||||
* Returns methods collection. |
||||
* Creates new collection on first access. |
||||
*/ |
||||
protected Methods getMethods() { |
||||
if (methods == null) { |
||||
methods = new Methods(this); |
||||
} |
||||
return methods; |
||||
} |
||||
|
||||
/** |
||||
* Returns {@link MethodDescriptor method descriptor} identified by name and parameters. |
||||
*/ |
||||
public MethodDescriptor getMethodDescriptor(final String name, final boolean declared) { |
||||
final MethodDescriptor methodDescriptor = getMethods().getMethodDescriptor(name); |
||||
|
||||
if ((methodDescriptor != null) && methodDescriptor.matchDeclared(declared)) { |
||||
return methodDescriptor; |
||||
} |
||||
|
||||
return methodDescriptor; |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Returns {@link MethodDescriptor method descriptor} identified by name and parameters. |
||||
*/ |
||||
public MethodDescriptor getMethodDescriptor(final String name, final Class[] params, final boolean declared) { |
||||
final MethodDescriptor methodDescriptor = getMethods().getMethodDescriptor(name, params); |
||||
|
||||
if ((methodDescriptor != null) && methodDescriptor.matchDeclared(declared)) { |
||||
return methodDescriptor; |
||||
} |
||||
|
||||
return null; |
||||
} |
||||
|
||||
/** |
||||
* Returns an array of all methods with the same name. |
||||
*/ |
||||
public MethodDescriptor[] getAllMethodDescriptors(final String name) { |
||||
return getMethods().getAllMethodDescriptors(name); |
||||
} |
||||
|
||||
/** |
||||
* Returns an array of all methods. |
||||
*/ |
||||
public MethodDescriptor[] getAllMethodDescriptors() { |
||||
return getMethods().getAllMethodDescriptors(); |
||||
} |
||||
|
||||
// ---------------------------------------------------------------- properties
|
||||
|
||||
private Properties properties; |
||||
|
||||
/** |
||||
* Returns properties collection. |
||||
* Creates new collection on first access. |
||||
*/ |
||||
protected Properties getProperties() { |
||||
if (properties == null) { |
||||
properties = new Properties(this); |
||||
} |
||||
return properties; |
||||
} |
||||
|
||||
/** |
||||
* Returns property descriptor. Declared flag is matched on both read and write |
||||
* methods. |
||||
*/ |
||||
public PropertyDescriptor getPropertyDescriptor(final String name, final boolean declared) { |
||||
PropertyDescriptor propertyDescriptor = getProperties().getPropertyDescriptor(name); |
||||
|
||||
if ((propertyDescriptor != null) && propertyDescriptor.matchDeclared(declared)) { |
||||
return propertyDescriptor; |
||||
} |
||||
|
||||
return null; |
||||
} |
||||
|
||||
/** |
||||
* Returns all properties descriptors. |
||||
*/ |
||||
public PropertyDescriptor[] getAllPropertyDescriptors() { |
||||
return getProperties().getAllPropertyDescriptors(); |
||||
} |
||||
|
||||
// ---------------------------------------------------------------- ctors
|
||||
|
||||
private Ctors ctors; |
||||
|
||||
/** |
||||
* Returns constructors collection. |
||||
* Creates new collection of first access. |
||||
*/ |
||||
protected Ctors getCtors() { |
||||
if (ctors == null) { |
||||
ctors = new Ctors(this); |
||||
} |
||||
return ctors; |
||||
} |
||||
|
||||
/** |
||||
* Returns the default ctor or <code>null</code> if not found. |
||||
*/ |
||||
public CtorDescriptor getDefaultCtorDescriptor(final boolean declared) { |
||||
CtorDescriptor defaultCtor = getCtors().getDefaultCtor(); |
||||
|
||||
if ((defaultCtor != null) && defaultCtor.matchDeclared(declared)) { |
||||
return defaultCtor; |
||||
} |
||||
return null; |
||||
} |
||||
|
||||
/** |
||||
* Returns the constructor identified by arguments or <code>null</code> if not found. |
||||
*/ |
||||
public CtorDescriptor getCtorDescriptor(final Class[] args, final boolean declared) { |
||||
CtorDescriptor ctorDescriptor = getCtors().getCtorDescriptor(args); |
||||
|
||||
if ((ctorDescriptor != null) && ctorDescriptor.matchDeclared(declared)) { |
||||
return ctorDescriptor; |
||||
} |
||||
return null; |
||||
} |
||||
|
||||
/** |
||||
* Returns an array of all {@link CtorDescriptor constructor descriptors}. |
||||
*/ |
||||
public CtorDescriptor[] getAllCtorDescriptors() { |
||||
return getCtors().getAllCtorDescriptors(); |
||||
} |
||||
|
||||
|
||||
// ---------------------------------------------------------------- interfaces
|
||||
|
||||
/** |
||||
* Returns <b>all</b> interfaces of this class. |
||||
*/ |
||||
public Class[] getAllInterfaces() { |
||||
return interfaces; |
||||
} |
||||
|
||||
/** |
||||
* Returns <b>all</b> superclasses of this class. |
||||
* <code>Object.class</code> is <b>not</b> included in the |
||||
* returned list. |
||||
*/ |
||||
public Class[] getAllSuperclasses() { |
||||
return superclasses; |
||||
} |
||||
} |
@ -1,66 +0,0 @@
|
||||
// Copyright (c) 2003-present, Jodd Team (http://jodd.org)
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
package com.fr.third.jodd.introspector; |
||||
|
||||
|
||||
import java.util.Objects; |
||||
|
||||
/** |
||||
* Default class {@link ClassIntrospector} simply delegates method calls for |
||||
* more convenient usage. |
||||
*/ |
||||
public interface ClassIntrospector { |
||||
|
||||
class Implementation { |
||||
private static ClassIntrospector classIntrospector = new CachingIntrospector(); |
||||
|
||||
/** |
||||
* Sets default implementation. |
||||
*/ |
||||
public static void set(final ClassIntrospector classIntrospector) { |
||||
Objects.requireNonNull(classIntrospector); |
||||
Implementation.classIntrospector = classIntrospector; |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Returns default implementation. |
||||
*/ |
||||
static ClassIntrospector get() { |
||||
return Implementation.classIntrospector; |
||||
} |
||||
|
||||
/** |
||||
* Returns class descriptor for specified type. |
||||
*/ |
||||
ClassDescriptor lookup(Class type); |
||||
|
||||
/** |
||||
* Clears all cached data. |
||||
*/ |
||||
void reset(); |
||||
|
||||
} |
@ -1,79 +0,0 @@
|
||||
// Copyright (c) 2003-present, Jodd Team (http://jodd.org)
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
package com.fr.third.jodd.introspector; |
||||
|
||||
import com.fr.third.jodd.util.ClassUtil; |
||||
|
||||
import java.lang.reflect.Constructor; |
||||
|
||||
/** |
||||
* Constructor descriptor. |
||||
*/ |
||||
public class CtorDescriptor extends Descriptor { |
||||
|
||||
protected final Constructor constructor; |
||||
protected final Class[] parameters; |
||||
|
||||
public CtorDescriptor(final ClassDescriptor classDescriptor, final Constructor constructor) { |
||||
super(classDescriptor, ClassUtil.isPublic(constructor)); |
||||
this.constructor = constructor; |
||||
this.parameters = constructor.getParameterTypes(); |
||||
|
||||
ClassUtil.forceAccess(constructor); |
||||
} |
||||
|
||||
/** |
||||
* Returns constructor name. |
||||
*/ |
||||
@Override |
||||
public String getName() { |
||||
return constructor.getName(); |
||||
} |
||||
|
||||
/** |
||||
* Returns constructor. |
||||
*/ |
||||
public Constructor getConstructor() { |
||||
return constructor; |
||||
} |
||||
|
||||
/** |
||||
* Returns constructors parameters. The returned array |
||||
* is not cloned. |
||||
*/ |
||||
public Class[] getParameters() { |
||||
return parameters; |
||||
} |
||||
|
||||
/** |
||||
* Returns <code>true</code> if this is a default constructor |
||||
* (with no parameters). |
||||
*/ |
||||
public boolean isDefault() { |
||||
return parameters.length == 0; |
||||
} |
||||
|
||||
} |
@ -1,113 +0,0 @@
|
||||
// Copyright (c) 2003-present, Jodd Team (http://jodd.org)
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
package com.fr.third.jodd.introspector; |
||||
|
||||
import java.lang.reflect.Constructor; |
||||
|
||||
/** |
||||
* Constructors collection. |
||||
*/ |
||||
public class Ctors { |
||||
|
||||
protected final ClassDescriptor classDescriptor; |
||||
protected final CtorDescriptor[] allCtors; |
||||
protected CtorDescriptor defaultCtor; |
||||
|
||||
public Ctors(final ClassDescriptor classDescriptor) { |
||||
this.classDescriptor = classDescriptor; |
||||
this.allCtors = inspectConstructors(); |
||||
} |
||||
|
||||
/** |
||||
* Inspects all declared constructors of a target type. |
||||
*/ |
||||
protected CtorDescriptor[] inspectConstructors() { |
||||
Class type = classDescriptor.getType(); |
||||
Constructor[] ctors = type.getDeclaredConstructors(); |
||||
|
||||
CtorDescriptor[] allCtors = new CtorDescriptor[ctors.length]; |
||||
|
||||
for (int i = 0; i < ctors.length; i++) { |
||||
Constructor ctor = ctors[i]; |
||||
|
||||
CtorDescriptor ctorDescriptor = createCtorDescriptor(ctor); |
||||
allCtors[i] = ctorDescriptor; |
||||
|
||||
if (ctorDescriptor.isDefault()) { |
||||
defaultCtor = ctorDescriptor; |
||||
} |
||||
} |
||||
|
||||
return allCtors; |
||||
} |
||||
|
||||
/** |
||||
* Creates new {@link CtorDescriptor}. |
||||
*/ |
||||
protected CtorDescriptor createCtorDescriptor(final Constructor ctor) { |
||||
return new CtorDescriptor(classDescriptor, ctor); |
||||
} |
||||
|
||||
// ---------------------------------------------------------------- get
|
||||
|
||||
/** |
||||
* Returns default (no-args) constructor descriptor. |
||||
*/ |
||||
public CtorDescriptor getDefaultCtor() { |
||||
return defaultCtor; |
||||
} |
||||
|
||||
/** |
||||
* Finds constructor description that matches given argument types. |
||||
*/ |
||||
public CtorDescriptor getCtorDescriptor(final Class... args) { |
||||
ctors: |
||||
for (CtorDescriptor ctorDescriptor : allCtors) { |
||||
Class[] arg = ctorDescriptor.getParameters(); |
||||
|
||||
if (arg.length != args.length) { |
||||
continue; |
||||
} |
||||
|
||||
for (int j = 0; j < arg.length; j++) { |
||||
if (arg[j] != args[j]) { |
||||
continue ctors; |
||||
} |
||||
} |
||||
|
||||
return ctorDescriptor; |
||||
} |
||||
return null; |
||||
} |
||||
|
||||
/** |
||||
* Returns all constructor descriptors. |
||||
*/ |
||||
CtorDescriptor[] getAllCtorDescriptors() { |
||||
return allCtors; |
||||
} |
||||
|
||||
} |
@ -1,70 +0,0 @@
|
||||
// Copyright (c) 2003-present, Jodd Team (http://jodd.org)
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
package com.fr.third.jodd.introspector; |
||||
|
||||
/** |
||||
* Common descriptor stuff. |
||||
*/ |
||||
public abstract class Descriptor { |
||||
|
||||
protected final ClassDescriptor classDescriptor; |
||||
protected final boolean isPublic; |
||||
|
||||
protected Descriptor(final ClassDescriptor classDescriptor, final boolean isPublic) { |
||||
this.classDescriptor = classDescriptor; |
||||
this.isPublic = isPublic; |
||||
} |
||||
|
||||
/** |
||||
* Returns belonging class descriptor. |
||||
*/ |
||||
public ClassDescriptor getClassDescriptor() { |
||||
return classDescriptor; |
||||
} |
||||
|
||||
/** |
||||
* Returns <code>true</code> if descriptor content is public. |
||||
*/ |
||||
public boolean isPublic() { |
||||
return isPublic; |
||||
} |
||||
|
||||
/** |
||||
* Returns <code>true</code> if descriptor content matches required declared flag. |
||||
*/ |
||||
public boolean matchDeclared(final boolean declared) { |
||||
if (!declared) { |
||||
return isPublic; |
||||
} |
||||
return true; |
||||
} |
||||
|
||||
/** |
||||
* Returns the name of descriptors target. |
||||
*/ |
||||
public abstract String getName(); |
||||
|
||||
} |
@ -1,134 +0,0 @@
|
||||
// Copyright (c) 2003-present, Jodd Team (http://jodd.org)
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
package com.fr.third.jodd.introspector; |
||||
|
||||
import com.fr.third.jodd.util.ClassUtil; |
||||
|
||||
import java.lang.reflect.Field; |
||||
import java.lang.reflect.Type; |
||||
|
||||
/** |
||||
* Field descriptor. Holds additional field data, |
||||
* that might be specific to implementation class. |
||||
*/ |
||||
public class FieldDescriptor extends Descriptor { |
||||
|
||||
public static final FieldDescriptor[] EMPTY_ARRAY = new FieldDescriptor[0]; |
||||
|
||||
protected final Field field; |
||||
protected final Type type; |
||||
protected final Class rawType; |
||||
protected final Class rawComponentType; |
||||
protected final Class rawKeyComponentType; |
||||
protected final MapperFunction mapperFunction; |
||||
|
||||
/** |
||||
* Creates new field descriptor and resolve all additional field data. |
||||
* Also, forces access to a field. |
||||
*/ |
||||
public FieldDescriptor(final ClassDescriptor classDescriptor, final Field field) { |
||||
super(classDescriptor, ClassUtil.isPublic(field)); |
||||
this.field = field; |
||||
this.type = field.getGenericType(); |
||||
this.rawType = ClassUtil.getRawType(type, classDescriptor.getType()); |
||||
|
||||
final Class[] componentTypes = ClassUtil.getComponentTypes(type, classDescriptor.getType()); |
||||
if (componentTypes != null) { |
||||
this.rawComponentType = componentTypes[componentTypes.length - 1]; |
||||
this.rawKeyComponentType = componentTypes[0]; |
||||
} else { |
||||
this.rawComponentType = null; |
||||
this.rawKeyComponentType = null; |
||||
} |
||||
|
||||
// force access
|
||||
|
||||
ClassUtil.forceAccess(field); |
||||
|
||||
// mapper
|
||||
|
||||
final Mapper mapper = field.getAnnotation(Mapper.class); |
||||
|
||||
if (mapper != null) { |
||||
mapperFunction = MapperFunctionInstances.get().lookup(mapper.value()); |
||||
} else { |
||||
mapperFunction = null; |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Returns field name. |
||||
*/ |
||||
@Override |
||||
public String getName() { |
||||
return field.getName(); |
||||
} |
||||
|
||||
/** |
||||
* Returns field. |
||||
*/ |
||||
public Field getField() { |
||||
return field; |
||||
} |
||||
|
||||
/** |
||||
* Returns fields raw type. |
||||
*/ |
||||
public Class getRawType() { |
||||
return rawType; |
||||
} |
||||
|
||||
/** |
||||
* Returns fields raw component type. Returns <code>null</code> |
||||
* if field has no component type. |
||||
*/ |
||||
public Class getRawComponentType() { |
||||
return rawComponentType; |
||||
} |
||||
|
||||
/** |
||||
* Returns fields raw component type. Returns <code>null</code> |
||||
* if field has no component type. |
||||
*/ |
||||
public Class getRawKeyComponentType() { |
||||
return rawKeyComponentType; |
||||
} |
||||
|
||||
/** |
||||
* Resolves raw component type for given index. This value is NOT cached. |
||||
*/ |
||||
public Class[] resolveRawComponentTypes() { |
||||
return ClassUtil.getComponentTypes(type, classDescriptor.getType()); |
||||
} |
||||
|
||||
// ---------------------------------------------------------------- toString
|
||||
|
||||
@Override |
||||
public String toString() { |
||||
return classDescriptor.getType().getSimpleName() + '#' + field.getName(); |
||||
} |
||||
|
||||
} |
@ -1,130 +0,0 @@
|
||||
// Copyright (c) 2003-present, Jodd Team (http://jodd.org)
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
package com.fr.third.jodd.introspector; |
||||
|
||||
import com.fr.third.jodd.util.ClassUtil; |
||||
|
||||
import java.lang.reflect.Field; |
||||
import java.util.Arrays; |
||||
import java.util.Collections; |
||||
import java.util.Comparator; |
||||
import java.util.HashMap; |
||||
import java.util.Map; |
||||
|
||||
/** |
||||
* Collection of {@link FieldDescriptor field descriptors}. |
||||
*/ |
||||
public class Fields { |
||||
|
||||
protected final ClassDescriptor classDescriptor; |
||||
protected final Map<String, FieldDescriptor> fieldsMap; |
||||
|
||||
// cache
|
||||
private FieldDescriptor[] allFields; |
||||
|
||||
/** |
||||
* Creates new fields collection. |
||||
*/ |
||||
public Fields(final ClassDescriptor classDescriptor) { |
||||
this.classDescriptor = classDescriptor; |
||||
this.fieldsMap = inspectFields(); |
||||
} |
||||
|
||||
/** |
||||
* Inspects fields and returns map of {@link FieldDescriptor field descriptors}. |
||||
*/ |
||||
private Map<String, FieldDescriptor> inspectFields() { |
||||
if (classDescriptor.isSystemClass()) { |
||||
return emptyFields(); |
||||
} |
||||
final boolean scanAccessible = classDescriptor.isScanAccessible(); |
||||
final Class type = classDescriptor.getType(); |
||||
|
||||
final Field[] fields = scanAccessible ? ClassUtil.getAccessibleFields(type) : ClassUtil.getSupportedFields(type); |
||||
|
||||
final HashMap<String, FieldDescriptor> map = new HashMap<>(fields.length); |
||||
|
||||
for (final Field field : fields) { |
||||
final String fieldName = field.getName(); |
||||
|
||||
if (fieldName.equals("serialVersionUID")) { |
||||
continue; |
||||
} |
||||
|
||||
map.put(fieldName, createFieldDescriptor(field)); |
||||
} |
||||
|
||||
return map; |
||||
} |
||||
|
||||
/** |
||||
* Defines empty fields for special cases. |
||||
*/ |
||||
private Map<String, FieldDescriptor> emptyFields() { |
||||
allFields = FieldDescriptor.EMPTY_ARRAY; |
||||
return Collections.emptyMap(); |
||||
} |
||||
|
||||
/** |
||||
* Creates new {@code FieldDescriptor}. |
||||
*/ |
||||
protected FieldDescriptor createFieldDescriptor(final Field field) { |
||||
return new FieldDescriptor(classDescriptor, field); |
||||
} |
||||
|
||||
|
||||
// ---------------------------------------------------------------- get
|
||||
|
||||
/** |
||||
* Returns {@link FieldDescriptor field descriptor} for given field name |
||||
* or <code>null</code> if field does not exist. |
||||
*/ |
||||
public FieldDescriptor getFieldDescriptor(final String name) { |
||||
return fieldsMap.get(name); |
||||
} |
||||
|
||||
/** |
||||
* Returns all fields of this collection. Returns empty array |
||||
* if no fields exist. Initialized lazy. |
||||
*/ |
||||
public FieldDescriptor[] getAllFieldDescriptors() { |
||||
if (allFields == null) { |
||||
FieldDescriptor[] allFields = new FieldDescriptor[fieldsMap.size()]; |
||||
|
||||
int index = 0; |
||||
for (FieldDescriptor fieldDescriptor : fieldsMap.values()) { |
||||
allFields[index] = fieldDescriptor; |
||||
index++; |
||||
} |
||||
|
||||
Arrays.sort(allFields, Comparator.comparing(fd -> fd.getField().getName())); |
||||
|
||||
this.allFields = allFields; |
||||
} |
||||
return allFields; |
||||
} |
||||
|
||||
} |
@ -1,94 +0,0 @@
|
||||
// Copyright (c) 2003-present, Jodd Team (http://jodd.org)
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
package com.fr.third.jodd.introspector; |
||||
|
||||
import java.lang.reflect.InvocationTargetException; |
||||
|
||||
/** |
||||
* Unified getter property interface for both methods and fields. |
||||
*/ |
||||
public interface Getter { |
||||
|
||||
static Getter of(final MethodDescriptor methodDescriptor) { |
||||
|
||||
return new Getter() { |
||||
|
||||
@Override |
||||
public Object invokeGetter(final Object target) throws InvocationTargetException, IllegalAccessException { |
||||
return methodDescriptor.method.invoke(target); |
||||
} |
||||
|
||||
@Override |
||||
public Class getGetterRawType() { |
||||
return methodDescriptor.getRawReturnType(); |
||||
} |
||||
|
||||
@Override |
||||
public Class getGetterRawComponentType() { |
||||
return methodDescriptor.getRawReturnComponentType(); |
||||
} |
||||
|
||||
@Override |
||||
public Class getGetterRawKeyComponentType() { |
||||
return methodDescriptor.getRawReturnKeyComponentType(); |
||||
} |
||||
}; |
||||
} |
||||
|
||||
static Getter of(final FieldDescriptor fieldDescriptor) { |
||||
return new Getter() { |
||||
|
||||
@Override |
||||
public Object invokeGetter(final Object target) throws IllegalAccessException { |
||||
return fieldDescriptor.field.get(target); |
||||
} |
||||
|
||||
@Override |
||||
public Class getGetterRawType() { |
||||
return fieldDescriptor.getRawType(); |
||||
} |
||||
|
||||
@Override |
||||
public Class getGetterRawComponentType() { |
||||
return fieldDescriptor.getRawComponentType(); |
||||
} |
||||
|
||||
@Override |
||||
public Class getGetterRawKeyComponentType() { |
||||
return fieldDescriptor.getRawKeyComponentType(); |
||||
} |
||||
}; |
||||
} |
||||
|
||||
Object invokeGetter(Object target) throws InvocationTargetException, IllegalAccessException; |
||||
|
||||
Class getGetterRawType(); |
||||
|
||||
Class getGetterRawComponentType(); |
||||
|
||||
Class getGetterRawKeyComponentType(); |
||||
|
||||
} |
@ -1,43 +0,0 @@
|
||||
// Copyright (c) 2003-present, Jodd Team (http://jodd.org)
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
package com.fr.third.jodd.introspector; |
||||
|
||||
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; |
||||
|
||||
/** |
||||
* Value or type mapper. |
||||
* @see MapperFunction |
||||
*/ |
||||
@Documented |
||||
@Retention(value = RetentionPolicy.RUNTIME) |
||||
@Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER}) |
||||
public @interface Mapper { |
||||
Class<? extends MapperFunction> value(); |
||||
} |
@ -1,37 +0,0 @@
|
||||
// Copyright (c) 2003-present, Jodd Team (http://jodd.org)
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
package com.fr.third.jodd.introspector; |
||||
|
||||
import java.util.function.Function; |
||||
|
||||
/** |
||||
* Mapper function allows object to be converted before actually used - usually before injected using |
||||
* {@link com.fr.third.jodd.bean.BeanUtil}. |
||||
*/ |
||||
@FunctionalInterface |
||||
public interface MapperFunction<IN, OUT> extends Function<IN, OUT> { |
||||
|
||||
} |
@ -1,57 +0,0 @@
|
||||
// Copyright (c) 2003-present, Jodd Team (http://jodd.org)
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
package com.fr.third.jodd.introspector; |
||||
|
||||
import com.fr.third.jodd.cache.TypeCache; |
||||
import com.fr.third.jodd.util.ClassUtil; |
||||
|
||||
/** |
||||
* Simple cache of {@link MapperFunction} instances. |
||||
*/ |
||||
public class MapperFunctionInstances { |
||||
|
||||
private static final MapperFunctionInstances MAPPER_FUNCTION_INSTANCES = new MapperFunctionInstances(); |
||||
|
||||
/** |
||||
* Returns the instance. |
||||
*/ |
||||
public static MapperFunctionInstances get() { |
||||
return MAPPER_FUNCTION_INSTANCES; |
||||
} |
||||
|
||||
protected TypeCache<MapperFunction> typeCache = TypeCache.createDefault(); |
||||
|
||||
public MapperFunction lookup(final Class<? extends MapperFunction> mapperFunctionClass) { |
||||
return typeCache.get(mapperFunctionClass, (c) -> { |
||||
try { |
||||
return ClassUtil.newInstance(mapperFunctionClass); |
||||
} catch (final Exception ex) { |
||||
throw new IllegalArgumentException("Invalid mapper class " + c, ex); |
||||
} |
||||
}); |
||||
} |
||||
|
||||
} |
@ -1,193 +0,0 @@
|
||||
// Copyright (c) 2003-present, Jodd Team (http://jodd.org)
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
package com.fr.third.jodd.introspector; |
||||
|
||||
import com.fr.third.jodd.util.ClassUtil; |
||||
|
||||
import java.lang.reflect.Method; |
||||
import java.lang.reflect.Type; |
||||
|
||||
/** |
||||
* Method descriptor. Holds additional method data, |
||||
* that might be specific to implementation class. |
||||
*/ |
||||
public class MethodDescriptor extends Descriptor { |
||||
|
||||
private static final MethodParamDescriptor[] NO_PARAMS = new MethodParamDescriptor[0]; |
||||
|
||||
protected final Method method; |
||||
protected final Type returnType; |
||||
protected final Class rawReturnType; |
||||
protected final Class rawReturnComponentType; |
||||
protected final Class rawReturnKeyComponentType; |
||||
protected final MethodParamDescriptor[] parameters; |
||||
protected final MapperFunction mapperFunction; |
||||
|
||||
// protected final Function getterFunction;
|
||||
|
||||
public MethodDescriptor(final ClassDescriptor classDescriptor, final Method method) { |
||||
super(classDescriptor, ClassUtil.isPublic(method)); |
||||
this.method = method; |
||||
this.returnType = method.getGenericReturnType(); |
||||
this.rawReturnType = ClassUtil.getRawType(returnType, classDescriptor.getType()); |
||||
|
||||
final Class[] componentTypes = ClassUtil.getComponentTypes(returnType, classDescriptor.getType()); |
||||
if (componentTypes != null) { |
||||
this.rawReturnComponentType = componentTypes[componentTypes.length - 1]; |
||||
this.rawReturnKeyComponentType = componentTypes[0]; |
||||
} else { |
||||
this.rawReturnComponentType = null; |
||||
this.rawReturnKeyComponentType = null; |
||||
} |
||||
|
||||
// force access
|
||||
|
||||
ClassUtil.forceAccess(method); |
||||
|
||||
// mapper
|
||||
|
||||
final Mapper mapper = method.getAnnotation(Mapper.class); |
||||
|
||||
if (mapper != null) { |
||||
mapperFunction = MapperFunctionInstances.get().lookup(mapper.value()); |
||||
} else { |
||||
mapperFunction = null; |
||||
} |
||||
|
||||
// parameters
|
||||
|
||||
if (method.getParameterCount() == 0) { |
||||
parameters = NO_PARAMS; |
||||
} |
||||
else { |
||||
parameters = new MethodParamDescriptor[method.getParameterCount()]; |
||||
|
||||
Class[] params = method.getParameterTypes(); |
||||
Type[] genericParams = method.getGenericParameterTypes(); |
||||
|
||||
for (int i = 0; i < params.length; i++) { |
||||
final Class parameterType = params[i]; |
||||
final Class rawParameterType = genericParams.length == 0 ? |
||||
parameterType : |
||||
ClassUtil.getRawType(genericParams[i], classDescriptor.getType()); |
||||
final Class rawParameterComponentType = genericParams.length == 0 ? |
||||
null : |
||||
ClassUtil.getComponentType(genericParams[i], classDescriptor.getType(), -1); |
||||
|
||||
parameters[i] = new MethodParamDescriptor(parameterType, rawParameterType, rawParameterComponentType); |
||||
} |
||||
} |
||||
|
||||
// try {
|
||||
// MethodHandles.Lookup lookup = MethodHandles.lookup();
|
||||
// CallSite callSite = LambdaMetafactory.metafactory(lookup,
|
||||
// "apply",
|
||||
// MethodType.methodType(Function.class),
|
||||
// MethodType.methodType(Object.class, Object.class),
|
||||
// lookup.findVirtual(
|
||||
// classDescriptor.getType(),
|
||||
// method.getName(),
|
||||
// MethodType.methodType(method.getReturnType())),
|
||||
// MethodType.methodType(method.getReturnType(), classDescriptor.type)
|
||||
// );
|
||||
//
|
||||
// this.getterFunction = (Function) callSite.getTarget().invokeExact();
|
||||
// }
|
||||
// catch (Throwable ex) {
|
||||
// throw new IllegalArgumentException(ex);
|
||||
// }
|
||||
} |
||||
|
||||
/** |
||||
* Returns method name. |
||||
*/ |
||||
@Override |
||||
public String getName() { |
||||
return method.getName(); |
||||
} |
||||
|
||||
/** |
||||
* Returns method. |
||||
*/ |
||||
public Method getMethod() { |
||||
return method; |
||||
} |
||||
|
||||
/** |
||||
* Returns raw return type. |
||||
*/ |
||||
public Class getRawReturnType() { |
||||
return rawReturnType; |
||||
} |
||||
|
||||
/** |
||||
* Returns raw component type of return type. |
||||
* May be <code>null</code> if return type does not have |
||||
* components. |
||||
*/ |
||||
public Class getRawReturnComponentType() { |
||||
return rawReturnComponentType; |
||||
} |
||||
|
||||
/** |
||||
* Returns raw component type of return type. |
||||
* May be <code>null</code> if return type does not have |
||||
* components. |
||||
*/ |
||||
public Class getRawReturnKeyComponentType() { |
||||
return rawReturnKeyComponentType; |
||||
} |
||||
|
||||
/** |
||||
* Resolves raw return component types |
||||
* This value is NOT cached. |
||||
*/ |
||||
public Class[] resolveRawReturnComponentTypes() { |
||||
return ClassUtil.getComponentTypes(returnType, classDescriptor.getType()); |
||||
} |
||||
|
||||
/** |
||||
* Returns {@link MethodParamDescriptor method parameteres}. |
||||
*/ |
||||
public MethodParamDescriptor[] getParameters() { |
||||
return parameters; |
||||
} |
||||
|
||||
/** |
||||
* Returns number of parameters. |
||||
*/ |
||||
public int getParameterCount() { |
||||
return parameters.length; |
||||
} |
||||
|
||||
// ---------------------------------------------------------------- toString
|
||||
|
||||
@Override |
||||
public String toString() { |
||||
return classDescriptor.getType().getSimpleName() + '#' + method.getName() + "()"; |
||||
} |
||||
|
||||
} |
@ -1,53 +0,0 @@
|
||||
// Copyright (c) 2003-present, Jodd Team (http://jodd.org)
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
package com.fr.third.jodd.introspector; |
||||
|
||||
/** |
||||
* Method parameter descriptor. |
||||
*/ |
||||
public class MethodParamDescriptor { |
||||
protected final Class type; |
||||
protected final Class rawType; |
||||
protected final Class rawComponentType; |
||||
|
||||
public MethodParamDescriptor(final Class parameterType, final Class rawParameterType, final Class rawParameterComponentType) { |
||||
this.type = parameterType; |
||||
this.rawType = rawParameterType; |
||||
this.rawComponentType = rawParameterComponentType; |
||||
} |
||||
|
||||
public Class getType() { |
||||
return type; |
||||
} |
||||
|
||||
public Class getRawType() { |
||||
return rawType; |
||||
} |
||||
|
||||
public Class getRawComponentType() { |
||||
return rawComponentType; |
||||
} |
||||
} |
@ -1,162 +0,0 @@
|
||||
// Copyright (c) 2003-present, Jodd Team (http://jodd.org)
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
package com.fr.third.jodd.introspector; |
||||
|
||||
import com.fr.third.jodd.util.ArraysUtil; |
||||
import com.fr.third.jodd.util.ClassUtil; |
||||
|
||||
import java.lang.reflect.Method; |
||||
import java.util.ArrayList; |
||||
import java.util.Arrays; |
||||
import java.util.Collections; |
||||
import java.util.Comparator; |
||||
import java.util.HashMap; |
||||
import java.util.List; |
||||
|
||||
/** |
||||
* Methods collection. |
||||
*/ |
||||
public class Methods { |
||||
|
||||
protected final ClassDescriptor classDescriptor; |
||||
protected final HashMap<String, MethodDescriptor[]> methodsMap; |
||||
|
||||
// cache
|
||||
private MethodDescriptor[] allMethods; |
||||
|
||||
public Methods(final ClassDescriptor classDescriptor) { |
||||
this.classDescriptor = classDescriptor; |
||||
this.methodsMap = inspectMethods(); |
||||
} |
||||
|
||||
/** |
||||
* Inspects types methods and return map of {@link MethodDescriptor method descriptors}. |
||||
*/ |
||||
protected HashMap<String, MethodDescriptor[]> inspectMethods() { |
||||
boolean scanAccessible = classDescriptor.isScanAccessible(); |
||||
|
||||
if (classDescriptor.isSystemClass()) { |
||||
scanAccessible = false; |
||||
} |
||||
|
||||
final Class type = classDescriptor.getType(); |
||||
|
||||
final Method[] methods = scanAccessible ? ClassUtil.getAccessibleMethods(type) : ClassUtil.getSupportedMethods(type); |
||||
|
||||
final HashMap<String, MethodDescriptor[]> map = new HashMap<>(methods.length); |
||||
|
||||
for (final Method method : methods) { |
||||
final String methodName = method.getName(); |
||||
|
||||
MethodDescriptor[] mds = map.get(methodName); |
||||
|
||||
if (mds == null) { |
||||
mds = new MethodDescriptor[1]; |
||||
} else { |
||||
mds = ArraysUtil.resize(mds, mds.length + 1); |
||||
} |
||||
|
||||
map.put(methodName, mds); |
||||
|
||||
mds[mds.length - 1] = createMethodDescriptor(method); |
||||
} |
||||
|
||||
return map; |
||||
} |
||||
|
||||
/** |
||||
* Creates new {@code MethodDescriptor}. |
||||
*/ |
||||
protected MethodDescriptor createMethodDescriptor(final Method method) { |
||||
return new MethodDescriptor(classDescriptor, method); |
||||
} |
||||
|
||||
|
||||
// ---------------------------------------------------------------- get
|
||||
|
||||
/** |
||||
* Returns a method that matches given name and parameter types. |
||||
* Returns <code>null</code> if method is not found. |
||||
*/ |
||||
public MethodDescriptor getMethodDescriptor(final String name, final Class[] paramTypes) { |
||||
final MethodDescriptor[] methodDescriptors = methodsMap.get(name); |
||||
if (methodDescriptors == null) { |
||||
return null; |
||||
} |
||||
for (MethodDescriptor methodDescriptor : methodDescriptors) { |
||||
final Method m = methodDescriptor.getMethod(); |
||||
if (ClassUtil.compareParameters(m.getParameterTypes(), paramTypes)) { |
||||
return methodDescriptor; |
||||
} |
||||
} |
||||
return null; |
||||
} |
||||
|
||||
/** |
||||
* Returns method descriptor for given name. If more then one methods with |
||||
* the same name exists, one method will be returned (not determined which one). |
||||
* Returns <code>null</code> if no method exist in this collection by given name. |
||||
* @see #getMethodDescriptor(String, Class[]) |
||||
*/ |
||||
public MethodDescriptor getMethodDescriptor(final String name) { |
||||
final MethodDescriptor[] methodDescriptors = methodsMap.get(name); |
||||
if (methodDescriptors == null) { |
||||
return null; |
||||
} |
||||
if (methodDescriptors.length != 1) { |
||||
throw new IllegalArgumentException("Method name not unique: " + name); |
||||
} |
||||
return methodDescriptors[0]; |
||||
} |
||||
|
||||
/** |
||||
* Returns all methods for given name. Returns <code>null</code> if method not found. |
||||
*/ |
||||
public MethodDescriptor[] getAllMethodDescriptors(final String name) { |
||||
return methodsMap.get(name); |
||||
} |
||||
|
||||
/** |
||||
* Returns all methods. Cached. Lazy. |
||||
*/ |
||||
public MethodDescriptor[] getAllMethodDescriptors() { |
||||
if (allMethods == null) { |
||||
final List<MethodDescriptor> allMethodsList = new ArrayList<>(); |
||||
|
||||
for (MethodDescriptor[] methodDescriptors : methodsMap.values()) { |
||||
Collections.addAll(allMethodsList, methodDescriptors); |
||||
} |
||||
|
||||
final MethodDescriptor[] allMethods = allMethodsList.toArray(new MethodDescriptor[0]); |
||||
|
||||
Arrays.sort(allMethods, Comparator.comparing(md -> md.getMethod().getName())); |
||||
|
||||
this.allMethods = allMethods; |
||||
} |
||||
return allMethods; |
||||
} |
||||
|
||||
} |
@ -1,255 +0,0 @@
|
||||
// Copyright (c) 2003-present, Jodd Team (http://jodd.org)
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
package com.fr.third.jodd.introspector; |
||||
|
||||
import com.fr.third.jodd.util.ClassUtil; |
||||
|
||||
import java.lang.reflect.Field; |
||||
import java.lang.reflect.Method; |
||||
import java.lang.reflect.Modifier; |
||||
import java.util.Arrays; |
||||
import java.util.Comparator; |
||||
import java.util.HashMap; |
||||
|
||||
import static com.fr.third.jodd.util.ClassUtil.METHOD_GET_PREFIX; |
||||
import static com.fr.third.jodd.util.ClassUtil.METHOD_IS_PREFIX; |
||||
|
||||
/** |
||||
* Bean properties collection. Property in Java is defined as a pair of |
||||
* read and write method. In Jodd, property can be extended with field |
||||
* definition. Moreover, properties will include just single fields. |
||||
* This behavior can be controlled via {@link ClassDescriptor}. |
||||
*/ |
||||
public class Properties { |
||||
|
||||
protected final ClassDescriptor classDescriptor; |
||||
protected final HashMap<String, PropertyDescriptor> propertyDescriptors; |
||||
|
||||
// cache
|
||||
private PropertyDescriptor[] allProperties; |
||||
|
||||
public Properties(final ClassDescriptor classDescriptor) { |
||||
this.classDescriptor = classDescriptor; |
||||
this.propertyDescriptors = inspectProperties(); |
||||
} |
||||
|
||||
/** |
||||
* Inspects all properties of target type. |
||||
*/ |
||||
protected HashMap<String, PropertyDescriptor> inspectProperties() { |
||||
boolean scanAccessible = classDescriptor.isScanAccessible(); |
||||
Class type = classDescriptor.getType(); |
||||
|
||||
HashMap<String, PropertyDescriptor> map = new HashMap<>(); |
||||
|
||||
Method[] methods = scanAccessible ? ClassUtil.getAccessibleMethods(type) : ClassUtil.getSupportedMethods(type); |
||||
|
||||
for (int iteration = 0; iteration < 2; iteration++) { |
||||
// first find the getters, and then the setters!
|
||||
for (Method method : methods) { |
||||
if (Modifier.isStatic(method.getModifiers())) { |
||||
continue; // ignore static methods
|
||||
} |
||||
|
||||
boolean add = false; |
||||
boolean issetter = false; |
||||
|
||||
String propertyName; |
||||
|
||||
if (iteration == 0) { |
||||
propertyName = ClassUtil.getBeanPropertyGetterName(method); |
||||
if (propertyName != null) { |
||||
add = true; |
||||
issetter = false; |
||||
} |
||||
} else { |
||||
propertyName = ClassUtil.getBeanPropertySetterName(method); |
||||
if (propertyName != null) { |
||||
add = true; |
||||
issetter = true; |
||||
} |
||||
} |
||||
|
||||
if (add) { |
||||
MethodDescriptor methodDescriptor = classDescriptor.getMethodDescriptor(method.getName(), method.getParameterTypes(), true); |
||||
addProperty(map, propertyName, methodDescriptor, issetter); |
||||
} |
||||
} |
||||
} |
||||
|
||||
if (classDescriptor.isIncludeFieldsAsProperties()) { |
||||
FieldDescriptor[] fieldDescriptors = classDescriptor.getAllFieldDescriptors(); |
||||
String[] prefix = classDescriptor.getPropertyFieldPrefix(); |
||||
|
||||
for (FieldDescriptor fieldDescriptor : fieldDescriptors) { |
||||
Field field = fieldDescriptor.getField(); |
||||
|
||||
if (Modifier.isStatic(field.getModifiers())) { |
||||
continue; // ignore static fields
|
||||
} |
||||
|
||||
String name = field.getName(); |
||||
|
||||
if (prefix != null) { |
||||
for (String p : prefix) { |
||||
if (!name.startsWith(p)) { |
||||
continue; |
||||
} |
||||
name = name.substring(p.length()); |
||||
break; |
||||
} |
||||
} |
||||
|
||||
if (!map.containsKey(name)) { |
||||
// add missing field as a potential property
|
||||
map.put(name, createPropertyDescriptor(name, fieldDescriptor)); |
||||
} |
||||
} |
||||
|
||||
} |
||||
|
||||
return map; |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Adds a setter and/or getter method to the property. |
||||
* If property is already defined, the new, updated, definition will be created. |
||||
*/ |
||||
protected void addProperty(final HashMap<String, PropertyDescriptor> map, final String name, final MethodDescriptor methodDescriptor, final boolean isSetter) { |
||||
MethodDescriptor setterMethod = isSetter ? methodDescriptor : null; |
||||
MethodDescriptor getterMethod = isSetter ? null : methodDescriptor; |
||||
|
||||
PropertyDescriptor existing = map.get(name); |
||||
|
||||
if (existing == null) { |
||||
// new property, just add it
|
||||
PropertyDescriptor propertyDescriptor = createPropertyDescriptor(name, getterMethod, setterMethod); |
||||
|
||||
map.put(name, propertyDescriptor); |
||||
return; |
||||
} |
||||
|
||||
// property exist
|
||||
|
||||
if (!isSetter) { |
||||
// use existing setter
|
||||
setterMethod = existing.getWriteMethodDescriptor(); |
||||
|
||||
// check existing
|
||||
MethodDescriptor existingMethodDescriptor = existing.getReadMethodDescriptor(); |
||||
if (existingMethodDescriptor != null) { |
||||
// check for special case of double get/is
|
||||
|
||||
// getter with the same name already exist
|
||||
String methodName = methodDescriptor.getMethod().getName(); |
||||
String existingMethodName = existingMethodDescriptor.getMethod().getName(); |
||||
|
||||
if ( |
||||
existingMethodName.startsWith(METHOD_IS_PREFIX) && |
||||
methodName.startsWith(METHOD_GET_PREFIX)) { |
||||
|
||||
// ignore getter when ister exist
|
||||
return; |
||||
} |
||||
} |
||||
} else { |
||||
// setter
|
||||
// use existing getter
|
||||
getterMethod = existing.getReadMethodDescriptor(); |
||||
|
||||
if (getterMethod != null) { |
||||
Class returnType = getterMethod.getMethod().getReturnType(); |
||||
|
||||
if (setterMethod != null) { |
||||
Class parameterType = setterMethod.getMethod().getParameterTypes()[0]; |
||||
|
||||
if (returnType != parameterType) { |
||||
// getter's type is different then setter's
|
||||
return; |
||||
} |
||||
|
||||
} |
||||
} |
||||
} |
||||
|
||||
PropertyDescriptor propertyDescriptor = createPropertyDescriptor(name, getterMethod, setterMethod); |
||||
|
||||
map.put(name, propertyDescriptor); |
||||
} |
||||
|
||||
/** |
||||
* Creates new {@link PropertyDescriptor}. Note that this method may be called |
||||
* up to three times (depends on use case) for the same property. Each time when |
||||
* a property is updated, a new definition is created with updated information. |
||||
*/ |
||||
protected PropertyDescriptor createPropertyDescriptor(final String name, final MethodDescriptor getterMethod, final MethodDescriptor setterMethod) { |
||||
return new PropertyDescriptor(classDescriptor, name, getterMethod, setterMethod); |
||||
} |
||||
|
||||
/** |
||||
* Creates new field-only {@link PropertyDescriptor}. It will be invoked only once. |
||||
*/ |
||||
protected PropertyDescriptor createPropertyDescriptor(final String name, final FieldDescriptor fieldDescriptor) { |
||||
return new PropertyDescriptor(classDescriptor, name, fieldDescriptor); |
||||
} |
||||
|
||||
// ---------------------------------------------------------------- get
|
||||
|
||||
/** |
||||
* Returns {@link PropertyDescriptor property descriptor}. |
||||
*/ |
||||
public PropertyDescriptor getPropertyDescriptor(final String name) { |
||||
return propertyDescriptors.get(name); |
||||
} |
||||
|
||||
/** |
||||
* Returns all property descriptors. |
||||
* Properties are sorted by name. |
||||
*/ |
||||
public PropertyDescriptor[] getAllPropertyDescriptors() { |
||||
if (allProperties == null) { |
||||
PropertyDescriptor[] allProperties = new PropertyDescriptor[propertyDescriptors.size()]; |
||||
|
||||
int index = 0; |
||||
for (PropertyDescriptor propertyDescriptor : propertyDescriptors.values()) { |
||||
allProperties[index] = propertyDescriptor; |
||||
index++; |
||||
} |
||||
|
||||
Arrays.sort(allProperties, new Comparator<PropertyDescriptor>() { |
||||
@Override |
||||
public int compare(final PropertyDescriptor pd1, final PropertyDescriptor pd2) { |
||||
return pd1.getName().compareTo(pd2.getName()); |
||||
} |
||||
}); |
||||
|
||||
this.allProperties = allProperties; |
||||
} |
||||
return allProperties; |
||||
} |
||||
|
||||
} |
@ -1,313 +0,0 @@
|
||||
// Copyright (c) 2003-present, Jodd Team (http://jodd.org)
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
package com.fr.third.jodd.introspector; |
||||
|
||||
/** |
||||
* Property descriptor. It consist of read, write and field descriptor. |
||||
* Only one of those three descriptors may exist. |
||||
*/ |
||||
public class PropertyDescriptor extends Descriptor { |
||||
|
||||
protected final String name; |
||||
protected final MethodDescriptor readMethodDescriptor; |
||||
protected final MethodDescriptor writeMethodDescriptor; |
||||
protected final FieldDescriptor fieldDescriptor; |
||||
|
||||
/** |
||||
* Creates field-only property descriptor. |
||||
*/ |
||||
public PropertyDescriptor(final ClassDescriptor classDescriptor, final String propertyName, final FieldDescriptor fieldDescriptor) { |
||||
super(classDescriptor, false); |
||||
this.name = propertyName; |
||||
this.readMethodDescriptor = null; |
||||
this.writeMethodDescriptor = null; |
||||
this.fieldDescriptor = fieldDescriptor; |
||||
} |
||||
|
||||
/** |
||||
* Creates property descriptor. |
||||
*/ |
||||
public PropertyDescriptor(final ClassDescriptor classDescriptor, final String propertyName, final MethodDescriptor readMethod, final MethodDescriptor writeMethod) { |
||||
super(classDescriptor, |
||||
((readMethod == null) || readMethod.isPublic()) & (writeMethod == null || writeMethod.isPublic()) |
||||
); |
||||
this.name = propertyName; |
||||
this.readMethodDescriptor = readMethod; |
||||
this.writeMethodDescriptor = writeMethod; |
||||
|
||||
if (classDescriptor.isExtendedProperties()) { |
||||
String[] prefix = classDescriptor.getPropertyFieldPrefix(); |
||||
|
||||
FieldDescriptor fd = null; |
||||
|
||||
if (prefix != null) { |
||||
for (String p : prefix) { |
||||
fd = findField(p + propertyName); |
||||
|
||||
if (fd != null) { |
||||
break; |
||||
} |
||||
} |
||||
} |
||||
else { |
||||
fd = findField(propertyName); |
||||
} |
||||
|
||||
this.fieldDescriptor = fd; |
||||
} else { |
||||
this.fieldDescriptor = null; |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Locates property field. Field is being searched also in all |
||||
* superclasses of current class. |
||||
*/ |
||||
protected FieldDescriptor findField(final String fieldName) { |
||||
FieldDescriptor fieldDescriptor = classDescriptor.getFieldDescriptor(fieldName, true); |
||||
|
||||
if (fieldDescriptor != null) { |
||||
return fieldDescriptor; |
||||
} |
||||
|
||||
// field descriptor not found in this class
|
||||
// try to locate it in the superclasses
|
||||
|
||||
Class[] superclasses = classDescriptor.getAllSuperclasses(); |
||||
|
||||
for (Class superclass : superclasses) { |
||||
|
||||
ClassDescriptor classDescriptor = ClassIntrospector.get().lookup(superclass); |
||||
|
||||
fieldDescriptor = classDescriptor.getFieldDescriptor(fieldName, true); |
||||
|
||||
if (fieldDescriptor != null) { |
||||
return fieldDescriptor; |
||||
} |
||||
} |
||||
|
||||
// nothing found
|
||||
return null; |
||||
} |
||||
|
||||
/** |
||||
* Returns property name. |
||||
*/ |
||||
@Override |
||||
public String getName() { |
||||
return name; |
||||
} |
||||
|
||||
/** |
||||
* Returns read method of this property. |
||||
* May be <code>null</code> if read method is not defined. |
||||
*/ |
||||
public MethodDescriptor getReadMethodDescriptor() { |
||||
return readMethodDescriptor; |
||||
} |
||||
|
||||
/** |
||||
* Returns write method of this property. |
||||
* May be <code>null</code> for read-only properties. |
||||
*/ |
||||
public MethodDescriptor getWriteMethodDescriptor() { |
||||
return writeMethodDescriptor; |
||||
} |
||||
|
||||
/** |
||||
* Returns the associated field of this property. |
||||
* May be <code>null</code> if properties are not enhanced by field description. |
||||
*/ |
||||
public FieldDescriptor getFieldDescriptor() { |
||||
return fieldDescriptor; |
||||
} |
||||
|
||||
/** |
||||
* Returns <code>true</code> if this is an extended property with |
||||
* only field definition and without getter and setter. |
||||
*/ |
||||
public boolean isFieldOnly() { |
||||
return (readMethodDescriptor == null) && (writeMethodDescriptor == null); |
||||
} |
||||
|
||||
/** |
||||
* Returns <code>true</code> if this property has only a getter method. |
||||
*/ |
||||
public boolean isGetterOnly() { |
||||
return (fieldDescriptor == null) && (writeMethodDescriptor == null); |
||||
} |
||||
|
||||
/** |
||||
* Returns <code>true</code> if this property has only a setter method. |
||||
*/ |
||||
public boolean isSetterOnly() { |
||||
return (fieldDescriptor == null) && (readMethodDescriptor == null); |
||||
} |
||||
|
||||
// ---------------------------------------------------------------- type
|
||||
|
||||
protected Class type; |
||||
|
||||
/** |
||||
* Returns property type. Raw types are detected. |
||||
*/ |
||||
public Class getType() { |
||||
if (type == null) { |
||||
if (fieldDescriptor != null) { |
||||
type = fieldDescriptor.getRawType(); |
||||
} |
||||
else if (readMethodDescriptor != null) { |
||||
type = getGetter(true).getGetterRawType(); |
||||
//type = readMethodDescriptor.getGetterRawType();
|
||||
} |
||||
else if (writeMethodDescriptor != null) { |
||||
type = getSetter(true).getSetterRawType(); |
||||
//type = writeMethodDescriptor.getSetterRawType();
|
||||
} |
||||
} |
||||
|
||||
return type; |
||||
} |
||||
|
||||
// ---------------------------------------------------------------- getters & setters
|
||||
|
||||
protected Getter[] getters; |
||||
protected Setter[] setters; |
||||
|
||||
/** |
||||
* Returns {@link Getter}. May return <code>null</code> |
||||
* if no matched getter is found. |
||||
*/ |
||||
public Getter getGetter(final boolean declared) { |
||||
if (getters == null) { |
||||
getters = new Getter[] { |
||||
createGetter(false), |
||||
createGetter(true), |
||||
}; |
||||
} |
||||
|
||||
return getters[declared ? 1 : 0]; |
||||
} |
||||
|
||||
/** |
||||
* Creates a {@link Getter}. |
||||
*/ |
||||
protected Getter createGetter(final boolean declared) { |
||||
if (readMethodDescriptor != null) { |
||||
if (readMethodDescriptor.matchDeclared(declared)) { |
||||
return Getter.of(readMethodDescriptor); |
||||
} |
||||
} |
||||
if (fieldDescriptor != null) { |
||||
if (fieldDescriptor.matchDeclared(declared)) { |
||||
return Getter.of(fieldDescriptor); |
||||
} |
||||
} |
||||
return null; |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Returns {@link Setter}. May return <code>null</code> |
||||
* if no matched setter is found. |
||||
*/ |
||||
public Setter getSetter(final boolean declared) { |
||||
if (setters == null) { |
||||
setters = new Setter[] { |
||||
createSetter(false), |
||||
createSetter(true), |
||||
}; |
||||
} |
||||
|
||||
return setters[declared ? 1 : 0]; |
||||
} |
||||
|
||||
/** |
||||
* Creates a {@link Setter}. |
||||
*/ |
||||
protected Setter createSetter(final boolean declared) { |
||||
if (writeMethodDescriptor != null) { |
||||
if (writeMethodDescriptor.matchDeclared(declared)) { |
||||
return Setter.of(writeMethodDescriptor); |
||||
} |
||||
} |
||||
if (fieldDescriptor != null) { |
||||
if (fieldDescriptor.matchDeclared(declared)) { |
||||
return Setter.of(fieldDescriptor); |
||||
} |
||||
} |
||||
return null; |
||||
} |
||||
|
||||
// ---------------------------------------------------------------- resolvers
|
||||
|
||||
/** |
||||
* Resolves key type for given property descriptor. |
||||
*/ |
||||
public Class resolveKeyType(final boolean declared) { |
||||
Class keyType = null; |
||||
|
||||
Getter getter = getGetter(declared); |
||||
|
||||
if (getter != null) { |
||||
keyType = getter.getGetterRawKeyComponentType(); |
||||
} |
||||
|
||||
if (keyType == null) { |
||||
FieldDescriptor fieldDescriptor = getFieldDescriptor(); |
||||
|
||||
if (fieldDescriptor != null) { |
||||
keyType = fieldDescriptor.getRawKeyComponentType(); |
||||
} |
||||
} |
||||
|
||||
return keyType; |
||||
} |
||||
|
||||
/** |
||||
* Resolves component type for given property descriptor. |
||||
*/ |
||||
public Class resolveComponentType(final boolean declared) { |
||||
Class componentType = null; |
||||
|
||||
Getter getter = getGetter(declared); |
||||
|
||||
if (getter != null) { |
||||
componentType = getter.getGetterRawComponentType(); |
||||
} |
||||
|
||||
if (componentType == null) { |
||||
FieldDescriptor fieldDescriptor = getFieldDescriptor(); |
||||
|
||||
if (fieldDescriptor != null) { |
||||
componentType = fieldDescriptor.getRawComponentType(); |
||||
} |
||||
} |
||||
|
||||
return componentType; |
||||
} |
||||
|
||||
} |
@ -1,90 +0,0 @@
|
||||
// Copyright (c) 2003-present, Jodd Team (http://jodd.org)
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
package com.fr.third.jodd.introspector; |
||||
|
||||
import java.lang.reflect.InvocationTargetException; |
||||
|
||||
/** |
||||
* Unified setter property interface for both methods and fields. |
||||
*/ |
||||
public interface Setter { |
||||
|
||||
static Setter of(final MethodDescriptor methodDescriptor) { |
||||
return new Setter() { |
||||
@Override |
||||
public void invokeSetter(final Object target, final Object argument) throws InvocationTargetException, IllegalAccessException { |
||||
methodDescriptor.method.invoke(target, argument); |
||||
} |
||||
|
||||
@Override |
||||
public Class getSetterRawType() { |
||||
return methodDescriptor.getParameters()[0].getRawType(); |
||||
} |
||||
|
||||
@Override |
||||
public Class getSetterRawComponentType() { |
||||
return methodDescriptor.getParameters()[0].getRawComponentType(); |
||||
} |
||||
|
||||
@Override |
||||
public MapperFunction getMapperFunction() { |
||||
return methodDescriptor.mapperFunction; |
||||
} |
||||
}; |
||||
} |
||||
|
||||
static Setter of(final FieldDescriptor fieldDescriptor) { |
||||
return new Setter() { |
||||
@Override |
||||
public void invokeSetter(final Object target, final Object argument) throws IllegalAccessException { |
||||
fieldDescriptor.field.set(target, argument); |
||||
} |
||||
|
||||
@Override |
||||
public Class getSetterRawType() { |
||||
return fieldDescriptor.getRawType(); |
||||
} |
||||
|
||||
@Override |
||||
public Class getSetterRawComponentType() { |
||||
return fieldDescriptor.getRawComponentType(); |
||||
} |
||||
|
||||
@Override |
||||
public MapperFunction getMapperFunction() { |
||||
return fieldDescriptor.mapperFunction; |
||||
} |
||||
}; |
||||
} |
||||
|
||||
void invokeSetter(Object target, Object argument) throws IllegalAccessException, InvocationTargetException; |
||||
|
||||
Class getSetterRawType(); |
||||
|
||||
Class getSetterRawComponentType(); |
||||
|
||||
MapperFunction getMapperFunction(); |
||||
} |
@ -1,29 +0,0 @@
|
||||
// Copyright (c) 2003-present, Jodd Team (http://jodd.org)
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
/** |
||||
* Very fast reflection introspector. |
||||
*/ |
||||
package com.fr.third.jodd.introspector; |
@ -1,121 +0,0 @@
|
||||
// Copyright (c) 2003-present, Jodd Team (http://jodd.org)
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
package com.fr.third.jodd.io; |
||||
|
||||
import java.io.Closeable; |
||||
import java.io.Flushable; |
||||
import java.io.IOException; |
||||
import java.io.Writer; |
||||
import java.nio.CharBuffer; |
||||
|
||||
/** |
||||
* Appendable writer adapter. |
||||
*/ |
||||
public class AppendableWriter extends Writer { |
||||
|
||||
private final Appendable appendable; |
||||
private final boolean flushable; |
||||
private boolean closed; |
||||
|
||||
public AppendableWriter(final Appendable appendable) { |
||||
this.appendable = appendable; |
||||
this.flushable = appendable instanceof Flushable; |
||||
this.closed = false; |
||||
} |
||||
|
||||
@Override |
||||
public void write(final char[] cbuf, final int off, final int len) throws IOException { |
||||
checkNotClosed(); |
||||
appendable.append(CharBuffer.wrap(cbuf), off, off + len); |
||||
} |
||||
|
||||
@Override |
||||
public void write(final int c) throws IOException { |
||||
checkNotClosed(); |
||||
appendable.append((char) c); |
||||
} |
||||
|
||||
@Override |
||||
public Writer append(final char c) throws IOException { |
||||
checkNotClosed(); |
||||
appendable.append(c); |
||||
return this; |
||||
} |
||||
|
||||
@Override |
||||
public Writer append(final CharSequence csq, final int start, final int end) throws IOException { |
||||
checkNotClosed(); |
||||
appendable.append(csq, start, end); |
||||
return this; |
||||
} |
||||
|
||||
@Override |
||||
public Writer append(final CharSequence csq) throws IOException { |
||||
checkNotClosed(); |
||||
appendable.append(csq); |
||||
return this; |
||||
} |
||||
|
||||
@Override |
||||
public void write(final String str, final int off, final int len) throws IOException { |
||||
checkNotClosed(); |
||||
appendable.append(str, off, off + len); |
||||
} |
||||
|
||||
@Override |
||||
public void write(final String str) throws IOException { |
||||
appendable.append(str); |
||||
} |
||||
|
||||
@Override |
||||
public void write(final char[] cbuf) throws IOException { |
||||
appendable.append(CharBuffer.wrap(cbuf)); |
||||
} |
||||
|
||||
@Override |
||||
public void flush() throws IOException { |
||||
checkNotClosed(); |
||||
if (flushable) { |
||||
((Flushable) appendable).flush(); |
||||
} |
||||
} |
||||
|
||||
private void checkNotClosed() throws IOException { |
||||
if (closed) { |
||||
throw new IOException("Cannot write to closed writer " + this); |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
public void close() throws IOException { |
||||
if (!closed) { |
||||
flush(); |
||||
if (appendable instanceof Closeable) { |
||||
((Closeable) appendable).close(); |
||||
} |
||||
closed = true; |
||||
} |
||||
} |
||||
} |
@ -1,60 +0,0 @@
|
||||
// Copyright (c) 2003-present, Jodd Team (http://jodd.org)
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
package com.fr.third.jodd.io; |
||||
|
||||
import java.io.Reader; |
||||
import java.nio.CharBuffer; |
||||
|
||||
/** |
||||
* Reader that wraps a <code>CharBuffer</code>. |
||||
*/ |
||||
public class CharBufferReader extends Reader { |
||||
|
||||
private final CharBuffer charBuffer; |
||||
|
||||
public CharBufferReader(final CharBuffer charBuffer) { |
||||
// duplicate so to allow to move independently,
|
||||
// but share the same underlying data.
|
||||
this.charBuffer = charBuffer.duplicate(); |
||||
} |
||||
|
||||
@Override |
||||
public int read(final char[] chars, final int offset, final int length) { |
||||
int read = Math.min(charBuffer.remaining(), length); |
||||
charBuffer.get(chars, offset, read); |
||||
return read; |
||||
} |
||||
|
||||
@Override |
||||
public int read() { |
||||
return charBuffer.position() < charBuffer.limit() ? charBuffer.get() : -1; |
||||
} |
||||
|
||||
@Override |
||||
public void close() { |
||||
} |
||||
|
||||
} |
@ -1,146 +0,0 @@
|
||||
// Copyright (c) 2003-present, Jodd Team (http://jodd.org)
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
package com.fr.third.jodd.io; |
||||
|
||||
import com.fr.third.jodd.util.StringUtil; |
||||
import com.fr.third.jodd.buffer.FastByteBuffer; |
||||
|
||||
import java.io.ByteArrayOutputStream; |
||||
import java.io.IOException; |
||||
import java.io.OutputStream; |
||||
|
||||
/** |
||||
* This class implements an {@link OutputStream} in which the data is |
||||
* written into a byte array. The buffer automatically grows as data |
||||
* is written to it. |
||||
* <p> |
||||
* The data can be retrieved using {@link #toByteArray()} and {@link #toString}. |
||||
* <p> |
||||
* Closing a {@link FastByteArrayOutputStream} has no effect. The methods in |
||||
* this class can be called after the stream has been closed without |
||||
* generating an {@link IOException}. |
||||
* <p> |
||||
* This is an alternative implementation of the {@code java.io.FastByteArrayOutputStream} |
||||
* class. The original implementation only allocates 32 bytes at the beginning. |
||||
* As this class is designed for heavy duty it starts at 1024 bytes. In contrast |
||||
* to the original it doesn't reallocate the whole memory block but allocates |
||||
* additional buffers. This way no buffers need to be garbage collected and |
||||
* the contents don't have to be copied to the new buffer. This class is |
||||
* designed to behave exactly like the original. The only exception is the |
||||
* deprecated {@code java.io.FastByteArrayOutputStream#toString(int)} method that has been ignored. |
||||
*/ |
||||
public class FastByteArrayOutputStream extends OutputStream { |
||||
|
||||
private final FastByteBuffer buffer; |
||||
|
||||
/** |
||||
* Creates a new byte array {@link OutputStream}. The buffer capacity is |
||||
* initially 1024 bytes, though its size increases if necessary. |
||||
*/ |
||||
public FastByteArrayOutputStream() { |
||||
this(1024); |
||||
} |
||||
|
||||
/** |
||||
* Creates a new byte array output stream, with a buffer capacity of |
||||
* the specified size, in bytes. |
||||
* |
||||
* @param size the initial size. |
||||
* @throws IllegalArgumentException if size is negative. |
||||
*/ |
||||
public FastByteArrayOutputStream(final int size) { |
||||
buffer = new FastByteBuffer(size); |
||||
} |
||||
|
||||
/** |
||||
* @see OutputStream#write(byte[], int, int) |
||||
*/ |
||||
@Override |
||||
public void write(final byte[] b, final int off, final int len) { |
||||
buffer.append(b, off, len); |
||||
} |
||||
|
||||
/** |
||||
* Writes single byte. |
||||
*/ |
||||
@Override |
||||
public void write(final int b) { |
||||
buffer.append((byte) b); |
||||
} |
||||
|
||||
/** |
||||
* @see ByteArrayOutputStream#size() |
||||
*/ |
||||
public int size() { |
||||
return buffer.size(); |
||||
} |
||||
|
||||
/** |
||||
* Closing a {@link FastByteArrayOutputStream} has no effect. The methods in |
||||
* this class can be called after the stream has been closed without |
||||
* generating an {@link IOException}. |
||||
*/ |
||||
@Override |
||||
public void close() { |
||||
//nop
|
||||
} |
||||
|
||||
/** |
||||
* @see ByteArrayOutputStream#reset() |
||||
*/ |
||||
public void reset() { |
||||
buffer.clear(); |
||||
} |
||||
|
||||
/** |
||||
* @see ByteArrayOutputStream#writeTo(OutputStream) |
||||
*/ |
||||
public void writeTo(final OutputStream out) throws IOException { |
||||
out.write(buffer.toArray()); |
||||
} |
||||
|
||||
/** |
||||
* @see ByteArrayOutputStream#toByteArray() |
||||
*/ |
||||
public byte[] toByteArray() { |
||||
return buffer.toArray(); |
||||
} |
||||
|
||||
/** |
||||
* @see ByteArrayOutputStream#toString() |
||||
*/ |
||||
@Override |
||||
public String toString() { |
||||
return new String(toByteArray()); |
||||
} |
||||
|
||||
/** |
||||
* @see ByteArrayOutputStream#toString(String) |
||||
*/ |
||||
public String toString(final String enc) { |
||||
return StringUtil.newString(toByteArray(), enc); |
||||
} |
||||
} |
@ -1,134 +0,0 @@
|
||||
// Copyright (c) 2003-present, Jodd Team (http://jodd.org)
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
package com.fr.third.jodd.io; |
||||
|
||||
import com.fr.third.jodd.buffer.FastCharBuffer; |
||||
|
||||
import java.io.CharArrayWriter; |
||||
import java.io.IOException; |
||||
import java.io.Writer; |
||||
|
||||
/** |
||||
* Similar to {@link FastByteArrayOutputStream} but for {@link Writer}. |
||||
*/ |
||||
public class FastCharArrayWriter extends Writer { |
||||
|
||||
private final FastCharBuffer buffer; |
||||
|
||||
/** |
||||
* Creates a new writer. The buffer capacity is |
||||
* initially 1024 bytes, though its size increases if necessary. |
||||
*/ |
||||
public FastCharArrayWriter() { |
||||
this(1024); |
||||
} |
||||
|
||||
/** |
||||
* Creates a new char array {@link Writer}, with a buffer capacity of |
||||
* the specified size, in bytes. |
||||
* |
||||
* @param size the initial size. |
||||
* @throws IllegalArgumentException if size is negative. |
||||
*/ |
||||
public FastCharArrayWriter(final int size) { |
||||
buffer = new FastCharBuffer(size); |
||||
} |
||||
|
||||
/** |
||||
* @see Writer#write(char[], int, int) |
||||
*/ |
||||
@Override |
||||
public void write(final char[] b, final int off, final int len) { |
||||
buffer.append(b, off, len); |
||||
} |
||||
|
||||
/** |
||||
* Writes single byte. |
||||
*/ |
||||
@Override |
||||
public void write(final int b) { |
||||
buffer.append((char) b); |
||||
} |
||||
|
||||
@Override |
||||
public void write(final String s, final int off, final int len) { |
||||
write(s.toCharArray(), off, len); |
||||
} |
||||
|
||||
/** |
||||
* @see CharArrayWriter#size() |
||||
*/ |
||||
public int size() { |
||||
return buffer.size(); |
||||
} |
||||
|
||||
/** |
||||
* Closing a {@link FastCharArrayWriter} has no effect. The methods in |
||||
* this class can be called after the stream has been closed without |
||||
* generating an {@link IOException}. |
||||
*/ |
||||
@Override |
||||
public void close() { |
||||
//nop
|
||||
} |
||||
|
||||
/** |
||||
* Flushing a {@link FastCharArrayWriter} has no effects. |
||||
*/ |
||||
@Override |
||||
public void flush() { |
||||
//nop
|
||||
} |
||||
|
||||
/** |
||||
* @see CharArrayWriter#reset() |
||||
*/ |
||||
public void reset() { |
||||
buffer.clear(); |
||||
} |
||||
|
||||
/** |
||||
* @see CharArrayWriter#writeTo(Writer) |
||||
*/ |
||||
public void writeTo(final Writer out) throws IOException { |
||||
out.write(buffer.toArray()); |
||||
} |
||||
|
||||
/** |
||||
* @see CharArrayWriter#toCharArray() |
||||
*/ |
||||
public char[] toCharArray() { |
||||
return buffer.toArray(); |
||||
} |
||||
|
||||
/** |
||||
* @see CharArrayWriter#toString() |
||||
*/ |
||||
@Override |
||||
public String toString() { |
||||
return new String(toCharArray()); |
||||
} |
||||
} |
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue