Rock
1 year ago
895 changed files with 0 additions and 139529 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
@ -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.io; |
|
||||||
|
|
||||||
import com.fr.third.jodd.util.StringUtil; |
|
||||||
|
|
||||||
import java.io.File; |
|
||||||
import java.io.IOException; |
|
||||||
import java.io.InputStream; |
|
||||||
import java.net.HttpURLConnection; |
|
||||||
import java.net.Inet4Address; |
|
||||||
import java.net.InetAddress; |
|
||||||
import java.net.URL; |
|
||||||
import java.net.UnknownHostException; |
|
||||||
import java.nio.channels.Channels; |
|
||||||
import java.nio.channels.FileChannel; |
|
||||||
import java.nio.channels.ReadableByteChannel; |
|
||||||
import java.nio.file.StandardOpenOption; |
|
||||||
import java.util.regex.Matcher; |
|
||||||
import java.util.regex.Pattern; |
|
||||||
|
|
||||||
/** |
|
||||||
* Network utilities. |
|
||||||
*/ |
|
||||||
public class NetUtil { |
|
||||||
|
|
||||||
public static final String LOCAL_HOST = "localhost"; |
|
||||||
public static final String LOCAL_IP = "127.0.0.1"; |
|
||||||
public static final String DEFAULT_MASK = "255.255.255.0"; |
|
||||||
public static final int INT_VALUE_127_0_0_1 = 0x7f000001; |
|
||||||
|
|
||||||
/** |
|
||||||
* Resolves IP address from a hostname. |
|
||||||
*/ |
|
||||||
public static String resolveIpAddress(final String hostname) { |
|
||||||
try { |
|
||||||
InetAddress netAddress; |
|
||||||
|
|
||||||
if (hostname == null || hostname.equalsIgnoreCase(LOCAL_HOST)) { |
|
||||||
netAddress = InetAddress.getLocalHost(); |
|
||||||
} else { |
|
||||||
netAddress = Inet4Address.getByName(hostname); |
|
||||||
} |
|
||||||
return netAddress.getHostAddress(); |
|
||||||
} catch (UnknownHostException ignore) { |
|
||||||
return null; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Returns IP address as integer. |
|
||||||
*/ |
|
||||||
public static int getIpAsInt(final String ipAddress) { |
|
||||||
int ipIntValue = 0; |
|
||||||
String[] tokens = StringUtil.splitc(ipAddress, '.'); |
|
||||||
for (String token : tokens) { |
|
||||||
if (ipIntValue > 0) { |
|
||||||
ipIntValue <<= 8; |
|
||||||
} |
|
||||||
ipIntValue += Integer.parseInt(token); |
|
||||||
} |
|
||||||
return ipIntValue; |
|
||||||
} |
|
||||||
|
|
||||||
public static int getMaskAsInt(String mask) { |
|
||||||
if (!validateIPv4(mask)) { |
|
||||||
mask = DEFAULT_MASK; |
|
||||||
} |
|
||||||
return getIpAsInt(mask); |
|
||||||
} |
|
||||||
|
|
||||||
public static boolean isSocketAccessAllowed(final int localIp, final int socketIp, final int mask) { |
|
||||||
boolean _retVal = false; |
|
||||||
|
|
||||||
if (socketIp == INT_VALUE_127_0_0_1 || (localIp & mask) == (socketIp & mask)) { |
|
||||||
_retVal = true; |
|
||||||
} |
|
||||||
return _retVal; |
|
||||||
} |
|
||||||
|
|
||||||
private static final Pattern ip4RegExp = Pattern.compile("^((?:1?[1-9]?\\d|2(?:[0-4]\\d|5[0-5]))\\.){4}$"); |
|
||||||
|
|
||||||
/** |
|
||||||
* Checks given string against IP address v4 format. |
|
||||||
* |
|
||||||
* @param input an ip address - may be null |
|
||||||
* @return <tt>true</tt> if param has a valid ip v4 format <tt>false</tt> otherwise |
|
||||||
* @see <a href="https://en.wikipedia.org/wiki/IP_address#IPv4_addresses">ip address v4</a> |
|
||||||
*/ |
|
||||||
public static boolean validateIPv4(final String input) { |
|
||||||
Matcher m = ip4RegExp.matcher(input + '.'); |
|
||||||
return m.matches(); |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Resolves host name from IP address bytes. |
|
||||||
*/ |
|
||||||
public static String resolveHostName(final byte[] ip) { |
|
||||||
try { |
|
||||||
InetAddress address = InetAddress.getByAddress(ip); |
|
||||||
return address.getHostName(); |
|
||||||
} catch (UnknownHostException ignore) { |
|
||||||
return null; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
// ---------------------------------------------------------------- download
|
|
||||||
|
|
||||||
/** |
|
||||||
* Downloads resource as byte array. |
|
||||||
*/ |
|
||||||
public static byte[] downloadBytes(final String url) throws IOException { |
|
||||||
try (InputStream inputStream = new URL(url).openStream()) { |
|
||||||
return StreamUtil.readBytes(inputStream); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Downloads resource as String. |
|
||||||
*/ |
|
||||||
public static String downloadString(final String url, final String encoding) throws IOException { |
|
||||||
try (InputStream inputStream = new URL(url).openStream()) { |
|
||||||
return new String(StreamUtil.readChars(inputStream, encoding)); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Downloads resource as String. |
|
||||||
*/ |
|
||||||
public static String downloadString(final String url) throws IOException { |
|
||||||
try (InputStream inputStream = new URL(url).openStream()) { |
|
||||||
return new String(StreamUtil.readChars(inputStream)); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Downloads resource to a file, potentially very efficiently. |
|
||||||
*/ |
|
||||||
public static void downloadFile(final String url, final File file) throws IOException { |
|
||||||
try ( |
|
||||||
InputStream inputStream = new URL(url).openStream(); |
|
||||||
ReadableByteChannel rbc = Channels.newChannel(inputStream); |
|
||||||
FileChannel fileChannel = FileChannel.open( |
|
||||||
file.toPath(), |
|
||||||
StandardOpenOption.CREATE, |
|
||||||
StandardOpenOption.TRUNCATE_EXISTING, |
|
||||||
StandardOpenOption.WRITE) |
|
||||||
) { |
|
||||||
fileChannel.transferFrom(rbc, 0, Long.MAX_VALUE); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Get remote file size. Returns -1 if the content length is unknown |
|
||||||
* |
|
||||||
* @param url remote file url |
|
||||||
* @return file size |
|
||||||
* @throws IOException JDK-IOException |
|
||||||
*/ |
|
||||||
public static long getRemoteFileSize(String url) throws IOException { |
|
||||||
HttpURLConnection connection = null; |
|
||||||
try { |
|
||||||
connection = (HttpURLConnection) new URL(url).openConnection(); |
|
||||||
return connection.getContentLengthLong(); |
|
||||||
} finally { |
|
||||||
if (connection != null) { |
|
||||||
connection.disconnect(); |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
@ -1,92 +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 java.io.BufferedReader; |
|
||||||
import java.io.File; |
|
||||||
import java.io.IOException; |
|
||||||
import java.io.StringWriter; |
|
||||||
import java.nio.charset.StandardCharsets; |
|
||||||
import java.nio.file.FileVisitResult; |
|
||||||
import java.nio.file.Files; |
|
||||||
import java.nio.file.Path; |
|
||||||
import java.nio.file.SimpleFileVisitor; |
|
||||||
import java.nio.file.attribute.BasicFileAttributes; |
|
||||||
|
|
||||||
public class PathUtil { |
|
||||||
|
|
||||||
/** |
|
||||||
* Resolves subpath in safer way. For some reason, if child starts with |
|
||||||
* a separator it gets resolved as a full path, ignoring the base. |
|
||||||
* This method acts different. |
|
||||||
*/ |
|
||||||
public static Path resolve(final Path base, String child) { |
|
||||||
if (StringUtil.startsWithChar(child, File.separatorChar)) { |
|
||||||
child = child.substring(1); |
|
||||||
} |
|
||||||
return base.resolve(child); |
|
||||||
} |
|
||||||
|
|
||||||
public static Path resolve(Path path, final String... childs) { |
|
||||||
for (String child : childs) { |
|
||||||
path = resolve(path, child); |
|
||||||
} |
|
||||||
return path; |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Reads path content. |
|
||||||
*/ |
|
||||||
public static String readString(final Path path) throws IOException { |
|
||||||
try (BufferedReader reader = Files.newBufferedReader(path, StandardCharsets.UTF_8)) { |
|
||||||
StringWriter writer = new StringWriter(); // flush & close not needed for StringWriter-instance
|
|
||||||
StreamUtil.copy(reader, writer); |
|
||||||
return writer.toString(); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Deletes a directory recursively. |
|
||||||
*/ |
|
||||||
public static void deleteFileTree(final Path directory) throws IOException { |
|
||||||
Files.walkFileTree(directory, new SimpleFileVisitor<Path>() { |
|
||||||
@Override |
|
||||||
public FileVisitResult visitFile(final Path file, final BasicFileAttributes attrs) throws IOException { |
|
||||||
Files.delete(file); |
|
||||||
return FileVisitResult.CONTINUE; |
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
public FileVisitResult postVisitDirectory(final Path dir, final IOException exc) throws IOException { |
|
||||||
Files.delete(dir); |
|
||||||
return FileVisitResult.CONTINUE; |
|
||||||
} |
|
||||||
}); |
|
||||||
} |
|
||||||
|
|
||||||
} |
|
@ -1,125 +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.StringPool; |
|
||||||
|
|
||||||
import java.io.BufferedReader; |
|
||||||
import java.io.IOException; |
|
||||||
import java.io.InputStream; |
|
||||||
import java.io.InputStreamReader; |
|
||||||
import java.io.OutputStream; |
|
||||||
import java.io.PrintStream; |
|
||||||
|
|
||||||
/** |
|
||||||
* Consumes a stream. |
|
||||||
* For any <code>Process</code>, the input and error streams must read even |
|
||||||
* if the data written to these streams is not used by the application. |
|
||||||
* The generally accepted solution for this problem is a stream gobbler thread |
|
||||||
* that does nothing but consume data from an input stream until stopped. |
|
||||||
*/ |
|
||||||
public class StreamGobbler extends Thread { |
|
||||||
|
|
||||||
protected final InputStream is; |
|
||||||
protected final String prefix; |
|
||||||
protected final OutputStream out; |
|
||||||
protected final Object lock = new Object(); |
|
||||||
protected boolean end = false; |
|
||||||
|
|
||||||
public StreamGobbler(final InputStream is) { |
|
||||||
this(is, null, null); |
|
||||||
} |
|
||||||
|
|
||||||
public StreamGobbler(final InputStream is, final OutputStream output) { |
|
||||||
this(is, output, null); |
|
||||||
} |
|
||||||
|
|
||||||
public StreamGobbler(final InputStream is, final OutputStream output, final String prefix) { |
|
||||||
this.is = is; |
|
||||||
this.prefix = prefix; |
|
||||||
this.out = output; |
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
public void run() { |
|
||||||
InputStreamReader isr = new InputStreamReader(is); |
|
||||||
BufferedReader br = new BufferedReader(isr); |
|
||||||
|
|
||||||
try { |
|
||||||
String line; |
|
||||||
while ((line = br.readLine()) != null) { |
|
||||||
if (out != null) { |
|
||||||
if (prefix != null) { |
|
||||||
out.write(prefix.getBytes()); |
|
||||||
} |
|
||||||
out.write(line.getBytes()); |
|
||||||
out.write(StringPool.BYTES_NEW_LINE); |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
catch (IOException ioe) { |
|
||||||
if (out != null) { |
|
||||||
ioe.printStackTrace(new PrintStream(out)); |
|
||||||
} |
|
||||||
} |
|
||||||
finally { |
|
||||||
if (out != null) { |
|
||||||
try { |
|
||||||
out.flush(); |
|
||||||
} |
|
||||||
catch (IOException ignore) { |
|
||||||
} |
|
||||||
} |
|
||||||
try { |
|
||||||
br.close(); |
|
||||||
} |
|
||||||
catch (IOException ignore) { |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
synchronized (lock) { |
|
||||||
lock.notifyAll(); |
|
||||||
end = true; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Waits for gobbler to end. |
|
||||||
*/ |
|
||||||
public void waitFor() { |
|
||||||
try { |
|
||||||
synchronized (lock) { |
|
||||||
if (!end) { |
|
||||||
lock.wait(); |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
catch (InterruptedException ignore) { |
|
||||||
Thread.currentThread().interrupt(); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
} |
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue