You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@directory.apache.org by ak...@apache.org on 2004/09/25 21:11:48 UTC
svn commit: rev 47215 - in incubator/directory/ldap/trunk/common: . src/antlr src/java/org/apache/ldap/common src/java/org/apache/ldap/common/filter src/java/org/apache/ldap/common/ldif src/java/org/apache/ldap/common/message src/java/org/apache/ldap/common/name src/java/org/apache/ldap/common/util
Author: akarasulu
Date: Sat Sep 25 12:11:47 2004
New Revision: 47215
Added:
incubator/directory/ldap/trunk/common/jakarta-commons-forks.txt (contents, props changed)
incubator/directory/ldap/trunk/common/src/java/org/apache/ldap/common/util/ArrayUtils.java (contents, props changed)
incubator/directory/ldap/trunk/common/src/java/org/apache/ldap/common/util/BooleanUtils.java (contents, props changed)
incubator/directory/ldap/trunk/common/src/java/org/apache/ldap/common/util/ClassUtils.java (contents, props changed)
incubator/directory/ldap/trunk/common/src/java/org/apache/ldap/common/util/Enum.java (contents, props changed)
incubator/directory/ldap/trunk/common/src/java/org/apache/ldap/common/util/EnumUtils.java (contents, props changed)
incubator/directory/ldap/trunk/common/src/java/org/apache/ldap/common/util/EqualsBuilder.java (contents, props changed)
incubator/directory/ldap/trunk/common/src/java/org/apache/ldap/common/util/ExceptionUtils.java (contents, props changed)
incubator/directory/ldap/trunk/common/src/java/org/apache/ldap/common/util/HashCodeBuilder.java (contents, props changed)
incubator/directory/ldap/trunk/common/src/java/org/apache/ldap/common/util/MultiMap.java (contents, props changed)
incubator/directory/ldap/trunk/common/src/java/org/apache/ldap/common/util/Nestable.java (contents, props changed)
incubator/directory/ldap/trunk/common/src/java/org/apache/ldap/common/util/NestableDelegate.java (contents, props changed)
incubator/directory/ldap/trunk/common/src/java/org/apache/ldap/common/util/NestableError.java (contents, props changed)
incubator/directory/ldap/trunk/common/src/java/org/apache/ldap/common/util/NestableException.java (contents, props changed)
incubator/directory/ldap/trunk/common/src/java/org/apache/ldap/common/util/NestableRuntimeException.java (contents, props changed)
incubator/directory/ldap/trunk/common/src/java/org/apache/ldap/common/util/ObjectUtils.java (contents, props changed)
incubator/directory/ldap/trunk/common/src/java/org/apache/ldap/common/util/ReflectionToStringBuilder.java (contents, props changed)
incubator/directory/ldap/trunk/common/src/java/org/apache/ldap/common/util/SystemUtils.java (contents, props changed)
incubator/directory/ldap/trunk/common/src/java/org/apache/ldap/common/util/ToStringBuilder.java (contents, props changed)
incubator/directory/ldap/trunk/common/src/java/org/apache/ldap/common/util/ToStringStyle.java (contents, props changed)
incubator/directory/ldap/trunk/common/src/java/org/apache/ldap/common/util/ValuedEnum.java (contents, props changed)
Modified:
incubator/directory/ldap/trunk/common/project.xml
incubator/directory/ldap/trunk/common/src/antlr/dnparser.g
incubator/directory/ldap/trunk/common/src/antlr/filter.g
incubator/directory/ldap/trunk/common/src/antlr/typelexer.g
incubator/directory/ldap/trunk/common/src/antlr/valuelexer.g
incubator/directory/ldap/trunk/common/src/antlr/valueparser.g
incubator/directory/ldap/trunk/common/src/java/org/apache/ldap/common/AbstractLockable.java
incubator/directory/ldap/trunk/common/src/java/org/apache/ldap/common/filter/FilterParserImpl.java
incubator/directory/ldap/trunk/common/src/java/org/apache/ldap/common/ldif/LdifComposer.java
incubator/directory/ldap/trunk/common/src/java/org/apache/ldap/common/ldif/LdifComposerImpl.java
incubator/directory/ldap/trunk/common/src/java/org/apache/ldap/common/ldif/LdifParser.java
incubator/directory/ldap/trunk/common/src/java/org/apache/ldap/common/ldif/LdifParserImpl.java
incubator/directory/ldap/trunk/common/src/java/org/apache/ldap/common/message/BindRequestImpl.java
incubator/directory/ldap/trunk/common/src/java/org/apache/ldap/common/message/BindResponseImpl.java
incubator/directory/ldap/trunk/common/src/java/org/apache/ldap/common/message/DerefAliasesEnum.java
incubator/directory/ldap/trunk/common/src/java/org/apache/ldap/common/message/ExtendedRequestImpl.java
incubator/directory/ldap/trunk/common/src/java/org/apache/ldap/common/message/ExtendedResponseImpl.java
incubator/directory/ldap/trunk/common/src/java/org/apache/ldap/common/message/LockableAttributesImpl.java
incubator/directory/ldap/trunk/common/src/java/org/apache/ldap/common/message/MessageTypeEnum.java
incubator/directory/ldap/trunk/common/src/java/org/apache/ldap/common/message/ResultCodeEnum.java
incubator/directory/ldap/trunk/common/src/java/org/apache/ldap/common/message/ScopeEnum.java
incubator/directory/ldap/trunk/common/src/java/org/apache/ldap/common/name/DnParser.java
Log:
removed dependency on commons lang and collections
Added: incubator/directory/ldap/trunk/common/jakarta-commons-forks.txt
==============================================================================
--- (empty file)
+++ incubator/directory/ldap/trunk/common/jakarta-commons-forks.txt Sat Sep 25 12:11:47 2004
@@ -0,0 +1,41 @@
+In an effort to reduce the amount of jars users have to include during
+runtime we have forked some of the commons classes that we use or depend
+upon. The following list of classes have been forked. We did not want
+to fork these classes but users just don't want too many dependencies.
+We appologise for this temporary impediment to reuse.
+
+The use of these classes are really for trivial means. Much of the
+functionality can actually be replaced all together with a tiny bit of
+effort to remove most of the forked classes here. So expect many of
+these forked classes to gradually disappear.
+
+src/java/org/apache/ldap/common/util/ArrayUtils.java
+src/java/org/apache/ldap/common/util/BooleanUtils.java
+src/java/org/apache/ldap/common/util/EqualsBuilder.java
+src/java/org/apache/ldap/common/util/Enum.java
+src/java/org/apache/ldap/common/util/SystemUtils.java
+src/java/org/apache/ldap/common/util/ValuedEnum.java
+src/java/org/apache/ldap/common/util/NestableError.java
+src/java/org/apache/ldap/common/util/NestableException.java
+src/java/org/apache/ldap/common/util/ExceptionUtils.java
+src/java/org/apache/ldap/common/util/ToStringBuilder.java
+src/java/org/apache/ldap/common/util/NestableRuntimeException.java
+src/java/org/apache/ldap/common/util/HashCodeBuilder.java
+src/java/org/apache/ldap/common/util/EnumUtils.java
+src/java/org/apache/ldap/common/util/ClassUtils.java
+src/java/org/apache/ldap/common/util/ObjectUtils.java
+src/java/org/apache/ldap/common/util/NestableDelegate.java
+src/java/org/apache/ldap/common/util/MultiMap.java
+src/java/org/apache/ldap/common/util/ToStringStyle.java
+src/java/org/apache/ldap/common/util/ReflectionToStringBuilder.java
+src/java/org/apache/ldap/common/util/Nestable.java
+
+At this point we only have two runtime dependencies. Regexp and the
+antlr runtime. Eventually as changes are made to the backend we will
+move away from using Regexp to using the regular expressions packaged
+with the 1.4 JDK. The best however would be to have a single commons-logging
+like wrapper around the various RE implementations out there.
+
+Cheers,
+Alex
+
Modified: incubator/directory/ldap/trunk/common/project.xml
==============================================================================
--- incubator/directory/ldap/trunk/common/project.xml (original)
+++ incubator/directory/ldap/trunk/common/project.xml Sat Sep 25 12:11:47 2004
@@ -29,29 +29,15 @@
Common LDAP packages used by clients and servers.
</shortDescription>
- <dependencies>
-
- <dependency>
- <groupId>commons-collections</groupId>
- <artifactId>commons-collections</artifactId>
- <version>2.1</version>
- <url>http://jakarta.apache.org/commons/collections</url>
- </dependency>
+ <dependencies>
<dependency>
- <groupId>commons-lang</groupId>
- <artifactId>commons-lang</artifactId>
- <version>2.0</version>
- <url>http://jakarta.apache.org/commons/lang</url>
+ <groupId>regexp</groupId>
+ <artifactId>regexp</artifactId>
+ <version>1.2</version>
+ <url>http://jakarta.apache.org/regexp/index.html</url>
</dependency>
- <dependency>
- <groupId>regexp</groupId>
- <artifactId>regexp</artifactId>
- <version>1.2</version>
- <url>http://jakarta.apache.org/regexp/index.html</url>
- </dependency>
-
<dependency>
<groupId>antlr</groupId>
<artifactId>antlr</artifactId>
@@ -72,7 +58,7 @@
<version>SNAPSHOT</version>
</dependency>
- </dependencies>
+ </dependencies>
<build>
<nagEmailAddress>directory-dev@incubator.apache.org</nagEmailAddress>
Modified: incubator/directory/ldap/trunk/common/src/antlr/dnparser.g
==============================================================================
--- incubator/directory/ldap/trunk/common/src/antlr/dnparser.g (original)
+++ incubator/directory/ldap/trunk/common/src/antlr/dnparser.g Sat Sep 25 12:11:47 2004
@@ -1,59 +1,17 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
+/*
+ * Copyright 2002-2004 The Apache Software Foundation.
*
- * Copyright (c) 2000 The Apache Software Foundation. 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.
- *
- * 3. The end-user documentation included with the redistribution,
- * if any, must include the following acknowledgment:
- * "This product includes software developed by the
- * Apache Software Foundation (http://www.apache.org/)."
- * Alternately, this acknowledgment may appear in the software itself,
- * if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- * not be used to endorse or promote products derived from this
- * software without prior written permission. For written
- * permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- * nor may "Apache" appear in their name, without prior written
- * permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED 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 APACHE SOFTWARE FOUNDATION OR
- * ITS 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.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- *
- * Portions of this software are based upon public domain software
- * originally written at the National Center for Supercomputing Applications,
- * University of Illinois, Urbana-Champaign.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
*/
header {
Modified: incubator/directory/ldap/trunk/common/src/antlr/filter.g
==============================================================================
--- incubator/directory/ldap/trunk/common/src/antlr/filter.g (original)
+++ incubator/directory/ldap/trunk/common/src/antlr/filter.g Sat Sep 25 12:11:47 2004
@@ -27,8 +27,8 @@
*
*/
/*
- * Keep the semicolon right next to org.apache.ldap.common.name.filter or
- * else there will be a bug that comes into the foreground in the new antlr
+ * Keep the semicolon right next to org.apache.ldap.common.name.filter or
+ * else there will be a bug that comes into the foreground in the new antlr
* release.
*/
package org.apache.ldap.common.filter;
Modified: incubator/directory/ldap/trunk/common/src/antlr/typelexer.g
==============================================================================
--- incubator/directory/ldap/trunk/common/src/antlr/typelexer.g (original)
+++ incubator/directory/ldap/trunk/common/src/antlr/typelexer.g Sat Sep 25 12:11:47 2004
@@ -1,61 +1,18 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
+/*
+ * Copyright 2002-2004 The Apache Software Foundation.
*
- * Copyright (c) 2000 The Apache Software Foundation. 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.
- *
- * 3. The end-user documentation included with the redistribution,
- * if any, must include the following acknowledgment:
- * "This product includes software developed by the
- * Apache Software Foundation (http://www.apache.org/)."
- * Alternately, this acknowledgment may appear in the software itself,
- * if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- * not be used to endorse or promote products derived from this
- * software without prior written permission. For written
- * permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- * nor may "Apache" appear in their name, without prior written
- * permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED 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 APACHE SOFTWARE FOUNDATION OR
- * ITS 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.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- *
- * Portions of this software are based upon public domain software
- * originally written at the National Center for Supercomputing Applications,
- * University of Illinois, Urbana-Champaign.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
*/
-
header {
/*
* Keep the semicolon right next to org.apache.ldap.common.name or else there
Modified: incubator/directory/ldap/trunk/common/src/antlr/valuelexer.g
==============================================================================
--- incubator/directory/ldap/trunk/common/src/antlr/valuelexer.g (original)
+++ incubator/directory/ldap/trunk/common/src/antlr/valuelexer.g Sat Sep 25 12:11:47 2004
@@ -1,61 +1,18 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
+/*
+ * Copyright 2002-2004 The Apache Software Foundation.
*
- * Copyright (c) 2000 The Apache Software Foundation. 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.
- *
- * 3. The end-user documentation included with the redistribution,
- * if any, must include the following acknowledgment:
- * "This product includes software developed by the
- * Apache Software Foundation (http://www.apache.org/)."
- * Alternately, this acknowledgment may appear in the software itself,
- * if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- * not be used to endorse or promote products derived from this
- * software without prior written permission. For written
- * permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- * nor may "Apache" appear in their name, without prior written
- * permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED 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 APACHE SOFTWARE FOUNDATION OR
- * ITS 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.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- *
- * Portions of this software are based upon public domain software
- * originally written at the National Center for Supercomputing Applications,
- * University of Illinois, Urbana-Champaign.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
*/
-
header {
/*
* Keep the semicolon right next to org.apache.ldap.common.name or else there
Modified: incubator/directory/ldap/trunk/common/src/antlr/valueparser.g
==============================================================================
--- incubator/directory/ldap/trunk/common/src/antlr/valueparser.g (original)
+++ incubator/directory/ldap/trunk/common/src/antlr/valueparser.g Sat Sep 25 12:11:47 2004
@@ -22,7 +22,7 @@
package org.apache.ldap.common.name;
import javax.naming.NamingException ;
-import org.apache.commons.lang.exception.NestableRuntimeException ;
+import org.apache.ldap.common.util.NestableRuntimeException ;
}
class antlrValueParser extends Parser ;
Modified: incubator/directory/ldap/trunk/common/src/java/org/apache/ldap/common/AbstractLockable.java
==============================================================================
--- incubator/directory/ldap/trunk/common/src/java/org/apache/ldap/common/AbstractLockable.java (original)
+++ incubator/directory/ldap/trunk/common/src/java/org/apache/ldap/common/AbstractLockable.java Sat Sep 25 12:11:47 2004
@@ -1,217 +1,18 @@
-/*
- * Apache License
- * Version 2.0, January 2004
- * http://www.apache.org/licenses/
- *
- * TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
- *
- * 1. Definitions.
- *
- * "License" shall mean the terms and conditions for use, reproduction,
- * and distribution as defined by Sections 1 through 9 of this document.
- *
- * "Licensor" shall mean the copyright owner or entity authorized by
- * the copyright owner that is granting the License.
- *
- * "Legal Entity" shall mean the union of the acting entity and all
- * other entities that control, are controlled by, or are under common
- * control with that entity. For the purposes of this definition,
- * "control" means (i) the power, direct or indirect, to cause the
- * direction or management of such entity, whether by contract or
- * otherwise, or (ii) ownership of fifty percent (50%) or more of the
- * outstanding shares, or (iii) beneficial ownership of such entity.
- *
- * "You" (or "Your") shall mean an individual or Legal Entity
- * exercising permissions granted by this License.
- *
- * "Source" form shall mean the preferred form for making modifications,
- * including but not limited to software source code, documentation
- * source, and configuration files.
- *
- * "Object" form shall mean any form resulting from mechanical
- * transformation or translation of a Source form, including but
- * not limited to compiled object code, generated documentation,
- * and conversions to other media types.
- *
- * "Work" shall mean the work of authorship, whether in Source or
- * Object form, made available under the License, as indicated by a
- * copyright notice that is included in or attached to the work
- * (an example is provided in the Appendix below).
- *
- * "Derivative Works" shall mean any work, whether in Source or Object
- * form, that is based on (or derived from) the Work and for which the
- * editorial revisions, annotations, elaborations, or other modifications
- * represent, as a whole, an original work of authorship. For the purposes
- * of this License, Derivative Works shall not include works that remain
- * separable from, or merely link (or bind by name) to the interfaces of,
- * the Work and Derivative Works thereof.
- *
- * "Contribution" shall mean any work of authorship, including
- * the original version of the Work and any modifications or additions
- * to that Work or Derivative Works thereof, that is intentionally
- * submitted to Licensor for inclusion in the Work by the copyright owner
- * or by an individual or Legal Entity authorized to submit on behalf of
- * the copyright owner. For the purposes of this definition, "submitted"
- * means any form of electronic, verbal, or written communication sent
- * to the Licensor or its representatives, including but not limited to
- * communication on electronic mailing lists, source code control systems,
- * and issue tracking systems that are managed by, or on behalf of, the
- * Licensor for the purpose of discussing and improving the Work, but
- * excluding communication that is conspicuously marked or otherwise
- * designated in writing by the copyright owner as "Not a Contribution."
- *
- * "Contributor" shall mean Licensor and any individual or Legal Entity
- * on behalf of whom a Contribution has been received by Licensor and
- * subsequently incorporated within the Work.
- *
- * 2. Grant of Copyright License. Subject to the terms and conditions of
- * this License, each Contributor hereby grants to You a perpetual,
- * worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- * copyright license to reproduce, prepare Derivative Works of,
- * publicly display, publicly perform, sublicense, and distribute the
- * Work and such Derivative Works in Source or Object form.
- *
- * 3. Grant of Patent License. Subject to the terms and conditions of
- * this License, each Contributor hereby grants to You a perpetual,
- * worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- * (except as stated in this section) patent license to make, have made,
- * use, offer to sell, sell, import, and otherwise transfer the Work,
- * where such license applies only to those patent claims licensable
- * by such Contributor that are necessarily infringed by their
- * Contribution(s) alone or by combination of their Contribution(s)
- * with the Work to which such Contribution(s) was submitted. If You
- * institute patent litigation against any entity (including a
- * cross-claim or counterclaim in a lawsuit) alleging that the Work
- * or a Contribution incorporated within the Work constitutes direct
- * or contributory patent infringement, then any patent licenses
- * granted to You under this License for that Work shall terminate
- * as of the date such litigation is filed.
- *
- * 4. Redistribution. You may reproduce and distribute copies of the
- * Work or Derivative Works thereof in any medium, with or without
- * modifications, and in Source or Object form, provided that You
- * meet the following conditions:
- *
- * (a) You must give any other recipients of the Work or
- * Derivative Works a copy of this License; and
- *
- * (b) You must cause any modified files to carry prominent notices
- * stating that You changed the files; and
- *
- * (c) You must retain, in the Source form of any Derivative Works
- * that You distribute, all copyright, patent, trademark, and
- * attribution notices from the Source form of the Work,
- * excluding those notices that do not pertain to any part of
- * the Derivative Works; and
- *
- * (d) If the Work includes a "NOTICE" text file as part of its
- * distribution, then any Derivative Works that You distribute must
- * include a readable copy of the attribution notices contained
- * within such NOTICE file, excluding those notices that do not
- * pertain to any part of the Derivative Works, in at least one
- * of the following places: within a NOTICE text file distributed
- * as part of the Derivative Works; within the Source form or
- * documentation, if provided along with the Derivative Works; or,
- * within a display generated by the Derivative Works, if and
- * wherever such third-party notices normally appear. The contents
- * of the NOTICE file are for informational purposes only and
- * do not modify the License. You may add Your own attribution
- * notices within Derivative Works that You distribute, alongside
- * or as an addendum to the NOTICE text from the Work, provided
- * that such additional attribution notices cannot be construed
- * as modifying the License.
- *
- * You may add Your own copyright statement to Your modifications and
- * may provide additional or different license terms and conditions
- * for use, reproduction, or distribution of Your modifications, or
- * for any such Derivative Works as a whole, provided Your use,
- * reproduction, and distribution of the Work otherwise complies with
- * the conditions stated in this License.
- *
- * 5. Submission of Contributions. Unless You explicitly state otherwise,
- * any Contribution intentionally submitted for inclusion in the Work
- * by You to the Licensor shall be under the terms and conditions of
- * this License, without any additional terms or conditions.
- * Notwithstanding the above, nothing herein shall supersede or modify
- * the terms of any separate license agreement you may have executed
- * with Licensor regarding such Contributions.
- *
- * 6. Trademarks. This License does not grant permission to use the trade
- * names, trademarks, service marks, or product names of the Licensor,
- * except as required for reasonable and customary use in describing the
- * origin of the Work and reproducing the content of the NOTICE file.
- *
- * 7. Disclaimer of Warranty. Unless required by applicable law or
- * agreed to in writing, Licensor provides the Work (and each
- * Contributor provides its Contributions) on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
- * implied, including, without limitation, any warranties or conditions
- * of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
- * PARTICULAR PURPOSE. You are solely responsible for determining the
- * appropriateness of using or redistributing the Work and assume any
- * risks associated with Your exercise of permissions under this License.
- *
- * 8. Limitation of Liability. In no event and under no legal theory,
- * whether in tort (including negligence), contract, or otherwise,
- * unless required by applicable law (such as deliberate and grossly
- * negligent acts) or agreed to in writing, shall any Contributor be
- * liable to You for damages, including any direct, indirect, special,
- * incidental, or consequential damages of any character arising as a
- * result of this License or out of the use or inability to use the
- * Work (including but not limited to damages for loss of goodwill,
- * work stoppage, computer failure or malfunction, or any and all
- * other commercial damages or losses), even if such Contributor
- * has been advised of the possibility of such damages.
- *
- * 9. Accepting Warranty or Additional Liability. While redistributing
- * the Work or Derivative Works thereof, You may choose to offer,
- * and charge a fee for, acceptance of support, warranty, indemnity,
- * or other liability obligations and/or rights consistent with this
- * License. However, in accepting such obligations, You may act only
- * on Your own behalf and on Your sole responsibility, not on behalf
- * of any other Contributor, and only if You agree to indemnify,
- * defend, and hold each Contributor harmless for any liability
- * incurred by, or claims asserted against, such Contributor by reason
- * of your accepting any such warranty or additional liability.
- *
- * END OF TERMS AND CONDITIONS
- *
- * APPENDIX: How to apply the Apache License to your work.
- *
- * To apply the Apache License to your work, attach the following
- * boilerplate notice, with the fields enclosed by brackets "[]"
- * replaced with your own identifying information. (Don't include
- * the brackets!) The text should be enclosed in the appropriate
- * comment syntax for the file format. We also recommend that a
- * file or class name and description of purpose be included on the
- * same "printed page" as the copyright notice for easier
- * identification within third-party archives.
- *
- * Copyright [yyyy] [name of copyright owner]
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
/*
- * $Id: AbstractLockable.java,v 1.8 2003/09/18 22:42:31 akarasulu Exp $
+ * Copyright 2002-2004 The Apache Software Foundation.
*
- * -- (c) LDAPd Group --
- * -- Please refer to the LICENSE.txt file in the root directory of --
- * -- any LDAPd project for copyright and distribution information. --
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
*
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
*/
-
package org.apache.ldap.common ;
Modified: incubator/directory/ldap/trunk/common/src/java/org/apache/ldap/common/filter/FilterParserImpl.java
==============================================================================
--- incubator/directory/ldap/trunk/common/src/java/org/apache/ldap/common/filter/FilterParserImpl.java (original)
+++ incubator/directory/ldap/trunk/common/src/java/org/apache/ldap/common/filter/FilterParserImpl.java Sat Sep 25 12:11:47 2004
@@ -21,11 +21,10 @@
import java.text.ParseException ;
import java.io.PipedInputStream ;
import java.io.PipedOutputStream ;
-
-import org.apache.commons.lang.exception.ExceptionUtils ;
+import org.apache.ldap.common.util.ExceptionUtils;
import antlr.RecognitionException ;
-import antlr.TokenStreamException ;
+import antlr.TokenStreamException ;
/**
@@ -37,7 +36,7 @@
*/
public class FilterParserImpl
implements FilterParser
-{
+{
private FilterParserMonitor monitor = new FilterParserMonitorAdapter() ;
/** The antlr generated parser */
private antlrFilterParser m_parser = null ;
@@ -91,7 +90,7 @@
}
if ( null == monitor )
- {
+ {
monitor = new FilterParserMonitorAdapter() ;
}
@@ -121,15 +120,15 @@
}
return l_root ;
- }
-
-
- /* (non-Javadoc)
- * @see org.apache.ldap.common.filter.FilterParser#setFilterParserMonitor(
- * org.apache.ldap.common.filter.FilterParserMonitor)
- */
- public void setFilterParserMonitor( FilterParserMonitor monitor )
- {
- this.monitor = monitor ;
+ }
+
+
+ /* (non-Javadoc)
+ * @see org.apache.ldap.common.filter.FilterParser#setFilterParserMonitor(
+ * org.apache.ldap.common.filter.FilterParserMonitor)
+ */
+ public void setFilterParserMonitor( FilterParserMonitor monitor )
+ {
+ this.monitor = monitor ;
}
}
Modified: incubator/directory/ldap/trunk/common/src/java/org/apache/ldap/common/ldif/LdifComposer.java
==============================================================================
--- incubator/directory/ldap/trunk/common/src/java/org/apache/ldap/common/ldif/LdifComposer.java (original)
+++ incubator/directory/ldap/trunk/common/src/java/org/apache/ldap/common/ldif/LdifComposer.java Sat Sep 25 12:11:47 2004
@@ -1,207 +1,207 @@
-/*
- * Apache License
- * Version 2.0, January 2004
- * http://www.apache.org/licenses/
- *
- * TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
- *
- * 1. Definitions.
- *
- * "License" shall mean the terms and conditions for use, reproduction,
- * and distribution as defined by Sections 1 through 9 of this document.
- *
- * "Licensor" shall mean the copyright owner or entity authorized by
- * the copyright owner that is granting the License.
- *
- * "Legal Entity" shall mean the union of the acting entity and all
- * other entities that control, are controlled by, or are under common
- * control with that entity. For the purposes of this definition,
- * "control" means (i) the power, direct or indirect, to cause the
- * direction or management of such entity, whether by contract or
- * otherwise, or (ii) ownership of fifty percent (50%) or more of the
- * outstanding shares, or (iii) beneficial ownership of such entity.
- *
- * "You" (or "Your") shall mean an individual or Legal Entity
- * exercising permissions granted by this License.
- *
- * "Source" form shall mean the preferred form for making modifications,
- * including but not limited to software source code, documentation
- * source, and configuration files.
- *
- * "Object" form shall mean any form resulting from mechanical
- * transformation or translation of a Source form, including but
- * not limited to compiled object code, generated documentation,
- * and conversions to other media types.
- *
- * "Work" shall mean the work of authorship, whether in Source or
- * Object form, made available under the License, as indicated by a
- * copyright notice that is included in or attached to the work
- * (an example is provided in the Appendix below).
- *
- * "Derivative Works" shall mean any work, whether in Source or Object
- * form, that is based on (or derived from) the Work and for which the
- * editorial revisions, annotations, elaborations, or other modifications
- * represent, as a whole, an original work of authorship. For the purposes
- * of this License, Derivative Works shall not include works that remain
- * separable from, or merely link (or bind by name) to the interfaces of,
- * the Work and Derivative Works thereof.
- *
- * "Contribution" shall mean any work of authorship, including
- * the original version of the Work and any modifications or additions
- * to that Work or Derivative Works thereof, that is intentionally
- * submitted to Licensor for inclusion in the Work by the copyright owner
- * or by an individual or Legal Entity authorized to submit on behalf of
- * the copyright owner. For the purposes of this definition, "submitted"
- * means any form of electronic, verbal, or written communication sent
- * to the Licensor or its representatives, including but not limited to
- * communication on electronic mailing lists, source code control systems,
- * and issue tracking systems that are managed by, or on behalf of, the
- * Licensor for the purpose of discussing and improving the Work, but
- * excluding communication that is conspicuously marked or otherwise
- * designated in writing by the copyright owner as "Not a Contribution."
- *
- * "Contributor" shall mean Licensor and any individual or Legal Entity
- * on behalf of whom a Contribution has been received by Licensor and
- * subsequently incorporated within the Work.
- *
- * 2. Grant of Copyright License. Subject to the terms and conditions of
- * this License, each Contributor hereby grants to You a perpetual,
- * worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- * copyright license to reproduce, prepare Derivative Works of,
- * publicly display, publicly perform, sublicense, and distribute the
- * Work and such Derivative Works in Source or Object form.
- *
- * 3. Grant of Patent License. Subject to the terms and conditions of
- * this License, each Contributor hereby grants to You a perpetual,
- * worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- * (except as stated in this section) patent license to make, have made,
- * use, offer to sell, sell, import, and otherwise transfer the Work,
- * where such license applies only to those patent claims licensable
- * by such Contributor that are necessarily infringed by their
- * Contribution(s) alone or by combination of their Contribution(s)
- * with the Work to which such Contribution(s) was submitted. If You
- * institute patent litigation against any entity (including a
- * cross-claim or counterclaim in a lawsuit) alleging that the Work
- * or a Contribution incorporated within the Work constitutes direct
- * or contributory patent infringement, then any patent licenses
- * granted to You under this License for that Work shall terminate
- * as of the date such litigation is filed.
- *
- * 4. Redistribution. You may reproduce and distribute copies of the
- * Work or Derivative Works thereof in any medium, with or without
- * modifications, and in Source or Object form, provided that You
- * meet the following conditions:
- *
- * (a) You must give any other recipients of the Work or
- * Derivative Works a copy of this License; and
- *
- * (b) You must cause any modified files to carry prominent notices
- * stating that You changed the files; and
- *
- * (c) You must retain, in the Source form of any Derivative Works
- * that You distribute, all copyright, patent, trademark, and
- * attribution notices from the Source form of the Work,
- * excluding those notices that do not pertain to any part of
- * the Derivative Works; and
- *
- * (d) If the Work includes a "NOTICE" text file as part of its
- * distribution, then any Derivative Works that You distribute must
- * include a readable copy of the attribution notices contained
- * within such NOTICE file, excluding those notices that do not
- * pertain to any part of the Derivative Works, in at least one
- * of the following places: within a NOTICE text file distributed
- * as part of the Derivative Works; within the Source form or
- * documentation, if provided along with the Derivative Works; or,
- * within a display generated by the Derivative Works, if and
- * wherever such third-party notices normally appear. The contents
- * of the NOTICE file are for informational purposes only and
- * do not modify the License. You may add Your own attribution
- * notices within Derivative Works that You distribute, alongside
- * or as an addendum to the NOTICE text from the Work, provided
- * that such additional attribution notices cannot be construed
- * as modifying the License.
- *
- * You may add Your own copyright statement to Your modifications and
- * may provide additional or different license terms and conditions
- * for use, reproduction, or distribution of Your modifications, or
- * for any such Derivative Works as a whole, provided Your use,
- * reproduction, and distribution of the Work otherwise complies with
- * the conditions stated in this License.
- *
- * 5. Submission of Contributions. Unless You explicitly state otherwise,
- * any Contribution intentionally submitted for inclusion in the Work
- * by You to the Licensor shall be under the terms and conditions of
- * this License, without any additional terms or conditions.
- * Notwithstanding the above, nothing herein shall supersede or modify
- * the terms of any separate license agreement you may have executed
- * with Licensor regarding such Contributions.
- *
- * 6. Trademarks. This License does not grant permission to use the trade
- * names, trademarks, service marks, or product names of the Licensor,
- * except as required for reasonable and customary use in describing the
- * origin of the Work and reproducing the content of the NOTICE file.
- *
- * 7. Disclaimer of Warranty. Unless required by applicable law or
- * agreed to in writing, Licensor provides the Work (and each
- * Contributor provides its Contributions) on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
- * implied, including, without limitation, any warranties or conditions
- * of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
- * PARTICULAR PURPOSE. You are solely responsible for determining the
- * appropriateness of using or redistributing the Work and assume any
- * risks associated with Your exercise of permissions under this License.
- *
- * 8. Limitation of Liability. In no event and under no legal theory,
- * whether in tort (including negligence), contract, or otherwise,
- * unless required by applicable law (such as deliberate and grossly
- * negligent acts) or agreed to in writing, shall any Contributor be
- * liable to You for damages, including any direct, indirect, special,
- * incidental, or consequential damages of any character arising as a
- * result of this License or out of the use or inability to use the
- * Work (including but not limited to damages for loss of goodwill,
- * work stoppage, computer failure or malfunction, or any and all
- * other commercial damages or losses), even if such Contributor
- * has been advised of the possibility of such damages.
- *
- * 9. Accepting Warranty or Additional Liability. While redistributing
- * the Work or Derivative Works thereof, You may choose to offer,
- * and charge a fee for, acceptance of support, warranty, indemnity,
- * or other liability obligations and/or rights consistent with this
- * License. However, in accepting such obligations, You may act only
- * on Your own behalf and on Your sole responsibility, not on behalf
- * of any other Contributor, and only if You agree to indemnify,
- * defend, and hold each Contributor harmless for any liability
- * incurred by, or claims asserted against, such Contributor by reason
- * of your accepting any such warranty or additional liability.
- *
- * END OF TERMS AND CONDITIONS
- *
- * APPENDIX: How to apply the Apache License to your work.
- *
- * To apply the Apache License to your work, attach the following
- * boilerplate notice, with the fields enclosed by brackets "[]"
- * replaced with your own identifying information. (Don't include
- * the brackets!) The text should be enclosed in the appropriate
- * comment syntax for the file format. We also recommend that a
- * file or class name and description of purpose be included on the
- * same "printed page" as the copyright notice for easier
- * identification within third-party archives.
- *
- * Copyright [yyyy] [name of copyright owner]
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
+/*
+ * Apache License
+ * Version 2.0, January 2004
+ * http://www.apache.org/licenses/
+ *
+ * TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+ *
+ * 1. Definitions.
+ *
+ * "License" shall mean the terms and conditions for use, reproduction,
+ * and distribution as defined by Sections 1 through 9 of this document.
+ *
+ * "Licensor" shall mean the copyright owner or entity authorized by
+ * the copyright owner that is granting the License.
+ *
+ * "Legal Entity" shall mean the union of the acting entity and all
+ * other entities that control, are controlled by, or are under common
+ * control with that entity. For the purposes of this definition,
+ * "control" means (i) the power, direct or indirect, to cause the
+ * direction or management of such entity, whether by contract or
+ * otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ * outstanding shares, or (iii) beneficial ownership of such entity.
+ *
+ * "You" (or "Your") shall mean an individual or Legal Entity
+ * exercising permissions granted by this License.
+ *
+ * "Source" form shall mean the preferred form for making modifications,
+ * including but not limited to software source code, documentation
+ * source, and configuration files.
+ *
+ * "Object" form shall mean any form resulting from mechanical
+ * transformation or translation of a Source form, including but
+ * not limited to compiled object code, generated documentation,
+ * and conversions to other media types.
+ *
+ * "Work" shall mean the work of authorship, whether in Source or
+ * Object form, made available under the License, as indicated by a
+ * copyright notice that is included in or attached to the work
+ * (an example is provided in the Appendix below).
+ *
+ * "Derivative Works" shall mean any work, whether in Source or Object
+ * form, that is based on (or derived from) the Work and for which the
+ * editorial revisions, annotations, elaborations, or other modifications
+ * represent, as a whole, an original work of authorship. For the purposes
+ * of this License, Derivative Works shall not include works that remain
+ * separable from, or merely link (or bind by name) to the interfaces of,
+ * the Work and Derivative Works thereof.
+ *
+ * "Contribution" shall mean any work of authorship, including
+ * the original version of the Work and any modifications or additions
+ * to that Work or Derivative Works thereof, that is intentionally
+ * submitted to Licensor for inclusion in the Work by the copyright owner
+ * or by an individual or Legal Entity authorized to submit on behalf of
+ * the copyright owner. For the purposes of this definition, "submitted"
+ * means any form of electronic, verbal, or written communication sent
+ * to the Licensor or its representatives, including but not limited to
+ * communication on electronic mailing lists, source code control systems,
+ * and issue tracking systems that are managed by, or on behalf of, the
+ * Licensor for the purpose of discussing and improving the Work, but
+ * excluding communication that is conspicuously marked or otherwise
+ * designated in writing by the copyright owner as "Not a Contribution."
+ *
+ * "Contributor" shall mean Licensor and any individual or Legal Entity
+ * on behalf of whom a Contribution has been received by Licensor and
+ * subsequently incorporated within the Work.
+ *
+ * 2. Grant of Copyright License. Subject to the terms and conditions of
+ * this License, each Contributor hereby grants to You a perpetual,
+ * worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ * copyright license to reproduce, prepare Derivative Works of,
+ * publicly display, publicly perform, sublicense, and distribute the
+ * Work and such Derivative Works in Source or Object form.
+ *
+ * 3. Grant of Patent License. Subject to the terms and conditions of
+ * this License, each Contributor hereby grants to You a perpetual,
+ * worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ * (except as stated in this section) patent license to make, have made,
+ * use, offer to sell, sell, import, and otherwise transfer the Work,
+ * where such license applies only to those patent claims licensable
+ * by such Contributor that are necessarily infringed by their
+ * Contribution(s) alone or by combination of their Contribution(s)
+ * with the Work to which such Contribution(s) was submitted. If You
+ * institute patent litigation against any entity (including a
+ * cross-claim or counterclaim in a lawsuit) alleging that the Work
+ * or a Contribution incorporated within the Work constitutes direct
+ * or contributory patent infringement, then any patent licenses
+ * granted to You under this License for that Work shall terminate
+ * as of the date such litigation is filed.
+ *
+ * 4. Redistribution. You may reproduce and distribute copies of the
+ * Work or Derivative Works thereof in any medium, with or without
+ * modifications, and in Source or Object form, provided that You
+ * meet the following conditions:
+ *
+ * (a) You must give any other recipients of the Work or
+ * Derivative Works a copy of this License; and
+ *
+ * (b) You must cause any modified files to carry prominent notices
+ * stating that You changed the files; and
+ *
+ * (c) You must retain, in the Source form of any Derivative Works
+ * that You distribute, all copyright, patent, trademark, and
+ * attribution notices from the Source form of the Work,
+ * excluding those notices that do not pertain to any part of
+ * the Derivative Works; and
+ *
+ * (d) If the Work includes a "NOTICE" text file as part of its
+ * distribution, then any Derivative Works that You distribute must
+ * include a readable copy of the attribution notices contained
+ * within such NOTICE file, excluding those notices that do not
+ * pertain to any part of the Derivative Works, in at least one
+ * of the following places: within a NOTICE text file distributed
+ * as part of the Derivative Works; within the Source form or
+ * documentation, if provided along with the Derivative Works; or,
+ * within a display generated by the Derivative Works, if and
+ * wherever such third-party notices normally appear. The contents
+ * of the NOTICE file are for informational purposes only and
+ * do not modify the License. You may add Your own attribution
+ * notices within Derivative Works that You distribute, alongside
+ * or as an addendum to the NOTICE text from the Work, provided
+ * that such additional attribution notices cannot be construed
+ * as modifying the License.
+ *
+ * You may add Your own copyright statement to Your modifications and
+ * may provide additional or different license terms and conditions
+ * for use, reproduction, or distribution of Your modifications, or
+ * for any such Derivative Works as a whole, provided Your use,
+ * reproduction, and distribution of the Work otherwise complies with
+ * the conditions stated in this License.
+ *
+ * 5. Submission of Contributions. Unless You explicitly state otherwise,
+ * any Contribution intentionally submitted for inclusion in the Work
+ * by You to the Licensor shall be under the terms and conditions of
+ * this License, without any additional terms or conditions.
+ * Notwithstanding the above, nothing herein shall supersede or modify
+ * the terms of any separate license agreement you may have executed
+ * with Licensor regarding such Contributions.
+ *
+ * 6. Trademarks. This License does not grant permission to use the trade
+ * names, trademarks, service marks, or product names of the Licensor,
+ * except as required for reasonable and customary use in describing the
+ * origin of the Work and reproducing the content of the NOTICE file.
+ *
+ * 7. Disclaimer of Warranty. Unless required by applicable law or
+ * agreed to in writing, Licensor provides the Work (and each
+ * Contributor provides its Contributions) on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied, including, without limitation, any warranties or conditions
+ * of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ * PARTICULAR PURPOSE. You are solely responsible for determining the
+ * appropriateness of using or redistributing the Work and assume any
+ * risks associated with Your exercise of permissions under this License.
+ *
+ * 8. Limitation of Liability. In no event and under no legal theory,
+ * whether in tort (including negligence), contract, or otherwise,
+ * unless required by applicable law (such as deliberate and grossly
+ * negligent acts) or agreed to in writing, shall any Contributor be
+ * liable to You for damages, including any direct, indirect, special,
+ * incidental, or consequential damages of any character arising as a
+ * result of this License or out of the use or inability to use the
+ * Work (including but not limited to damages for loss of goodwill,
+ * work stoppage, computer failure or malfunction, or any and all
+ * other commercial damages or losses), even if such Contributor
+ * has been advised of the possibility of such damages.
+ *
+ * 9. Accepting Warranty or Additional Liability. While redistributing
+ * the Work or Derivative Works thereof, You may choose to offer,
+ * and charge a fee for, acceptance of support, warranty, indemnity,
+ * or other liability obligations and/or rights consistent with this
+ * License. However, in accepting such obligations, You may act only
+ * on Your own behalf and on Your sole responsibility, not on behalf
+ * of any other Contributor, and only if You agree to indemnify,
+ * defend, and hold each Contributor harmless for any liability
+ * incurred by, or claims asserted against, such Contributor by reason
+ * of your accepting any such warranty or additional liability.
+ *
+ * END OF TERMS AND CONDITIONS
+ *
+ * APPENDIX: How to apply the Apache License to your work.
+ *
+ * To apply the Apache License to your work, attach the following
+ * boilerplate notice, with the fields enclosed by brackets "[]"
+ * replaced with your own identifying information. (Don't include
+ * the brackets!) The text should be enclosed in the appropriate
+ * comment syntax for the file format. We also recommend that a
+ * file or class name and description of purpose be included on the
+ * same "printed page" as the copyright notice for easier
+ * identification within third-party archives.
+ *
+ * Copyright [yyyy] [name of copyright owner]
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
/*
* $Id: LdifComposer.java,v 1.4 2003/07/31 21:44:49 akarasulu Exp $
@@ -216,7 +216,7 @@
package org.apache.ldap.common.ldif ;
-import org.apache.commons.collections.MultiMap ;
+import org.apache.ldap.common.util.MultiMap ;
/**
Modified: incubator/directory/ldap/trunk/common/src/java/org/apache/ldap/common/ldif/LdifComposerImpl.java
==============================================================================
--- incubator/directory/ldap/trunk/common/src/java/org/apache/ldap/common/ldif/LdifComposerImpl.java (original)
+++ incubator/directory/ldap/trunk/common/src/java/org/apache/ldap/common/ldif/LdifComposerImpl.java Sat Sep 25 12:11:47 2004
@@ -1,207 +1,207 @@
-/*
- * Apache License
- * Version 2.0, January 2004
- * http://www.apache.org/licenses/
- *
- * TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
- *
- * 1. Definitions.
- *
- * "License" shall mean the terms and conditions for use, reproduction,
- * and distribution as defined by Sections 1 through 9 of this document.
- *
- * "Licensor" shall mean the copyright owner or entity authorized by
- * the copyright owner that is granting the License.
- *
- * "Legal Entity" shall mean the union of the acting entity and all
- * other entities that control, are controlled by, or are under common
- * control with that entity. For the purposes of this definition,
- * "control" means (i) the power, direct or indirect, to cause the
- * direction or management of such entity, whether by contract or
- * otherwise, or (ii) ownership of fifty percent (50%) or more of the
- * outstanding shares, or (iii) beneficial ownership of such entity.
- *
- * "You" (or "Your") shall mean an individual or Legal Entity
- * exercising permissions granted by this License.
- *
- * "Source" form shall mean the preferred form for making modifications,
- * including but not limited to software source code, documentation
- * source, and configuration files.
- *
- * "Object" form shall mean any form resulting from mechanical
- * transformation or translation of a Source form, including but
- * not limited to compiled object code, generated documentation,
- * and conversions to other media types.
- *
- * "Work" shall mean the work of authorship, whether in Source or
- * Object form, made available under the License, as indicated by a
- * copyright notice that is included in or attached to the work
- * (an example is provided in the Appendix below).
- *
- * "Derivative Works" shall mean any work, whether in Source or Object
- * form, that is based on (or derived from) the Work and for which the
- * editorial revisions, annotations, elaborations, or other modifications
- * represent, as a whole, an original work of authorship. For the purposes
- * of this License, Derivative Works shall not include works that remain
- * separable from, or merely link (or bind by name) to the interfaces of,
- * the Work and Derivative Works thereof.
- *
- * "Contribution" shall mean any work of authorship, including
- * the original version of the Work and any modifications or additions
- * to that Work or Derivative Works thereof, that is intentionally
- * submitted to Licensor for inclusion in the Work by the copyright owner
- * or by an individual or Legal Entity authorized to submit on behalf of
- * the copyright owner. For the purposes of this definition, "submitted"
- * means any form of electronic, verbal, or written communication sent
- * to the Licensor or its representatives, including but not limited to
- * communication on electronic mailing lists, source code control systems,
- * and issue tracking systems that are managed by, or on behalf of, the
- * Licensor for the purpose of discussing and improving the Work, but
- * excluding communication that is conspicuously marked or otherwise
- * designated in writing by the copyright owner as "Not a Contribution."
- *
- * "Contributor" shall mean Licensor and any individual or Legal Entity
- * on behalf of whom a Contribution has been received by Licensor and
- * subsequently incorporated within the Work.
- *
- * 2. Grant of Copyright License. Subject to the terms and conditions of
- * this License, each Contributor hereby grants to You a perpetual,
- * worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- * copyright license to reproduce, prepare Derivative Works of,
- * publicly display, publicly perform, sublicense, and distribute the
- * Work and such Derivative Works in Source or Object form.
- *
- * 3. Grant of Patent License. Subject to the terms and conditions of
- * this License, each Contributor hereby grants to You a perpetual,
- * worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- * (except as stated in this section) patent license to make, have made,
- * use, offer to sell, sell, import, and otherwise transfer the Work,
- * where such license applies only to those patent claims licensable
- * by such Contributor that are necessarily infringed by their
- * Contribution(s) alone or by combination of their Contribution(s)
- * with the Work to which such Contribution(s) was submitted. If You
- * institute patent litigation against any entity (including a
- * cross-claim or counterclaim in a lawsuit) alleging that the Work
- * or a Contribution incorporated within the Work constitutes direct
- * or contributory patent infringement, then any patent licenses
- * granted to You under this License for that Work shall terminate
- * as of the date such litigation is filed.
- *
- * 4. Redistribution. You may reproduce and distribute copies of the
- * Work or Derivative Works thereof in any medium, with or without
- * modifications, and in Source or Object form, provided that You
- * meet the following conditions:
- *
- * (a) You must give any other recipients of the Work or
- * Derivative Works a copy of this License; and
- *
- * (b) You must cause any modified files to carry prominent notices
- * stating that You changed the files; and
- *
- * (c) You must retain, in the Source form of any Derivative Works
- * that You distribute, all copyright, patent, trademark, and
- * attribution notices from the Source form of the Work,
- * excluding those notices that do not pertain to any part of
- * the Derivative Works; and
- *
- * (d) If the Work includes a "NOTICE" text file as part of its
- * distribution, then any Derivative Works that You distribute must
- * include a readable copy of the attribution notices contained
- * within such NOTICE file, excluding those notices that do not
- * pertain to any part of the Derivative Works, in at least one
- * of the following places: within a NOTICE text file distributed
- * as part of the Derivative Works; within the Source form or
- * documentation, if provided along with the Derivative Works; or,
- * within a display generated by the Derivative Works, if and
- * wherever such third-party notices normally appear. The contents
- * of the NOTICE file are for informational purposes only and
- * do not modify the License. You may add Your own attribution
- * notices within Derivative Works that You distribute, alongside
- * or as an addendum to the NOTICE text from the Work, provided
- * that such additional attribution notices cannot be construed
- * as modifying the License.
- *
- * You may add Your own copyright statement to Your modifications and
- * may provide additional or different license terms and conditions
- * for use, reproduction, or distribution of Your modifications, or
- * for any such Derivative Works as a whole, provided Your use,
- * reproduction, and distribution of the Work otherwise complies with
- * the conditions stated in this License.
- *
- * 5. Submission of Contributions. Unless You explicitly state otherwise,
- * any Contribution intentionally submitted for inclusion in the Work
- * by You to the Licensor shall be under the terms and conditions of
- * this License, without any additional terms or conditions.
- * Notwithstanding the above, nothing herein shall supersede or modify
- * the terms of any separate license agreement you may have executed
- * with Licensor regarding such Contributions.
- *
- * 6. Trademarks. This License does not grant permission to use the trade
- * names, trademarks, service marks, or product names of the Licensor,
- * except as required for reasonable and customary use in describing the
- * origin of the Work and reproducing the content of the NOTICE file.
- *
- * 7. Disclaimer of Warranty. Unless required by applicable law or
- * agreed to in writing, Licensor provides the Work (and each
- * Contributor provides its Contributions) on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
- * implied, including, without limitation, any warranties or conditions
- * of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
- * PARTICULAR PURPOSE. You are solely responsible for determining the
- * appropriateness of using or redistributing the Work and assume any
- * risks associated with Your exercise of permissions under this License.
- *
- * 8. Limitation of Liability. In no event and under no legal theory,
- * whether in tort (including negligence), contract, or otherwise,
- * unless required by applicable law (such as deliberate and grossly
- * negligent acts) or agreed to in writing, shall any Contributor be
- * liable to You for damages, including any direct, indirect, special,
- * incidental, or consequential damages of any character arising as a
- * result of this License or out of the use or inability to use the
- * Work (including but not limited to damages for loss of goodwill,
- * work stoppage, computer failure or malfunction, or any and all
- * other commercial damages or losses), even if such Contributor
- * has been advised of the possibility of such damages.
- *
- * 9. Accepting Warranty or Additional Liability. While redistributing
- * the Work or Derivative Works thereof, You may choose to offer,
- * and charge a fee for, acceptance of support, warranty, indemnity,
- * or other liability obligations and/or rights consistent with this
- * License. However, in accepting such obligations, You may act only
- * on Your own behalf and on Your sole responsibility, not on behalf
- * of any other Contributor, and only if You agree to indemnify,
- * defend, and hold each Contributor harmless for any liability
- * incurred by, or claims asserted against, such Contributor by reason
- * of your accepting any such warranty or additional liability.
- *
- * END OF TERMS AND CONDITIONS
- *
- * APPENDIX: How to apply the Apache License to your work.
- *
- * To apply the Apache License to your work, attach the following
- * boilerplate notice, with the fields enclosed by brackets "[]"
- * replaced with your own identifying information. (Don't include
- * the brackets!) The text should be enclosed in the appropriate
- * comment syntax for the file format. We also recommend that a
- * file or class name and description of purpose be included on the
- * same "printed page" as the copyright notice for easier
- * identification within third-party archives.
- *
- * Copyright [yyyy] [name of copyright owner]
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
+/*
+ * Apache License
+ * Version 2.0, January 2004
+ * http://www.apache.org/licenses/
+ *
+ * TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+ *
+ * 1. Definitions.
+ *
+ * "License" shall mean the terms and conditions for use, reproduction,
+ * and distribution as defined by Sections 1 through 9 of this document.
+ *
+ * "Licensor" shall mean the copyright owner or entity authorized by
+ * the copyright owner that is granting the License.
+ *
+ * "Legal Entity" shall mean the union of the acting entity and all
+ * other entities that control, are controlled by, or are under common
+ * control with that entity. For the purposes of this definition,
+ * "control" means (i) the power, direct or indirect, to cause the
+ * direction or management of such entity, whether by contract or
+ * otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ * outstanding shares, or (iii) beneficial ownership of such entity.
+ *
+ * "You" (or "Your") shall mean an individual or Legal Entity
+ * exercising permissions granted by this License.
+ *
+ * "Source" form shall mean the preferred form for making modifications,
+ * including but not limited to software source code, documentation
+ * source, and configuration files.
+ *
+ * "Object" form shall mean any form resulting from mechanical
+ * transformation or translation of a Source form, including but
+ * not limited to compiled object code, generated documentation,
+ * and conversions to other media types.
+ *
+ * "Work" shall mean the work of authorship, whether in Source or
+ * Object form, made available under the License, as indicated by a
+ * copyright notice that is included in or attached to the work
+ * (an example is provided in the Appendix below).
+ *
+ * "Derivative Works" shall mean any work, whether in Source or Object
+ * form, that is based on (or derived from) the Work and for which the
+ * editorial revisions, annotations, elaborations, or other modifications
+ * represent, as a whole, an original work of authorship. For the purposes
+ * of this License, Derivative Works shall not include works that remain
+ * separable from, or merely link (or bind by name) to the interfaces of,
+ * the Work and Derivative Works thereof.
+ *
+ * "Contribution" shall mean any work of authorship, including
+ * the original version of the Work and any modifications or additions
+ * to that Work or Derivative Works thereof, that is intentionally
+ * submitted to Licensor for inclusion in the Work by the copyright owner
+ * or by an individual or Legal Entity authorized to submit on behalf of
+ * the copyright owner. For the purposes of this definition, "submitted"
+ * means any form of electronic, verbal, or written communication sent
+ * to the Licensor or its representatives, including but not limited to
+ * communication on electronic mailing lists, source code control systems,
+ * and issue tracking systems that are managed by, or on behalf of, the
+ * Licensor for the purpose of discussing and improving the Work, but
+ * excluding communication that is conspicuously marked or otherwise
+ * designated in writing by the copyright owner as "Not a Contribution."
+ *
+ * "Contributor" shall mean Licensor and any individual or Legal Entity
+ * on behalf of whom a Contribution has been received by Licensor and
+ * subsequently incorporated within the Work.
+ *
+ * 2. Grant of Copyright License. Subject to the terms and conditions of
+ * this License, each Contributor hereby grants to You a perpetual,
+ * worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ * copyright license to reproduce, prepare Derivative Works of,
+ * publicly display, publicly perform, sublicense, and distribute the
+ * Work and such Derivative Works in Source or Object form.
+ *
+ * 3. Grant of Patent License. Subject to the terms and conditions of
+ * this License, each Contributor hereby grants to You a perpetual,
+ * worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ * (except as stated in this section) patent license to make, have made,
+ * use, offer to sell, sell, import, and otherwise transfer the Work,
+ * where such license applies only to those patent claims licensable
+ * by such Contributor that are necessarily infringed by their
+ * Contribution(s) alone or by combination of their Contribution(s)
+ * with the Work to which such Contribution(s) was submitted. If You
+ * institute patent litigation against any entity (including a
+ * cross-claim or counterclaim in a lawsuit) alleging that the Work
+ * or a Contribution incorporated within the Work constitutes direct
+ * or contributory patent infringement, then any patent licenses
+ * granted to You under this License for that Work shall terminate
+ * as of the date such litigation is filed.
+ *
+ * 4. Redistribution. You may reproduce and distribute copies of the
+ * Work or Derivative Works thereof in any medium, with or without
+ * modifications, and in Source or Object form, provided that You
+ * meet the following conditions:
+ *
+ * (a) You must give any other recipients of the Work or
+ * Derivative Works a copy of this License; and
+ *
+ * (b) You must cause any modified files to carry prominent notices
+ * stating that You changed the files; and
+ *
+ * (c) You must retain, in the Source form of any Derivative Works
+ * that You distribute, all copyright, patent, trademark, and
+ * attribution notices from the Source form of the Work,
+ * excluding those notices that do not pertain to any part of
+ * the Derivative Works; and
+ *
+ * (d) If the Work includes a "NOTICE" text file as part of its
+ * distribution, then any Derivative Works that You distribute must
+ * include a readable copy of the attribution notices contained
+ * within such NOTICE file, excluding those notices that do not
+ * pertain to any part of the Derivative Works, in at least one
+ * of the following places: within a NOTICE text file distributed
+ * as part of the Derivative Works; within the Source form or
+ * documentation, if provided along with the Derivative Works; or,
+ * within a display generated by the Derivative Works, if and
+ * wherever such third-party notices normally appear. The contents
+ * of the NOTICE file are for informational purposes only and
+ * do not modify the License. You may add Your own attribution
+ * notices within Derivative Works that You distribute, alongside
+ * or as an addendum to the NOTICE text from the Work, provided
+ * that such additional attribution notices cannot be construed
+ * as modifying the License.
+ *
+ * You may add Your own copyright statement to Your modifications and
+ * may provide additional or different license terms and conditions
+ * for use, reproduction, or distribution of Your modifications, or
+ * for any such Derivative Works as a whole, provided Your use,
+ * reproduction, and distribution of the Work otherwise complies with
+ * the conditions stated in this License.
+ *
+ * 5. Submission of Contributions. Unless You explicitly state otherwise,
+ * any Contribution intentionally submitted for inclusion in the Work
+ * by You to the Licensor shall be under the terms and conditions of
+ * this License, without any additional terms or conditions.
+ * Notwithstanding the above, nothing herein shall supersede or modify
+ * the terms of any separate license agreement you may have executed
+ * with Licensor regarding such Contributions.
+ *
+ * 6. Trademarks. This License does not grant permission to use the trade
+ * names, trademarks, service marks, or product names of the Licensor,
+ * except as required for reasonable and customary use in describing the
+ * origin of the Work and reproducing the content of the NOTICE file.
+ *
+ * 7. Disclaimer of Warranty. Unless required by applicable law or
+ * agreed to in writing, Licensor provides the Work (and each
+ * Contributor provides its Contributions) on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied, including, without limitation, any warranties or conditions
+ * of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ * PARTICULAR PURPOSE. You are solely responsible for determining the
+ * appropriateness of using or redistributing the Work and assume any
+ * risks associated with Your exercise of permissions under this License.
+ *
+ * 8. Limitation of Liability. In no event and under no legal theory,
+ * whether in tort (including negligence), contract, or otherwise,
+ * unless required by applicable law (such as deliberate and grossly
+ * negligent acts) or agreed to in writing, shall any Contributor be
+ * liable to You for damages, including any direct, indirect, special,
+ * incidental, or consequential damages of any character arising as a
+ * result of this License or out of the use or inability to use the
+ * Work (including but not limited to damages for loss of goodwill,
+ * work stoppage, computer failure or malfunction, or any and all
+ * other commercial damages or losses), even if such Contributor
+ * has been advised of the possibility of such damages.
+ *
+ * 9. Accepting Warranty or Additional Liability. While redistributing
+ * the Work or Derivative Works thereof, You may choose to offer,
+ * and charge a fee for, acceptance of support, warranty, indemnity,
+ * or other liability obligations and/or rights consistent with this
+ * License. However, in accepting such obligations, You may act only
+ * on Your own behalf and on Your sole responsibility, not on behalf
+ * of any other Contributor, and only if You agree to indemnify,
+ * defend, and hold each Contributor harmless for any liability
+ * incurred by, or claims asserted against, such Contributor by reason
+ * of your accepting any such warranty or additional liability.
+ *
+ * END OF TERMS AND CONDITIONS
+ *
+ * APPENDIX: How to apply the Apache License to your work.
+ *
+ * To apply the Apache License to your work, attach the following
+ * boilerplate notice, with the fields enclosed by brackets "[]"
+ * replaced with your own identifying information. (Don't include
+ * the brackets!) The text should be enclosed in the appropriate
+ * comment syntax for the file format. We also recommend that a
+ * file or class name and description of purpose be included on the
+ * same "printed page" as the copyright notice for easier
+ * identification within third-party archives.
+ *
+ * Copyright [yyyy] [name of copyright owner]
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
/*
* $Id: LdifComposerImpl.java,v 1.4 2003/07/31 22:01:52 akarasulu Exp $
@@ -221,10 +221,8 @@
import java.util.Collection;
import java.util.Iterator;
-import org.apache.commons.collections.MultiMap;
-
import org.apache.ldap.common.util.Base64;
-
+import org.apache.ldap.common.util.MultiMap;
/**
Modified: incubator/directory/ldap/trunk/common/src/java/org/apache/ldap/common/ldif/LdifParser.java
==============================================================================
--- incubator/directory/ldap/trunk/common/src/java/org/apache/ldap/common/ldif/LdifParser.java (original)
+++ incubator/directory/ldap/trunk/common/src/java/org/apache/ldap/common/ldif/LdifParser.java Sat Sep 25 12:11:47 2004
@@ -1,218 +1,18 @@
-/*
- * Apache License
- * Version 2.0, January 2004
- * http://www.apache.org/licenses/
- *
- * TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
- *
- * 1. Definitions.
- *
- * "License" shall mean the terms and conditions for use, reproduction,
- * and distribution as defined by Sections 1 through 9 of this document.
- *
- * "Licensor" shall mean the copyright owner or entity authorized by
- * the copyright owner that is granting the License.
- *
- * "Legal Entity" shall mean the union of the acting entity and all
- * other entities that control, are controlled by, or are under common
- * control with that entity. For the purposes of this definition,
- * "control" means (i) the power, direct or indirect, to cause the
- * direction or management of such entity, whether by contract or
- * otherwise, or (ii) ownership of fifty percent (50%) or more of the
- * outstanding shares, or (iii) beneficial ownership of such entity.
- *
- * "You" (or "Your") shall mean an individual or Legal Entity
- * exercising permissions granted by this License.
- *
- * "Source" form shall mean the preferred form for making modifications,
- * including but not limited to software source code, documentation
- * source, and configuration files.
- *
- * "Object" form shall mean any form resulting from mechanical
- * transformation or translation of a Source form, including but
- * not limited to compiled object code, generated documentation,
- * and conversions to other media types.
- *
- * "Work" shall mean the work of authorship, whether in Source or
- * Object form, made available under the License, as indicated by a
- * copyright notice that is included in or attached to the work
- * (an example is provided in the Appendix below).
- *
- * "Derivative Works" shall mean any work, whether in Source or Object
- * form, that is based on (or derived from) the Work and for which the
- * editorial revisions, annotations, elaborations, or other modifications
- * represent, as a whole, an original work of authorship. For the purposes
- * of this License, Derivative Works shall not include works that remain
- * separable from, or merely link (or bind by name) to the interfaces of,
- * the Work and Derivative Works thereof.
- *
- * "Contribution" shall mean any work of authorship, including
- * the original version of the Work and any modifications or additions
- * to that Work or Derivative Works thereof, that is intentionally
- * submitted to Licensor for inclusion in the Work by the copyright owner
- * or by an individual or Legal Entity authorized to submit on behalf of
- * the copyright owner. For the purposes of this definition, "submitted"
- * means any form of electronic, verbal, or written communication sent
- * to the Licensor or its representatives, including but not limited to
- * communication on electronic mailing lists, source code control systems,
- * and issue tracking systems that are managed by, or on behalf of, the
- * Licensor for the purpose of discussing and improving the Work, but
- * excluding communication that is conspicuously marked or otherwise
- * designated in writing by the copyright owner as "Not a Contribution."
- *
- * "Contributor" shall mean Licensor and any individual or Legal Entity
- * on behalf of whom a Contribution has been received by Licensor and
- * subsequently incorporated within the Work.
- *
- * 2. Grant of Copyright License. Subject to the terms and conditions of
- * this License, each Contributor hereby grants to You a perpetual,
- * worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- * copyright license to reproduce, prepare Derivative Works of,
- * publicly display, publicly perform, sublicense, and distribute the
- * Work and such Derivative Works in Source or Object form.
- *
- * 3. Grant of Patent License. Subject to the terms and conditions of
- * this License, each Contributor hereby grants to You a perpetual,
- * worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- * (except as stated in this section) patent license to make, have made,
- * use, offer to sell, sell, import, and otherwise transfer the Work,
- * where such license applies only to those patent claims licensable
- * by such Contributor that are necessarily infringed by their
- * Contribution(s) alone or by combination of their Contribution(s)
- * with the Work to which such Contribution(s) was submitted. If You
- * institute patent litigation against any entity (including a
- * cross-claim or counterclaim in a lawsuit) alleging that the Work
- * or a Contribution incorporated within the Work constitutes direct
- * or contributory patent infringement, then any patent licenses
- * granted to You under this License for that Work shall terminate
- * as of the date such litigation is filed.
- *
- * 4. Redistribution. You may reproduce and distribute copies of the
- * Work or Derivative Works thereof in any medium, with or without
- * modifications, and in Source or Object form, provided that You
- * meet the following conditions:
- *
- * (a) You must give any other recipients of the Work or
- * Derivative Works a copy of this License; and
- *
- * (b) You must cause any modified files to carry prominent notices
- * stating that You changed the files; and
- *
- * (c) You must retain, in the Source form of any Derivative Works
- * that You distribute, all copyright, patent, trademark, and
- * attribution notices from the Source form of the Work,
- * excluding those notices that do not pertain to any part of
- * the Derivative Works; and
- *
- * (d) If the Work includes a "NOTICE" text file as part of its
- * distribution, then any Derivative Works that You distribute must
- * include a readable copy of the attribution notices contained
- * within such NOTICE file, excluding those notices that do not
- * pertain to any part of the Derivative Works, in at least one
- * of the following places: within a NOTICE text file distributed
- * as part of the Derivative Works; within the Source form or
- * documentation, if provided along with the Derivative Works; or,
- * within a display generated by the Derivative Works, if and
- * wherever such third-party notices normally appear. The contents
- * of the NOTICE file are for informational purposes only and
- * do not modify the License. You may add Your own attribution
- * notices within Derivative Works that You distribute, alongside
- * or as an addendum to the NOTICE text from the Work, provided
- * that such additional attribution notices cannot be construed
- * as modifying the License.
- *
- * You may add Your own copyright statement to Your modifications and
- * may provide additional or different license terms and conditions
- * for use, reproduction, or distribution of Your modifications, or
- * for any such Derivative Works as a whole, provided Your use,
- * reproduction, and distribution of the Work otherwise complies with
- * the conditions stated in this License.
- *
- * 5. Submission of Contributions. Unless You explicitly state otherwise,
- * any Contribution intentionally submitted for inclusion in the Work
- * by You to the Licensor shall be under the terms and conditions of
- * this License, without any additional terms or conditions.
- * Notwithstanding the above, nothing herein shall supersede or modify
- * the terms of any separate license agreement you may have executed
- * with Licensor regarding such Contributions.
- *
- * 6. Trademarks. This License does not grant permission to use the trade
- * names, trademarks, service marks, or product names of the Licensor,
- * except as required for reasonable and customary use in describing the
- * origin of the Work and reproducing the content of the NOTICE file.
- *
- * 7. Disclaimer of Warranty. Unless required by applicable law or
- * agreed to in writing, Licensor provides the Work (and each
- * Contributor provides its Contributions) on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
- * implied, including, without limitation, any warranties or conditions
- * of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
- * PARTICULAR PURPOSE. You are solely responsible for determining the
- * appropriateness of using or redistributing the Work and assume any
- * risks associated with Your exercise of permissions under this License.
- *
- * 8. Limitation of Liability. In no event and under no legal theory,
- * whether in tort (including negligence), contract, or otherwise,
- * unless required by applicable law (such as deliberate and grossly
- * negligent acts) or agreed to in writing, shall any Contributor be
- * liable to You for damages, including any direct, indirect, special,
- * incidental, or consequential damages of any character arising as a
- * result of this License or out of the use or inability to use the
- * Work (including but not limited to damages for loss of goodwill,
- * work stoppage, computer failure or malfunction, or any and all
- * other commercial damages or losses), even if such Contributor
- * has been advised of the possibility of such damages.
- *
- * 9. Accepting Warranty or Additional Liability. While redistributing
- * the Work or Derivative Works thereof, You may choose to offer,
- * and charge a fee for, acceptance of support, warranty, indemnity,
- * or other liability obligations and/or rights consistent with this
- * License. However, in accepting such obligations, You may act only
- * on Your own behalf and on Your sole responsibility, not on behalf
- * of any other Contributor, and only if You agree to indemnify,
- * defend, and hold each Contributor harmless for any liability
- * incurred by, or claims asserted against, such Contributor by reason
- * of your accepting any such warranty or additional liability.
- *
- * END OF TERMS AND CONDITIONS
- *
- * APPENDIX: How to apply the Apache License to your work.
- *
- * To apply the Apache License to your work, attach the following
- * boilerplate notice, with the fields enclosed by brackets "[]"
- * replaced with your own identifying information. (Don't include
- * the brackets!) The text should be enclosed in the appropriate
- * comment syntax for the file format. We also recommend that a
- * file or class name and description of purpose be included on the
- * same "printed page" as the copyright notice for easier
- * identification within third-party archives.
- *
- * Copyright [yyyy] [name of copyright owner]
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
/*
- * $Id: LdifParser.java,v 1.7 2003/07/31 21:44:49 akarasulu Exp $
- * $Prologue$
+ * Copyright 2001-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
*
- * -- (c) LDAPd Group --
- * -- Please refer to the LICENSE.txt file in the root directory of --
- * -- any LDAPd project for copyright and distribution information. --
+ * http://www.apache.org/licenses/LICENSE-2.0
*
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
*/
-
package org.apache.ldap.common.ldif ;
@@ -221,7 +21,7 @@
import javax.naming.NamingException ;
import javax.naming.directory.Attributes ;
-import org.apache.commons.collections.MultiMap ;
+import org.apache.ldap.common.util.MultiMap;
Modified: incubator/directory/ldap/trunk/common/src/java/org/apache/ldap/common/ldif/LdifParserImpl.java
==============================================================================
--- incubator/directory/ldap/trunk/common/src/java/org/apache/ldap/common/ldif/LdifParserImpl.java (original)
+++ incubator/directory/ldap/trunk/common/src/java/org/apache/ldap/common/ldif/LdifParserImpl.java Sat Sep 25 12:11:47 2004
@@ -1,215 +1,17 @@
-/*
- * Apache License
- * Version 2.0, January 2004
- * http://www.apache.org/licenses/
- *
- * TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
- *
- * 1. Definitions.
- *
- * "License" shall mean the terms and conditions for use, reproduction,
- * and distribution as defined by Sections 1 through 9 of this document.
- *
- * "Licensor" shall mean the copyright owner or entity authorized by
- * the copyright owner that is granting the License.
- *
- * "Legal Entity" shall mean the union of the acting entity and all
- * other entities that control, are controlled by, or are under common
- * control with that entity. For the purposes of this definition,
- * "control" means (i) the power, direct or indirect, to cause the
- * direction or management of such entity, whether by contract or
- * otherwise, or (ii) ownership of fifty percent (50%) or more of the
- * outstanding shares, or (iii) beneficial ownership of such entity.
- *
- * "You" (or "Your") shall mean an individual or Legal Entity
- * exercising permissions granted by this License.
- *
- * "Source" form shall mean the preferred form for making modifications,
- * including but not limited to software source code, documentation
- * source, and configuration files.
- *
- * "Object" form shall mean any form resulting from mechanical
- * transformation or translation of a Source form, including but
- * not limited to compiled object code, generated documentation,
- * and conversions to other media types.
- *
- * "Work" shall mean the work of authorship, whether in Source or
- * Object form, made available under the License, as indicated by a
- * copyright notice that is included in or attached to the work
- * (an example is provided in the Appendix below).
- *
- * "Derivative Works" shall mean any work, whether in Source or Object
- * form, that is based on (or derived from) the Work and for which the
- * editorial revisions, annotations, elaborations, or other modifications
- * represent, as a whole, an original work of authorship. For the purposes
- * of this License, Derivative Works shall not include works that remain
- * separable from, or merely link (or bind by name) to the interfaces of,
- * the Work and Derivative Works thereof.
- *
- * "Contribution" shall mean any work of authorship, including
- * the original version of the Work and any modifications or additions
- * to that Work or Derivative Works thereof, that is intentionally
- * submitted to Licensor for inclusion in the Work by the copyright owner
- * or by an individual or Legal Entity authorized to submit on behalf of
- * the copyright owner. For the purposes of this definition, "submitted"
- * means any form of electronic, verbal, or written communication sent
- * to the Licensor or its representatives, including but not limited to
- * communication on electronic mailing lists, source code control systems,
- * and issue tracking systems that are managed by, or on behalf of, the
- * Licensor for the purpose of discussing and improving the Work, but
- * excluding communication that is conspicuously marked or otherwise
- * designated in writing by the copyright owner as "Not a Contribution."
- *
- * "Contributor" shall mean Licensor and any individual or Legal Entity
- * on behalf of whom a Contribution has been received by Licensor and
- * subsequently incorporated within the Work.
- *
- * 2. Grant of Copyright License. Subject to the terms and conditions of
- * this License, each Contributor hereby grants to You a perpetual,
- * worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- * copyright license to reproduce, prepare Derivative Works of,
- * publicly display, publicly perform, sublicense, and distribute the
- * Work and such Derivative Works in Source or Object form.
- *
- * 3. Grant of Patent License. Subject to the terms and conditions of
- * this License, each Contributor hereby grants to You a perpetual,
- * worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- * (except as stated in this section) patent license to make, have made,
- * use, offer to sell, sell, import, and otherwise transfer the Work,
- * where such license applies only to those patent claims licensable
- * by such Contributor that are necessarily infringed by their
- * Contribution(s) alone or by combination of their Contribution(s)
- * with the Work to which such Contribution(s) was submitted. If You
- * institute patent litigation against any entity (including a
- * cross-claim or counterclaim in a lawsuit) alleging that the Work
- * or a Contribution incorporated within the Work constitutes direct
- * or contributory patent infringement, then any patent licenses
- * granted to You under this License for that Work shall terminate
- * as of the date such litigation is filed.
- *
- * 4. Redistribution. You may reproduce and distribute copies of the
- * Work or Derivative Works thereof in any medium, with or without
- * modifications, and in Source or Object form, provided that You
- * meet the following conditions:
- *
- * (a) You must give any other recipients of the Work or
- * Derivative Works a copy of this License; and
- *
- * (b) You must cause any modified files to carry prominent notices
- * stating that You changed the files; and
- *
- * (c) You must retain, in the Source form of any Derivative Works
- * that You distribute, all copyright, patent, trademark, and
- * attribution notices from the Source form of the Work,
- * excluding those notices that do not pertain to any part of
- * the Derivative Works; and
- *
- * (d) If the Work includes a "NOTICE" text file as part of its
- * distribution, then any Derivative Works that You distribute must
- * include a readable copy of the attribution notices contained
- * within such NOTICE file, excluding those notices that do not
- * pertain to any part of the Derivative Works, in at least one
- * of the following places: within a NOTICE text file distributed
- * as part of the Derivative Works; within the Source form or
- * documentation, if provided along with the Derivative Works; or,
- * within a display generated by the Derivative Works, if and
- * wherever such third-party notices normally appear. The contents
- * of the NOTICE file are for informational purposes only and
- * do not modify the License. You may add Your own attribution
- * notices within Derivative Works that You distribute, alongside
- * or as an addendum to the NOTICE text from the Work, provided
- * that such additional attribution notices cannot be construed
- * as modifying the License.
- *
- * You may add Your own copyright statement to Your modifications and
- * may provide additional or different license terms and conditions
- * for use, reproduction, or distribution of Your modifications, or
- * for any such Derivative Works as a whole, provided Your use,
- * reproduction, and distribution of the Work otherwise complies with
- * the conditions stated in this License.
- *
- * 5. Submission of Contributions. Unless You explicitly state otherwise,
- * any Contribution intentionally submitted for inclusion in the Work
- * by You to the Licensor shall be under the terms and conditions of
- * this License, without any additional terms or conditions.
- * Notwithstanding the above, nothing herein shall supersede or modify
- * the terms of any separate license agreement you may have executed
- * with Licensor regarding such Contributions.
- *
- * 6. Trademarks. This License does not grant permission to use the trade
- * names, trademarks, service marks, or product names of the Licensor,
- * except as required for reasonable and customary use in describing the
- * origin of the Work and reproducing the content of the NOTICE file.
- *
- * 7. Disclaimer of Warranty. Unless required by applicable law or
- * agreed to in writing, Licensor provides the Work (and each
- * Contributor provides its Contributions) on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
- * implied, including, without limitation, any warranties or conditions
- * of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
- * PARTICULAR PURPOSE. You are solely responsible for determining the
- * appropriateness of using or redistributing the Work and assume any
- * risks associated with Your exercise of permissions under this License.
- *
- * 8. Limitation of Liability. In no event and under no legal theory,
- * whether in tort (including negligence), contract, or otherwise,
- * unless required by applicable law (such as deliberate and grossly
- * negligent acts) or agreed to in writing, shall any Contributor be
- * liable to You for damages, including any direct, indirect, special,
- * incidental, or consequential damages of any character arising as a
- * result of this License or out of the use or inability to use the
- * Work (including but not limited to damages for loss of goodwill,
- * work stoppage, computer failure or malfunction, or any and all
- * other commercial damages or losses), even if such Contributor
- * has been advised of the possibility of such damages.
- *
- * 9. Accepting Warranty or Additional Liability. While redistributing
- * the Work or Derivative Works thereof, You may choose to offer,
- * and charge a fee for, acceptance of support, warranty, indemnity,
- * or other liability obligations and/or rights consistent with this
- * License. However, in accepting such obligations, You may act only
- * on Your own behalf and on Your sole responsibility, not on behalf
- * of any other Contributor, and only if You agree to indemnify,
- * defend, and hold each Contributor harmless for any liability
- * incurred by, or claims asserted against, such Contributor by reason
- * of your accepting any such warranty or additional liability.
- *
- * END OF TERMS AND CONDITIONS
- *
- * APPENDIX: How to apply the Apache License to your work.
- *
- * To apply the Apache License to your work, attach the following
- * boilerplate notice, with the fields enclosed by brackets "[]"
- * replaced with your own identifying information. (Don't include
- * the brackets!) The text should be enclosed in the appropriate
- * comment syntax for the file format. We also recommend that a
- * file or class name and description of purpose be included on the
- * same "printed page" as the copyright notice for easier
- * identification within third-party archives.
- *
- * Copyright [yyyy] [name of copyright owner]
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
/*
- * $id$
+ * Copyright 2001-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
*
- * -- (c) LDAPd Group --
- * -- Please refer to the LICENSE.txt file in the root directory of --
- * -- any LDAPd project for copyright and distribution information. --
+ * http://www.apache.org/licenses/LICENSE-2.0
*
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
*/
package org.apache.ldap.common.ldif ;
@@ -224,9 +26,8 @@
import javax.naming.directory.Attributes ;
import javax.naming.directory.DirContext ;
-import org.apache.commons.collections.MultiMap ;
-
import org.apache.ldap.common.util.Base64 ;
+import org.apache.ldap.common.util.MultiMap;
/**
@@ -446,7 +247,6 @@
String l_line ;
String l_attrName = new String () ;
String l_attrValue = new String () ;
- String l_prevAttrName = null ;
String l_prevAttrValue = null ;
StringReader l_strIn = new StringReader( an_ldif ) ;
BufferedReader l_in = new BufferedReader( l_strIn ) ;
@@ -465,7 +265,8 @@
{
if ( l_currentModOp == -1 )
{
- throw new ParseException( "A modification"
+ " type must be supplied for a change "
+ throw new ParseException( "A modification"
+ + " type must be supplied for a change "
+ "type of modify", l_lineCount ) ;
}
l_entry.addModificationItem( l_currentModOp,
@@ -487,7 +288,6 @@
}
l_currentModOp = -1 ;
l_prevAttrValue = null ;
- l_prevAttrName = null ;
continue ;
}
// Try to advance to ':' if one exists.
@@ -579,7 +379,6 @@
l_currentModOp = DirContext.REMOVE_ATTRIBUTE ;
if ( l_attrValue != null )
{
- l_prevAttrName = l_attrName ;
l_prevAttrValue = l_attrValue ;
}
}
Modified: incubator/directory/ldap/trunk/common/src/java/org/apache/ldap/common/message/BindRequestImpl.java
==============================================================================
--- incubator/directory/ldap/trunk/common/src/java/org/apache/ldap/common/message/BindRequestImpl.java (original)
+++ incubator/directory/ldap/trunk/common/src/java/org/apache/ldap/common/message/BindRequestImpl.java Sat Sep 25 12:11:47 2004
@@ -16,7 +16,8 @@
*/
package org.apache.ldap.common.message;
-import org.apache.commons.lang.ArrayUtils;
+
+import org.apache.ldap.common.util.ArrayUtils;
/**
Modified: incubator/directory/ldap/trunk/common/src/java/org/apache/ldap/common/message/BindResponseImpl.java
==============================================================================
--- incubator/directory/ldap/trunk/common/src/java/org/apache/ldap/common/message/BindResponseImpl.java (original)
+++ incubator/directory/ldap/trunk/common/src/java/org/apache/ldap/common/message/BindResponseImpl.java Sat Sep 25 12:11:47 2004
@@ -16,7 +16,8 @@
*/
package org.apache.ldap.common.message;
-import org.apache.commons.lang.ArrayUtils;
+
+import org.apache.ldap.common.util.ArrayUtils;
/**
Modified: incubator/directory/ldap/trunk/common/src/java/org/apache/ldap/common/message/DerefAliasesEnum.java
==============================================================================
--- incubator/directory/ldap/trunk/common/src/java/org/apache/ldap/common/message/DerefAliasesEnum.java (original)
+++ incubator/directory/ldap/trunk/common/src/java/org/apache/ldap/common/message/DerefAliasesEnum.java Sat Sep 25 12:11:47 2004
@@ -1,27 +1,27 @@
-/*
- * Copyright 2004 The Apache Software Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
+/*
+ * Copyright 2004 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
package org.apache.ldap.common.message ;
-import java.util.Hashtable ;
-
-import org.apache.commons.lang.enum.ValuedEnum ;
+import java.util.Hashtable ;
+
+import org.apache.ldap.common.util.ValuedEnum;
+
-
/**
* Type-safe derefAliases search parameter enumeration which determines the mode
* of alias handling. Note that the names of these ValuedEnums correspond to
Modified: incubator/directory/ldap/trunk/common/src/java/org/apache/ldap/common/message/ExtendedRequestImpl.java
==============================================================================
--- incubator/directory/ldap/trunk/common/src/java/org/apache/ldap/common/message/ExtendedRequestImpl.java (original)
+++ incubator/directory/ldap/trunk/common/src/java/org/apache/ldap/common/message/ExtendedRequestImpl.java Sat Sep 25 12:11:47 2004
@@ -16,7 +16,8 @@
*/
package org.apache.ldap.common.message;
-import org.apache.commons.lang.ArrayUtils;
+
+import org.apache.ldap.common.util.ArrayUtils;
/**
Modified: incubator/directory/ldap/trunk/common/src/java/org/apache/ldap/common/message/ExtendedResponseImpl.java
==============================================================================
--- incubator/directory/ldap/trunk/common/src/java/org/apache/ldap/common/message/ExtendedResponseImpl.java (original)
+++ incubator/directory/ldap/trunk/common/src/java/org/apache/ldap/common/message/ExtendedResponseImpl.java Sat Sep 25 12:11:47 2004
@@ -16,7 +16,8 @@
*/
package org.apache.ldap.common.message ;
-import org.apache.commons.lang.ArrayUtils;
+
+import org.apache.ldap.common.util.ArrayUtils;
/**
Modified: incubator/directory/ldap/trunk/common/src/java/org/apache/ldap/common/message/LockableAttributesImpl.java
==============================================================================
--- incubator/directory/ldap/trunk/common/src/java/org/apache/ldap/common/message/LockableAttributesImpl.java (original)
+++ incubator/directory/ldap/trunk/common/src/java/org/apache/ldap/common/message/LockableAttributesImpl.java Sat Sep 25 12:11:47 2004
@@ -26,7 +26,7 @@
import javax.naming.directory.Attribute;
import javax.naming.directory.Attributes;
-import org.apache.commons.lang.exception.ExceptionUtils;
+import org.apache.ldap.common.util.ExceptionUtils;
import org.apache.ldap.common.Lockable;
import org.apache.ldap.common.AbstractLockable;
Modified: incubator/directory/ldap/trunk/common/src/java/org/apache/ldap/common/message/MessageTypeEnum.java
==============================================================================
--- incubator/directory/ldap/trunk/common/src/java/org/apache/ldap/common/message/MessageTypeEnum.java (original)
+++ incubator/directory/ldap/trunk/common/src/java/org/apache/ldap/common/message/MessageTypeEnum.java Sat Sep 25 12:11:47 2004
@@ -1,23 +1,23 @@
-/*
- * Copyright 2004 The Apache Software Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
+/*
+ * Copyright 2004 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
package org.apache.ldap.common.message ;
-
-
-import org.apache.commons.lang.enum.ValuedEnum ;
+
+
+import org.apache.ldap.common.util.ValuedEnum ;
/**
Modified: incubator/directory/ldap/trunk/common/src/java/org/apache/ldap/common/message/ResultCodeEnum.java
==============================================================================
--- incubator/directory/ldap/trunk/common/src/java/org/apache/ldap/common/message/ResultCodeEnum.java (original)
+++ incubator/directory/ldap/trunk/common/src/java/org/apache/ldap/common/message/ResultCodeEnum.java Sat Sep 25 12:11:47 2004
@@ -1,23 +1,23 @@
-/*
- * Copyright 2004 The Apache Software Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
+/*
+ * Copyright 2004 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
package org.apache.ldap.common.message ;
-import org.apache.commons.lang.enum.ValuedEnum ;
+import org.apache.ldap.common.util.ValuedEnum ;
/**
@@ -918,9 +918,9 @@
private ResultCodeEnum( final String a_name, final int a_value )
{
super( a_name, a_value ) ;
- }
-
-
+ }
+
+
/**
* Gets the set of general error codes.
*
Modified: incubator/directory/ldap/trunk/common/src/java/org/apache/ldap/common/message/ScopeEnum.java
==============================================================================
--- incubator/directory/ldap/trunk/common/src/java/org/apache/ldap/common/message/ScopeEnum.java (original)
+++ incubator/directory/ldap/trunk/common/src/java/org/apache/ldap/common/message/ScopeEnum.java Sat Sep 25 12:11:47 2004
@@ -19,6 +19,8 @@
import javax.naming.directory.SearchControls ;
+import org.apache.ldap.common.util.ValuedEnum;
+
/**
* Type-safe scope parameter enumeration.
@@ -28,7 +30,7 @@
* @version $Revision: 1.4 $
*/
public class ScopeEnum
- extends org.apache.commons.lang.enum.ValuedEnum
+ extends ValuedEnum
{
/** Search scope parameter value for base object search */
public static final int BASEOBJECT_VAL = SearchControls.OBJECT_SCOPE ;
Modified: incubator/directory/ldap/trunk/common/src/java/org/apache/ldap/common/name/DnParser.java
==============================================================================
--- incubator/directory/ldap/trunk/common/src/java/org/apache/ldap/common/name/DnParser.java (original)
+++ incubator/directory/ldap/trunk/common/src/java/org/apache/ldap/common/name/DnParser.java Sat Sep 25 12:11:47 2004
@@ -26,8 +26,8 @@
import javax.naming.NamingException ;
import javax.naming.InvalidNameException ;
-import org.apache.commons.lang.exception.ExceptionUtils ;
-import org.apache.commons.lang.exception.NestableRuntimeException ;
+import org.apache.ldap.common.util.ExceptionUtils ;
+import org.apache.ldap.common.util.NestableRuntimeException ;
import antlr.TokenStreamSelector ;
import antlr.RecognitionException ;
Added: incubator/directory/ldap/trunk/common/src/java/org/apache/ldap/common/util/ArrayUtils.java
==============================================================================
--- (empty file)
+++ incubator/directory/ldap/trunk/common/src/java/org/apache/ldap/common/util/ArrayUtils.java Sat Sep 25 12:11:47 2004
@@ -0,0 +1,3838 @@
+/*
+ * Copyright 2002-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.ldap.common.util;
+
+import java.lang.reflect.Array;
+import java.util.HashMap;
+import java.util.Map;
+
+
+/**
+ * <p>Operations on arrays, primitive arrays (like <code>int[]</code>) and
+ * primitive wrapper arrays (like <code>Integer[]</code>).</p>
+ *
+ * <p>This class tries to handle <code>null</code> input gracefully.
+ * An exception will not be thrown for a <code>null</code>
+ * array input. However, an Object array that contains a <code>null</code>
+ * element may throw an exception. Each method documents its behaviour.</p>
+ *
+ * @author Stephen Colebourne
+ * @author Moritz Petersen
+ * @author <a href="mailto:fredrik@westermarck.com">Fredrik Westermarck</a>
+ * @author Nikolay Metchev
+ * @author Matthew Hawthorne
+ * @author Tim O'Brien
+ * @author Pete Gieser
+ * @author Gary Gregory
+ * @author <a href="mailto:equinus100@hotmail.com">Ashwin S</a>
+ * @author Maarten Coene
+ * @since 2.0
+ * @version $Id: ArrayUtils.java,v 1.46 2004/08/15 02:12:51 bayard Exp $
+ */
+public class ArrayUtils {
+
+ /**
+ * An empty immutable <code>Object</code> array.
+ */
+ public static final Object[] EMPTY_OBJECT_ARRAY = new Object[0];
+ /**
+ * An empty immutable <code>Class</code> array.
+ */
+ public static final Class[] EMPTY_CLASS_ARRAY = new Class[0];
+ /**
+ * An empty immutable <code>String</code> array.
+ */
+ public static final String[] EMPTY_STRING_ARRAY = new String[0];
+ /**
+ * An empty immutable <code>long</code> array.
+ */
+ public static final long[] EMPTY_LONG_ARRAY = new long[0];
+ /**
+ * An empty immutable <code>Long</code> array.
+ */
+ public static final Long[] EMPTY_LONG_OBJECT_ARRAY = new Long[0];
+ /**
+ * An empty immutable <code>int</code> array.
+ */
+ public static final int[] EMPTY_INT_ARRAY = new int[0];
+ /**
+ * An empty immutable <code>Integer</code> array.
+ */
+ public static final Integer[] EMPTY_INTEGER_OBJECT_ARRAY = new Integer[0];
+ /**
+ * An empty immutable <code>short</code> array.
+ */
+ public static final short[] EMPTY_SHORT_ARRAY = new short[0];
+ /**
+ * An empty immutable <code>Short</code> array.
+ */
+ public static final Short[] EMPTY_SHORT_OBJECT_ARRAY = new Short[0];
+ /**
+ * An empty immutable <code>byte</code> array.
+ */
+ public static final byte[] EMPTY_BYTE_ARRAY = new byte[0];
+ /**
+ * An empty immutable <code>Byte</code> array.
+ */
+ public static final Byte[] EMPTY_BYTE_OBJECT_ARRAY = new Byte[0];
+ /**
+ * An empty immutable <code>double</code> array.
+ */
+ public static final double[] EMPTY_DOUBLE_ARRAY = new double[0];
+ /**
+ * An empty immutable <code>Double</code> array.
+ */
+ public static final Double[] EMPTY_DOUBLE_OBJECT_ARRAY = new Double[0];
+ /**
+ * An empty immutable <code>float</code> array.
+ */
+ public static final float[] EMPTY_FLOAT_ARRAY = new float[0];
+ /**
+ * An empty immutable <code>Float</code> array.
+ */
+ public static final Float[] EMPTY_FLOAT_OBJECT_ARRAY = new Float[0];
+ /**
+ * An empty immutable <code>boolean</code> array.
+ */
+ public static final boolean[] EMPTY_BOOLEAN_ARRAY = new boolean[0];
+ /**
+ * An empty immutable <code>Boolean</code> array.
+ */
+ public static final Boolean[] EMPTY_BOOLEAN_OBJECT_ARRAY = new Boolean[0];
+ /**
+ * An empty immutable <code>char</code> array.
+ */
+ public static final char[] EMPTY_CHAR_ARRAY = new char[0];
+ /**
+ * An empty immutable <code>Character</code> array.
+ */
+ public static final Character[] EMPTY_CHARACTER_OBJECT_ARRAY = new Character[0];
+
+ /**
+ * <p>ArrayUtils instances should NOT be constructed in standard programming.
+ * Instead, the class should be used as <code>ArrayUtils.clone(new int[] {2})</code>.</p>
+ *
+ * <p>This constructor is public to permit tools that require a JavaBean instance
+ * to operate.</p>
+ */
+ public ArrayUtils() {
+ }
+
+ // Basic methods handling multi-dimensional arrays
+ //-----------------------------------------------------------------------
+ /**
+ * <p>Outputs an array as a String, treating <code>null</code> as an empty array.</p>
+ *
+ * <p>Multi-dimensional arrays are handled correctly, including
+ * multi-dimensional primitive arrays.</p>
+ *
+ * <p>The format is that of Java source code, for example <code>{a,b}</code>.</p>
+ *
+ * @param array the array to get a toString for, may be <code>null</code>
+ * @return a String representation of the array, '{}' if null array input
+ */
+ public static String toString(Object array) {
+ return toString(array, "{}");
+ }
+
+ /**
+ * <p>Outputs an array as a String handling <code>null</code>s.</p>
+ *
+ * <p>Multi-dimensional arrays are handled correctly, including
+ * multi-dimensional primitive arrays.</p>
+ *
+ * <p>The format is that of Java source code, for example <code>{a,b}</code>.</p>
+ *
+ * @param array the array to get a toString for, may be <code>null</code>
+ * @param stringIfNull the String to return if the array is <code>null</code>
+ * @return a String representation of the array
+ */
+ public static String toString(Object array, String stringIfNull) {
+ if (array == null) {
+ return stringIfNull;
+ }
+ return new ToStringBuilder(array, ToStringStyle.SIMPLE_STYLE).append(array).toString();
+ }
+
+ /**
+ * <p>Get a hashCode for an array handling multi-dimensional arrays correctly.</p>
+ *
+ * <p>Multi-dimensional primitive arrays are also handled correctly by this method.</p>
+ *
+ * @param array the array to get a hashCode for, may be <code>null</code>
+ * @return a hashCode for the array, zero if null array input
+ */
+ public static int hashCode(Object array) {
+ return new HashCodeBuilder().append(array).toHashCode();
+ }
+
+ /**
+ * <p>Compares two arrays, using equals(), handling multi-dimensional arrays
+ * correctly.</p>
+ *
+ * <p>Multi-dimensional primitive arrays are also handled correctly by this method.</p>
+ *
+ * @param array1 the left hand array to compare, may be <code>null</code>
+ * @param array2 the right hand array to compare, may be <code>null</code>
+ * @return <code>true</code> if the arrays are equal
+ */
+ public static boolean isEquals(Object array1, Object array2) {
+ return new EqualsBuilder().append(array1, array2).isEquals();
+ }
+
+ // To map
+ //-----------------------------------------------------------------------
+ /**
+ * <p>Converts the given array into a {@link java.util.Map}. Each element of the array
+ * must be either a {@link java.util.Map.Entry} or an Array, containing at least two
+ * elements, where the first element is used as key and the second as
+ * value.</p>
+ *
+ * <p>This method can be used to initialize:</p>
+ * <pre>
+ * // Create a Map mapping colors.
+ * Map colorMap = MapUtils.toMap(new String[][] {{
+ * {"RED", "#FF0000"},
+ * {"GREEN", "#00FF00"},
+ * {"BLUE", "#0000FF"}});
+ * </pre>
+ *
+ * <p>This method returns <code>null</code> if <code>null</code> array input.</p>
+ *
+ * @param array an array whose elements are either a {@link java.util.Map.Entry} or
+ * an Array containing at least two elements, may be <code>null</code>
+ * @return a <code>Map</code> that was created from the array
+ * @throws IllegalArgumentException if one element of this Array is
+ * itself an Array containing less then two elements
+ * @throws IllegalArgumentException if the array contains elements other
+ * than {@link java.util.Map.Entry} and an Array
+ */
+ public static Map toMap(Object[] array) {
+ if (array == null) {
+ return null;
+ }
+ final Map map = new HashMap((int) (array.length * 1.5));
+ for (int i = 0; i < array.length; i++) {
+ Object object = array[i];
+ if (object instanceof Map.Entry) {
+ Map.Entry entry = (Map.Entry) object;
+ map.put(entry.getKey(), entry.getValue());
+ } else if (object instanceof Object[]) {
+ Object[] entry = (Object[]) object;
+ if (entry.length < 2) {
+ throw new IllegalArgumentException("Array element " + i + ", '"
+ + object
+ + "', has a length less than 2");
+ }
+ map.put(entry[0], entry[1]);
+ } else {
+ throw new IllegalArgumentException("Array element " + i + ", '"
+ + object
+ + "', is neither of type Map.Entry nor an Array");
+ }
+ }
+ return map;
+ }
+
+ // Clone
+ //-----------------------------------------------------------------------
+ /**
+ * <p>Shallow clones an array returning a typecast result and handling
+ * <code>null</code>.</p>
+ *
+ * <p>The objects in the array are not cloned, thus there is no special
+ * handling for multi-dimensional arrays.</p>
+ *
+ * <p>This method returns <code>null</code> if <code>null</code> array input.</p>
+ *
+ * @param array the array to shallow clone, may be <code>null</code>
+ * @return the cloned array, <code>null</code> if <code>null</code> input
+ */
+ public static Object[] clone(Object[] array) {
+ if (array == null) {
+ return null;
+ }
+ return (Object[]) array.clone();
+ }
+
+ /**
+ * <p>Clones an array returning a typecast result and handling
+ * <code>null</code>.</p>
+ *
+ * <p>This method returns <code>null</code> if <code>null</code> array input.</p>
+ *
+ * @param array the array to clone, may be <code>null</code>
+ * @return the cloned array, <code>null</code> if <code>null</code> input
+ */
+ public static long[] clone(long[] array) {
+ if (array == null) {
+ return null;
+ }
+ return (long[]) array.clone();
+ }
+
+ /**
+ * <p>Clones an array returning a typecast result and handling
+ * <code>null</code>.</p>
+ *
+ * <p>This method returns <code>null</code> if <code>null</code> array input.</p>
+ *
+ * @param array the array to clone, may be <code>null</code>
+ * @return the cloned array, <code>null</code> if <code>null</code> input
+ */
+ public static int[] clone(int[] array) {
+ if (array == null) {
+ return null;
+ }
+ return (int[]) array.clone();
+ }
+
+ /**
+ * <p>Clones an array returning a typecast result and handling
+ * <code>null</code>.</p>
+ *
+ * <p>This method returns <code>null</code> if <code>null</code> array input.</p>
+ *
+ * @param array the array to clone, may be <code>null</code>
+ * @return the cloned array, <code>null</code> if <code>null</code> input
+ */
+ public static short[] clone(short[] array) {
+ if (array == null) {
+ return null;
+ }
+ return (short[]) array.clone();
+ }
+
+ /**
+ * <p>Clones an array returning a typecast result and handling
+ * <code>null</code>.</p>
+ *
+ * <p>This method returns <code>null</code> if <code>null</code> array input.</p>
+ *
+ * @param array the array to clone, may be <code>null</code>
+ * @return the cloned array, <code>null</code> if <code>null</code> input
+ */
+ public static char[] clone(char[] array) {
+ if (array == null) {
+ return null;
+ }
+ return (char[]) array.clone();
+ }
+
+ /**
+ * <p>Clones an array returning a typecast result and handling
+ * <code>null</code>.</p>
+ *
+ * <p>This method returns <code>null</code> if <code>null</code> array input.</p>
+ *
+ * @param array the array to clone, may be <code>null</code>
+ * @return the cloned array, <code>null</code> if <code>null</code> input
+ */
+ public static byte[] clone(byte[] array) {
+ if (array == null) {
+ return null;
+ }
+ return (byte[]) array.clone();
+ }
+
+ /**
+ * <p>Clones an array returning a typecast result and handling
+ * <code>null</code>.</p>
+ *
+ * <p>This method returns <code>null</code> if <code>null</code> array input.</p>
+ *
+ * @param array the array to clone, may be <code>null</code>
+ * @return the cloned array, <code>null</code> if <code>null</code> input
+ */
+ public static double[] clone(double[] array) {
+ if (array == null) {
+ return null;
+ }
+ return (double[]) array.clone();
+ }
+
+ /**
+ * <p>Clones an array returning a typecast result and handling
+ * <code>null</code>.</p>
+ *
+ * <p>This method returns <code>null</code> if <code>null</code> array input.</p>
+ *
+ * @param array the array to clone, may be <code>null</code>
+ * @return the cloned array, <code>null</code> if <code>null</code> input
+ */
+ public static float[] clone(float[] array) {
+ if (array == null) {
+ return null;
+ }
+ return (float[]) array.clone();
+ }
+
+ /**
+ * <p>Clones an array returning a typecast result and handling
+ * <code>null</code>.</p>
+ *
+ * <p>This method returns <code>null</code> if <code>null</code> array input.</p>
+ *
+ * @param array the array to clone, may be <code>null</code>
+ * @return the cloned array, <code>null</code> if <code>null</code> input
+ */
+ public static boolean[] clone(boolean[] array) {
+ if (array == null) {
+ return null;
+ }
+ return (boolean[]) array.clone();
+ }
+
+ // Subarrays
+ //-----------------------------------------------------------------------
+ /**
+ * <p>Produces a new array containing the elements between
+ * the start and end indices.</p>
+ *
+ * <p>The start index is inclusive, the end index exclusive.
+ * Null array input produces null output.</p>
+ *
+ * <p>The component type of the subarray is always the same as
+ * that of the input array. Thus, if the input is an array of type
+ * <code>Date</code>, the following usage is envisaged:</p>
+ *
+ * <pre>
+ * Date[] someDates = (Date[])ArrayUtils.subarray(allDates, 2, 5);
+ * </pre>
+ *
+ * @param array the array
+ * @param startIndexInclusive the starting index. Undervalue (<0)
+ * is promoted to 0, overvalue (>array.length) results
+ * in an empty array.
+ * @param endIndexExclusive elements up to endIndex-1 are present in the
+ * returned subarray. Undervalue (< startIndex) produces
+ * empty array, overvalue (>array.length) is demoted to
+ * array length.
+ * @return a new array containing the elements between
+ * the start and end indices.
+ */
+ public static Object[] subarray(Object[] array, int startIndexInclusive, int endIndexExclusive) {
+ if (array == null) {
+ return null;
+ }
+ if (startIndexInclusive < 0) {
+ startIndexInclusive = 0;
+ }
+ if (endIndexExclusive > array.length) {
+ endIndexExclusive = array.length;
+ }
+ int newSize = endIndexExclusive - startIndexInclusive;
+ Class type = array.getClass().getComponentType();
+ if (newSize <= 0) {
+ return (Object[]) Array.newInstance(type, 0);
+ }
+ Object[] subarray = (Object[]) Array.newInstance(type, newSize);
+ System.arraycopy(array, startIndexInclusive, subarray, 0, newSize);
+ return subarray;
+ }
+
+ /**
+ * <p>Produces a new <code>long</code> array containing the elements
+ * between the start and end indices.</p>
+ *
+ * <p>The start index is inclusive, the end index exclusive.
+ * Null array input produces null output.</p>
+ *
+ * @param array the array
+ * @param startIndexInclusive the starting index. Undervalue (<0)
+ * is promoted to 0, overvalue (>array.length) results
+ * in an empty array.
+ * @param endIndexExclusive elements up to endIndex-1 are present in the
+ * returned subarray. Undervalue (< startIndex) produces
+ * empty array, overvalue (>array.length) is demoted to
+ * array length.
+ * @return a new array containing the elements between
+ * the start and end indices.
+ */
+ public static long[] subarray(long[] array, int startIndexInclusive, int endIndexExclusive) {
+ if (array == null) {
+ return null;
+ }
+ if (startIndexInclusive < 0) {
+ startIndexInclusive = 0;
+ }
+ if (endIndexExclusive > array.length) {
+ endIndexExclusive = array.length;
+ }
+ int newSize = endIndexExclusive - startIndexInclusive;
+ if (newSize <= 0) {
+ return EMPTY_LONG_ARRAY;
+ }
+
+ long[] subarray = new long[newSize];
+ System.arraycopy(array, startIndexInclusive, subarray, 0, newSize);
+ return subarray;
+ }
+
+ /**
+ * <p>Produces a new <code>int</code> array containing the elements
+ * between the start and end indices.</p>
+ *
+ * <p>The start index is inclusive, the end index exclusive.
+ * Null array input produces null output.</p>
+ *
+ * @param array the array
+ * @param startIndexInclusive the starting index. Undervalue (<0)
+ * is promoted to 0, overvalue (>array.length) results
+ * in an empty array.
+ * @param endIndexExclusive elements up to endIndex-1 are present in the
+ * returned subarray. Undervalue (< startIndex) produces
+ * empty array, overvalue (>array.length) is demoted to
+ * array length.
+ * @return a new array containing the elements between
+ * the start and end indices.
+ */
+ public static int[] subarray(int[] array, int startIndexInclusive, int endIndexExclusive) {
+ if (array == null) {
+ return null;
+ }
+ if (startIndexInclusive < 0) {
+ startIndexInclusive = 0;
+ }
+ if (endIndexExclusive > array.length) {
+ endIndexExclusive = array.length;
+ }
+ int newSize = endIndexExclusive - startIndexInclusive;
+ if (newSize <= 0) {
+ return EMPTY_INT_ARRAY;
+ }
+
+ int[] subarray = new int[newSize];
+ System.arraycopy(array, startIndexInclusive, subarray, 0, newSize);
+ return subarray;
+ }
+
+ /**
+ * <p>Produces a new <code>short</code> array containing the elements
+ * between the start and end indices.</p>
+ *
+ * <p>The start index is inclusive, the end index exclusive.
+ * Null array input produces null output.</p>
+ *
+ * @param array the array
+ * @param startIndexInclusive the starting index. Undervalue (<0)
+ * is promoted to 0, overvalue (>array.length) results
+ * in an empty array.
+ * @param endIndexExclusive elements up to endIndex-1 are present in the
+ * returned subarray. Undervalue (< startIndex) produces
+ * empty array, overvalue (>array.length) is demoted to
+ * array length.
+ * @return a new array containing the elements between
+ * the start and end indices.
+ */
+ public static short[] subarray(short[] array, int startIndexInclusive, int endIndexExclusive) {
+ if (array == null) {
+ return null;
+ }
+ if (startIndexInclusive < 0) {
+ startIndexInclusive = 0;
+ }
+ if (endIndexExclusive > array.length) {
+ endIndexExclusive = array.length;
+ }
+ int newSize = endIndexExclusive - startIndexInclusive;
+ if (newSize <= 0) {
+ return EMPTY_SHORT_ARRAY;
+ }
+
+ short[] subarray = new short[newSize];
+ System.arraycopy(array, startIndexInclusive, subarray, 0, newSize);
+ return subarray;
+ }
+
+ /**
+ * <p>Produces a new <code>char</code> array containing the elements
+ * between the start and end indices.</p>
+ *
+ * <p>The start index is inclusive, the end index exclusive.
+ * Null array input produces null output.</p>
+ *
+ * @param array the array
+ * @param startIndexInclusive the starting index. Undervalue (<0)
+ * is promoted to 0, overvalue (>array.length) results
+ * in an empty array.
+ * @param endIndexExclusive elements up to endIndex-1 are present in the
+ * returned subarray. Undervalue (< startIndex) produces
+ * empty array, overvalue (>array.length) is demoted to
+ * array length.
+ * @return a new array containing the elements between
+ * the start and end indices.
+ */
+ public static char[] subarray(char[] array, int startIndexInclusive, int endIndexExclusive) {
+ if (array == null) {
+ return null;
+ }
+ if (startIndexInclusive < 0) {
+ startIndexInclusive = 0;
+ }
+ if (endIndexExclusive > array.length) {
+ endIndexExclusive = array.length;
+ }
+ int newSize = endIndexExclusive - startIndexInclusive;
+ if (newSize <= 0) {
+ return EMPTY_CHAR_ARRAY;
+ }
+
+ char[] subarray = new char[newSize];
+ System.arraycopy(array, startIndexInclusive, subarray, 0, newSize);
+ return subarray;
+ }
+
+ /**
+ * <p>Produces a new <code>byte</code> array containing the elements
+ * between the start and end indices.</p>
+ *
+ * <p>The start index is inclusive, the end index exclusive.
+ * Null array input produces null output.</p>
+ *
+ * @param array the array
+ * @param startIndexInclusive the starting index. Undervalue (<0)
+ * is promoted to 0, overvalue (>array.length) results
+ * in an empty array.
+ * @param endIndexExclusive elements up to endIndex-1 are present in the
+ * returned subarray. Undervalue (< startIndex) produces
+ * empty array, overvalue (>array.length) is demoted to
+ * array length.
+ * @return a new array containing the elements between
+ * the start and end indices.
+ */
+ public static byte[] subarray(byte[] array, int startIndexInclusive, int endIndexExclusive) {
+ if (array == null) {
+ return null;
+ }
+ if (startIndexInclusive < 0) {
+ startIndexInclusive = 0;
+ }
+ if (endIndexExclusive > array.length) {
+ endIndexExclusive = array.length;
+ }
+ int newSize = endIndexExclusive - startIndexInclusive;
+ if (newSize <= 0) {
+ return EMPTY_BYTE_ARRAY;
+ }
+
+ byte[] subarray = new byte[newSize];
+ System.arraycopy(array, startIndexInclusive, subarray, 0, newSize);
+ return subarray;
+ }
+
+ /**
+ * <p>Produces a new <code>double</code> array containing the elements
+ * between the start and end indices.</p>
+ *
+ * <p>The start index is inclusive, the end index exclusive.
+ * Null array input produces null output.</p>
+ *
+ * @param array the array
+ * @param startIndexInclusive the starting index. Undervalue (<0)
+ * is promoted to 0, overvalue (>array.length) results
+ * in an empty array.
+ * @param endIndexExclusive elements up to endIndex-1 are present in the
+ * returned subarray. Undervalue (< startIndex) produces
+ * empty array, overvalue (>array.length) is demoted to
+ * array length.
+ * @return a new array containing the elements between
+ * the start and end indices.
+ */
+ public static double[] subarray(double[] array, int startIndexInclusive, int endIndexExclusive) {
+ if (array == null) {
+ return null;
+ }
+ if (startIndexInclusive < 0) {
+ startIndexInclusive = 0;
+ }
+ if (endIndexExclusive > array.length) {
+ endIndexExclusive = array.length;
+ }
+ int newSize = endIndexExclusive - startIndexInclusive;
+ if (newSize <= 0) {
+ return EMPTY_DOUBLE_ARRAY;
+ }
+
+ double[] subarray = new double[newSize];
+ System.arraycopy(array, startIndexInclusive, subarray, 0, newSize);
+ return subarray;
+ }
+
+ /**
+ * <p>Produces a new <code>float</code> array containing the elements
+ * between the start and end indices.</p>
+ *
+ * <p>The start index is inclusive, the end index exclusive.
+ * Null array input produces null output.</p>
+ *
+ * @param array the array
+ * @param startIndexInclusive the starting index. Undervalue (<0)
+ * is promoted to 0, overvalue (>array.length) results
+ * in an empty array.
+ * @param endIndexExclusive elements up to endIndex-1 are present in the
+ * returned subarray. Undervalue (< startIndex) produces
+ * empty array, overvalue (>array.length) is demoted to
+ * array length.
+ * @return a new array containing the elements between
+ * the start and end indices.
+ */
+ public static float[] subarray(float[] array, int startIndexInclusive, int endIndexExclusive) {
+ if (array == null) {
+ return null;
+ }
+ if (startIndexInclusive < 0) {
+ startIndexInclusive = 0;
+ }
+ if (endIndexExclusive > array.length) {
+ endIndexExclusive = array.length;
+ }
+ int newSize = endIndexExclusive - startIndexInclusive;
+ if (newSize <= 0) {
+ return EMPTY_FLOAT_ARRAY;
+ }
+
+ float[] subarray = new float[newSize];
+ System.arraycopy(array, startIndexInclusive, subarray, 0, newSize);
+ return subarray;
+ }
+
+ /**
+ * <p>Produces a new <code>boolean</code> array containing the elements
+ * between the start and end indices.</p>
+ *
+ * <p>The start index is inclusive, the end index exclusive.
+ * Null array input produces null output.</p>
+ *
+ * @param array the array
+ * @param startIndexInclusive the starting index. Undervalue (<0)
+ * is promoted to 0, overvalue (>array.length) results
+ * in an empty array.
+ * @param endIndexExclusive elements up to endIndex-1 are present in the
+ * returned subarray. Undervalue (< startIndex) produces
+ * empty array, overvalue (>array.length) is demoted to
+ * array length.
+ * @return a new array containing the elements between
+ * the start and end indices.
+ */
+ public static boolean[] subarray(boolean[] array, int startIndexInclusive, int endIndexExclusive) {
+ if (array == null) {
+ return null;
+ }
+ if (startIndexInclusive < 0) {
+ startIndexInclusive = 0;
+ }
+ if (endIndexExclusive > array.length) {
+ endIndexExclusive = array.length;
+ }
+ int newSize = endIndexExclusive - startIndexInclusive;
+ if (newSize <= 0) {
+ return EMPTY_BOOLEAN_ARRAY;
+ }
+
+ boolean[] subarray = new boolean[newSize];
+ System.arraycopy(array, startIndexInclusive, subarray, 0, newSize);
+ return subarray;
+ }
+
+ // Is same length
+ //-----------------------------------------------------------------------
+ /**
+ * <p>Checks whether two arrays are the same length, treating
+ * <code>null</code> arrays as length <code>0</code>.
+ *
+ * <p>Any multi-dimensional aspects of the arrays are ignored.</p>
+ *
+ * @param array1 the first array, may be <code>null</code>
+ * @param array2 the second array, may be <code>null</code>
+ * @return <code>true</code> if length of arrays matches, treating
+ * <code>null</code> as an empty array
+ */
+ public static boolean isSameLength(Object[] array1, Object[] array2) {
+ if ((array1 == null && array2 != null && array2.length > 0) ||
+ (array2 == null && array1 != null && array1.length > 0) ||
+ (array1 != null && array2 != null && array1.length != array2.length)) {
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * <p>Checks whether two arrays are the same length, treating
+ * <code>null</code> arrays as length <code>0</code>.</p>
+ *
+ * @param array1 the first array, may be <code>null</code>
+ * @param array2 the second array, may be <code>null</code>
+ * @return <code>true</code> if length of arrays matches, treating
+ * <code>null</code> as an empty array
+ */
+ public static boolean isSameLength(long[] array1, long[] array2) {
+ if ((array1 == null && array2 != null && array2.length > 0) ||
+ (array2 == null && array1 != null && array1.length > 0) ||
+ (array1 != null && array2 != null && array1.length != array2.length)) {
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * <p>Checks whether two arrays are the same length, treating
+ * <code>null</code> arrays as length <code>0</code>.</p>
+ *
+ * @param array1 the first array, may be <code>null</code>
+ * @param array2 the second array, may be <code>null</code>
+ * @return <code>true</code> if length of arrays matches, treating
+ * <code>null</code> as an empty array
+ */
+ public static boolean isSameLength(int[] array1, int[] array2) {
+ if ((array1 == null && array2 != null && array2.length > 0) ||
+ (array2 == null && array1 != null && array1.length > 0) ||
+ (array1 != null && array2 != null && array1.length != array2.length)) {
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * <p>Checks whether two arrays are the same length, treating
+ * <code>null</code> arrays as length <code>0</code>.</p>
+ *
+ * @param array1 the first array, may be <code>null</code>
+ * @param array2 the second array, may be <code>null</code>
+ * @return <code>true</code> if length of arrays matches, treating
+ * <code>null</code> as an empty array
+ */
+ public static boolean isSameLength(short[] array1, short[] array2) {
+ if ((array1 == null && array2 != null && array2.length > 0) ||
+ (array2 == null && array1 != null && array1.length > 0) ||
+ (array1 != null && array2 != null && array1.length != array2.length)) {
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * <p>Checks whether two arrays are the same length, treating
+ * <code>null</code> arrays as length <code>0</code>.</p>
+ *
+ * @param array1 the first array, may be <code>null</code>
+ * @param array2 the second array, may be <code>null</code>
+ * @return <code>true</code> if length of arrays matches, treating
+ * <code>null</code> as an empty array
+ */
+ public static boolean isSameLength(char[] array1, char[] array2) {
+ if ((array1 == null && array2 != null && array2.length > 0) ||
+ (array2 == null && array1 != null && array1.length > 0) ||
+ (array1 != null && array2 != null && array1.length != array2.length)) {
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * <p>Checks whether two arrays are the same length, treating
+ * <code>null</code> arrays as length <code>0</code>.</p>
+ *
+ * @param array1 the first array, may be <code>null</code>
+ * @param array2 the second array, may be <code>null</code>
+ * @return <code>true</code> if length of arrays matches, treating
+ * <code>null</code> as an empty array
+ */
+ public static boolean isSameLength(byte[] array1, byte[] array2) {
+ if ((array1 == null && array2 != null && array2.length > 0) ||
+ (array2 == null && array1 != null && array1.length > 0) ||
+ (array1 != null && array2 != null && array1.length != array2.length)) {
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * <p>Checks whether two arrays are the same length, treating
+ * <code>null</code> arrays as length <code>0</code>.</p>
+ *
+ * @param array1 the first array, may be <code>null</code>
+ * @param array2 the second array, may be <code>null</code>
+ * @return <code>true</code> if length of arrays matches, treating
+ * <code>null</code> as an empty array
+ */
+ public static boolean isSameLength(double[] array1, double[] array2) {
+ if ((array1 == null && array2 != null && array2.length > 0) ||
+ (array2 == null && array1 != null && array1.length > 0) ||
+ (array1 != null && array2 != null && array1.length != array2.length)) {
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * <p>Checks whether two arrays are the same length, treating
+ * <code>null</code> arrays as length <code>0</code>.</p>
+ *
+ * @param array1 the first array, may be <code>null</code>
+ * @param array2 the second array, may be <code>null</code>
+ * @return <code>true</code> if length of arrays matches, treating
+ * <code>null</code> as an empty array
+ */
+ public static boolean isSameLength(float[] array1, float[] array2) {
+ if ((array1 == null && array2 != null && array2.length > 0) ||
+ (array2 == null && array1 != null && array1.length > 0) ||
+ (array1 != null && array2 != null && array1.length != array2.length)) {
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * <p>Checks whether two arrays are the same length, treating
+ * <code>null</code> arrays as length <code>0</code>.</p>
+ *
+ * @param array1 the first array, may be <code>null</code>
+ * @param array2 the second array, may be <code>null</code>
+ * @return <code>true</code> if length of arrays matches, treating
+ * <code>null</code> as an empty array
+ */
+ public static boolean isSameLength(boolean[] array1, boolean[] array2) {
+ if ((array1 == null && array2 != null && array2.length > 0) ||
+ (array2 == null && array1 != null && array1.length > 0) ||
+ (array1 != null && array2 != null && array1.length != array2.length)) {
+ return false;
+ }
+ return true;
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * <p>Returns the length of the specified array.
+ * This method can deal with <code>Object</code> arrays and with primitive arrays.</p>
+ *
+ * <p>If the input array is <code>null</code>, <code>0</code> is returned.</p>
+ *
+ * <pre>
+ * ArrayUtils.getLength(null) = 0
+ * ArrayUtils.getLength([]) = 0
+ * ArrayUtils.getLength([null]) = 1
+ * ArrayUtils.getLength([true, false]) = 2
+ * ArrayUtils.getLength([1, 2, 3]) = 3
+ * ArrayUtils.getLength(["a", "b", "c"]) = 3
+ * </pre>
+ *
+ * @param array the array to retrieve the length from, may be null
+ * @return The length of the array, or <code>0</code> if the array is <code>null</code>
+ * @throws IllegalArgumentException if the object arguement is not an array.
+ */
+ public static int getLength(Object array) {
+ if (array == null) {
+ return 0;
+ } else {
+ return Array.getLength(array);
+ }
+ }
+
+ /**
+ * Returns the last index of the given array or -1 if empty or null.
+ * This method can deal with <code>Object</code> arrays and with primitive arrays.
+ * This value is one less than the size since arrays indices are 0-based.</p>
+ *
+ * <pre>
+ * ArrayUtils.lastIndex(null) = -1
+ * ArrayUtils.lastIndex([]) = -1
+ * ArrayUtils.lastIndex([null]) = 0
+ * ArrayUtils.lastIndex([true, false]) = 1
+ * ArrayUtils.lastIndex([1, 2, 3]) = 2
+ * ArrayUtils.lastIndex(["a", "b", "c"]) = 2
+ * </pre>
+ *
+ * @param array the array to return the last index for, may be null
+ * @return the last index, -1 if empty or null
+ * @throws IllegalArgumentException if the object arguement is not an array.
+ */
+ public static int lastIndex(Object array) {
+ return ArrayUtils.getLength(array) - 1;
+ }
+
+ /**
+ * <p>Checks whether two arrays are the same type taking into account
+ * multi-dimensional arrays.</p>
+ *
+ * @param array1 the first array, must not be <code>null</code>
+ * @param array2 the second array, must not be <code>null</code>
+ * @return <code>true</code> if type of arrays matches
+ * @throws IllegalArgumentException if either array is <code>null</code>
+ */
+ public static boolean isSameType(Object array1, Object array2) {
+ if (array1 == null || array2 == null) {
+ throw new IllegalArgumentException("The Array must not be null");
+ }
+ return array1.getClass().getName().equals(array2.getClass().getName());
+ }
+
+ // Reverse
+ //-----------------------------------------------------------------------
+ /**
+ * <p>Reverses the order of the given array.</p>
+ *
+ * <p>There is no special handling for multi-dimensional arrays.</p>
+ *
+ * <p>This method does nothing if <code>null</code> array input.</p>
+ *
+ * @param array the array to reverse, may be <code>null</code>
+ */
+ public static void reverse(Object[] array) {
+ if (array == null) {
+ return;
+ }
+ int i = 0;
+ int j = array.length - 1;
+ Object tmp;
+ while (j > i) {
+ tmp = array[j];
+ array[j] = array[i];
+ array[i] = tmp;
+ j--;
+ i++;
+ }
+ }
+
+ /**
+ * <p>Reverses the order of the given array.</p>
+ *
+ * <p>This method does nothing if <code>null</code> array input.</p>
+ *
+ * @param array the array to reverse, may be <code>null</code>
+ */
+ public static void reverse(long[] array) {
+ if (array == null) {
+ return;
+ }
+ int i = 0;
+ int j = array.length - 1;
+ long tmp;
+ while (j > i) {
+ tmp = array[j];
+ array[j] = array[i];
+ array[i] = tmp;
+ j--;
+ i++;
+ }
+ }
+
+ /**
+ * <p>Reverses the order of the given array.</p>
+ *
+ * <p>This method does nothing if <code>null</code> array input.</p>
+ *
+ * @param array the array to reverse, may be <code>null</code>
+ */
+ public static void reverse(int[] array) {
+ if (array == null) {
+ return;
+ }
+ int i = 0;
+ int j = array.length - 1;
+ int tmp;
+ while (j > i) {
+ tmp = array[j];
+ array[j] = array[i];
+ array[i] = tmp;
+ j--;
+ i++;
+ }
+ }
+
+ /**
+ * <p>Reverses the order of the given array.</p>
+ *
+ * <p>This method does nothing if <code>null</code> array input.</p>
+ *
+ * @param array the array to reverse, may be <code>null</code>
+ */
+ public static void reverse(short[] array) {
+ if (array == null) {
+ return;
+ }
+ int i = 0;
+ int j = array.length - 1;
+ short tmp;
+ while (j > i) {
+ tmp = array[j];
+ array[j] = array[i];
+ array[i] = tmp;
+ j--;
+ i++;
+ }
+ }
+
+ /**
+ * <p>Reverses the order of the given array.</p>
+ *
+ * <p>This method does nothing if <code>null</code> array input.</p>
+ *
+ * @param array the array to reverse, may be <code>null</code>
+ */
+ public static void reverse(char[] array) {
+ if (array == null) {
+ return;
+ }
+ int i = 0;
+ int j = array.length - 1;
+ char tmp;
+ while (j > i) {
+ tmp = array[j];
+ array[j] = array[i];
+ array[i] = tmp;
+ j--;
+ i++;
+ }
+ }
+
+ /**
+ * <p>Reverses the order of the given array.</p>
+ *
+ * <p>This method does nothing if <code>null</code> array input.</p>
+ *
+ * @param array the array to reverse, may be <code>null</code>
+ */
+ public static void reverse(byte[] array) {
+ if (array == null) {
+ return;
+ }
+ int i = 0;
+ int j = array.length - 1;
+ byte tmp;
+ while (j > i) {
+ tmp = array[j];
+ array[j] = array[i];
+ array[i] = tmp;
+ j--;
+ i++;
+ }
+ }
+
+ /**
+ * <p>Reverses the order of the given array.</p>
+ *
+ * <p>This method does nothing if <code>null</code> array input.</p>
+ *
+ * @param array the array to reverse, may be <code>null</code>
+ */
+ public static void reverse(double[] array) {
+ if (array == null) {
+ return;
+ }
+ int i = 0;
+ int j = array.length - 1;
+ double tmp;
+ while (j > i) {
+ tmp = array[j];
+ array[j] = array[i];
+ array[i] = tmp;
+ j--;
+ i++;
+ }
+ }
+
+ /**
+ * <p>Reverses the order of the given array.</p>
+ *
+ * <p>This method does nothing if <code>null</code> array input.</p>
+ *
+ * @param array the array to reverse, may be <code>null</code>
+ */
+ public static void reverse(float[] array) {
+ if (array == null) {
+ return;
+ }
+ int i = 0;
+ int j = array.length - 1;
+ float tmp;
+ while (j > i) {
+ tmp = array[j];
+ array[j] = array[i];
+ array[i] = tmp;
+ j--;
+ i++;
+ }
+ }
+
+ /**
+ * <p>Reverses the order of the given array.</p>
+ *
+ * <p>This method does nothing if <code>null</code> array input.</p>
+ *
+ * @param array the array to reverse, may be <code>null</code>
+ */
+ public static void reverse(boolean[] array) {
+ if (array == null) {
+ return;
+ }
+ int i = 0;
+ int j = array.length - 1;
+ boolean tmp;
+ while (j > i) {
+ tmp = array[j];
+ array[j] = array[i];
+ array[i] = tmp;
+ j--;
+ i++;
+ }
+ }
+
+ // IndexOf search
+ // ----------------------------------------------------------------------
+
+ // Object IndexOf
+ //-----------------------------------------------------------------------
+ /**
+ * <p>Find the index of the given object in the array.</p>
+ *
+ * <p>This method returns <code>-1</code> if <code>null</code> array input.</p>
+ *
+ * @param array the array to search through for the object, may be <code>null</code>
+ * @param objectToFind the object to find, may be <code>null</code>
+ * @return the index of the object within the array,
+ * <code>-1</code> if not found or <code>null</code> array input
+ */
+ public static int indexOf(Object[] array, Object objectToFind) {
+ return indexOf(array, objectToFind, 0);
+ }
+
+ /**
+ * <p>Find the index of the given object in the array starting at the given index.</p>
+ *
+ * <p>This method returns <code>-1</code> if <code>null</code> array input.</p>
+ *
+ * <p>A negative startIndex is treated as zero. A startIndex larger than the array
+ * length will return <code>-1</code>.</p>
+ *
+ * @param array the array to search through for the object, may be <code>null</code>
+ * @param objectToFind the object to find, may be <code>null</code>
+ * @param startIndex the index to start searching at
+ * @return the index of the object within the array starting at the index,
+ * <code>-1</code> if not found or <code>null</code> array input
+ */
+ public static int indexOf(Object[] array, Object objectToFind, int startIndex) {
+ if (array == null) {
+ return -1;
+ }
+ if (startIndex < 0) {
+ startIndex = 0;
+ }
+ if (objectToFind == null) {
+ for (int i = startIndex; i < array.length; i++) {
+ if (array[i] == null) {
+ return i;
+ }
+ }
+ } else {
+ for (int i = startIndex; i < array.length; i++) {
+ if (objectToFind.equals(array[i])) {
+ return i;
+ }
+ }
+ }
+ return -1;
+ }
+
+ /**
+ * <p>Find the last index of the given object within the array.</p>
+ *
+ * <p>This method returns <code>-1</code> if <code>null</code> array input.</p>
+ *
+ * @param array the array to travers backwords looking for the object, may be <code>null</code>
+ * @param objectToFind the object to find, may be <code>null</code>
+ * @return the last index of the object within the array,
+ * <code>-1</code> if not found or <code>null</code> array input
+ */
+ public static int lastIndexOf(Object[] array, Object objectToFind) {
+ return lastIndexOf(array, objectToFind, Integer.MAX_VALUE);
+ }
+
+ /**
+ * <p>Find the last index of the given object in the array starting at the given index.</p>
+ *
+ * <p>This method returns <code>-1</code> if <code>null</code> array input.</p>
+ *
+ * <p>A negative startIndex will return <code>-1</code>. A startIndex larger than
+ * the array length will search from the end of the array.</p>
+ *
+ * @param array the array to traverse for looking for the object, may be <code>null</code>
+ * @param objectToFind the object to find, may be <code>null</code>
+ * @param startIndex the start index to travers backwards from
+ * @return the last index of the object within the array,
+ * <code>-1</code> if not found or <code>null</code> array input
+ */
+ public static int lastIndexOf(Object[] array, Object objectToFind, int startIndex) {
+ if (array == null) {
+ return -1;
+ }
+ if (startIndex < 0) {
+ return -1;
+ } else if (startIndex >= array.length) {
+ startIndex = array.length - 1;
+ }
+ if (objectToFind == null) {
+ for (int i = startIndex; i >= 0; i--) {
+ if (array[i] == null) {
+ return i;
+ }
+ }
+ } else {
+ for (int i = startIndex; i >= 0; i--) {
+ if (objectToFind.equals(array[i])) {
+ return i;
+ }
+ }
+ }
+ return -1;
+ }
+
+ /**
+ * <p>Checks if the object is in the given array.</p>
+ *
+ * <p>The method returns <code>false</code> if a <code>null</code> array is passed in.</p>
+ *
+ * @param array the array to search through
+ * @param objectToFind the object to find
+ * @return <code>true</code> if the array contains the object
+ */
+ public static boolean contains(Object[] array, Object objectToFind) {
+ return (indexOf(array, objectToFind) != -1);
+ }
+
+ // long IndexOf
+ //-----------------------------------------------------------------------
+ /**
+ * <p>Find the index of the given value in the array.</p>
+ *
+ * <p>This method returns <code>-1</code> if <code>null</code> array input.</p>
+ *
+ * @param array the array to search through for the object, may be <code>null</code>
+ * @param valueToFind the value to find
+ * @return the index of the value within the array,
+ * <code>-1</code> if not found or <code>null</code> array input
+ */
+ public static int indexOf(long[] array, long valueToFind) {
+ return indexOf(array, valueToFind, 0);
+ }
+
+ /**
+ * <p>Find the index of the given value in the array starting at the given index.</p>
+ *
+ * <p>This method returns <code>-1</code> if <code>null</code> array input.</p>
+ *
+ * <p>A negative startIndex is treated as zero. A startIndex larger than the array
+ * length will return -1.</p>
+ *
+ * @param array the array to search through for the object, may be <code>null</code>
+ * @param valueToFind the value to find
+ * @param startIndex the index to start searching at
+ * @return the index of the value within the array,
+ * <code>-1</code> if not found or <code>null</code> array input
+ */
+ public static int indexOf(long[] array, long valueToFind, int startIndex) {
+ if (array == null) {
+ return -1;
+ }
+ if (startIndex < 0) {
+ startIndex = 0;
+ }
+ for (int i = startIndex; i < array.length; i++) {
+ if (valueToFind == array[i]) {
+ return i;
+ }
+ }
+ return -1;
+ }
+
+ /**
+ * <p>Find the last index of the given value within the array.</p>
+ *
+ * <p>This method returns <code>-1</code> if <code>null</code> array input.</p>
+ *
+ * @param array the array to travers backwords looking for the object, may be <code>null</code>
+ * @param valueToFind the object to find
+ * @return the last index of the value within the array,
+ * <code>-1</code> if not found or <code>null</code> array input
+ */
+ public static int lastIndexOf(long[] array, long valueToFind) {
+ return lastIndexOf(array, valueToFind, Integer.MAX_VALUE);
+ }
+
+ /**
+ * <p>Find the last index of the given value in the array starting at the given index.</p>
+ *
+ * <p>This method returns <code>-1</code> if <code>null</code> array input.</p>
+ *
+ * <p>A negative startIndex will return -1. A startIndex larger than the array
+ * length will search from the end of the array.</p>
+ *
+ * @param array the array to traverse for looking for the object, may be <code>null</code>
+ * @param valueToFind the value to find
+ * @param startIndex the start index to travers backwards from
+ * @return the last index of the value within the array,
+ * <code>-1</code> if not found or <code>null</code> array input
+ */
+ public static int lastIndexOf(long[] array, long valueToFind, int startIndex) {
+ if (array == null) {
+ return -1;
+ }
+ if (startIndex < 0) {
+ return -1;
+ } else if (startIndex >= array.length) {
+ startIndex = array.length - 1;
+ }
+ for (int i = startIndex; i >= 0; i--) {
+ if (valueToFind == array[i]) {
+ return i;
+ }
+ }
+ return -1;
+ }
+
+ /**
+ * <p>Checks if the value is in the given array.</p>
+ *
+ * <p>The method returns <code>false</code> if a <code>null</code> array is passed in.</p>
+ *
+ * @param array the array to search through
+ * @param valueToFind the value to find
+ * @return <code>true</code> if the array contains the object
+ */
+ public static boolean contains(long[] array, long valueToFind) {
+ return (indexOf(array, valueToFind) != -1);
+ }
+
+ // int IndexOf
+ //-----------------------------------------------------------------------
+ /**
+ * <p>Find the index of the given value in the array.</p>
+ *
+ * <p>This method returns <code>-1</code> if <code>null</code> array input.</p>
+ *
+ * @param array the array to search through for the object, may be <code>null</code>
+ * @param valueToFind the value to find
+ * @return the index of the value within the array,
+ * <code>-1</code> if not found or <code>null</code> array input
+ */
+ public static int indexOf(int[] array, int valueToFind) {
+ return indexOf(array, valueToFind, 0);
+ }
+
+ /**
+ * <p>Find the index of the given value in the array starting at the given index.</p>
+ *
+ * <p>This method returns <code>-1</code> if <code>null</code> array input.</p>
+ *
+ * <p>A negative startIndex is treated as zero. A startIndex larger than the array
+ * length will return -1.</p>
+ *
+ * @param array the array to search through for the object, may be <code>null</code>
+ * @param valueToFind the value to find
+ * @param startIndex the index to start searching at
+ * @return the index of the value within the array,
+ * <code>-1</code> if not found or <code>null</code> array input
+ */
+ public static int indexOf(int[] array, int valueToFind, int startIndex) {
+ if (array == null) {
+ return -1;
+ }
+ if (startIndex < 0) {
+ startIndex = 0;
+ }
+ for (int i = startIndex; i < array.length; i++) {
+ if (valueToFind == array[i]) {
+ return i;
+ }
+ }
+ return -1;
+ }
+
+ /**
+ * <p>Find the last index of the given value within the array.</p>
+ *
+ * <p>This method returns <code>-1</code> if <code>null</code> array input.</p>
+ *
+ * @param array the array to travers backwords looking for the object, may be <code>null</code>
+ * @param valueToFind the object to find
+ * @return the last index of the value within the array,
+ * <code>-1</code> if not found or <code>null</code> array input
+ */
+ public static int lastIndexOf(int[] array, int valueToFind) {
+ return lastIndexOf(array, valueToFind, Integer.MAX_VALUE);
+ }
+
+ /**
+ * <p>Find the last index of the given value in the array starting at the given index.</p>
+ *
+ * <p>This method returns <code>-1</code> if <code>null</code> array input.</p>
+ *
+ * <p>A negative startIndex will return -1. A startIndex larger than the array
+ * length will search from the end of the array.</p>
+ *
+ * @param array the array to traverse for looking for the object, may be <code>null</code>
+ * @param valueToFind the value to find
+ * @param startIndex the start index to travers backwards from
+ * @return the last index of the value within the array,
+ * <code>-1</code> if not found or <code>null</code> array input
+ */
+ public static int lastIndexOf(int[] array, int valueToFind, int startIndex) {
+ if (array == null) {
+ return -1;
+ }
+ if (startIndex < 0) {
+ return -1;
+ } else if (startIndex >= array.length) {
+ startIndex = array.length - 1;
+ }
+ for (int i = startIndex; i >= 0; i--) {
+ if (valueToFind == array[i]) {
+ return i;
+ }
+ }
+ return -1;
+ }
+
+ /**
+ * <p>Checks if the value is in the given array.</p>
+ *
+ * <p>The method returns <code>false</code> if a <code>null</code> array is passed in.</p>
+ *
+ * @param array the array to search through
+ * @param valueToFind the value to find
+ * @return <code>true</code> if the array contains the object
+ */
+ public static boolean contains(int[] array, int valueToFind) {
+ return (indexOf(array, valueToFind) != -1);
+ }
+
+ // short IndexOf
+ //-----------------------------------------------------------------------
+ /**
+ * <p>Find the index of the given value in the array.</p>
+ *
+ * <p>This method returns <code>-1</code> if <code>null</code> array input.</p>
+ *
+ * @param array the array to search through for the object, may be <code>null</code>
+ * @param valueToFind the value to find
+ * @return the index of the value within the array,
+ * <code>-1</code> if not found or <code>null</code> array input
+ */
+ public static int indexOf(short[] array, short valueToFind) {
+ return indexOf(array, valueToFind, 0);
+ }
+
+ /**
+ * <p>Find the index of the given value in the array starting at the given index.</p>
+ *
+ * <p>This method returns <code>-1</code> if <code>null</code> array input.</p>
+ *
+ * <p>A negative startIndex is treated as zero. A startIndex larger than the array
+ * length will return -1.</p>
+ *
+ * @param array the array to search through for the object, may be <code>null</code>
+ * @param valueToFind the value to find
+ * @param startIndex the index to start searching at
+ * @return the index of the value within the array,
+ * <code>-1</code> if not found or <code>null</code> array input
+ */
+ public static int indexOf(short[] array, short valueToFind, int startIndex) {
+ if (array == null) {
+ return -1;
+ }
+ if (startIndex < 0) {
+ startIndex = 0;
+ }
+ for (int i = startIndex; i < array.length; i++) {
+ if (valueToFind == array[i]) {
+ return i;
+ }
+ }
+ return -1;
+ }
+
+ /**
+ * <p>Find the last index of the given value within the array.</p>
+ *
+ * <p>This method returns <code>-1</code> if <code>null</code> array input.</p>
+ *
+ * @param array the array to travers backwords looking for the object, may be <code>null</code>
+ * @param valueToFind the object to find
+ * @return the last index of the value within the array,
+ * <code>-1</code> if not found or <code>null</code> array input
+ */
+ public static int lastIndexOf(short[] array, short valueToFind) {
+ return lastIndexOf(array, valueToFind, Integer.MAX_VALUE);
+ }
+
+ /**
+ * <p>Find the last index of the given value in the array starting at the given index.</p>
+ *
+ * <p>This method returns <code>-1</code> if <code>null</code> array input.</p>
+ *
+ * <p>A negative startIndex will return -1. A startIndex larger than the array
+ * length will search from the end of the array.</p>
+ *
+ * @param array the array to traverse for looking for the object, may be <code>null</code>
+ * @param valueToFind the value to find
+ * @param startIndex the start index to travers backwards from
+ * @return the last index of the value within the array,
+ * <code>-1</code> if not found or <code>null</code> array input
+ */
+ public static int lastIndexOf(short[] array, short valueToFind, int startIndex) {
+ if (array == null) {
+ return -1;
+ }
+ if (startIndex < 0) {
+ return -1;
+ } else if (startIndex >= array.length) {
+ startIndex = array.length - 1;
+ }
+ for (int i = startIndex; i >= 0; i--) {
+ if (valueToFind == array[i]) {
+ return i;
+ }
+ }
+ return -1;
+ }
+
+ /**
+ * <p>Checks if the value is in the given array.</p>
+ *
+ * <p>The method returns <code>false</code> if a <code>null</code> array is passed in.</p>
+ *
+ * @param array the array to search through
+ * @param valueToFind the value to find
+ * @return <code>true</code> if the array contains the object
+ */
+ public static boolean contains(short[] array, short valueToFind) {
+ return (indexOf(array, valueToFind) != -1);
+ }
+
+ // char IndexOf
+ //-----------------------------------------------------------------------
+ /**
+ * <p>Find the index of the given value in the array.</p>
+ *
+ * <p>This method returns <code>-1</code> if <code>null</code> array input.</p>
+ *
+ * @param array the array to search through for the object, may be <code>null</code>
+ * @param valueToFind the value to find
+ * @return the index of the value within the array,
+ * <code>-1</code> if not found or <code>null</code> array input
+ */
+ public static int indexOf(char[] array, char valueToFind) {
+ return indexOf(array, valueToFind, 0);
+ }
+
+ /**
+ * <p>Find the index of the given value in the array starting at the given index.</p>
+ *
+ * <p>This method returns <code>-1</code> if <code>null</code> array input.</p>
+ *
+ * <p>A negative startIndex is treated as zero. A startIndex larger than the array
+ * length will return -1.</p>
+ *
+ * @param array the array to search through for the object, may be <code>null</code>
+ * @param valueToFind the value to find
+ * @param startIndex the index to start searching at
+ * @return the index of the value within the array,
+ * <code>-1</code> if not found or <code>null</code> array input
+ */
+ public static int indexOf(char[] array, char valueToFind, int startIndex) {
+ if (array == null) {
+ return -1;
+ }
+ if (startIndex < 0) {
+ startIndex = 0;
+ }
+ for (int i = startIndex; i < array.length; i++) {
+ if (valueToFind == array[i]) {
+ return i;
+ }
+ }
+ return -1;
+ }
+
+ /**
+ * <p>Find the last index of the given value within the array.</p>
+ *
+ * <p>This method returns <code>-1</code> if <code>null</code> array input.</p>
+ *
+ * @param array the array to travers backwords looking for the object, may be <code>null</code>
+ * @param valueToFind the object to find
+ * @return the last index of the value within the array,
+ * <code>-1</code> if not found or <code>null</code> array input
+ */
+ public static int lastIndexOf(char[] array, char valueToFind) {
+ return lastIndexOf(array, valueToFind, Integer.MAX_VALUE);
+ }
+
+ /**
+ * <p>Find the last index of the given value in the array starting at the given index.</p>
+ *
+ * <p>This method returns <code>-1</code> if <code>null</code> array input.</p>
+ *
+ * <p>A negative startIndex will return -1. A startIndex larger than the array
+ * length will search from the end of the array.</p>
+ *
+ * @param array the array to traverse for looking for the object, may be <code>null</code>
+ * @param valueToFind the value to find
+ * @param startIndex the start index to travers backwards from
+ * @return the last index of the value within the array,
+ * <code>-1</code> if not found or <code>null</code> array input
+ */
+ public static int lastIndexOf(char[] array, char valueToFind, int startIndex) {
+ if (array == null) {
+ return -1;
+ }
+ if (startIndex < 0) {
+ return -1;
+ } else if (startIndex >= array.length) {
+ startIndex = array.length - 1;
+ }
+ for (int i = startIndex; i >= 0; i--) {
+ if (valueToFind == array[i]) {
+ return i;
+ }
+ }
+ return -1;
+ }
+
+ /**
+ * <p>Checks if the value is in the given array.</p>
+ *
+ * <p>The method returns <code>false</code> if a <code>null</code> array is passed in.</p>
+ *
+ * @param array the array to search through
+ * @param valueToFind the value to find
+ * @return <code>true</code> if the array contains the object
+ */
+ public static boolean contains(char[] array, char valueToFind) {
+ return (indexOf(array, valueToFind) != -1);
+ }
+
+ // byte IndexOf
+ //-----------------------------------------------------------------------
+ /**
+ * <p>Find the index of the given value in the array.</p>
+ *
+ * <p>This method returns <code>-1</code> if <code>null</code> array input.</p>
+ *
+ * @param array the array to search through for the object, may be <code>null</code>
+ * @param valueToFind the value to find
+ * @return the index of the value within the array,
+ * <code>-1</code> if not found or <code>null</code> array input
+ */
+ public static int indexOf(byte[] array, byte valueToFind) {
+ return indexOf(array, valueToFind, 0);
+ }
+
+ /**
+ * <p>Find the index of the given value in the array starting at the given index.</p>
+ *
+ * <p>This method returns <code>-1</code> if <code>null</code> array input.</p>
+ *
+ * <p>A negative startIndex is treated as zero. A startIndex larger than the array
+ * length will return -1.</p>
+ *
+ * @param array the array to search through for the object, may be <code>null</code>
+ * @param valueToFind the value to find
+ * @param startIndex the index to start searching at
+ * @return the index of the value within the array,
+ * <code>-1</code> if not found or <code>null</code> array input
+ */
+ public static int indexOf(byte[] array, byte valueToFind, int startIndex) {
+ if (array == null) {
+ return -1;
+ }
+ if (startIndex < 0) {
+ startIndex = 0;
+ }
+ for (int i = startIndex; i < array.length; i++) {
+ if (valueToFind == array[i]) {
+ return i;
+ }
+ }
+ return -1;
+ }
+
+ /**
+ * <p>Find the last index of the given value within the array.</p>
+ *
+ * <p>This method returns <code>-1</code> if <code>null</code> array input.</p>
+ *
+ * @param array the array to travers backwords looking for the object, may be <code>null</code>
+ * @param valueToFind the object to find
+ * @return the last index of the value within the array,
+ * <code>-1</code> if not found or <code>null</code> array input
+ */
+ public static int lastIndexOf(byte[] array, byte valueToFind) {
+ return lastIndexOf(array, valueToFind, Integer.MAX_VALUE);
+ }
+
+ /**
+ * <p>Find the last index of the given value in the array starting at the given index.</p>
+ *
+ * <p>This method returns <code>-1</code> if <code>null</code> array input.</p>
+ *
+ * <p>A negative startIndex will return -1. A startIndex larger than the array
+ * length will search from the end of the array.</p>
+ *
+ * @param array the array to traverse for looking for the object, may be <code>null</code>
+ * @param valueToFind the value to find
+ * @param startIndex the start index to travers backwards from
+ * @return the last index of the value within the array,
+ * <code>-1</code> if not found or <code>null</code> array input
+ */
+ public static int lastIndexOf(byte[] array, byte valueToFind, int startIndex) {
+ if (array == null) {
+ return -1;
+ }
+ if (startIndex < 0) {
+ return -1;
+ } else if (startIndex >= array.length) {
+ startIndex = array.length - 1;
+ }
+ for (int i = startIndex; i >= 0; i--) {
+ if (valueToFind == array[i]) {
+ return i;
+ }
+ }
+ return -1;
+ }
+
+ /**
+ * <p>Checks if the value is in the given array.</p>
+ *
+ * <p>The method returns <code>false</code> if a <code>null</code> array is passed in.</p>
+ *
+ * @param array the array to search through
+ * @param valueToFind the value to find
+ * @return <code>true</code> if the array contains the object
+ */
+ public static boolean contains(byte[] array, byte valueToFind) {
+ return (indexOf(array, valueToFind) != -1);
+ }
+
+ // double IndexOf
+ //-----------------------------------------------------------------------
+ /**
+ * <p>Find the index of the given value in the array.</p>
+ *
+ * <p>This method returns <code>-1</code> if <code>null</code> array input.</p>
+ *
+ * @param array the array to search through for the object, may be <code>null</code>
+ * @param valueToFind the value to find
+ * @return the index of the value within the array,
+ * <code>-1</code> if not found or <code>null</code> array input
+ */
+ public static int indexOf(double[] array, double valueToFind) {
+ return indexOf(array, valueToFind, 0);
+ }
+
+ /**
+ * <p>Find the index of the given value within a given tolerance in the array.
+ * This method will return the index of the first value which falls between the region
+ * defined by valueToFind - tolerance and valueToFind + tolerance.</p>
+ *
+ * <p>This method returns <code>-1</code> if <code>null</code> array input.</p>
+ *
+ * @param array the array to search through for the object, may be <code>null</code>
+ * @param valueToFind the value to find
+ * @param tolerance tolerance of the search
+ * @return the index of the value within the array,
+ * <code>-1</code> if not found or <code>null</code> array input
+ */
+ public static int indexOf(double[] array, double valueToFind, double tolerance) {
+ return indexOf(array, valueToFind, 0, tolerance);
+ }
+
+ /**
+ * <p>Find the index of the given value in the array starting at the given index.</p>
+ *
+ * <p>This method returns <code>-1</code> if <code>null</code> array input.</p>
+ *
+ * <p>A negative startIndex is treated as zero. A startIndex larger than the array
+ * length will return -1.</p>
+ *
+ * @param array the array to search through for the object, may be <code>null</code>
+ * @param valueToFind the value to find
+ * @param startIndex the index to start searching at
+ * @return the index of the value within the array,
+ * <code>-1</code> if not found or <code>null</code> array input
+ */
+ public static int indexOf(double[] array, double valueToFind, int startIndex) {
+ if (ArrayUtils.isEmpty(array)) {
+ return -1;
+ }
+ if (startIndex < 0) {
+ startIndex = 0;
+ }
+ for (int i = startIndex; i < array.length; i++) {
+ if (valueToFind == array[i]) {
+ return i;
+ }
+ }
+ return -1;
+ }
+
+ /**
+ * <p>Find the index of the given value in the array starting at the given index.
+ * This method will return the index of the first value which falls between the region
+ * defined by valueToFind - tolerance and valueToFind + tolerance.</p>
+ *
+ * <p>This method returns <code>-1</code> if <code>null</code> array input.</p>
+ *
+ * <p>A negative startIndex is treated as zero. A startIndex larger than the array
+ * length will return -1.</p>
+ *
+ * @param array the array to search through for the object, may be <code>null</code>
+ * @param valueToFind the value to find
+ * @param startIndex the index to start searching at
+ * @param tolerance tolerance of the search
+ * @return the index of the value within the array,
+ * <code>-1</code> if not found or <code>null</code> array input
+ */
+ public static int indexOf(double[] array, double valueToFind, int startIndex, double tolerance) {
+ if (ArrayUtils.isEmpty(array)) {
+ return -1;
+ }
+ if (startIndex < 0) {
+ startIndex = 0;
+ }
+ double min = valueToFind - tolerance;
+ double max = valueToFind + tolerance;
+ for (int i = startIndex; i < array.length; i++) {
+ if (array[i] >= min && array[i] <= max) {
+ return i;
+ }
+ }
+ return -1;
+ }
+
+ /**
+ * <p>Find the last index of the given value within the array.</p>
+ *
+ * <p>This method returns <code>-1</code> if <code>null</code> array input.</p>
+ *
+ * @param array the array to travers backwords looking for the object, may be <code>null</code>
+ * @param valueToFind the object to find
+ * @return the last index of the value within the array,
+ * <code>-1</code> if not found or <code>null</code> array input
+ */
+ public static int lastIndexOf(double[] array, double valueToFind) {
+ return lastIndexOf(array, valueToFind, Integer.MAX_VALUE);
+ }
+
+ /**
+ * <p>Find the last index of the given value within a given tolerance in the array.
+ * This method will return the index of the last value which falls between the region
+ * defined by valueToFind - tolerance and valueToFind + tolerance.</p>
+ *
+ * <p>This method returns <code>-1</code> if <code>null</code> array input.</p>
+ *
+ * @param array the array to search through for the object, may be <code>null</code>
+ * @param valueToFind the value to find
+ * @param tolerance tolerance of the search
+ * @return the index of the value within the array,
+ * <code>-1</code> if not found or <code>null</code> array input
+ */
+ public static int lastIndexOf(double[] array, double valueToFind, double tolerance) {
+ return lastIndexOf(array, valueToFind, Integer.MAX_VALUE, tolerance);
+ }
+
+ /**
+ * <p>Find the last index of the given value in the array starting at the given index.</p>
+ *
+ * <p>This method returns <code>-1</code> if <code>null</code> array input.</p>
+ *
+ * <p>A negative startIndex will return -1. A startIndex larger than the array
+ * length will search from the end of the array.</p>
+ *
+ * @param array the array to traverse for looking for the object, may be <code>null</code>
+ * @param valueToFind the value to find
+ * @param startIndex the start index to travers backwards from
+ * @return the last index of the value within the array,
+ * <code>-1</code> if not found or <code>null</code> array input
+ */
+ public static int lastIndexOf(double[] array, double valueToFind, int startIndex) {
+ if (ArrayUtils.isEmpty(array)) {
+ return -1;
+ }
+ if (startIndex < 0) {
+ return -1;
+ } else if (startIndex >= array.length) {
+ startIndex = array.length - 1;
+ }
+ for (int i = startIndex; i >= 0; i--) {
+ if (valueToFind == array[i]) {
+ return i;
+ }
+ }
+ return -1;
+ }
+
+ /**
+ * <p>Find the last index of the given value in the array starting at the given index.
+ * This method will return the index of the last value which falls between the region
+ * defined by valueToFind - tolerance and valueToFind + tolerance.</p>
+ *
+ * <p>This method returns <code>-1</code> if <code>null</code> array input.</p>
+ *
+ * <p>A negative startIndex will return -1. A startIndex larger than the array
+ * length will search from the end of the array.</p>
+ *
+ * @param array the array to traverse for looking for the object, may be <code>null</code>
+ * @param valueToFind the value to find
+ * @param startIndex the start index to travers backwards from
+ * @param tolerance search for value within plus/minus this amount
+ * @return the last index of the value within the array,
+ * <code>-1</code> if not found or <code>null</code> array input
+ */
+ public static int lastIndexOf(double[] array, double valueToFind, int startIndex, double tolerance) {
+ if (ArrayUtils.isEmpty(array)) {
+ return -1;
+ }
+ if (startIndex < 0) {
+ return -1;
+ } else if (startIndex >= array.length) {
+ startIndex = array.length - 1;
+ }
+ double min = valueToFind - tolerance;
+ double max = valueToFind + tolerance;
+ for (int i = startIndex; i >= 0; i--) {
+ if (array[i] >= min && array[i] <= max) {
+ return i;
+ }
+ }
+ return -1;
+ }
+
+ /**
+ * <p>Checks if the value is in the given array.</p>
+ *
+ * <p>The method returns <code>false</code> if a <code>null</code> array is passed in.</p>
+ *
+ * @param array the array to search through
+ * @param valueToFind the value to find
+ * @return <code>true</code> if the array contains the object
+ */
+ public static boolean contains(double[] array, double valueToFind) {
+ return (indexOf(array, valueToFind) != -1);
+ }
+
+ /**
+ * <p>Checks if a value falling within the given tolerance is in the
+ * given array. If the array contains a value within the inclusive range
+ * defined by (value - tolerance) to (value + tolerance).</p>
+ *
+ * <p>The method returns <code>false</code> if a <code>null</code> array
+ * is passed in.</p>
+ *
+ * @param array the array to search
+ * @param valueToFind the value to find
+ * @param tolerance the array contains the tolerance of the search
+ * @return true if value falling within tolerance is in array
+ */
+ public static boolean contains(double[] array, double valueToFind, double tolerance) {
+ return (indexOf(array, valueToFind, 0, tolerance) != -1);
+ }
+
+ // float IndexOf
+ //-----------------------------------------------------------------------
+ /**
+ * <p>Find the index of the given value in the array.</p>
+ *
+ * <p>This method returns <code>-1</code> if <code>null</code> array input.</p>
+ *
+ * @param array the array to search through for the object, may be <code>null</code>
+ * @param valueToFind the value to find
+ * @return the index of the value within the array,
+ * <code>-1</code> if not found or <code>null</code> array input
+ */
+ public static int indexOf(float[] array, float valueToFind) {
+ return indexOf(array, valueToFind, 0);
+ }
+
+ /**
+ * <p>Find the index of the given value in the array starting at the given index.</p>
+ *
+ * <p>This method returns <code>-1</code> if <code>null</code> array input.</p>
+ *
+ * <p>A negative startIndex is treated as zero. A startIndex larger than the array
+ * length will return -1.</p>
+ *
+ * @param array the array to search through for the object, may be <code>null</code>
+ * @param valueToFind the value to find
+ * @param startIndex the index to start searching at
+ * @return the index of the value within the array,
+ * <code>-1</code> if not found or <code>null</code> array input
+ */
+ public static int indexOf(float[] array, float valueToFind, int startIndex) {
+ if (ArrayUtils.isEmpty(array)) {
+ return -1;
+ }
+ if (startIndex < 0) {
+ startIndex = 0;
+ }
+ for (int i = startIndex; i < array.length; i++) {
+ if (valueToFind == array[i]) {
+ return i;
+ }
+ }
+ return -1;
+ }
+
+ /**
+ * <p>Find the last index of the given value within the array.</p>
+ *
+ * <p>This method returns <code>-1</code> if <code>null</code> array input.</p>
+ *
+ * @param array the array to travers backwords looking for the object, may be <code>null</code>
+ * @param valueToFind the object to find
+ * @return the last index of the value within the array,
+ * <code>-1</code> if not found or <code>null</code> array input
+ */
+ public static int lastIndexOf(float[] array, float valueToFind) {
+ return lastIndexOf(array, valueToFind, Integer.MAX_VALUE);
+ }
+
+ /**
+ * <p>Find the last index of the given value in the array starting at the given index.</p>
+ *
+ * <p>This method returns <code>-1</code> if <code>null</code> array input.</p>
+ *
+ * <p>A negative startIndex will return -1. A startIndex larger than the array
+ * length will search from the end of the array.</p>
+ *
+ * @param array the array to traverse for looking for the object, may be <code>null</code>
+ * @param valueToFind the value to find
+ * @param startIndex the start index to travers backwards from
+ * @return the last index of the value within the array,
+ * <code>-1</code> if not found or <code>null</code> array input
+ */
+ public static int lastIndexOf(float[] array, float valueToFind, int startIndex) {
+ if (ArrayUtils.isEmpty(array)) {
+ return -1;
+ }
+ if (startIndex < 0) {
+ return -1;
+ } else if (startIndex >= array.length) {
+ startIndex = array.length - 1;
+ }
+ for (int i = startIndex; i >= 0; i--) {
+ if (valueToFind == array[i]) {
+ return i;
+ }
+ }
+ return -1;
+ }
+
+ /**
+ * <p>Checks if the value is in the given array.</p>
+ *
+ * <p>The method returns <code>false</code> if a <code>null</code> array is passed in.</p>
+ *
+ * @param array the array to search through
+ * @param valueToFind the value to find
+ * @return <code>true</code> if the array contains the object
+ */
+ public static boolean contains(float[] array, float valueToFind) {
+ return (indexOf(array, valueToFind) != -1);
+ }
+
+ // boolean IndexOf
+ //-----------------------------------------------------------------------
+ /**
+ * <p>Find the index of the given value in the array.</p>
+ *
+ * <p>This method returns <code>-1</code> if <code>null</code> array input.</p>
+ *
+ * @param array the array to search through for the object, may be <code>null</code>
+ * @param valueToFind the value to find
+ * @return the index of the value within the array,
+ * <code>-1</code> if not found or <code>null</code> array input
+ */
+ public static int indexOf(boolean[] array, boolean valueToFind) {
+ return indexOf(array, valueToFind, 0);
+ }
+
+ /**
+ * <p>Find the index of the given value in the array starting at the given index.</p>
+ *
+ * <p>This method returns <code>-1</code> if <code>null</code> array input.</p>
+ *
+ * <p>A negative startIndex is treated as zero. A startIndex larger than the array
+ * length will return -1.</p>
+ *
+ * @param array the array to search through for the object, may be <code>null</code>
+ * @param valueToFind the value to find
+ * @param startIndex the index to start searching at
+ * @return the index of the value within the array,
+ * <code>-1</code> if not found or <code>null</code> array input
+ */
+ public static int indexOf(boolean[] array, boolean valueToFind, int startIndex) {
+ if (ArrayUtils.isEmpty(array)) {
+ return -1;
+ }
+ if (startIndex < 0) {
+ startIndex = 0;
+ }
+ for (int i = startIndex; i < array.length; i++) {
+ if (valueToFind == array[i]) {
+ return i;
+ }
+ }
+ return -1;
+ }
+
+ /**
+ * <p>Find the last index of the given value within the array.</p>
+ *
+ * <p>This method returns <code>-1</code> if <code>null</code> array input.</p>
+ *
+ * @param array the array to travers backwords looking for the object, may be <code>null</code>
+ * @param valueToFind the object to find
+ * @return the last index of the value within the array,
+ * <code>-1</code> if not found or <code>null</code> array input
+ */
+ public static int lastIndexOf(boolean[] array, boolean valueToFind) {
+ return lastIndexOf(array, valueToFind, Integer.MAX_VALUE);
+ }
+
+ /**
+ * <p>Find the last index of the given value in the array starting at the given index.</p>
+ *
+ * <p>This method returns <code>-1</code> if <code>null</code> array input.</p>
+ *
+ * <p>A negative startIndex will return -1. A startIndex larger than the array
+ * length will search from the end of the array.</p>
+ *
+ * @param array the array to traverse for looking for the object, may be <code>null</code>
+ * @param valueToFind the value to find
+ * @param startIndex the start index to travers backwards from
+ * @return the last index of the value within the array,
+ * <code>-1</code> if not found or <code>null</code> array input
+ */
+ public static int lastIndexOf(boolean[] array, boolean valueToFind, int startIndex) {
+ if (ArrayUtils.isEmpty(array)) {
+ return -1;
+ }
+ if (startIndex < 0) {
+ return -1;
+ } else if (startIndex >= array.length) {
+ startIndex = array.length - 1;
+ }
+ for (int i = startIndex; i >= 0; i--) {
+ if (valueToFind == array[i]) {
+ return i;
+ }
+ }
+ return -1;
+ }
+
+ /**
+ * <p>Checks if the value is in the given array.</p>
+ *
+ * <p>The method returns <code>false</code> if a <code>null</code> array is passed in.</p>
+ *
+ * @param array the array to search through
+ * @param valueToFind the value to find
+ * @return <code>true</code> if the array contains the object
+ */
+ public static boolean contains(boolean[] array, boolean valueToFind) {
+ return (indexOf(array, valueToFind) != -1);
+ }
+
+ // Primitive/Object array converters
+ // ----------------------------------------------------------------------
+
+ // Long array converters
+ // ----------------------------------------------------------------------
+ /**
+ * <p>Converts an array of object Longs to primitives.</p>
+ *
+ * <p>This method returns <code>null</code> if <code>null</code> array input.</p>
+ *
+ * @param array a <code>Long</code> array, may be <code>null</code>
+ * @return a <code>long</code> array, <code>null</code> if null array input
+ * @throws NullPointerException if array content is <code>null</code>
+ */
+ public static long[] toPrimitive(Long[] array) {
+ if (array == null) {
+ return null;
+ } else if (array.length == 0) {
+ return EMPTY_LONG_ARRAY;
+ }
+ final long[] result = new long[array.length];
+ for (int i = 0; i < array.length; i++) {
+ result[i] = array[i].longValue();
+ }
+ return result;
+ }
+
+ /**
+ * <p>Converts an array of object Long to primitives handling <code>null</code>.</p>
+ *
+ * <p>This method returns <code>null</code> if <code>null</code> array input.</p>
+ *
+ * @param array a <code>Long</code> array, may be <code>null</code>
+ * @param valueForNull the value to insert if <code>null</code> found
+ * @return a <code>long</code> array, <code>null</code> if null array input
+ */
+ public static long[] toPrimitive(Long[] array, long valueForNull) {
+ if (array == null) {
+ return null;
+ } else if (array.length == 0) {
+ return EMPTY_LONG_ARRAY;
+ }
+ final long[] result = new long[array.length];
+ for (int i = 0; i < array.length; i++) {
+ Long b = array[i];
+ result[i] = (b == null ? valueForNull : b.longValue());
+ }
+ return result;
+ }
+
+ /**
+ * <p>Converts an array of primitive longs to objects.</p>
+ *
+ * <p>This method returns <code>null</code> if <code>null</code> array input.</p>
+ *
+ * @param array a <code>long</code> array
+ * @return a <code>Long</code> array, <code>null</code> if null array input
+ */
+ public static Long[] toObject(long[] array) {
+ if (array == null) {
+ return null;
+ } else if (array.length == 0) {
+ return EMPTY_LONG_OBJECT_ARRAY;
+ }
+ final Long[] result = new Long[array.length];
+ for (int i = 0; i < array.length; i++) {
+ result[i] = new Long(array[i]);
+ }
+ return result;
+ }
+
+ // Int array converters
+ // ----------------------------------------------------------------------
+ /**
+ * <p>Converts an array of object Integers to primitives.</p>
+ *
+ * <p>This method returns <code>null</code> if <code>null</code> array input.</p>
+ *
+ * @param array a <code>Integer</code> array, may be <code>null</code>
+ * @return an <code>int</code> array, <code>null</code> if null array input
+ * @throws NullPointerException if array content is <code>null</code>
+ */
+ public static int[] toPrimitive(Integer[] array) {
+ if (array == null) {
+ return null;
+ } else if (array.length == 0) {
+ return EMPTY_INT_ARRAY;
+ }
+ final int[] result = new int[array.length];
+ for (int i = 0; i < array.length; i++) {
+ result[i] = array[i].intValue();
+ }
+ return result;
+ }
+
+ /**
+ * <p>Converts an array of object Integer to primitives handling <code>null</code>.</p>
+ *
+ * <p>This method returns <code>null</code> if <code>null</code> array input.</p>
+ *
+ * @param array a <code>Integer</code> array, may be <code>null</code>
+ * @param valueForNull the value to insert if <code>null</code> found
+ * @return an <code>int</code> array, <code>null</code> if null array input
+ */
+ public static int[] toPrimitive(Integer[] array, int valueForNull) {
+ if (array == null) {
+ return null;
+ } else if (array.length == 0) {
+ return EMPTY_INT_ARRAY;
+ }
+ final int[] result = new int[array.length];
+ for (int i = 0; i < array.length; i++) {
+ Integer b = array[i];
+ result[i] = (b == null ? valueForNull : b.intValue());
+ }
+ return result;
+ }
+
+ /**
+ * <p>Converts an array of primitive ints to objects.</p>
+ *
+ * <p>This method returns <code>null</code> if <code>null</code> array input.</p>
+ *
+ * @param array an <code>int</code> array
+ * @return an <code>Integer</code> array, <code>null</code> if null array input
+ */
+ public static Integer[] toObject(int[] array) {
+ if (array == null) {
+ return null;
+ } else if (array.length == 0) {
+ return EMPTY_INTEGER_OBJECT_ARRAY;
+ }
+ final Integer[] result = new Integer[array.length];
+ for (int i = 0; i < array.length; i++) {
+ result[i] = new Integer(array[i]);
+ }
+ return result;
+ }
+
+ // Short array converters
+ // ----------------------------------------------------------------------
+ /**
+ * <p>Converts an array of object Shorts to primitives.</p>
+ *
+ * <p>This method returns <code>null</code> if <code>null</code> array input.</p>
+ *
+ * @param array a <code>Short</code> array, may be <code>null</code>
+ * @return a <code>byte</code> array, <code>null</code> if null array input
+ * @throws NullPointerException if array content is <code>null</code>
+ */
+ public static short[] toPrimitive(Short[] array) {
+ if (array == null) {
+ return null;
+ } else if (array.length == 0) {
+ return EMPTY_SHORT_ARRAY;
+ }
+ final short[] result = new short[array.length];
+ for (int i = 0; i < array.length; i++) {
+ result[i] = array[i].shortValue();
+ }
+ return result;
+ }
+
+ /**
+ * <p>Converts an array of object Short to primitives handling <code>null</code>.</p>
+ *
+ * <p>This method returns <code>null</code> if <code>null</code> array input.</p>
+ *
+ * @param array a <code>Short</code> array, may be <code>null</code>
+ * @param valueForNull the value to insert if <code>null</code> found
+ * @return a <code>byte</code> array, <code>null</code> if null array input
+ */
+ public static short[] toPrimitive(Short[] array, short valueForNull) {
+ if (array == null) {
+ return null;
+ } else if (array.length == 0) {
+ return EMPTY_SHORT_ARRAY;
+ }
+ final short[] result = new short[array.length];
+ for (int i = 0; i < array.length; i++) {
+ Short b = array[i];
+ result[i] = (b == null ? valueForNull : b.shortValue());
+ }
+ return result;
+ }
+
+ /**
+ * <p>Converts an array of primitive shorts to objects.</p>
+ *
+ * <p>This method returns <code>null</code> if <code>null</code> array input.</p>
+ *
+ * @param array a <code>short</code> array
+ * @return a <code>Short</code> array, <code>null</code> if null array input
+ */
+ public static Short[] toObject(short[] array) {
+ if (array == null) {
+ return null;
+ } else if (array.length == 0) {
+ return EMPTY_SHORT_OBJECT_ARRAY;
+ }
+ final Short[] result = new Short[array.length];
+ for (int i = 0; i < array.length; i++) {
+ result[i] = new Short(array[i]);
+ }
+ return result;
+ }
+
+ // Byte array converters
+ // ----------------------------------------------------------------------
+ /**
+ * <p>Converts an array of object Bytes to primitives.</p>
+ *
+ * <p>This method returns <code>null</code> if <code>null</code> array input.</p>
+ *
+ * @param array a <code>Byte</code> array, may be <code>null</code>
+ * @return a <code>byte</code> array, <code>null</code> if null array input
+ * @throws NullPointerException if array content is <code>null</code>
+ */
+ public static byte[] toPrimitive(Byte[] array) {
+ if (array == null) {
+ return null;
+ } else if (array.length == 0) {
+ return EMPTY_BYTE_ARRAY;
+ }
+ final byte[] result = new byte[array.length];
+ for (int i = 0; i < array.length; i++) {
+ result[i] = array[i].byteValue();
+ }
+ return result;
+ }
+
+ /**
+ * <p>Converts an array of object Bytes to primitives handling <code>null</code>.</p>
+ *
+ * <p>This method returns <code>null</code> if <code>null</code> array input.</p>
+ *
+ * @param array a <code>Byte</code> array, may be <code>null</code>
+ * @param valueForNull the value to insert if <code>null</code> found
+ * @return a <code>byte</code> array, <code>null</code> if null array input
+ */
+ public static byte[] toPrimitive(Byte[] array, byte valueForNull) {
+ if (array == null) {
+ return null;
+ } else if (array.length == 0) {
+ return EMPTY_BYTE_ARRAY;
+ }
+ final byte[] result = new byte[array.length];
+ for (int i = 0; i < array.length; i++) {
+ Byte b = array[i];
+ result[i] = (b == null ? valueForNull : b.byteValue());
+ }
+ return result;
+ }
+
+ /**
+ * <p>Converts an array of primitive bytes to objects.</p>
+ *
+ * <p>This method returns <code>null</code> if <code>null</code> array input.</p>
+ *
+ * @param array a <code>byte</code> array
+ * @return a <code>Byte</code> array, <code>null</code> if null array input
+ */
+ public static Byte[] toObject(byte[] array) {
+ if (array == null) {
+ return null;
+ } else if (array.length == 0) {
+ return EMPTY_BYTE_OBJECT_ARRAY;
+ }
+ final Byte[] result = new Byte[array.length];
+ for (int i = 0; i < array.length; i++) {
+ result[i] = new Byte(array[i]);
+ }
+ return result;
+ }
+
+ // Double array converters
+ // ----------------------------------------------------------------------
+ /**
+ * <p>Converts an array of object Doubles to primitives.</p>
+ *
+ * <p>This method returns <code>null</code> if <code>null</code> array input.</p>
+ *
+ * @param array a <code>Double</code> array, may be <code>null</code>
+ * @return a <code>double</code> array, <code>null</code> if null array input
+ * @throws NullPointerException if array content is <code>null</code>
+ */
+ public static double[] toPrimitive(Double[] array) {
+ if (array == null) {
+ return null;
+ } else if (array.length == 0) {
+ return EMPTY_DOUBLE_ARRAY;
+ }
+ final double[] result = new double[array.length];
+ for (int i = 0; i < array.length; i++) {
+ result[i] = array[i].doubleValue();
+ }
+ return result;
+ }
+
+ /**
+ * <p>Converts an array of object Doubles to primitives handling <code>null</code>.</p>
+ *
+ * <p>This method returns <code>null</code> if <code>null</code> array input.</p>
+ *
+ * @param array a <code>Double</code> array, may be <code>null</code>
+ * @param valueForNull the value to insert if <code>null</code> found
+ * @return a <code>double</code> array, <code>null</code> if null array input
+ */
+ public static double[] toPrimitive(Double[] array, double valueForNull) {
+ if (array == null) {
+ return null;
+ } else if (array.length == 0) {
+ return EMPTY_DOUBLE_ARRAY;
+ }
+ final double[] result = new double[array.length];
+ for (int i = 0; i < array.length; i++) {
+ Double b = array[i];
+ result[i] = (b == null ? valueForNull : b.doubleValue());
+ }
+ return result;
+ }
+
+ /**
+ * <p>Converts an array of primitive doubles to objects.</p>
+ *
+ * <p>This method returns <code>null</code> if <code>null</code> array input.</p>
+ *
+ * @param array a <code>double</code> array
+ * @return a <code>Double</code> array, <code>null</code> if null array input
+ */
+ public static Double[] toObject(double[] array) {
+ if (array == null) {
+ return null;
+ } else if (array.length == 0) {
+ return EMPTY_DOUBLE_OBJECT_ARRAY;
+ }
+ final Double[] result = new Double[array.length];
+ for (int i = 0; i < array.length; i++) {
+ result[i] = new Double(array[i]);
+ }
+ return result;
+ }
+
+ // Float array converters
+ // ----------------------------------------------------------------------
+ /**
+ * <p>Converts an array of object Floats to primitives.</p>
+ *
+ * <p>This method returns <code>null</code> if <code>null</code> array input.</p>
+ *
+ * @param array a <code>Float</code> array, may be <code>null</code>
+ * @return a <code>float</code> array, <code>null</code> if null array input
+ * @throws NullPointerException if array content is <code>null</code>
+ */
+ public static float[] toPrimitive(Float[] array) {
+ if (array == null) {
+ return null;
+ } else if (array.length == 0) {
+ return EMPTY_FLOAT_ARRAY;
+ }
+ final float[] result = new float[array.length];
+ for (int i = 0; i < array.length; i++) {
+ result[i] = array[i].floatValue();
+ }
+ return result;
+ }
+
+ /**
+ * <p>Converts an array of object Floats to primitives handling <code>null</code>.</p>
+ *
+ * <p>This method returns <code>null</code> if <code>null</code> array input.</p>
+ *
+ * @param array a <code>Float</code> array, may be <code>null</code>
+ * @param valueForNull the value to insert if <code>null</code> found
+ * @return a <code>float</code> array, <code>null</code> if null array input
+ */
+ public static float[] toPrimitive(Float[] array, float valueForNull) {
+ if (array == null) {
+ return null;
+ } else if (array.length == 0) {
+ return EMPTY_FLOAT_ARRAY;
+ }
+ final float[] result = new float[array.length];
+ for (int i = 0; i < array.length; i++) {
+ Float b = array[i];
+ result[i] = (b == null ? valueForNull : b.floatValue());
+ }
+ return result;
+ }
+
+ /**
+ * <p>Converts an array of primitive floats to objects.</p>
+ *
+ * <p>This method returns <code>null</code> if <code>null</code> array input.</p>
+ *
+ * @param array a <code>float</code> array
+ * @return a <code>Float</code> array, <code>null</code> if null array input
+ */
+ public static Float[] toObject(float[] array) {
+ if (array == null) {
+ return null;
+ } else if (array.length == 0) {
+ return EMPTY_FLOAT_OBJECT_ARRAY;
+ }
+ final Float[] result = new Float[array.length];
+ for (int i = 0; i < array.length; i++) {
+ result[i] = new Float(array[i]);
+ }
+ return result;
+ }
+
+ // Boolean array converters
+ // ----------------------------------------------------------------------
+ /**
+ * <p>Converts an array of object Booleans to primitives.</p>
+ *
+ * <p>This method returns <code>null</code> if <code>null</code> array input.</p>
+ *
+ * @param array a <code>Boolean</code> array, may be <code>null</code>
+ * @return a <code>boolean</code> array, <code>null</code> if null array input
+ * @throws NullPointerException if array content is <code>null</code>
+ */
+ public static boolean[] toPrimitive(Boolean[] array) {
+ if (array == null) {
+ return null;
+ } else if (array.length == 0) {
+ return EMPTY_BOOLEAN_ARRAY;
+ }
+ final boolean[] result = new boolean[array.length];
+ for (int i = 0; i < array.length; i++) {
+ result[i] = array[i].booleanValue();
+ }
+ return result;
+ }
+
+ /**
+ * <p>Converts an array of object Booleans to primitives handling <code>null</code>.</p>
+ *
+ * <p>This method returns <code>null</code> if <code>null</code> array input.</p>
+ *
+ * @param array a <code>Boolean</code> array, may be <code>null</code>
+ * @param valueForNull the value to insert if <code>null</code> found
+ * @return a <code>boolean</code> array, <code>null</code> if null array input
+ */
+ public static boolean[] toPrimitive(Boolean[] array, boolean valueForNull) {
+ if (array == null) {
+ return null;
+ } else if (array.length == 0) {
+ return EMPTY_BOOLEAN_ARRAY;
+ }
+ final boolean[] result = new boolean[array.length];
+ for (int i = 0; i < array.length; i++) {
+ Boolean b = array[i];
+ result[i] = (b == null ? valueForNull : b.booleanValue());
+ }
+ return result;
+ }
+
+ /**
+ * <p>Converts an array of primitive booleans to objects.</p>
+ *
+ * <p>This method returns <code>null</code> if <code>null</code> array input.</p>
+ *
+ * @param array a <code>boolean</code> array
+ * @return a <code>Boolean</code> array, <code>null</code> if null array input
+ */
+ public static Boolean[] toObject(boolean[] array) {
+ if (array == null) {
+ return null;
+ } else if (array.length == 0) {
+ return EMPTY_BOOLEAN_OBJECT_ARRAY;
+ }
+ final Boolean[] result = new Boolean[array.length];
+ for (int i = 0; i < array.length; i++) {
+ result[i] = (array[i] ? Boolean.TRUE : Boolean.FALSE);
+ }
+ return result;
+ }
+
+ // ----------------------------------------------------------------------
+ /**
+ * <p>Checks if an array of Objects is empty or <code>null</code>.</p>
+ *
+ * @param array the array to test
+ * @return <code>true</code> if the array is empty or <code>null</code>
+ * @since 2.1
+ */
+ public static boolean isEmpty(Object[] array) {
+ if (array == null || array.length == 0) {
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * <p>Checks if an array of primitive longs is empty or <code>null</code>.</p>
+ *
+ * @param array the array to test
+ * @return <code>true</code> if the array is empty or <code>null</code>
+ * @since 2.1
+ */
+ public static boolean isEmpty(long[] array) {
+ if (array == null || array.length == 0) {
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * <p>Checks if an array of primitive ints is empty or <code>null</code>.</p>
+ *
+ * @param array the array to test
+ * @return <code>true</code> if the array is empty or <code>null</code>
+ * @since 2.1
+ */
+ public static boolean isEmpty(int[] array) {
+ if (array == null || array.length == 0) {
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * <p>Checks if an array of primitive shorts is empty or <code>null</code>.</p>
+ *
+ * @param array the array to test
+ * @return <code>true</code> if the array is empty or <code>null</code>
+ * @since 2.1
+ */
+ public static boolean isEmpty(short[] array) {
+ if (array == null || array.length == 0) {
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * <p>Checks if an array of primitive chars is empty or <code>null</code>.</p>
+ *
+ * @param array the array to test
+ * @return <code>true</code> if the array is empty or <code>null</code>
+ * @since 2.1
+ */
+ public static boolean isEmpty(char[] array) {
+ if (array == null || array.length == 0) {
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * <p>Checks if an array of primitive bytes is empty or <code>null</code>.</p>
+ *
+ * @param array the array to test
+ * @return <code>true</code> if the array is empty or <code>null</code>
+ * @since 2.1
+ */
+ public static boolean isEmpty(byte[] array) {
+ if (array == null || array.length == 0) {
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * <p>Checks if an array of primitive doubles is empty or <code>null</code>.</p>
+ *
+ * @param array the array to test
+ * @return <code>true</code> if the array is empty or <code>null</code>
+ * @since 2.1
+ */
+ public static boolean isEmpty(double[] array) {
+ if (array == null || array.length == 0) {
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * <p>Checks if an array of primitive floats is empty or <code>null</code>.</p>
+ *
+ * @param array the array to test
+ * @return <code>true</code> if the array is empty or <code>null</code>
+ * @since 2.1
+ */
+ public static boolean isEmpty(float[] array) {
+ if (array == null || array.length == 0) {
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * <p>Checks if an array of primitive booleans is empty or <code>null</code>.</p>
+ *
+ * @param array the array to test
+ * @return <code>true</code> if the array is empty or <code>null</code>
+ * @since 2.1
+ */
+ public static boolean isEmpty(boolean[] array) {
+ if (array == null || array.length == 0) {
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * <p>Adds all the elements of the given arrays into a new array.</p>
+ * <p>The new array contains all of the element of <code>array1</code> followed
+ * by all of the elements <code>array2</code>. When an array is returned, it is always
+ * a new array.</p>
+ *
+ * <pre>
+ * ArrayUtils.addAll(null, null) = null
+ * ArrayUtils.addAll(array1, null) = cloned copy of array1
+ * ArrayUtils.addAll(null, array2) = cloned copy of array2
+ * ArrayUtils.addAll([], []) = []
+ * ArrayUtils.addAll([null], [null]) = [null, null]
+ * ArrayUtils.addAll(["a", "b", "c"], ["1", "2", "3"]) = ["a", "b", "c", "1", "2", "3"]
+ * </pre>
+ *
+ * @param array1 the first array whose elements are added to the new array, may be <code>null</code>
+ * @param array2 the second array whose elements are added to the new array, may be <code>null</code>
+ * @return The new array, <code>null</code> if <code>null</code> array inputs.
+ * The type of the new array is the type of the first array.
+ * @since 2.1
+ */
+ public static Object[] addAll(Object[] array1, Object[] array2) {
+ if (array1 == null) {
+ return clone(array2);
+ } else if (array2 == null) {
+ return clone(array1);
+ } else {
+ Object[] joinedArray = (Object[]) Array.newInstance(array1.getClass().getComponentType(), array1.length
+ + array2.length);
+ System.arraycopy(array1, 0, joinedArray, 0, array1.length);
+ System.arraycopy(array2, 0, joinedArray, array1.length, array2.length);
+ return joinedArray;
+ }
+ }
+
+ /**
+ * <p>Copies the given array and adds the given element at the end of the new array.</p>
+ *
+ * <p>The new array contains the same elements of the input
+ * array plus the given element in the last position. The component type of
+ * the new array is the same as that of the input array.</p>
+ *
+ * <p>If the input array is <code>null</code>, a new one element array is returned
+ * whose component type is the same as the element.</p>
+ *
+ * <pre>
+ * ArrayUtils.add(null, null) = [null]
+ * ArrayUtils.add(null, "a") = ["a"]
+ * ArrayUtils.add(["a"], null) = ["a", null]
+ * ArrayUtils.add(["a"], "b") = ["a", "b"]
+ * ArrayUtils.add(["a", "b"], "c") = ["a", "b", "c"]
+ * </pre>
+ *
+ * @param array the array to "add" the element to, may be <code>null</code>
+ * @param element the object to add
+ * @return A new array containing the existing elements plus the new element
+ * @since 2.1
+ */
+ public static Object[] add(Object[] array, Object element) {
+ Object newArray = copyArrayGrow1(array, element != null ? element.getClass() : Object.class);
+ Array.set(newArray, lastIndex(newArray), element);
+ return (Object[]) newArray;
+ }
+
+ /**
+ * <p>Copies the given array and adds the given element at the end of the new array.</p>
+ *
+ * <p>The new array contains the same elements of the input
+ * array plus the given element in the last position. The component type of
+ * the new array is the same as that of the input array.</p>
+ *
+ * <p>If the input array is <code>null</code>, a new one element array is returned
+ * whose component type is the same as the element.</p>
+ *
+ * <pre>
+ * ArrayUtils.add(null, true) = [true]
+ * ArrayUtils.add([true], false) = [true, false]
+ * ArrayUtils.add([true, false], true) = [true, false, true]
+ * </pre>
+ *
+ * @param array the array to copy and add the element to, may be <code>null</code>
+ * @param element the object to add at the last index of the new array
+ * @return A new array containing the existing elements plus the new element
+ * @since 2.1
+ */
+ public static boolean[] add(boolean[] array, boolean element) {
+ boolean[] newArray = (boolean[])copyArrayGrow1(array, Boolean.TYPE);
+ newArray[lastIndex(newArray)] = element;
+ return newArray;
+ }
+
+ /**
+ * <p>Copies the given array and adds the given element at the end of the new array.</p>
+ *
+ * <p>The new array contains the same elements of the input
+ * array plus the given element in the last position. The component type of
+ * the new array is the same as that of the input array.</p>
+ *
+ * <p>If the input array is <code>null</code>, a new one element array is returned
+ * whose component type is the same as the element.</p>
+ *
+ * <pre>
+ * ArrayUtils.add(null, 0) = [0]
+ * ArrayUtils.add([1], 0) = [1, 0]
+ * ArrayUtils.add([1, 0], 1) = [1, 0, 1]
+ * </pre>
+ *
+ * @param array the array to copy and add the element to, may be <code>null</code>
+ * @param element the object to add at the last index of the new array
+ * @return A new array containing the existing elements plus the new element
+ * @since 2.1
+ */
+ public static byte[] add(byte[] array, byte element) {
+ byte[] newArray = (byte[])copyArrayGrow1(array, Byte.TYPE);
+ newArray[lastIndex(newArray)] = element;
+ return newArray;
+ }
+
+ /**
+ * <p>Copies the given array and adds the given element at the end of the new array.</p>
+ *
+ * <p>The new array contains the same elements of the input
+ * array plus the given element in the last position. The component type of
+ * the new array is the same as that of the input array.</p>
+ *
+ * <p>If the input array is <code>null</code>, a new one element array is returned
+ * whose component type is the same as the element.</p>
+ *
+ * <pre>
+ * ArrayUtils.add(null, '0') = ['0']
+ * ArrayUtils.add(['1'], '0') = ['1', '0']
+ * ArrayUtils.add(['1', '0'], '1') = ['1', '0', '1']
+ * </pre>
+ *
+ * @param array the array to copy and add the element to, may be <code>null</code>
+ * @param element the object to add at the last index of the new array
+ * @return A new array containing the existing elements plus the new element
+ * @since 2.1
+ */
+ public static char[] add(char[] array, char element) {
+ char[] newArray = (char[])copyArrayGrow1(array, Character.TYPE);
+ newArray[lastIndex(newArray)] = element;
+ return newArray;
+ }
+
+ /**
+ * <p>Copies the given array and adds the given element at the end of the new array.</p>
+ *
+ * <p>The new array contains the same elements of the input
+ * array plus the given element in the last position. The component type of
+ * the new array is the same as that of the input array.</p>
+ *
+ * <p>If the input array is <code>null</code>, a new one element array is returned
+ * whose component type is the same as the element.</p>
+ *
+ * <pre>
+ * ArrayUtils.add(null, 0) = [0]
+ * ArrayUtils.add([1], 0) = [1, 0]
+ * ArrayUtils.add([1, 0], 1) = [1, 0, 1]
+ * </pre>
+ *
+ * @param array the array to copy and add the element to, may be <code>null</code>
+ * @param element the object to add at the last index of the new array
+ * @return A new array containing the existing elements plus the new element
+ * @since 2.1
+ */
+ public static double[] add(double[] array, double element) {
+ double[] newArray = (double[])copyArrayGrow1(array, Double.TYPE);
+ newArray[lastIndex(newArray)] = element;
+ return newArray;
+ }
+
+ /**
+ * <p>Copies the given array and adds the given element at the end of the new array.</p>
+ *
+ * <p>The new array contains the same elements of the input
+ * array plus the given element in the last position. The component type of
+ * the new array is the same as that of the input array.</p>
+ *
+ * <p>If the input array is <code>null</code>, a new one element array is returned
+ * whose component type is the same as the element.</p>
+ *
+ * <pre>
+ * ArrayUtils.add(null, 0) = [0]
+ * ArrayUtils.add([1], 0) = [1, 0]
+ * ArrayUtils.add([1, 0], 1) = [1, 0, 1]
+ * </pre>
+ *
+ * @param array the array to copy and add the element to, may be <code>null</code>
+ * @param element the object to add at the last index of the new array
+ * @return A new array containing the existing elements plus the new element
+ * @since 2.1
+ */
+ public static float[] add(float[] array, float element) {
+ float[] newArray = (float[])copyArrayGrow1(array, Float.TYPE);
+ newArray[lastIndex(newArray)] = element;
+ return newArray;
+ }
+
+ /**
+ * <p>Copies the given array and adds the given element at the end of the new array.</p>
+ *
+ * <p>The new array contains the same elements of the input
+ * array plus the given element in the last position. The component type of
+ * the new array is the same as that of the input array.</p>
+ *
+ * <p>If the input array is <code>null</code>, a new one element array is returned
+ * whose component type is the same as the element.</p>
+ *
+ * <pre>
+ * ArrayUtils.add(null, 0) = [0]
+ * ArrayUtils.add([1], 0) = [1, 0]
+ * ArrayUtils.add([1, 0], 1) = [1, 0, 1]
+ * </pre>
+ *
+ * @param array the array to copy and add the element to, may be <code>null</code>
+ * @param element the object to add at the last index of the new array
+ * @return A new array containing the existing elements plus the new element
+ * @since 2.1
+ */
+ public static int[] add(int[] array, int element) {
+ int[] newArray = (int[])copyArrayGrow1(array, Integer.TYPE);
+ newArray[lastIndex(newArray)] = element;
+ return newArray;
+ }
+
+ /**
+ * <p>Copies the given array and adds the given element at the end of the new array.</p>
+ *
+ * <p>The new array contains the same elements of the input
+ * array plus the given element in the last position. The component type of
+ * the new array is the same as that of the input array.</p>
+ *
+ * <p>If the input array is <code>null</code>, a new one element array is returned
+ * whose component type is the same as the element.</p>
+ *
+ * <pre>
+ * ArrayUtils.add(null, 0) = [0]
+ * ArrayUtils.add([1], 0) = [1, 0]
+ * ArrayUtils.add([1, 0], 1) = [1, 0, 1]
+ * </pre>
+ *
+ * @param array the array to copy and add the element to, may be <code>null</code>
+ * @param element the object to add at the last index of the new array
+ * @return A new array containing the existing elements plus the new element
+ * @since 2.1
+ */
+ public static long[] add(long[] array, long element) {
+ long[] newArray = (long[])copyArrayGrow1(array, Long.TYPE);
+ newArray[lastIndex(newArray)] = element;
+ return newArray;
+ }
+
+ /**
+ * <p>Copies the given array and adds the given element at the end of the new array.</p>
+ *
+ * <p>The new array contains the same elements of the input
+ * array plus the given element in the last position. The component type of
+ * the new array is the same as that of the input array.</p>
+ *
+ * <p>If the input array is <code>null</code>, a new one element array is returned
+ * whose component type is the same as the element.</p>
+ *
+ * <pre>
+ * ArrayUtils.add(null, 0) = [0]
+ * ArrayUtils.add([1], 0) = [1, 0]
+ * ArrayUtils.add([1, 0], 1) = [1, 0, 1]
+ * </pre>
+ *
+ * @param array the array to copy and add the element to, may be <code>null</code>
+ * @param element the object to add at the last index of the new array
+ * @return A new array containing the existing elements plus the new element
+ * @since 2.1
+ */
+ public static short[] add(short[] array, short element) {
+ short[] newArray = (short[])copyArrayGrow1(array, Short.TYPE);
+ newArray[lastIndex(newArray)] = element;
+ return newArray;
+ }
+
+ /**
+ * Returns a copy of the given array of size 1 greater than the argument.
+ * The last value of the array is left to the default value.
+ *
+ * @param array The array to copy, must not be <code>null</code>.
+ * @param newArrayComponentType If <code>array</code> is <code>null</code>, create a
+ * size 1 array of this type.
+ * @return A new copy of the array of size 1 greater than the input.
+ */
+ private static Object copyArrayGrow1(Object array, Class newArrayComponentType) {
+ if (array != null) {
+ int arrayLength = Array.getLength(array);
+ Object newArray = Array.newInstance(array.getClass().getComponentType(), arrayLength + 1);
+ System.arraycopy(array, 0, newArray, 0, arrayLength);
+ return newArray;
+ } else {
+ return Array.newInstance(newArrayComponentType, 1);
+ }
+ }
+
+ /**
+ * <p>Inserts the specified element at the specified position in the array.
+ * Shifts the element currently at that position (if any) and any subsequent
+ * elements to the right (adds one to their indices).</p>
+ *
+ * <p>This method returns a new array with the same elements of the input
+ * array plus the given element on the specified position. The component
+ * type of the returned array is always the same as that of the input
+ * array.</p>
+ *
+ * <p>If the input array is <code>null</code>, a new one element array is returned
+ * whose component type is the same as the element.</p>
+ *
+ * <pre>
+ * ArrayUtils.add(null, 0, null) = [null]
+ * ArrayUtils.add(null, 0, "a") = ["a"]
+ * ArrayUtils.add(["a"], 1, null) = ["a", null]
+ * ArrayUtils.add(["a"], 1, "b") = ["a", "b"]
+ * ArrayUtils.add(["a", "b"], 3, "c") = ["a", "b", "c"]
+ * </pre>
+ *
+ * @param array the array to add the element to, may be <code>null</code>
+ * @param index the position of the new object
+ * @param element the object to add
+ * @return A new array containing the existing elements and the new element
+ * @throws IndexOutOfBoundsException if the index is out of range
+ * (index < 0 || index > array.length).
+ */
+ public static Object[] add(Object[] array, int index, Object element) {
+ if (array == null) {
+ if (index != 0) {
+ throw new IndexOutOfBoundsException("Index: " + index + ", Length: 0");
+ }
+ Object joinedArray = Array.newInstance(element != null ? element.getClass() : Object.class, 1);
+ Array.set(joinedArray, 0, element);
+ return (Object[]) joinedArray;
+ }
+ int length = array.length;
+ if (index > length || index < 0) {
+ throw new IndexOutOfBoundsException("Index: " + index + ", Length: " + length);
+ }
+ Object result = Array.newInstance(array.getClass().getComponentType(), length + 1);
+ System.arraycopy(array, 0, result, 0, index);
+ Array.set(result, index, element);
+ if (index < length) {
+ System.arraycopy(array, index, result, index + 1, length - index);
+ }
+ return (Object[]) result;
+ }
+
+ /**
+ * <p>Removes the element at the specified position from the specified array.
+ * All subsequent elements are shifted to the left (substracts one from
+ * their indices).</p>
+ *
+ * <p>This method returns a new array with the same elements of the input
+ * array except the element on the specified position. The component
+ * type of the returned array is always the same as that of the input
+ * array.</p>
+ *
+ * <p>If the input array is <code>null</code>, an IndexOutOfBoundsException
+ * will be thrown, because in that case no valid index can be specified.</p>
+ *
+ * <pre>
+ * ArrayUtils.remove(["a"], 0) = []
+ * ArrayUtils.remove(["a", "b"], 0) = ["b"]
+ * ArrayUtils.remove(["a", "b"], 1) = ["a"]
+ * ArrayUtils.remove(["a", "b", "c"], 1) = ["a", "c"]
+ * </pre>
+ *
+ * @param array the array to remove the element from, may not be <code>null</code>
+ * @param index the position of the element to be removed
+ * @return A new array containing the existing elements except the element
+ * at the specified position.
+ * @throws IndexOutOfBoundsException if the index is out of range
+ * (index < 0 || index >= array.length), or if the array is <code>null</code>.
+ * @since 2.1
+ */
+ public static Object[] remove(Object[] array, int index) {
+ return (Object[]) remove((Object) array, index);
+ }
+
+ /**
+ * <p>Removes the first occurrence of the specified element from the
+ * specified array. All subsequent elements are shifted to the left
+ * (substracts one from their indices). If the array doesn't contains
+ * such an element, no elements are removed from the array.</p>
+ *
+ * <p>This method returns a new array with the same elements of the input
+ * array except the first occurrence of the specified element. The component
+ * type of the returned array is always the same as that of the input
+ * array.</p>
+ *
+ * <pre>
+ * ArrayUtils.removeElement(null, "a") = null
+ * ArrayUtils.removeElement([], "a") = []
+ * ArrayUtils.removeElement(["a"], "b") = ["a"]
+ * ArrayUtils.removeElement(["a", "b"], "a") = ["b"]
+ * ArrayUtils.removeElement(["a", "b", "a"], "a") = ["b", "a"]
+ * </pre>
+ *
+ * @param array the array to remove the element from, may be <code>null</code>
+ * @param element the element to be removed
+ * @return A new array containing the existing elements except the first
+ * occurrence of the specified element.
+ * @since 2.1
+ */
+ public static Object[] removeElement(Object[] array, Object element) {
+ int index = indexOf(array, element);
+ if (index == -1) {
+ return clone(array);
+ }
+ return remove(array, index);
+ }
+
+ /**
+ * <p>Removes the element at the specified position from the specified array.
+ * All subsequent elements are shifted to the left (substracts one from
+ * their indices).</p>
+ *
+ * <p>This method returns a new array with the same elements of the input
+ * array except the element on the specified position. The component
+ * type of the returned array is always the same as that of the input
+ * array.</p>
+ *
+ * <p>If the input array is <code>null</code>, an IndexOutOfBoundsException
+ * will be thrown, because in that case no valid index can be specified.</p>
+ *
+ * <pre>
+ * ArrayUtils.remove([true], 0) = []
+ * ArrayUtils.remove([true, false], 0) = [false]
+ * ArrayUtils.remove([true, false], 1) = [true]
+ * ArrayUtils.remove([true, true, false], 1) = [true, false]
+ * </pre>
+ *
+ * @param array the array to remove the element from, may not be <code>null</code>
+ * @param index the position of the element to be removed
+ * @return A new array containing the existing elements except the element
+ * at the specified position.
+ * @throws IndexOutOfBoundsException if the index is out of range
+ * (index < 0 || index >= array.length), or if the array is <code>null</code>.
+ * @since 2.1
+ */
+ public static boolean[] remove(boolean[] array, int index) {
+ return (boolean[]) remove((Object) array, index);
+ }
+
+ /**
+ * <p>Removes the first occurrence of the specified element from the
+ * specified array. All subsequent elements are shifted to the left
+ * (substracts one from their indices). If the array doesn't contains
+ * such an element, no elements are removed from the array.</p>
+ *
+ * <p>This method returns a new array with the same elements of the input
+ * array except the first occurrence of the specified element. The component
+ * type of the returned array is always the same as that of the input
+ * array.</p>
+ *
+ * <pre>
+ * ArrayUtils.removeElement(null, true) = null
+ * ArrayUtils.removeElement([], true) = []
+ * ArrayUtils.removeElement([true], false) = [true]
+ * ArrayUtils.removeElement([true, false], false) = [true]
+ * ArrayUtils.removeElement([true, false, true], true) = [false, true]
+ * </pre>
+ *
+ * @param array the array to remove the element from, may be <code>null</code>
+ * @param element the element to be removed
+ * @return A new array containing the existing elements except the first
+ * occurrence of the specified element.
+ * @since 2.1
+ */
+ public static boolean[] removeElement(boolean[] array, boolean element) {
+ int index = indexOf(array, element);
+ if (index == -1) {
+ return clone(array);
+ }
+ return remove(array, index);
+ }
+
+ /**
+ * <p>Removes the element at the specified position from the specified array.
+ * All subsequent elements are shifted to the left (substracts one from
+ * their indices).</p>
+ *
+ * <p>This method returns a new array with the same elements of the input
+ * array except the element on the specified position. The component
+ * type of the returned array is always the same as that of the input
+ * array.</p>
+ *
+ * <p>If the input array is <code>null</code>, an IndexOutOfBoundsException
+ * will be thrown, because in that case no valid index can be specified.</p>
+ *
+ * <pre>
+ * ArrayUtils.remove([1], 0) = []
+ * ArrayUtils.remove([1, 0], 0) = [0]
+ * ArrayUtils.remove([1, 0], 1) = [1]
+ * ArrayUtils.remove([1, 0, 1], 1) = [1, 1]
+ * </pre>
+ *
+ * @param array the array to remove the element from, may not be <code>null</code>
+ * @param index the position of the element to be removed
+ * @return A new array containing the existing elements except the element
+ * at the specified position.
+ * @throws IndexOutOfBoundsException if the index is out of range
+ * (index < 0 || index >= array.length), or if the array is <code>null</code>.
+ * @since 2.1
+ */
+ public static byte[] remove(byte[] array, int index) {
+ return (byte[]) remove((Object) array, index);
+ }
+
+ /**
+ * <p>Removes the first occurrence of the specified element from the
+ * specified array. All subsequent elements are shifted to the left
+ * (substracts one from their indices). If the array doesn't contains
+ * such an element, no elements are removed from the array.</p>
+ *
+ * <p>This method returns a new array with the same elements of the input
+ * array except the first occurrence of the specified element. The component
+ * type of the returned array is always the same as that of the input
+ * array.</p>
+ *
+ * <pre>
+ * ArrayUtils.removeElement(null, 1) = null
+ * ArrayUtils.removeElement([], 1) = []
+ * ArrayUtils.removeElement([1], 0) = [1]
+ * ArrayUtils.removeElement([1, 0], 0) = [1]
+ * ArrayUtils.removeElement([1, 0, 1], 1) = [0, 1]
+ * </pre>
+ *
+ * @param array the array to remove the element from, may be <code>null</code>
+ * @param element the element to be removed
+ * @return A new array containing the existing elements except the first
+ * occurrence of the specified element.
+ * @since 2.1
+ */
+ public static byte[] removeElement(byte[] array, byte element) {
+ int index = indexOf(array, element);
+ if (index == -1) {
+ return clone(array);
+ }
+ return remove(array, index);
+ }
+
+ /**
+ * <p>Removes the element at the specified position from the specified array.
+ * All subsequent elements are shifted to the left (substracts one from
+ * their indices).</p>
+ *
+ * <p>This method returns a new array with the same elements of the input
+ * array except the element on the specified position. The component
+ * type of the returned array is always the same as that of the input
+ * array.</p>
+ *
+ * <p>If the input array is <code>null</code>, an IndexOutOfBoundsException
+ * will be thrown, because in that case no valid index can be specified.</p>
+ *
+ * <pre>
+ * ArrayUtils.remove(['a'], 0) = []
+ * ArrayUtils.remove(['a', 'b'], 0) = ['b']
+ * ArrayUtils.remove(['a', 'b'], 1) = ['a']
+ * ArrayUtils.remove(['a', 'b', 'c'], 1) = ['a', 'c']
+ * </pre>
+ *
+ * @param array the array to remove the element from, may not be <code>null</code>
+ * @param index the position of the element to be removed
+ * @return A new array containing the existing elements except the element
+ * at the specified position.
+ * @throws IndexOutOfBoundsException if the index is out of range
+ * (index < 0 || index >= array.length), or if the array is <code>null</code>.
+ * @since 2.1
+ */
+ public static char[] remove(char[] array, int index) {
+ return (char[]) remove((Object) array, index);
+ }
+
+ /**
+ * <p>Removes the first occurrence of the specified element from the
+ * specified array. All subsequent elements are shifted to the left
+ * (substracts one from their indices). If the array doesn't contains
+ * such an element, no elements are removed from the array.</p>
+ *
+ * <p>This method returns a new array with the same elements of the input
+ * array except the first occurrence of the specified element. The component
+ * type of the returned array is always the same as that of the input
+ * array.</p>
+ *
+ * <pre>
+ * ArrayUtils.removeElement(null, 'a') = null
+ * ArrayUtils.removeElement([], 'a') = []
+ * ArrayUtils.removeElement(['a'], 'b') = ['a']
+ * ArrayUtils.removeElement(['a', 'b'], 'a') = ['b']
+ * ArrayUtils.removeElement(['a', 'b', 'a'], 'a') = ['b', 'a']
+ * </pre>
+ *
+ * @param array the array to remove the element from, may be <code>null</code>
+ * @param element the element to be removed
+ * @return A new array containing the existing elements except the first
+ * occurrence of the specified element.
+ * @since 2.1
+ */
+ public static char[] removeElement(char[] array, char element) {
+ int index = indexOf(array, element);
+ if (index == -1) {
+ return clone(array);
+ }
+ return remove(array, index);
+ }
+
+ /**
+ * <p>Removes the element at the specified position from the specified array.
+ * All subsequent elements are shifted to the left (substracts one from
+ * their indices).</p>
+ *
+ * <p>This method returns a new array with the same elements of the input
+ * array except the element on the specified position. The component
+ * type of the returned array is always the same as that of the input
+ * array.</p>
+ *
+ * <p>If the input array is <code>null</code>, an IndexOutOfBoundsException
+ * will be thrown, because in that case no valid index can be specified.</p>
+ *
+ * <pre>
+ * ArrayUtils.remove([1.1], 0) = []
+ * ArrayUtils.remove([2.5, 6.0], 0) = [6.0]
+ * ArrayUtils.remove([2.5, 6.0], 1) = [2.5]
+ * ArrayUtils.remove([2.5, 6.0, 3.8], 1) = [2.5, 3.8]
+ * </pre>
+ *
+ * @param array the array to remove the element from, may not be <code>null</code>
+ * @param index the position of the element to be removed
+ * @return A new array containing the existing elements except the element
+ * at the specified position.
+ * @throws IndexOutOfBoundsException if the index is out of range
+ * (index < 0 || index >= array.length), or if the array is <code>null</code>.
+ * @since 2.1
+ */
+ public static double[] remove(double[] array, int index) {
+ return (double[]) remove((Object) array, index);
+ }
+
+ /**
+ * <p>Removes the first occurrence of the specified element from the
+ * specified array. All subsequent elements are shifted to the left
+ * (substracts one from their indices). If the array doesn't contains
+ * such an element, no elements are removed from the array.</p>
+ *
+ * <p>This method returns a new array with the same elements of the input
+ * array except the first occurrence of the specified element. The component
+ * type of the returned array is always the same as that of the input
+ * array.</p>
+ *
+ * <pre>
+ * ArrayUtils.removeElement(null, 1.1) = null
+ * ArrayUtils.removeElement([], 1.1) = []
+ * ArrayUtils.removeElement([1.1], 1.2) = [1.1]
+ * ArrayUtils.removeElement([1.1, 2.3], 1.1) = [2.3]
+ * ArrayUtils.removeElement([1.1, 2.3, 1.1], 1.1) = [2.3, 1.1]
+ * </pre>
+ *
+ * @param array the array to remove the element from, may be <code>null</code>
+ * @param element the element to be removed
+ * @return A new array containing the existing elements except the first
+ * occurrence of the specified element.
+ * @since 2.1
+ */
+ public static double[] removeElement(double[] array, double element) {
+ int index = indexOf(array, element);
+ if (index == -1) {
+ return clone(array);
+ }
+ return remove(array, index);
+ }
+
+ /**
+ * <p>Removes the element at the specified position from the specified array.
+ * All subsequent elements are shifted to the left (substracts one from
+ * their indices).</p>
+ *
+ * <p>This method returns a new array with the same elements of the input
+ * array except the element on the specified position. The component
+ * type of the returned array is always the same as that of the input
+ * array.</p>
+ *
+ * <p>If the input array is <code>null</code>, an IndexOutOfBoundsException
+ * will be thrown, because in that case no valid index can be specified.</p>
+ *
+ * <pre>
+ * ArrayUtils.remove([1.1], 0) = []
+ * ArrayUtils.remove([2.5, 6.0], 0) = [6.0]
+ * ArrayUtils.remove([2.5, 6.0], 1) = [2.5]
+ * ArrayUtils.remove([2.5, 6.0, 3.8], 1) = [2.5, 3.8]
+ * </pre>
+ *
+ * @param array the array to remove the element from, may not be <code>null</code>
+ * @param index the position of the element to be removed
+ * @return A new array containing the existing elements except the element
+ * at the specified position.
+ * @throws IndexOutOfBoundsException if the index is out of range
+ * (index < 0 || index >= array.length), or if the array is <code>null</code>.
+ * @since 2.1
+ */
+ public static float[] remove(float[] array, int index) {
+ return (float[]) remove((Object) array, index);
+ }
+
+ /**
+ * <p>Removes the first occurrence of the specified element from the
+ * specified array. All subsequent elements are shifted to the left
+ * (substracts one from their indices). If the array doesn't contains
+ * such an element, no elements are removed from the array.</p>
+ *
+ * <p>This method returns a new array with the same elements of the input
+ * array except the first occurrence of the specified element. The component
+ * type of the returned array is always the same as that of the input
+ * array.</p>
+ *
+ * <pre>
+ * ArrayUtils.removeElement(null, 1.1) = null
+ * ArrayUtils.removeElement([], 1.1) = []
+ * ArrayUtils.removeElement([1.1], 1.2) = [1.1]
+ * ArrayUtils.removeElement([1.1, 2.3], 1.1) = [2.3]
+ * ArrayUtils.removeElement([1.1, 2.3, 1.1], 1.1) = [2.3, 1.1]
+ * </pre>
+ *
+ * @param array the array to remove the element from, may be <code>null</code>
+ * @param element the element to be removed
+ * @return A new array containing the existing elements except the first
+ * occurrence of the specified element.
+ * @since 2.1
+ */
+ public static float[] removeElement(float[] array, float element) {
+ int index = indexOf(array, element);
+ if (index == -1) {
+ return clone(array);
+ }
+ return remove(array, index);
+ }
+
+ /**
+ * <p>Removes the element at the specified position from the specified array.
+ * All subsequent elements are shifted to the left (substracts one from
+ * their indices).</p>
+ *
+ * <p>This method returns a new array with the same elements of the input
+ * array except the element on the specified position. The component
+ * type of the returned array is always the same as that of the input
+ * array.</p>
+ *
+ * <p>If the input array is <code>null</code>, an IndexOutOfBoundsException
+ * will be thrown, because in that case no valid index can be specified.</p>
+ *
+ * <pre>
+ * ArrayUtils.remove([1], 0) = []
+ * ArrayUtils.remove([2, 6], 0) = [6]
+ * ArrayUtils.remove([2, 6], 1) = [2]
+ * ArrayUtils.remove([2, 6, 3], 1) = [2, 3]
+ * </pre>
+ *
+ * @param array the array to remove the element from, may not be <code>null</code>
+ * @param index the position of the element to be removed
+ * @return A new array containing the existing elements except the element
+ * at the specified position.
+ * @throws IndexOutOfBoundsException if the index is out of range
+ * (index < 0 || index >= array.length), or if the array is <code>null</code>.
+ * @since 2.1
+ */
+ public static int[] remove(int[] array, int index) {
+ return (int[]) remove((Object) array, index);
+ }
+
+ /**
+ * <p>Removes the first occurrence of the specified element from the
+ * specified array. All subsequent elements are shifted to the left
+ * (substracts one from their indices). If the array doesn't contains
+ * such an element, no elements are removed from the array.</p>
+ *
+ * <p>This method returns a new array with the same elements of the input
+ * array except the first occurrence of the specified element. The component
+ * type of the returned array is always the same as that of the input
+ * array.</p>
+ *
+ * <pre>
+ * ArrayUtils.removeElement(null, 1) = null
+ * ArrayUtils.removeElement([], 1) = []
+ * ArrayUtils.removeElement([1], 2) = [1]
+ * ArrayUtils.removeElement([1, 3], 1) = [3]
+ * ArrayUtils.removeElement([1, 3, 1], 1) = [3, 1]
+ * </pre>
+ *
+ * @param array the array to remove the element from, may be <code>null</code>
+ * @param element the element to be removed
+ * @return A new array containing the existing elements except the first
+ * occurrence of the specified element.
+ * @since 2.1
+ */
+ public static int[] removeElement(int[] array, int element) {
+ int index = indexOf(array, element);
+ if (index == -1) {
+ return clone(array);
+ }
+ return remove(array, index);
+ }
+
+ /**
+ * <p>Removes the element at the specified position from the specified array.
+ * All subsequent elements are shifted to the left (substracts one from
+ * their indices).</p>
+ *
+ * <p>This method returns a new array with the same elements of the input
+ * array except the element on the specified position. The component
+ * type of the returned array is always the same as that of the input
+ * array.</p>
+ *
+ * <p>If the input array is <code>null</code>, an IndexOutOfBoundsException
+ * will be thrown, because in that case no valid index can be specified.</p>
+ *
+ * <pre>
+ * ArrayUtils.remove([1], 0) = []
+ * ArrayUtils.remove([2, 6], 0) = [6]
+ * ArrayUtils.remove([2, 6], 1) = [2]
+ * ArrayUtils.remove([2, 6, 3], 1) = [2, 3]
+ * </pre>
+ *
+ * @param array the array to remove the element from, may not be <code>null</code>
+ * @param index the position of the element to be removed
+ * @return A new array containing the existing elements except the element
+ * at the specified position.
+ * @throws IndexOutOfBoundsException if the index is out of range
+ * (index < 0 || index >= array.length), or if the array is <code>null</code>.
+ * @since 2.1
+ */
+ public static long[] remove(long[] array, int index) {
+ return (long[]) remove((Object) array, index);
+ }
+
+ /**
+ * <p>Removes the first occurrence of the specified element from the
+ * specified array. All subsequent elements are shifted to the left
+ * (substracts one from their indices). If the array doesn't contains
+ * such an element, no elements are removed from the array.</p>
+ *
+ * <p>This method returns a new array with the same elements of the input
+ * array except the first occurrence of the specified element. The component
+ * type of the returned array is always the same as that of the input
+ * array.</p>
+ *
+ * <pre>
+ * ArrayUtils.removeElement(null, 1) = null
+ * ArrayUtils.removeElement([], 1) = []
+ * ArrayUtils.removeElement([1], 2) = [1]
+ * ArrayUtils.removeElement([1, 3], 1) = [3]
+ * ArrayUtils.removeElement([1, 3, 1], 1) = [3, 1]
+ * </pre>
+ *
+ * @param array the array to remove the element from, may be <code>null</code>
+ * @param element the element to be removed
+ * @return A new array containing the existing elements except the first
+ * occurrence of the specified element.
+ * @since 2.1
+ */
+ public static long[] removeElement(long[] array, long element) {
+ int index = indexOf(array, element);
+ if (index == -1) {
+ return clone(array);
+ }
+ return remove(array, index);
+ }
+
+ /**
+ * <p>Removes the element at the specified position from the specified array.
+ * All subsequent elements are shifted to the left (substracts one from
+ * their indices).</p>
+ *
+ * <p>This method returns a new array with the same elements of the input
+ * array except the element on the specified position. The component
+ * type of the returned array is always the same as that of the input
+ * array.</p>
+ *
+ * <p>If the input array is <code>null</code>, an IndexOutOfBoundsException
+ * will be thrown, because in that case no valid index can be specified.</p>
+ *
+ * <pre>
+ * ArrayUtils.remove([1], 0) = []
+ * ArrayUtils.remove([2, 6], 0) = [6]
+ * ArrayUtils.remove([2, 6], 1) = [2]
+ * ArrayUtils.remove([2, 6, 3], 1) = [2, 3]
+ * </pre>
+ *
+ * @param array the array to remove the element from, may not be <code>null</code>
+ * @param index the position of the element to be removed
+ * @return A new array containing the existing elements except the element
+ * at the specified position.
+ * @throws IndexOutOfBoundsException if the index is out of range
+ * (index < 0 || index >= array.length), or if the array is <code>null</code>.
+ * @since 2.1
+ */
+ public static short[] remove(short[] array, int index) {
+ return (short[]) remove((Object) array, index);
+ }
+
+ /**
+ * <p>Removes the first occurrence of the specified element from the
+ * specified array. All subsequent elements are shifted to the left
+ * (substracts one from their indices). If the array doesn't contains
+ * such an element, no elements are removed from the array.</p>
+ *
+ * <p>This method returns a new array with the same elements of the input
+ * array except the first occurrence of the specified element. The component
+ * type of the returned array is always the same as that of the input
+ * array.</p>
+ *
+ * <pre>
+ * ArrayUtils.removeElement(null, 1) = null
+ * ArrayUtils.removeElement([], 1) = []
+ * ArrayUtils.removeElement([1], 2) = [1]
+ * ArrayUtils.removeElement([1, 3], 1) = [3]
+ * ArrayUtils.removeElement([1, 3, 1], 1) = [3, 1]
+ * </pre>
+ *
+ * @param array the array to remove the element from, may be <code>null</code>
+ * @param element the element to be removed
+ * @return A new array containing the existing elements except the first
+ * occurrence of the specified element.
+ * @since 2.1
+ */
+ public static short[] removeElement(short[] array, short element) {
+ int index = indexOf(array, element);
+ if (index == -1) {
+ return clone(array);
+ }
+ return remove(array, index);
+ }
+
+ /**
+ * <p>Removes the element at the specified position from the specified array.
+ * All subsequent elements are shifted to the left (substracts one from
+ * their indices).</p>
+ *
+ * <p>This method returns a new array with the same elements of the input
+ * array except the element on the specified position. The component
+ * type of the returned array is always the same as that of the input
+ * array.</p>
+ *
+ * <p>If the input array is <code>null</code>, an IndexOutOfBoundsException
+ * will be thrown, because in that case no valid index can be specified.</p>
+ *
+ * @param array the array to remove the element from, may not be <code>null</code>
+ * @param index the position of the element to be removed
+ * @return A new array containing the existing elements except the element
+ * at the specified position.
+ * @throws IndexOutOfBoundsException if the index is out of range
+ * (index < 0 || index >= array.length), or if the array is <code>null</code>.
+ * @since 2.1
+ */
+ private static Object remove(Object array, int index) {
+ int length = getLength(array);
+ if (index < 0 || index >= length) {
+ throw new IndexOutOfBoundsException("Index: " + index + ", Length: " + length);
+ }
+
+ Object result = Array.newInstance(array.getClass().getComponentType(), length - 1);
+ System.arraycopy(array, 0, result, 0, index);
+ if (index < length - 1) {
+ System.arraycopy(array, index + 1, result, index, length - index - 1);
+ }
+
+ return result;
+ }
+
+}
Added: incubator/directory/ldap/trunk/common/src/java/org/apache/ldap/common/util/BooleanUtils.java
==============================================================================
--- (empty file)
+++ incubator/directory/ldap/trunk/common/src/java/org/apache/ldap/common/util/BooleanUtils.java Sat Sep 25 12:11:47 2004
@@ -0,0 +1,889 @@
+/*
+ * Copyright 2002-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.ldap.common.util;
+
+
+/**
+ * <p>Operations on boolean primitives and Boolean objects.</p>
+ *
+ * <p>This class tries to handle <code>null</code> input gracefully.
+ * An exception will not be thrown for a <code>null</code> input.
+ * Each method documents its behaviour in more detail.</p>
+ *
+ * @author Stephen Colebourne
+ * @author Matthew Hawthorne
+ * @author Gary Gregory
+ * @since 2.0
+ * @version $Id: BooleanUtils.java,v 1.18 2004/02/18 22:59:50 ggregory Exp $
+ */
+public class BooleanUtils {
+ private static final Integer INTEGER_ZERO = new Integer( 0 );
+ private static final Integer INTEGER_ONE = new Integer( 1 );
+
+ /**
+ * <p><code>BooleanUtils</code> instances should NOT be constructed in standard programming.
+ * Instead, the class should be used as <code>BooleanUtils.toBooleanObject(true);</code>.</p>
+ *
+ * <p>This constructor is public to permit tools that require a JavaBean instance
+ * to operate.</p>
+ */
+ public BooleanUtils() {
+ }
+
+ // Boolean utilities
+ //--------------------------------------------------------------------------
+ /**
+ * <p>Negates the specified boolean.</p>
+ *
+ * <p>If <code>null</code> is passed in, <code>null</code> will be returned.</p>
+ *
+ * <pre>
+ * BooleanUtils.negate(Boolean.TRUE) = Boolean.FALSE;
+ * BooleanUtils.negate(Boolean.FALSE) = Boolean.TRUE;
+ * BooleanUtils.negate(null) = null;
+ * </pre>
+ *
+ * @param bool the Boolean to negate, may be null
+ * @return the negated Boolean, or <code>null</code> if <code>null</code> input
+ */
+ public static Boolean negate(Boolean bool) {
+ if (bool == null) {
+ return null;
+ }
+ return (bool.booleanValue() ? Boolean.FALSE : Boolean.TRUE);
+ }
+
+ // boolean Boolean methods
+ //-----------------------------------------------------------------------
+ /**
+ * <p>Boolean factory that avoids creating new Boolean objecs all the time.</p>
+ *
+ * <p>This method was added to JDK1.4 but is available here for earlier JDKs.</p>
+ *
+ * <pre>
+ * BooleanUtils.toBooleanObject(false) = Boolean.FALSE
+ * BooleanUtils.toBooleanObject(true) = Boolean.TRUE
+ * </pre>
+ *
+ * @param bool the boolean to convert
+ * @return Boolean.TRUE or Boolean.FALSE as appropriate
+ */
+ public static Boolean toBooleanObject(boolean bool) {
+ return (bool ? Boolean.TRUE : Boolean.FALSE);
+ }
+
+ /**
+ * <p>Converts a Boolean to a boolean handling <code>null</code>
+ * by returning <code>false</code>.</p>
+ *
+ * <pre>
+ * BooleanUtils.toBoolean(Boolean.TRUE) = true
+ * BooleanUtils.toBoolean(Boolean.FALSE) = false
+ * BooleanUtils.toBoolean(null) = false
+ * </pre>
+ *
+ * @param bool the boolean to convert
+ * @return <code>true</code> or <code>false</code>,
+ * <code>null</code> returns <code>false</code>
+ */
+ public static boolean toBoolean(Boolean bool) {
+ if (bool == null) {
+ return false;
+ }
+ return (bool.booleanValue() ? true : false);
+ }
+
+ /**
+ * <p>Converts a Boolean to a boolean handling <code>null</code>.</p>
+ *
+ * <pre>
+ * BooleanUtils.toBooleanDefaultIfNull(Boolean.TRUE, false) = true
+ * BooleanUtils.toBooleanDefaultIfNull(Boolean.FALSE, true) = false
+ * BooleanUtils.toBooleanDefaultIfNull(null, true) = true
+ * </pre>
+ *
+ * @param bool the boolean to convert
+ * @param valueIfNull the boolean value to return if <code>null</code>
+ * @return <code>true</code> or <code>false</code>
+ */
+ public static boolean toBooleanDefaultIfNull(Boolean bool, boolean valueIfNull) {
+ if (bool == null) {
+ return valueIfNull;
+ }
+ return (bool.booleanValue() ? true : false);
+ }
+
+ // Integer to Boolean methods
+ //-----------------------------------------------------------------------
+ /**
+ * <p>Converts an int to a boolean using the convention that <code>zero</code>
+ * is <code>false</code>.</p>
+ *
+ * <pre>
+ * BooleanUtils.toBoolean(0) = false
+ * BooleanUtils.toBoolean(1) = true
+ * BooleanUtils.toBoolean(2) = true
+ * </pre>
+ *
+ * @param value the int to convert
+ * @return <code>true</code> if non-zero, <code>false</code>
+ * if zero
+ */
+ public static boolean toBoolean(int value) {
+ return (value == 0 ? false : true);
+ }
+
+ /**
+ * <p>Converts an int to a Boolean using the convention that <code>zero</code>
+ * is <code>false</code>.</p>
+ *
+ * <pre>
+ * BooleanUtils.toBoolean(0) = Boolean.FALSE
+ * BooleanUtils.toBoolean(1) = Boolean.TRUE
+ * BooleanUtils.toBoolean(2) = Boolean.TRUE
+ * </pre>
+ *
+ * @param value the int to convert
+ * @return Boolean.TRUE if non-zero, Boolean.FALSE if zero,
+ * <code>null</code> if <code>null</code>
+ */
+ public static Boolean toBooleanObject(int value) {
+ return (value == 0 ? Boolean.FALSE : Boolean.TRUE);
+ }
+
+ /**
+ * <p>Converts an Integer to a Boolean using the convention that <code>zero</code>
+ * is <code>false</code>.</p>
+ *
+ * <p><code>null</code> will be converted to <code>null</code>.</p>
+ *
+ * <pre>
+ * BooleanUtils.toBoolean(new Integer(0)) = Boolean.FALSE
+ * BooleanUtils.toBoolean(new Integer(1)) = Boolean.TRUE
+ * BooleanUtils.toBoolean(new Integer(null)) = null
+ * </pre>
+ *
+ * @param value the Integer to convert
+ * @return Boolean.TRUE if non-zero, Boolean.FALSE if zero,
+ * <code>null</code> if <code>null</code> input
+ */
+ public static Boolean toBooleanObject(Integer value) {
+ if (value == null) {
+ return null;
+ }
+ return (value.intValue() == 0 ? Boolean.FALSE : Boolean.TRUE);
+ }
+
+ /**
+ * <p>Converts an int to a boolean specifying the conversion values.</p>
+ *
+ * <pre>
+ * BooleanUtils.toBoolean(0, 1, 0) = false
+ * BooleanUtils.toBoolean(1, 1, 0) = true
+ * BooleanUtils.toBoolean(2, 1, 2) = false
+ * BooleanUtils.toBoolean(2, 2, 0) = true
+ * </pre>
+ *
+ * @param value the Integer to convert
+ * @param trueValue the value to match for <code>true</code>
+ * @param falseValue the value to match for <code>false</code>
+ * @return <code>true</code> or <code>false</code>
+ * @throws IllegalArgumentException if no match
+ */
+ public static boolean toBoolean(int value, int trueValue, int falseValue) {
+ if (value == trueValue) {
+ return true;
+ } else if (value == falseValue) {
+ return false;
+ }
+ // no match
+ throw new IllegalArgumentException("The Integer did not match either specified value");
+ }
+
+ /**
+ * <p>Converts an Integer to a boolean specifying the conversion values.</p>
+ *
+ * <pre>
+ * BooleanUtils.toBoolean(new Integer(0), new Integer(1), new Integer(0)) = false
+ * BooleanUtils.toBoolean(new Integer(1), new Integer(1), new Integer(0)) = true
+ * BooleanUtils.toBoolean(new Integer(2), new Integer(1), new Integer(2)) = false
+ * BooleanUtils.toBoolean(new Integer(2), new Integer(2), new Integer(0)) = true
+ * BooleanUtils.toBoolean(null, null, new Integer(0)) = true
+ * </pre>
+ *
+ * @param value the Integer to convert
+ * @param trueValue the value to match for <code>true</code>,
+ * may be <code>null</code>
+ * @param falseValue the value to match for <code>false</code>,
+ * may be <code>null</code>
+ * @return <code>true</code> or <code>false</code>
+ * @throws IllegalArgumentException if no match
+ */
+ public static boolean toBoolean(Integer value, Integer trueValue, Integer falseValue) {
+ if (value == null) {
+ if (trueValue == null) {
+ return true;
+ } else if (falseValue == null) {
+ return false;
+ }
+ } else if (value.equals(trueValue)) {
+ return true;
+ } else if (value.equals(falseValue)) {
+ return false;
+ }
+ // no match
+ throw new IllegalArgumentException("The Integer did not match either specified value");
+ }
+
+ /**
+ * <p>Converts an int to a Boolean specifying the conversion values.</p>
+ *
+ * <pre>
+ * BooleanUtils.toBooleanObject(0, 0, 2, 3) = Boolean.TRUE
+ * BooleanUtils.toBooleanObject(2, 1, 2, 3) = Boolean.FALSE
+ * BooleanUtils.toBooleanObject(3, 1, 2, 3) = null
+ * </pre>
+ *
+ * @param value the Integer to convert
+ * @param trueValue the value to match for <code>true</code>
+ * @param falseValue the value to match for <code>false</code>
+ * @param nullValue the value to to match for <code>null</code>
+ * @return Boolean.TRUE, Boolean.FALSE, or <code>null</code>
+ * @throws IllegalArgumentException if no match
+ */
+ public static Boolean toBooleanObject(int value, int trueValue, int falseValue, int nullValue) {
+ if (value == trueValue) {
+ return Boolean.TRUE;
+ } else if (value == falseValue) {
+ return Boolean.FALSE;
+ } else if (value == nullValue) {
+ return null;
+ }
+ // no match
+ throw new IllegalArgumentException("The Integer did not match any specified value");
+ }
+
+ /**
+ * <p>Converts an Integer to a Boolean specifying the conversion values.</p>
+ *
+ * <pre>
+ * BooleanUtils.toBooleanObject(new Integer(0), new Integer(0), new Integer(2), new Integer(3)) = Boolean.TRUE
+ * BooleanUtils.toBooleanObject(new Integer(2), new Integer(1), new Integer(2), new Integer(3)) = Boolean.FALSE
+ * BooleanUtils.toBooleanObject(new Integer(3), new Integer(1), new Integer(2), new Integer(3)) = null
+ * </pre>
+ *
+ * @param value the Integer to convert
+ * @param trueValue the value to match for <code>true</code>,
+ * may be <code>null</code>
+ * @param falseValue the value to match for <code>false</code>,
+ * may be <code>null</code>
+ * @param nullValue the value to to match for <code>null</code>,
+ * may be <code>null</code>
+ * @return Boolean.TRUE, Boolean.FALSE, or <code>null</code>
+ * @throws IllegalArgumentException if no match
+ */
+ public static Boolean toBooleanObject(Integer value, Integer trueValue, Integer falseValue, Integer nullValue) {
+ if (value == null) {
+ if (trueValue == null) {
+ return Boolean.TRUE;
+ } else if (falseValue == null) {
+ return Boolean.FALSE;
+ } else if (nullValue == null) {
+ return null;
+ }
+ } else if (value.equals(trueValue)) {
+ return Boolean.TRUE;
+ } else if (value.equals(falseValue)) {
+ return Boolean.FALSE;
+ } else if (value.equals(nullValue)) {
+ return null;
+ }
+ // no match
+ throw new IllegalArgumentException("The Integer did not match any specified value");
+ }
+
+ // Boolean to Integer methods
+ //-----------------------------------------------------------------------
+ /**
+ * <p>Converts a boolean to an int using the convention that
+ * <code>zero</code> is <code>false</code>.</p>
+ *
+ * <pre>
+ * BooleanUtils.toInteger(true) = 1
+ * BooleanUtils.toInteger(false) = 0
+ * </pre>
+ *
+ * @param bool the boolean to convert
+ * @return one if <code>true</code>, zero if <code>false</code>
+ */
+ public static int toInteger(boolean bool) {
+ return (bool ? 1 : 0);
+ }
+
+ /**
+ * <p>Converts a boolean to an Integer using the convention that
+ * <code>zero</code> is <code>false</code>.</p>
+ *
+ * <pre>
+ * BooleanUtils.toIntegerObject(true) = new Integer(1)
+ * BooleanUtils.toIntegerObject(false) = new Integer(0)
+ * </pre>
+ *
+ * @param bool the boolean to convert
+ * @return one if <code>true</code>, zero if <code>false</code>
+ */
+ public static Integer toIntegerObject(boolean bool) {
+ return (bool ? INTEGER_ONE : INTEGER_ZERO);
+ }
+
+ /**
+ * <p>Converts a Boolean to a Integer using the convention that
+ * <code>zero</code> is <code>false</code>.</p>
+ *
+ * <p><code>null</code> will be converted to <code>null</code>.</p>
+ *
+ * <pre>
+ * BooleanUtils.toIntegerObject(Boolean.TRUE) = new Integer(1)
+ * BooleanUtils.toIntegerObject(Boolean.FALSE) = new Integer(0)
+ * </pre>
+ *
+ * @param bool the Boolean to convert
+ * @return one if Boolean.TRUE, zero if Boolean.FALSE, <code>null</code> if <code>null</code>
+ */
+ public static Integer toIntegerObject(Boolean bool) {
+ if (bool == null) {
+ return null;
+ }
+ return (bool.booleanValue() ? INTEGER_ONE : INTEGER_ZERO);
+ }
+
+ /**
+ * <p>Converts a boolean to an int specifying the conversion values.</p>
+ *
+ * <pre>
+ * BooleanUtils.toInteger(true, 1, 0) = 1
+ * BooleanUtils.toInteger(false, 1, 0) = 0
+ * </pre>
+ *
+ * @param bool the to convert
+ * @param trueValue the value to return if <code>true</code>
+ * @param falseValue the value to return if <code>false</code>
+ * @return the appropriate value
+ */
+ public static int toInteger(boolean bool, int trueValue, int falseValue) {
+ return (bool ? trueValue : falseValue);
+ }
+
+ /**
+ * <p>Converts a Boolean to an int specifying the conversion values.</p>
+ *
+ * <pre>
+ * BooleanUtils.toInteger(Boolean.TRUE, 1, 0, 2) = 1
+ * BooleanUtils.toInteger(Boolean.FALSE, 1, 0, 2) = 0
+ * BooleanUtils.toInteger(null, 1, 0, 2) = 2
+ * </pre>
+ *
+ * @param bool the Boolean to convert
+ * @param trueValue the value to return if <code>true</code>
+ * @param falseValue the value to return if <code>false</code>
+ * @param nullValue the value to return if <code>null</code>
+ * @return the appropriate value
+ */
+ public static int toInteger(Boolean bool, int trueValue, int falseValue, int nullValue) {
+ if (bool == null) {
+ return nullValue;
+ }
+ return (bool.booleanValue() ? trueValue : falseValue);
+ }
+
+ /**
+ * <p>Converts a boolean to an Integer specifying the conversion values.</p>
+ *
+ * <pre>
+ * BooleanUtils.toIntegerObject(true, new Integer(1), new Integer(0)) = new Integer(1)
+ * BooleanUtils.toIntegerObject(false, new Integer(1), new Integer(0)) = new Integer(0)
+ * </pre>
+ *
+ * @param bool the to convert
+ * @param trueValue the value to return if <code>true</code>,
+ * may be <code>null</code>
+ * @param falseValue the value to return if <code>false</code>,
+ * may be <code>null</code>
+ * @return the appropriate value
+ */
+ public static Integer toIntegerObject(boolean bool, Integer trueValue, Integer falseValue) {
+ return (bool ? trueValue : falseValue);
+ }
+
+ /**
+ * <p>Converts a Boolean to an Integer specifying the conversion values.</p>
+ *
+ * <pre>
+ * BooleanUtils.toIntegerObject(Boolean.TRUE, new Integer(1), new Integer(0), new Integer(2)) = new Integer(1)
+ * BooleanUtils.toIntegerObject(Boolean.FALSE, new Integer(1), new Integer(0), new Integer(2)) = new Integer(0)
+ * BooleanUtils.toIntegerObject(null, new Integer(1), new Integer(0), new Integer(2)) = new Integer(2)
+ * </pre>
+ *
+ * @param bool the Boolean to convert
+ * @param trueValue the value to return if <code>true</code>,
+ * may be <code>null</code>
+ * @param falseValue the value to return if <code>false</code>,
+ * may be <code>null</code>
+ * @param nullValue the value to return if <code>null</code>,
+ * may be <code>null</code>
+ * @return the appropriate value
+ */
+ public static Integer toIntegerObject(Boolean bool, Integer trueValue, Integer falseValue, Integer nullValue) {
+ if (bool == null) {
+ return nullValue;
+ }
+ return (bool.booleanValue() ? trueValue : falseValue);
+ }
+
+ // String to Boolean methods
+ //-----------------------------------------------------------------------
+ /**
+ * <p>Converts a String to a Boolean.</p>
+ *
+ * <p><code>'true'</code>, <code>'on'</code> or <code>'yes'</code>
+ * (case insensitive) will return <code>true</code>.
+ * <code>'false'</code>, <code>'off'</code> or <code>'no'</code>
+ * (case insensitive) will return <code>false</code>.
+ * Otherwise, <code>null</code> is returned.</p>
+ *
+ * <pre>
+ * BooleanUtils.toBooleanObject(null) = null
+ * BooleanUtils.toBooleanObject("true") = Boolean.TRUE
+ * BooleanUtils.toBooleanObject("false") = Boolean.FALSE
+ * BooleanUtils.toBooleanObject("on") = Boolean.TRUE
+ * BooleanUtils.toBooleanObject("ON") = Boolean.TRUE
+ * BooleanUtils.toBooleanObject("off") = Boolean.FALSE
+ * BooleanUtils.toBooleanObject("oFf") = Boolean.FALSE
+ * BooleanUtils.toBooleanObject("blue") = null
+ * </pre>
+ *
+ * @param str the String to check
+ * @return the Boolean value of the string,
+ * <code>null</code> if no match or <code>null</code> input
+ */
+ public static Boolean toBooleanObject(String str) {
+ if ("true".equalsIgnoreCase(str)) {
+ return Boolean.TRUE;
+ } else if ("false".equalsIgnoreCase(str)) {
+ return Boolean.FALSE;
+ } else if ("on".equalsIgnoreCase(str)) {
+ return Boolean.TRUE;
+ } else if ("off".equalsIgnoreCase(str)) {
+ return Boolean.FALSE;
+ } else if ("yes".equalsIgnoreCase(str)) {
+ return Boolean.TRUE;
+ } else if ("no".equalsIgnoreCase(str)) {
+ return Boolean.FALSE;
+ }
+ // no match
+ return null;
+ }
+
+ /**
+ * <p>Converts a String to a Boolean throwing an exception if no match.</p>
+ *
+ * <pre>
+ * BooleanUtils.toBooleanObject("true", "true", "false", "null") = Boolean.TRUE
+ * BooleanUtils.toBooleanObject("false", "true", "false", "null") = Boolean.FALSE
+ * BooleanUtils.toBooleanObject("null", "true", "false", "null") = null
+ * </pre>
+ *
+ * @param str the String to check
+ * @param trueString the String to match for <code>true</code>
+ * (case sensitive), may be <code>null</code>
+ * @param falseString the String to match for <code>false</code>
+ * (case sensitive), may be <code>null</code>
+ * @param nullString the String to match for <code>null</code>
+ * (case sensitive), may be <code>null</code>
+ * @return the Boolean value of the string,
+ * <code>null</code> if no match or <code>null</code> input
+ */
+ public static Boolean toBooleanObject(String str, String trueString, String falseString, String nullString) {
+ if (str == null) {
+ if (trueString == null) {
+ return Boolean.TRUE;
+ } else if (falseString == null) {
+ return Boolean.FALSE;
+ } else if (nullString == null) {
+ return null;
+ }
+ } else if (str.equals(trueString)) {
+ return Boolean.TRUE;
+ } else if (str.equals(falseString)) {
+ return Boolean.FALSE;
+ } else if (str.equals(nullString)) {
+ return null;
+ }
+ // no match
+ throw new IllegalArgumentException("The String did not match any specified value");
+ }
+
+ // String to boolean methods
+ //-----------------------------------------------------------------------
+ /**
+ * <p>Converts a String to a boolean (optimised for performance).</p>
+ *
+ * <p><code>'true'</code>, <code>'on'</code> or <code>'yes'</code>
+ * (case insensitive) will return <code>true</code>. Otherwise,
+ * <code>false</code> is returned.</p>
+ *
+ * <p>This method performs 4 times faster (JDK1.4) than
+ * <code>Boolean.valueOf(String)</code>. However, this method accepts
+ * 'on' and 'yes' as true values.
+ *
+ * <pre>
+ * BooleanUtils.toBoolean(null) = false
+ * BooleanUtils.toBoolean("true") = true
+ * BooleanUtils.toBoolean("TRUE") = true
+ * BooleanUtils.toBoolean("tRUe") = true
+ * BooleanUtils.toBoolean("on") = true
+ * BooleanUtils.toBoolean("yes") = true
+ * BooleanUtils.toBoolean("false") = false
+ * BooleanUtils.toBoolean("x gti") = false
+ * </pre>
+ *
+ * @param str the String to check
+ * @return the boolean value of the string, <code>false</code> if no match
+ */
+ public static boolean toBoolean(String str) {
+ // Previously used equalsIgnoreCase, which was fast for interned 'true'.
+ // Non interned 'true' matched 15 times slower.
+ //
+ // Optimisation provides same performance as before for interned 'true'.
+ // Similar performance for null, 'false', and other strings not length 2/3/4.
+ // 'true'/'TRUE' match 4 times slower, 'tRUE'/'True' 7 times slower.
+ if (str == "true") {
+ return true;
+ }
+ if (str == null) {
+ return false;
+ }
+ switch (str.length()) {
+ case 2: {
+ char ch0 = str.charAt(0);
+ char ch1 = str.charAt(1);
+ return
+ (ch0 == 'o' || ch0 == 'O') &&
+ (ch1 == 'n' || ch1 == 'N');
+ }
+ case 3: {
+ char ch = str.charAt(0);
+ if (ch == 'y') {
+ return
+ (str.charAt(1) == 'e' || str.charAt(1) == 'E') &&
+ (str.charAt(2) == 's' || str.charAt(2) == 'S');
+ }
+ if (ch == 'Y') {
+ return
+ (str.charAt(1) == 'E' || str.charAt(1) == 'e') &&
+ (str.charAt(2) == 'S' || str.charAt(2) == 's');
+ }
+ }
+ case 4: {
+ char ch = str.charAt(0);
+ if (ch == 't') {
+ return
+ (str.charAt(1) == 'r' || str.charAt(1) == 'R') &&
+ (str.charAt(2) == 'u' || str.charAt(2) == 'U') &&
+ (str.charAt(3) == 'e' || str.charAt(3) == 'E');
+ }
+ if (ch == 'T') {
+ return
+ (str.charAt(1) == 'R' || str.charAt(1) == 'r') &&
+ (str.charAt(2) == 'U' || str.charAt(2) == 'u') &&
+ (str.charAt(3) == 'E' || str.charAt(3) == 'e');
+ }
+ }
+ }
+ return false;
+ }
+
+// public static void main(String[] args) {
+// long start = System.currentTimeMillis();
+// boolean flag = true;
+// int count = 0;
+// for (int i = 0; i < 100000000; i++) {
+// flag = toBoolean("YES");
+// }
+// long end = System.currentTimeMillis();
+// System.out.println((end - start) + " " + flag + " " + count);
+// }
+
+ /**
+ * <p>Converts a String to a Boolean throwing an exception if no match found.</p>
+ *
+ * <p>null is returned if there is no match.</p>
+ *
+ * <pre>
+ * BooleanUtils.toBoolean("true", "true", "false") = true
+ * BooleanUtils.toBoolean("false", "true", "false") = false
+ * </pre>
+ *
+ * @param str the String to check
+ * @param trueString the String to match for <code>true</code>
+ * (case sensitive), may be <code>null</code>
+ * @param falseString the String to match for <code>false</code>
+ * (case sensitive), may be <code>null</code>
+ * @return the boolean value of the string
+ * @throws IllegalArgumentException if the String doesn't match
+ */
+ public static boolean toBoolean(String str, String trueString, String falseString) {
+ if (str == null) {
+ if (trueString == null) {
+ return true;
+ } else if (falseString == null) {
+ return false;
+ }
+ } else if (str.equals(trueString)) {
+ return true;
+ } else if (str.equals(falseString)) {
+ return false;
+ }
+ // no match
+ throw new IllegalArgumentException("The String did not match either specified value");
+ }
+
+ // Boolean to String methods
+ //-----------------------------------------------------------------------
+ /**
+ * <p>Converts a Boolean to a String returning <code>'true'</code>,
+ * <code>'false'</code>, or <code>null</code>.</p>
+ *
+ * <pre>
+ * BooleanUtils.toStringTrueFalse(Boolean.TRUE) = "true"
+ * BooleanUtils.toStringTrueFalse(Boolean.FALSE) = "false"
+ * BooleanUtils.toStringTrueFalse(null) = null;
+ * </pre>
+ *
+ * @param bool the Boolean to check
+ * @return <code>'true'</code>, <code>'false'</code>,
+ * or <code>null</code>
+ */
+ public static String toStringTrueFalse(Boolean bool) {
+ return toString(bool, "true", "false", null);
+ }
+
+ /**
+ * <p>Converts a Boolean to a String returning <code>'on'</code>,
+ * <code>'off'</code>, or <code>null</code>.</p>
+ *
+ * <pre>
+ * BooleanUtils.toStringOnOff(Boolean.TRUE) = "on"
+ * BooleanUtils.toStringOnOff(Boolean.FALSE) = "off"
+ * BooleanUtils.toStringOnOff(null) = null;
+ * </pre>
+ *
+ * @param bool the Boolean to check
+ * @return <code>'on'</code>, <code>'off'</code>,
+ * or <code>null</code>
+ */
+ public static String toStringOnOff(Boolean bool) {
+ return toString(bool, "on", "off", null);
+ }
+
+ /**
+ * <p>Converts a Boolean to a String returning <code>'yes'</code>,
+ * <code>'no'</code>, or <code>null</code>.</p>
+ *
+ * <pre>
+ * BooleanUtils.toStringYesNo(Boolean.TRUE) = "yes"
+ * BooleanUtils.toStringYesNo(Boolean.FALSE) = "no"
+ * BooleanUtils.toStringYesNo(null) = null;
+ * </pre>
+ *
+ * @param bool the Boolean to check
+ * @return <code>'yes'</code>, <code>'no'</code>,
+ * or <code>null</code>
+ */
+ public static String toStringYesNo(Boolean bool) {
+ return toString(bool, "yes", "no", null);
+ }
+
+ /**
+ * <p>Converts a Boolean to a String returning one of the input Strings.</p>
+ *
+ * <pre>
+ * BooleanUtils.toString(Boolean.TRUE, "true", "false", null) = "true"
+ * BooleanUtils.toString(Boolean.FALSE, "true", "false", null) = "false"
+ * BooleanUtils.toString(null, "true", "false", null) = null;
+ * </pre>
+ *
+ * @param bool the Boolean to check
+ * @param trueString the String to return if <code>true</code>,
+ * may be <code>null</code>
+ * @param falseString the String to return if <code>false</code>,
+ * may be <code>null</code>
+ * @param nullString the String to return if <code>null</code>,
+ * may be <code>null</code>
+ * @return one of the three input Strings
+ */
+ public static String toString(Boolean bool, String trueString, String falseString, String nullString) {
+ if (bool == null) {
+ return nullString;
+ }
+ return (bool.booleanValue() ? trueString : falseString);
+ }
+
+ // boolean to String methods
+ //-----------------------------------------------------------------------
+ /**
+ * <p>Converts a boolean to a String returning <code>'true'</code>
+ * or <code>'false'</code>.</p>
+ *
+ * <pre>
+ * BooleanUtils.toStringTrueFalse(true) = "true"
+ * BooleanUtils.toStringTrueFalse(false) = "false"
+ * </pre>
+ *
+ * @param bool the Boolean to check
+ * @return <code>'true'</code>, <code>'false'</code>,
+ * or <code>null</code>
+ */
+ public static String toStringTrueFalse(boolean bool) {
+ return toString(bool, "true", "false");
+ }
+
+ /**
+ * <p>Converts a boolean to a String returning <code>'on'</code>
+ * or <code>'off'</code>.</p>
+ *
+ * <pre>
+ * BooleanUtils.toStringOnOff(true) = "on"
+ * BooleanUtils.toStringOnOff(false) = "off"
+ * </pre>
+ *
+ * @param bool the Boolean to check
+ * @return <code>'on'</code>, <code>'off'</code>,
+ * or <code>null</code>
+ */
+ public static String toStringOnOff(boolean bool) {
+ return toString(bool, "on", "off");
+ }
+
+ /**
+ * <p>Converts a boolean to a String returning <code>'yes'</code>
+ * or <code>'no'</code>.</p>
+ *
+ * <pre>
+ * BooleanUtils.toStringYesNo(true) = "yes"
+ * BooleanUtils.toStringYesNo(false) = "no"
+ * </pre>
+ *
+ * @param bool the Boolean to check
+ * @return <code>'yes'</code>, <code>'no'</code>,
+ * or <code>null</code>
+ */
+ public static String toStringYesNo(boolean bool) {
+ return toString(bool, "yes", "no");
+ }
+
+ /**
+ * <p>Converts a boolean to a String returning one of the input Strings.</p>
+ *
+ * <pre>
+ * BooleanUtils.toString(true, "true", "false") = "true"
+ * BooleanUtils.toString(false, "true", "false") = "false"
+ * </pre>
+ *
+ * @param bool the Boolean to check
+ * @param trueString the String to return if <code>true</code>,
+ * may be <code>null</code>
+ * @param falseString the String to return if <code>false</code>,
+ * may be <code>null</code>
+ * @return one of the two input Strings
+ */
+ public static String toString(boolean bool, String trueString, String falseString) {
+ return (bool ? trueString : falseString);
+ }
+
+ // xor methods
+ // ----------------------------------------------------------------------
+ /**
+ * <p>Performs an xor on a set of booleans.</p>
+ *
+ * <pre>
+ * BooleanUtils.xor(new boolean[] { true, true }) = false
+ * BooleanUtils.xor(new boolean[] { false, false }) = false
+ * BooleanUtils.xor(new boolean[] { true, false }) = true
+ * </pre>
+ *
+ * @param array an array of <code>boolean<code>s
+ * @return <code>true</code> if the xor is successful.
+ * @throws IllegalArgumentException if <code>array</code> is <code>null</code>
+ * @throws IllegalArgumentException if <code>array</code> is empty.
+ */
+ public static boolean xor(boolean[] array) {
+ // Validates input
+ if (array == null) {
+ throw new IllegalArgumentException("The Array must not be null");
+ } else if (array.length == 0) {
+ throw new IllegalArgumentException("Array is empty");
+ }
+
+ // Loops through array, comparing each item
+ int trueCount = 0;
+ for (int i = 0; i < array.length; i++) {
+ // If item is true, and trueCount is < 1, increments count
+ // Else, xor fails
+ if (array[i]) {
+ if (trueCount < 1) {
+ trueCount++;
+ } else {
+ return false;
+ }
+ }
+ }
+
+ // Returns true if there was exactly 1 true item
+ return trueCount == 1;
+ }
+
+ /**
+ * <p>Performs an xor on an array of Booleans.</p>
+ *
+ * <pre>
+ * BooleanUtils.xor(new Boolean[] { Boolean.TRUE, Boolean.TRUE }) = Boolean.FALSE
+ * BooleanUtils.xor(new Boolean[] { Boolean.FALSE, Boolean.FALSE }) = Boolean.FALSE
+ * BooleanUtils.xor(new Boolean[] { Boolean.TRUE, Boolean.FALSE }) = Boolean.TRUE
+ * </pre>
+ *
+ * @param array an array of <code>Boolean<code>s
+ * @return <code>true</code> if the xor is successful.
+ * @throws IllegalArgumentException if <code>array</code> is <code>null</code>
+ * @throws IllegalArgumentException if <code>array</code> is empty.
+ * @throws IllegalArgumentException if <code>array</code> contains a <code>null</code>
+ */
+ public static Boolean xor(Boolean[] array) {
+ if (array == null) {
+ throw new IllegalArgumentException("The Array must not be null");
+ } else if (array.length == 0) {
+ throw new IllegalArgumentException("Array is empty");
+ }
+ boolean[] primitive = null;
+ try {
+ primitive = ArrayUtils.toPrimitive(array);
+ } catch (NullPointerException ex) {
+ throw new IllegalArgumentException("The array must not contain any null elements");
+ }
+ return (xor(primitive) ? Boolean.TRUE : Boolean.FALSE);
+ }
+
+}
Added: incubator/directory/ldap/trunk/common/src/java/org/apache/ldap/common/util/ClassUtils.java
==============================================================================
--- (empty file)
+++ incubator/directory/ldap/trunk/common/src/java/org/apache/ldap/common/util/ClassUtils.java Sat Sep 25 12:11:47 2004
@@ -0,0 +1,616 @@
+/*
+ * Copyright 2002-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.ldap.common.util;
+
+
+import java.util.ArrayList;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+
+/**
+ * <p>Operates on classes without using reflection.</p>
+ *
+ * <p>This class handles invalid <code>null</code> inputs as best it can.
+ * Each method documents its behaviour in more detail.</p>
+ *
+ * @author Stephen Colebourne
+ * @author Gary Gregory
+ * @author Norm Deane
+ * @since 2.0
+ * @version $Id: ClassUtils.java,v 1.30 2004/06/30 18:33:58 ggregory Exp $
+ */
+public class ClassUtils {
+ private static final String EMPTY = "";
+
+
+ /**
+ * <p>The package separator character: <code>'.' == {@}</code>.</p>
+ */
+ public static final char PACKAGE_SEPARATOR_CHAR = '.';
+
+ /**
+ * <p>The package separator String: <code>"."</code>.</p>
+ */
+ public static final String PACKAGE_SEPARATOR = String.valueOf(PACKAGE_SEPARATOR_CHAR);
+
+ /**
+ * <p>The inner class separator character: <code>'$' == {@}</code>.</p>
+ */
+ public static final char INNER_CLASS_SEPARATOR_CHAR = '$';
+
+ /**
+ * <p>The inner class separator String: <code>"$"</code>.</p>
+ */
+ public static final String INNER_CLASS_SEPARATOR = String.valueOf(INNER_CLASS_SEPARATOR_CHAR);
+
+ /**
+ * Maps primitive <code>Class</code>es to their corresponding wrapper <code>Class</code>.
+ */
+ private static Map primitiveWrapperMap = new HashMap();
+ static {
+ primitiveWrapperMap.put(Boolean.TYPE, Boolean.class);
+ primitiveWrapperMap.put(Byte.TYPE, Byte.class);
+ primitiveWrapperMap.put(Character.TYPE, Character.class);
+ primitiveWrapperMap.put(Short.TYPE, Short.class);
+ primitiveWrapperMap.put(Integer.TYPE, Integer.class);
+ primitiveWrapperMap.put(Long.TYPE, Long.class);
+ primitiveWrapperMap.put(Double.TYPE, Double.class);
+ primitiveWrapperMap.put(Float.TYPE, Float.class);
+ }
+
+ /**
+ * <p>ClassUtils instances should NOT be constructed in standard programming.
+ * Instead, the class should be used as
+ * <code>ClassUtils.getShortClassName(cls)</code>.</p>
+ *
+ * <p>This constructor is public to permit tools that require a JavaBean
+ * instance to operate.</p>
+ */
+ public ClassUtils() {
+ }
+
+ // Short class name
+ // ----------------------------------------------------------------------
+ /**
+ * <p>Gets the class name minus the package name for an <code>Object</code>.</p>
+ *
+ * @param object the class to get the short name for, may be null
+ * @param valueIfNull the value to return if null
+ * @return the class name of the object without the package name, or the null value
+ */
+ public static String getShortClassName(Object object, String valueIfNull) {
+ if (object == null) {
+ return valueIfNull;
+ }
+ return getShortClassName(object.getClass().getName());
+ }
+
+ /**
+ * <p>Gets the class name minus the package name from a <code>Class</code>.</p>
+ *
+ * @param cls the class to get the short name for.
+ * @return the class name without the package name or an empty string
+ */
+ public static String getShortClassName(Class cls) {
+ if (cls == null) {
+ return EMPTY;
+ }
+ return getShortClassName(cls.getName());
+ }
+
+ /**
+ * <p>Gets the class name minus the package name from a String.</p>
+ *
+ * <p>The string passed in is assumed to be a class name - it is not checked.</p>
+ *
+ * @param className the className to get the short name for
+ * @return the class name of the class without the package name or an empty string
+ */
+ public static String getShortClassName(String className) {
+ if (className == null) {
+ return EMPTY;
+ }
+ if (className.length() == 0) {
+ return EMPTY;
+ }
+ char[] chars = className.toCharArray();
+ int lastDot = 0;
+ for (int i = 0; i < chars.length; i++) {
+ if (chars[i] == PACKAGE_SEPARATOR_CHAR) {
+ lastDot = i + 1;
+ } else if (chars[i] == INNER_CLASS_SEPARATOR_CHAR) { // handle inner classes
+ chars[i] = PACKAGE_SEPARATOR_CHAR;
+ }
+ }
+ return new String(chars, lastDot, chars.length - lastDot);
+ }
+
+ // Package name
+ // ----------------------------------------------------------------------
+ /**
+ * <p>Gets the package name of an <code>Object</code>.</p>
+ *
+ * @param object the class to get the package name for, may be null
+ * @param valueIfNull the value to return if null
+ * @return the package name of the object, or the null value
+ */
+ public static String getPackageName(Object object, String valueIfNull) {
+ if (object == null) {
+ return valueIfNull;
+ }
+ return getPackageName(object.getClass().getName());
+ }
+
+ /**
+ * <p>Gets the package name of a <code>Class</code>.</p>
+ *
+ * @param cls the class to get the package name for, may be <code>null</code>.
+ * @return the package name or an empty string
+ */
+ public static String getPackageName(Class cls) {
+ if (cls == null) {
+ return EMPTY;
+ }
+ return getPackageName(cls.getName());
+ }
+
+ /**
+ * <p>Gets the package name from a <code>String</code>.</p>
+ *
+ * <p>The string passed in is assumed to be a class name - it is not checked.</p>
+ * <p>If the class is unpackaged, return an empty string.</p>
+ *
+ * @param className the className to get the package name for, may be <code>null</code>
+ * @return the package name or an empty string
+ */
+ public static String getPackageName(String className) {
+ if (className == null) {
+ return EMPTY;
+ }
+ int i = className.lastIndexOf(PACKAGE_SEPARATOR_CHAR);
+ if (i == -1) {
+ return EMPTY;
+ }
+ return className.substring(0, i);
+ }
+
+ // Superclasses/Superinterfaces
+ // ----------------------------------------------------------------------
+ /**
+ * <p>Gets a <code>List</code> of superclasses for the given class.</p>
+ *
+ * @param cls the class to look up, may be <code>null</code>
+ * @return the <code>List</code> of superclasses in order going up from this one
+ * <code>null</code> if null input
+ */
+ public static List getAllSuperclasses(Class cls) {
+ if (cls == null) {
+ return null;
+ }
+ List classes = new ArrayList();
+ Class superclass = cls.getSuperclass();
+ while (superclass != null) {
+ classes.add(superclass);
+ superclass = superclass.getSuperclass();
+ }
+ return classes;
+ }
+
+ /**
+ * <p>Gets a <code>List</code> of all interfaces implemented by the given
+ * class and its superclasses.</p>
+ *
+ * <p>The order is determined by looking through each interface in turn as
+ * declared in the source file and following its hierarchy up. Then each
+ * superclass is considered in the same way. Later duplicates are ignored,
+ * so the order is maintained.</p>
+ *
+ * @param cls the class to look up, may be <code>null</code>
+ * @return the <code>List</code> of interfaces in order,
+ * <code>null</code> if null input
+ */
+ public static List getAllInterfaces(Class cls) {
+ if (cls == null) {
+ return null;
+ }
+ List list = new ArrayList();
+ while (cls != null) {
+ Class[] interfaces = cls.getInterfaces();
+ for (int i = 0; i < interfaces.length; i++) {
+ if (list.contains(interfaces[i]) == false) {
+ list.add(interfaces[i]);
+ }
+ List superInterfaces = getAllInterfaces(interfaces[i]);
+ for (Iterator it = superInterfaces.iterator(); it.hasNext();) {
+ Class intface = (Class) it.next();
+ if (list.contains(intface) == false) {
+ list.add(intface);
+ }
+ }
+ }
+ cls = cls.getSuperclass();
+ }
+ return list;
+ }
+
+// /**
+// * <p>Gets a <code>List</code> of subclasses of the specified class.</p>
+// *
+// * <p>This method searches the classpath to find all the subclasses
+// * of a particular class available. No classes are loaded, the
+// * returned list contains class names, not classes.</p>
+// *
+// * @param cls the class to find subclasses for
+// * @return the <code>List</code> of subclass String class names
+// * @throws IllegalArgumentException if the class is <code>null</code>
+// */
+// public static List getAllSubclassNames(Class cls) {
+// if (cls == null) {
+// throw new IllegalArgumentException("The class must not be null");
+// }
+// // TODO Use JavaWorld tip for searching the classpath
+// return null;
+// }
+
+// /**
+// * <p>Gets a <code>List</code> of subclasses of the specified class.</p>
+// *
+// * <p>This method searches the classpath to find all the subclasses
+// * of a particular class available.</p>
+// *
+// * @param cls the class to find subclasses for
+// * @return the <code>List</code> of subclasses
+// * @throws IllegalArgumentException if the class is <code>null</code>
+// */
+// public static List getAllSubclasses(Class cls) {
+// List names = getAllSubclassNames(cls);
+// return convertClassNamesToClasses(names);
+// }
+
+// /**
+// * <p>Gets a <code>List</code> of implementations of the specified interface.</p>
+// *
+// * <p>This method searches the classpath to find all the implementations
+// * of a particular interface available. No classes are loaded, the
+// * returned list contains class names, not classes.</p>
+// *
+// * @param cls the class to find sub classes for
+// * @return the <code>List</code> of implementation String class names
+// * @throws IllegalArgumentException if the class is <code>null</code>
+// */
+// public static List getAllImplementationClassNames(Class cls) {
+// if (cls == null) {
+// throw new IllegalArgumentException("The class must not be null");
+// }
+// // TODO Use JavaWorld tip for searching the classpath
+// return null;
+// }
+
+ // Convert list
+ // ----------------------------------------------------------------------
+ /**
+ * <p>Given a <code>List</code> of class names, this method converts them into classes.</p>
+ *
+ * <p>A new <code>List</code> is returned. If the class name cannot be found, <code>null</code>
+ * is stored in the <code>List</code>. If the class name in the <code>List</code> is
+ * <code>null</code>, <code>null</code> is stored in the output <code>List</code>.</p>
+ *
+ * @param classNames the classNames to change
+ * @return a <code>List</code> of Class objects corresponding to the class names,
+ * <code>null</code> if null input
+ * @throws ClassCastException if classNames contains a non String entry
+ */
+ public static List convertClassNamesToClasses(List classNames) {
+ if (classNames == null) {
+ return null;
+ }
+ List classes = new ArrayList(classNames.size());
+ for (Iterator it = classNames.iterator(); it.hasNext();) {
+ String className = (String) it.next();
+ try {
+ classes.add(Class.forName(className));
+ } catch (Exception ex) {
+ classes.add(null);
+ }
+ }
+ return classes;
+ }
+
+ /**
+ * <p>Given a <code>List</code> of <code>Class</code> objects, this method converts
+ * them into class names.</p>
+ *
+ * <p>A new <code>List</code> is returned. <code>null</code> objects will be copied into
+ * the returned list as <code>null</code>.</p>
+ *
+ * @param classes the classes to change
+ * @return a <code>List</code> of class names corresponding to the Class objects,
+ * <code>null</code> if null input
+ * @throws ClassCastException if <code>classes</code> contains a non-<code>Class</code> entry
+ */
+ public static List convertClassesToClassNames(List classes) {
+ if (classes == null) {
+ return null;
+ }
+ List classNames = new ArrayList(classes.size());
+ for (Iterator it = classes.iterator(); it.hasNext();) {
+ Class cls = (Class) it.next();
+ if (cls == null) {
+ classNames.add(null);
+ } else {
+ classNames.add(cls.getName());
+ }
+ }
+ return classNames;
+ }
+
+ // Is assignable
+ // ----------------------------------------------------------------------
+ /**
+ * <p>Checks if an array of Classes can be assigned to another array of Classes.</p>
+ *
+ * <p>This method calls {@link #isAssignable(Class, Class) isAssignable} for each
+ * Class pair in the input arrays. It can be used to check if a set of arguments
+ * (the first parameter) are suitably compatible with a set of method parameter types
+ * (the second parameter).</p>
+ *
+ * <p>Unlike the {@link Class#isAssignableFrom(java.lang.Class)} method, this
+ * method takes into account widenings of primitive classes and
+ * <code>null</code>s.</p>
+ *
+ * <p>Primitive widenings allow an int to be assigned to a <code>long</code>,
+ * <code>float</code> or <code>double</code>. This method returns the correct
+ * result for these cases.</p>
+ *
+ * <p><code>Null</code> may be assigned to any reference type. This method will
+ * return <code>true</code> if <code>null</code> is passed in and the toClass is
+ * non-primitive.</p>
+ *
+ * <p>Specifically, this method tests whether the type represented by the
+ * specified <code>Class</code> parameter can be converted to the type
+ * represented by this <code>Class</code> object via an identity conversion
+ * widening primitive or widening reference conversion. See
+ * <em><a href="http://java.sun.com/docs/books/jls/">The Java Language Specification</a></em>,
+ * sections 5.1.1, 5.1.2 and 5.1.4 for details.</p>
+ *
+ * @param classArray the array of Classes to check, may be <code>null</code>
+ * @param toClassArray the array of Classes to try to assign into, may be <code>null</code>
+ * @return <code>true</code> if assignment possible
+ */
+ public static boolean isAssignable(Class[] classArray, Class[] toClassArray) {
+ if (ArrayUtils.isSameLength(classArray, toClassArray) == false) {
+ return false;
+ }
+ if (classArray == null) {
+ classArray = ArrayUtils.EMPTY_CLASS_ARRAY;
+ }
+ if (toClassArray == null) {
+ toClassArray = ArrayUtils.EMPTY_CLASS_ARRAY;
+ }
+ for (int i = 0; i < classArray.length; i++) {
+ if (isAssignable(classArray[i], toClassArray[i]) == false) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * <p>Checks if one <code>Class</code> can be assigned to a variable of
+ * another <code>Class</code>.</p>
+ *
+ * <p>Unlike the {@link Class#isAssignableFrom(java.lang.Class)} method,
+ * this method takes into account widenings of primitive classes and
+ * <code>null</code>s.</p>
+ *
+ * <p>Primitive widenings allow an int to be assigned to a long, float or
+ * double. This method returns the correct result for these cases.</p>
+ *
+ * <p><code>Null</code> may be assigned to any reference type. This method
+ * will return <code>true</code> if <code>null</code> is passed in and the
+ * toClass is non-primitive.</p>
+ *
+ * <p>Specifically, this method tests whether the type represented by the
+ * specified <code>Class</code> parameter can be converted to the type
+ * represented by this <code>Class</code> object via an identity conversion
+ * widening primitive or widening reference conversion. See
+ * <em><a href="http://java.sun.com/docs/books/jls/">The Java Language Specification</a></em>,
+ * sections 5.1.1, 5.1.2 and 5.1.4 for details.</p>
+ *
+ * @param cls the Class to check, may be null
+ * @param toClass the Class to try to assign into, returns false if null
+ * @return <code>true</code> if assignment possible
+ */
+ public static boolean isAssignable(Class cls, Class toClass) {
+ if (toClass == null) {
+ return false;
+ }
+ // have to check for null, as isAssignableFrom doesn't
+ if (cls == null) {
+ return !(toClass.isPrimitive());
+ }
+ if (cls.equals(toClass)) {
+ return true;
+ }
+ if (cls.isPrimitive()) {
+ if (toClass.isPrimitive() == false) {
+ return false;
+ }
+ if (Integer.TYPE.equals(cls)) {
+ return Long.TYPE.equals(toClass)
+ || Float.TYPE.equals(toClass)
+ || Double.TYPE.equals(toClass);
+ }
+ if (Long.TYPE.equals(cls)) {
+ return Float.TYPE.equals(toClass)
+ || Double.TYPE.equals(toClass);
+ }
+ if (Boolean.TYPE.equals(cls)) {
+ return false;
+ }
+ if (Double.TYPE.equals(cls)) {
+ return false;
+ }
+ if (Float.TYPE.equals(cls)) {
+ return Double.TYPE.equals(toClass);
+ }
+ if (Character.TYPE.equals(cls)) {
+ return Integer.TYPE.equals(toClass)
+ || Long.TYPE.equals(toClass)
+ || Float.TYPE.equals(toClass)
+ || Double.TYPE.equals(toClass);
+ }
+ if (Short.TYPE.equals(cls)) {
+ return Integer.TYPE.equals(toClass)
+ || Long.TYPE.equals(toClass)
+ || Float.TYPE.equals(toClass)
+ || Double.TYPE.equals(toClass);
+ }
+ if (Byte.TYPE.equals(cls)) {
+ return Short.TYPE.equals(toClass)
+ || Integer.TYPE.equals(toClass)
+ || Long.TYPE.equals(toClass)
+ || Float.TYPE.equals(toClass)
+ || Double.TYPE.equals(toClass);
+ }
+ // should never get here
+ return false;
+ }
+ return toClass.isAssignableFrom(cls);
+ }
+
+ /**
+ * <p>Converts the specified primitive Class object to its corresponding
+ * wrapper Class object.</p>
+ *
+ * @param cls the class to convert, may be null
+ * @return the wrapper class for <code>cls</code> or <code>cls</code> if
+ * <code>cls</code> is not a primitive. <code>null</code> if null input.
+ */
+ public static Class primitiveToWrapper(Class cls) {
+ Class convertedClass = cls;
+ if (cls != null && cls.isPrimitive()) {
+ convertedClass = (Class) primitiveWrapperMap.get(cls);
+ }
+ return convertedClass;
+ }
+
+ /**
+ * <p>Converts the specified array of primitive Class objects to an array of
+ * its corresponding wrapper Class objects.</p>
+ *
+ * @param classes the class array to convert, may be null or empty
+ * @return an array which contains for each given class, the wrapper class or
+ * the original class if class is not a primitive. <code>null</code> if null input.
+ * Empty array if an empty array passed in.
+ */
+ public static Class[] primitivesToWrappers(Class[] classes) {
+ if (classes == null) {
+ return null;
+ }
+
+ if (classes.length == 0) {
+ return ArrayUtils.EMPTY_CLASS_ARRAY;
+ }
+
+ Class[] convertedClasses = new Class[classes.length];
+ for (int i=0; i < classes.length; i++) {
+ convertedClasses[i] = primitiveToWrapper( classes[i] );
+ }
+ return convertedClasses;
+ }
+
+ // Inner class
+ // ----------------------------------------------------------------------
+ /**
+ * <p>Is the specified class an inner class or static nested class.</p>
+ *
+ * @param cls the class to check, may be null
+ * @return <code>true</code> if the class is an inner or static nested class,
+ * false if not or <code>null</code>
+ */
+ public static boolean isInnerClass(Class cls) {
+ if (cls == null) {
+ return false;
+ }
+ return (cls.getName().indexOf(INNER_CLASS_SEPARATOR_CHAR) >= 0);
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * Compares two <code>Class</code>s by name.
+ */
+ private static class ClassNameComparator implements Comparator {
+ /**
+ * Compares two <code>Class</code>s by name.
+ *
+ * @throws ClassCastException
+ * If <code>o1</code> or <code>o2</code> are not <code>Class</code>
+ * instances.
+ */
+ public int compare(Object o1, Object o2) {
+ Class class1 = (Class) o1;
+ Class class2 = (Class) o2;
+ if (class1 == null) {
+ return class2 == null ? 0 : -1;
+ }
+ if (class2 == null) {
+ return 1;
+ }
+ return class1.getName().compareTo(class2.getName());
+ }
+ }
+
+ /**
+ * Compares two <code>Class</code>s by name.
+ */
+ public static final Comparator CLASS_NAME_COMPARATOR = new ClassNameComparator();
+
+ /**
+ * Compares two <code>Package</code>s by name.
+ */
+ private static class PackageNameComparator implements Comparator {
+
+ /**
+ * Compares two <code>Package</code>s by name.
+ *
+ * @throws ClassCastException
+ * If <code>o1</code> or <code>o2</code> are not <code>Package</code>
+ * instances.
+ */
+ public int compare(Object o1, Object o2) {
+ Package package1 = (Package) o1;
+ Package package2 = (Package) o2;
+ if (package1 == null) {
+ return package2 == null ? 0 : -1;
+ }
+ if (package2 == null) {
+ return 1;
+ }
+ return package1.getName().compareTo(package2.getName());
+ }
+ }
+
+ /**
+ * Compares two <code>Package</code>s by name.
+ */
+ public static final Comparator PACKAGE_NAME_COMPARATOR = new PackageNameComparator();
+
+}
Added: incubator/directory/ldap/trunk/common/src/java/org/apache/ldap/common/util/Enum.java
==============================================================================
--- (empty file)
+++ incubator/directory/ldap/trunk/common/src/java/org/apache/ldap/common/util/Enum.java Sat Sep 25 12:11:47 2004
@@ -0,0 +1,602 @@
+/*
+ * Copyright 2002-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.ldap.common.util;
+
+import java.io.Serializable;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+
+/**
+ * <p>Abstract superclass for type-safe enums.</p>
+ *
+ * <p>One feature of the C programming language lacking in Java is enumerations. The
+ * C implementation based on ints was poor and open to abuse. The original Java
+ * recommendation and most of the JDK also uses int constants. It has been recognised
+ * however that a more robust type-safe class-based solution can be designed. This
+ * class follows the basic Java type-safe enumeration pattern.</p>
+ *
+ * <p><em>NOTE:</em>Due to the way in which Java ClassLoaders work, comparing
+ * Enum objects should always be done using <code>equals()</code>, not <code>==</code>.
+ * The equals() method will try == first so in most cases the effect is the same.</p>
+ *
+ * <p>Of course, if you actually want (or don't mind) Enums in different class
+ * loaders being non-equal, then you can use <code>==</code>.</p>
+ *
+ * <h4>Simple Enums</h4>
+ *
+ * <p>To use this class, it must be subclassed. For example:</p>
+ *
+ * <pre>
+ * public final class ColorEnum extends Enum {
+ * public static final ColorEnum RED = new ColorEnum("Red");
+ * public static final ColorEnum GREEN = new ColorEnum("Green");
+ * public static final ColorEnum BLUE = new ColorEnum("Blue");
+ *
+ * private ColorEnum(String color) {
+ * super(color);
+ * }
+ *
+ * public static ColorEnum getEnum(String color) {
+ * return (ColorEnum) getEnum(ColorEnum.class, color);
+ * }
+ *
+ * public static Map getEnumMap() {
+ * return getEnumMap(ColorEnum.class);
+ * }
+ *
+ * public static List getEnumList() {
+ * return getEnumList(ColorEnum.class);
+ * }
+ *
+ * public static Iterator iterator() {
+ * return iterator(ColorEnum.class);
+ * }
+ * }
+ * </pre>
+ *
+ * <p>As shown, each enum has a name. This can be accessed using <code>getName</code>.</p>
+ *
+ * <p>The <code>getEnum</code> and <code>iterator</code> methods are recommended.
+ * Unfortunately, Java restrictions require these to be coded as shown in each subclass.
+ * An alternative choice is to use the {@link EnumUtils} class.</p>
+ *
+ * <h4>Subclassed Enums</h4>
+ * <p>A hierarchy of Enum classes can be built. In this case, the superclass is
+ * unaffected by the addition of subclasses (as per normal Java). The subclasses
+ * may add additional Enum constants <em>of the type of the superclass</em>. The
+ * query methods on the subclass will return all of the Enum constants from the
+ * superclass and subclass.</p>
+ *
+ * <pre>
+ * public final class ExtraColorEnum extends ColorEnum {
+ * // NOTE: Color enum declared above is final, change that to get this
+ * // example to compile.
+ * public static final ColorEnum YELLOW = new ExtraColorEnum("Yellow");
+ *
+ * private ExtraColorEnum(String color) {
+ * super(color);
+ * }
+ *
+ * public static ColorEnum getEnum(String color) {
+ * return (ColorEnum) getEnum(ExtraColorEnum.class, color);
+ * }
+ *
+ * public static Map getEnumMap() {
+ * return getEnumMap(ExtraColorEnum.class);
+ * }
+ *
+ * public static List getEnumList() {
+ * return getEnumList(ExtraColorEnum.class);
+ * }
+ *
+ * public static Iterator iterator() {
+ * return iterator(ExtraColorEnum.class);
+ * }
+ * }
+ * </pre>
+ *
+ * <p>This example will return RED, GREEN, BLUE, YELLOW from the List and iterator
+ * methods in that order. The RED, GREEN and BLUE instances will be the same (==)
+ * as those from the superclass ColorEnum. Note that YELLOW is declared as a
+ * ColorEnum and not an ExtraColorEnum.</p>
+ *
+ * <h4>Functional Enums</h4>
+ *
+ * <p>The enums can have functionality by defining subclasses and
+ * overriding the <code>getEnumClass()</code> method:</p>
+ *
+ * <pre>
+ * public static final OperationEnum PLUS = new PlusOperation();
+ * private static final class PlusOperation extends OperationEnum {
+ * private PlusOperation() {
+ * super("Plus");
+ * }
+ * public int eval(int a, int b) {
+ * return (a + b);
+ * }
+ * }
+ * public static final OperationEnum MINUS = new MinusOperation();
+ * private static final class MinusOperation extends OperationEnum {
+ * private MinusOperation() {
+ * super("Minus");
+ * }
+ * public int eval(int a, int b) {
+ * return (a - b);
+ * }
+ * }
+ *
+ * private OperationEnum(String color) {
+ * super(color);
+ * }
+ *
+ * public final Class getEnumClass() { // NOTE: new method!
+ * return OperationEnum.class;
+ * }
+ *
+ * public abstract double eval(double a, double b);
+ *
+ * public static OperationEnum getEnum(String name) {
+ * return (OperationEnum) getEnum(OperationEnum.class, name);
+ * }
+ *
+ * public static Map getEnumMap() {
+ * return getEnumMap(OperationEnum.class);
+ * }
+ *
+ * public static List getEnumList() {
+ * return getEnumList(OperationEnum.class);
+ * }
+ *
+ * public static Iterator iterator() {
+ * return iterator(OperationEnum.class);
+ * }
+ * }
+ * </pre>
+ * <p>The code above will work on JDK 1.2. If JDK1.3 and later is used,
+ * the subclasses may be defined as anonymous.</p>
+ *
+ * <h4>Nested class Enums</h4>
+ *
+ * <p>Care must be taken with class loading when defining a static nested class
+ * for enums. The static nested class can be loaded without the surrounding outer
+ * class being loaded. This can result in an empty list/map/iterator being returned.
+ * One solution is to define a static block that references the outer class where
+ * the constants are defined. For example:</p>
+ *
+ * <pre>
+ * public final class Outer {
+ * public static final BWEnum BLACK = new BWEnum("Black");
+ * public static final BWEnum WHITE = new BWEnum("White");
+ *
+ * // static nested enum class
+ * public static final class BWEnum extends Enum {
+ *
+ * static {
+ * // explicitly reference BWEnum class to force constants to load
+ * Object obj = Outer.BLACK;
+ * }
+ *
+ * // ... other methods omitted
+ * }
+ * }
+ * </pre>
+ *
+ * <p>Although the above solves the problem, it is not recommended. The best solution
+ * is to define the constants in the enum class, and hold references in the outer class:
+ *
+ * <pre>
+ * public final class Outer {
+ * public static final BWEnum BLACK = BWEnum.BLACK;
+ * public static final BWEnum WHITE = BWEnum.WHITE;
+ *
+ * // static nested enum class
+ * public static final class BWEnum extends Enum {
+ * // only define constants in enum classes - private if desired
+ * private static final BWEnum BLACK = new BWEnum("Black");
+ * private static final BWEnum WHITE = new BWEnum("White");
+ *
+ * // ... other methods omitted
+ * }
+ * }
+ * </pre>
+ *
+ * <p>For more details, see the 'Nested' test cases.
+ *
+ * @author Apache Avalon project
+ * @author Stephen Colebourne
+ * @author Chris Webb
+ * @author Mike Bowler
+ * @since 1.0
+ * @version $Id: Enum.java,v 1.28 2004/02/23 04:34:20 ggregory Exp $
+ */
+public abstract class Enum implements Comparable, Serializable {
+
+ /** Lang version 1.0.1 serial compatibility */
+ private static final long serialVersionUID = -487045951170455942L;
+
+ // After discussion, the default size for HashMaps is used, as the
+ // sizing algorithm changes across the JDK versions
+ /**
+ * An empty <code>Map</code>, as JDK1.2 didn't have an empty map.
+ */
+ private static final Map EMPTY_MAP = Collections.unmodifiableMap(new HashMap(0));
+
+ /**
+ * <code>Map</code>, key of class name, value of <code>Entry</code>.
+ */
+ private static final Map cEnumClasses = new HashMap();
+
+ /**
+ * The string representation of the Enum.
+ */
+ private final String iName;
+
+ /**
+ * The hashcode representation of the Enum.
+ */
+ private transient final int iHashCode;
+
+ /**
+ * The toString representation of the Enum.
+ * @since 2.0
+ */
+ protected transient String iToString = null;
+
+ /**
+ * <p>Enable the iterator to retain the source code order.</p>
+ */
+ private static class Entry {
+ /**
+ * Map of Enum name to Enum.
+ */
+ final Map map = new HashMap();
+ /**
+ * Map of Enum name to Enum.
+ */
+ final Map unmodifiableMap = Collections.unmodifiableMap(map);
+ /**
+ * List of Enums in source code order.
+ */
+ final List list = new ArrayList(25);
+ /**
+ * Map of Enum name to Enum.
+ */
+ final List unmodifiableList = Collections.unmodifiableList(list);
+
+ /**
+ * <p>Restrictive constructor.</p>
+ */
+ private Entry() {
+ }
+ }
+
+ /**
+ * <p>Constructor to add a new named item to the enumeration.</p>
+ *
+ * @param name the name of the enum object,
+ * must not be empty or <code>null</code>
+ * @throws IllegalArgumentException if the name is <code>null</code>
+ * or an empty string
+ * @throws IllegalArgumentException if the getEnumClass() method returns
+ * a null or invalid Class
+ */
+ protected Enum(String name) {
+ super();
+ init(name);
+ iName = name;
+ iHashCode = 7 + getEnumClass().hashCode() + 3 * name.hashCode();
+ // cannot create toString here as subclasses may want to include other data
+ }
+
+ private static boolean isEmpty(String str) {
+ return (str == null || str.length() == 0);
+ }
+
+ /**
+ * Initializes the enumeration.
+ *
+ * @param name the enum name
+ * @throws IllegalArgumentException if the name is null or empty or duplicate
+ * @throws IllegalArgumentException if the enumClass is null or invalid
+ */
+ private void init(String name) {
+ if (isEmpty(name)) {
+ throw new IllegalArgumentException("The Enum name must not be empty or null");
+ }
+
+ Class enumClass = getEnumClass();
+ if (enumClass == null) {
+ throw new IllegalArgumentException("getEnumClass() must not be null");
+ }
+ Class cls = getClass();
+ boolean ok = false;
+ while (cls != null && cls != Enum.class && cls != ValuedEnum.class) {
+ if (cls == enumClass) {
+ ok = true;
+ break;
+ }
+ cls = cls.getSuperclass();
+ }
+ if (ok == false) {
+ throw new IllegalArgumentException("getEnumClass() must return a superclass of this class");
+ }
+
+ // create entry
+ Entry entry = (Entry) cEnumClasses.get(enumClass);
+ if (entry == null) {
+ entry = createEntry(enumClass);
+ cEnumClasses.put(enumClass, entry);
+ }
+ if (entry.map.containsKey(name)) {
+ throw new IllegalArgumentException("The Enum name must be unique, '" + name + "' has already been added");
+ }
+ entry.map.put(name, this);
+ entry.list.add(this);
+ }
+
+ /**
+ * <p>Handle the deserialization of the class to ensure that multiple
+ * copies are not wastefully created, or illegal enum types created.</p>
+ *
+ * @return the resolved object
+ */
+ protected Object readResolve() {
+ Entry entry = (Entry) cEnumClasses.get(getEnumClass());
+ if (entry == null) {
+ return null;
+ }
+ return (Enum) entry.map.get(getName());
+ }
+
+ //--------------------------------------------------------------------------------
+
+ /**
+ * <p>Gets an <code>Enum</code> object by class and name.</p>
+ *
+ * @param enumClass the class of the Enum to get, must not
+ * be <code>null</code>
+ * @param name the name of the <code>Enum</code> to get,
+ * may be <code>null</code>
+ * @return the enum object, or null if the enum does not exist
+ * @throws IllegalArgumentException if the enum class
+ * is <code>null</code>
+ */
+ protected static Enum getEnum(Class enumClass, String name) {
+ Entry entry = getEntry(enumClass);
+ if (entry == null) {
+ return null;
+ }
+ return (Enum) entry.map.get(name);
+ }
+
+ /**
+ * <p>Gets the <code>Map</code> of <code>Enum</code> objects by
+ * name using the <code>Enum</code> class.</p>
+ *
+ * <p>If the requested class has no enum objects an empty
+ * <code>Map</code> is returned.</p>
+ *
+ * @param enumClass the class of the <code>Enum</code> to get,
+ * must not be <code>null</code>
+ * @return the enum object Map
+ * @throws IllegalArgumentException if the enum class is <code>null</code>
+ * @throws IllegalArgumentException if the enum class is not a subclass of Enum
+ */
+ protected static Map getEnumMap(Class enumClass) {
+ Entry entry = getEntry(enumClass);
+ if (entry == null) {
+ return EMPTY_MAP;
+ }
+ return entry.unmodifiableMap;
+ }
+
+ /**
+ * <p>Gets the <code>List</code> of <code>Enum</code> objects using the
+ * <code>Enum</code> class.</p>
+ *
+ * <p>The list is in the order that the objects were created (source code order).
+ * If the requested class has no enum objects an empty <code>List</code> is
+ * returned.</p>
+ *
+ * @param enumClass the class of the <code>Enum</code> to get,
+ * must not be <code>null</code>
+ * @return the enum object Map
+ * @throws IllegalArgumentException if the enum class is <code>null</code>
+ * @throws IllegalArgumentException if the enum class is not a subclass of Enum
+ */
+ protected static List getEnumList(Class enumClass) {
+ Entry entry = getEntry(enumClass);
+ if (entry == null) {
+ return Collections.EMPTY_LIST;
+ }
+ return entry.unmodifiableList;
+ }
+
+ /**
+ * <p>Gets an <code>Iterator</code> over the <code>Enum</code> objects in
+ * an <code>Enum</code> class.</p>
+ *
+ * <p>The <code>Iterator</code> is in the order that the objects were
+ * created (source code order). If the requested class has no enum
+ * objects an empty <code>Iterator</code> is returned.</p>
+ *
+ * @param enumClass the class of the <code>Enum</code> to get,
+ * must not be <code>null</code>
+ * @return an iterator of the Enum objects
+ * @throws IllegalArgumentException if the enum class is <code>null</code>
+ * @throws IllegalArgumentException if the enum class is not a subclass of Enum
+ */
+ protected static Iterator iterator(Class enumClass) {
+ return Enum.getEnumList(enumClass).iterator();
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * <p>Gets an <code>Entry</code> from the map of Enums.</p>
+ *
+ * @param enumClass the class of the <code>Enum</code> to get
+ * @return the enum entry
+ */
+ private static Entry getEntry(Class enumClass) {
+ if (enumClass == null) {
+ throw new IllegalArgumentException("The Enum Class must not be null");
+ }
+ if (Enum.class.isAssignableFrom(enumClass) == false) {
+ throw new IllegalArgumentException("The Class must be a subclass of Enum");
+ }
+ Entry entry = (Entry) cEnumClasses.get(enumClass);
+ return entry;
+ }
+
+ /**
+ * <p>Creates an <code>Entry</code> for storing the Enums.</p>
+ *
+ * <p>This accounts for subclassed Enums.</p>
+ *
+ * @param enumClass the class of the <code>Enum</code> to get
+ * @return the enum entry
+ */
+ private static Entry createEntry(Class enumClass) {
+ Entry entry = new Entry();
+ Class cls = enumClass.getSuperclass();
+ while (cls != null && cls != Enum.class && cls != ValuedEnum.class) {
+ Entry loopEntry = (Entry) cEnumClasses.get(cls);
+ if (loopEntry != null) {
+ entry.list.addAll(loopEntry.list);
+ entry.map.putAll(loopEntry.map);
+ break; // stop here, as this will already have had superclasses added
+ }
+ cls = cls.getSuperclass();
+ }
+ return entry;
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * <p>Retrieve the name of this Enum item, set in the constructor.</p>
+ *
+ * @return the <code>String</code> name of this Enum item
+ */
+ public final String getName() {
+ return iName;
+ }
+
+ /**
+ * <p>Retrieves the Class of this Enum item, set in the constructor.</p>
+ *
+ * <p>This is normally the same as <code>getClass()</code>, but for
+ * advanced Enums may be different. If overridden, it must return a
+ * constant value.</p>
+ *
+ * @return the <code>Class</code> of the enum
+ * @since 2.0
+ */
+ public Class getEnumClass() {
+ return getClass();
+ }
+
+ /**
+ * <p>Tests for equality.</p>
+ *
+ * <p>Two Enum objects are considered equal
+ * if they have the same class names and the same names.
+ * Identity is tested for first, so this method usually runs fast.</p>
+ *
+ * <p>If the parameter is in a different class loader than this instance,
+ * reflection is used to compare the names.</p>
+ *
+ * @param other the other object to compare for equality
+ * @return <code>true</code> if the Enums are equal
+ */
+ public final boolean equals(Object other) {
+ if (other == this) {
+ return true;
+ } else if (other == null) {
+ return false;
+ } else if (other.getClass() == this.getClass()) {
+ // Ok to do a class cast to Enum here since the test above
+ // guarantee both
+ // classes are in the same class loader.
+ return iName.equals(((Enum) other).iName);
+ } else {
+ // This and other are in different class loaders, we must use reflection.
+ try {
+ Method mth = other.getClass().getMethod("getName", null);
+ String name = (String) mth.invoke(other, null);
+ return iName.equals(name);
+ } catch (NoSuchMethodException e) {
+ // ignore - should never happen
+ } catch (IllegalAccessException e) {
+ // ignore - should never happen
+ } catch (InvocationTargetException e) {
+ // ignore - should never happen
+ }
+ return false;
+ }
+ }
+
+ /**
+ * <p>Returns a suitable hashCode for the enumeration.</p>
+ *
+ * @return a hashcode based on the name
+ */
+ public final int hashCode() {
+ return iHashCode;
+ }
+
+ /**
+ * <p>Tests for order.</p>
+ *
+ * <p>The default ordering is alphabetic by name, but this
+ * can be overridden by subclasses.</p>
+ *
+ * @see java.lang.Comparable#compareTo(Object)
+ * @param other the other object to compare to
+ * @return -ve if this is less than the other object, +ve if greater
+ * than, <code>0</code> of equal
+ * @throws ClassCastException if other is not an Enum
+ * @throws NullPointerException if other is <code>null</code>
+ */
+ public int compareTo(Object other) {
+ if (other == this) {
+ return 0;
+ }
+ return iName.compareTo(((Enum) other).iName);
+ }
+
+ /**
+ * <p>Human readable description of this Enum item.</p>
+ *
+ * @return String in the form <code>type[name]</code>, for example:
+ * <code>Color[Red]</code>. Note that the package name is stripped from
+ * the type name.
+ */
+ public String toString() {
+ if (iToString == null) {
+ String shortName = ClassUtils.getShortClassName(getEnumClass());
+ iToString = shortName + "[" + getName() + "]";
+ }
+ return iToString;
+ }
+
+}
Added: incubator/directory/ldap/trunk/common/src/java/org/apache/ldap/common/util/EnumUtils.java
==============================================================================
--- (empty file)
+++ incubator/directory/ldap/trunk/common/src/java/org/apache/ldap/common/util/EnumUtils.java Sat Sep 25 12:11:47 2004
@@ -0,0 +1,124 @@
+/*
+ * Copyright 2002-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.ldap.common.util;
+
+
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+
+/**
+ * <p>Utility class for accessing and manipulating {@link Enum}s.</p>
+ *
+ * @see Enum
+ * @see ValuedEnum
+ * @author Stephen Colebourne
+ * @author Gary Gregory
+ * @since 1.0
+ * @version $Id: EnumUtils.java,v 1.12 2004/02/23 04:34:20 ggregory Exp $
+ */
+public class EnumUtils {
+
+ /**
+ * Public constructor. This class should not normally be instantiated.
+ * @since 2.0
+ */
+ public EnumUtils() {
+ }
+
+ /**
+ * <p>Gets an <code>Enum</code> object by class and name.</p>
+ *
+ * @param enumClass the class of the <code>Enum</code> to get
+ * @param name the name of the Enum to get, may be <code>null</code>
+ * @return the enum object
+ * @throws IllegalArgumentException if the enum class is <code>null</code>
+ */
+ public static Enum getEnum(Class enumClass, String name) {
+ return Enum.getEnum(enumClass, name);
+ }
+
+ /**
+ * <p>Gets a <code>ValuedEnum</code> object by class and value.</p>
+ *
+ * @param enumClass the class of the <code>Enum</code> to get
+ * @param value the value of the <code>Enum</code> to get
+ * @return the enum object, or null if the enum does not exist
+ * @throws IllegalArgumentException if the enum class is <code>null</code>
+ */
+ public static ValuedEnum getEnum(Class enumClass, int value) {
+ return (ValuedEnum) ValuedEnum.getEnum(enumClass, value);
+ }
+
+ /**
+ * <p>Gets the <code>Map</code> of <code>Enum</code> objects by
+ * name using the <code>Enum</code> class.</p>
+ *
+ * <p>If the requested class has no enum objects an empty
+ * <code>Map</code> is returned. The <code>Map</code> is unmodifiable.</p>
+ *
+ * @param enumClass the class of the <code>Enum</code> to get
+ * @return the enum object Map
+ * @throws IllegalArgumentException if the enum class is <code>null</code>
+ * @throws IllegalArgumentException if the enum class is not a subclass
+ * of <code>Enum</code>
+ */
+ public static Map getEnumMap(Class enumClass) {
+ return Enum.getEnumMap(enumClass);
+ }
+
+ /**
+ * <p>Gets the <code>List</code> of <code>Enum</code> objects using
+ * the <code>Enum</code> class.</p>
+ *
+ * <p>The list is in the order that the objects were created
+ * (source code order).</p>
+ *
+ * <p>If the requested class has no enum objects an empty
+ * <code>List</code> is returned. The <code>List</code> is unmodifiable.</p>
+ *
+ * @param enumClass the class of the Enum to get
+ * @return the enum object Map
+ * @throws IllegalArgumentException if the enum class is <code>null</code>
+ * @throws IllegalArgumentException if the enum class is not a subclass
+ * of <code>Enum</code>
+ */
+ public static List getEnumList(Class enumClass) {
+ return Enum.getEnumList(enumClass);
+ }
+
+ /**
+ * <p>Gets an <code>Iterator</code> over the <code>Enum</code> objects
+ * in an <code>Enum</code> class.</p>
+ *
+ * <p>The iterator is in the order that the objects were created
+ * (source code order).</p>
+ *
+ * <p>If the requested class has no enum objects an empty
+ * <code>Iterator</code> is returned. The <code>Iterator</code>
+ * is unmodifiable.</p>
+ *
+ * @param enumClass the class of the <code>Enum</code> to get
+ * @return an <code>Iterator</code> of the <code>Enum</code> objects
+ * @throws IllegalArgumentException if the enum class is <code>null</code>
+ * @throws IllegalArgumentException if the enum class is not a subclass of <code>Enum</code>
+ */
+ public static Iterator iterator(Class enumClass) {
+ return Enum.getEnumList(enumClass).iterator();
+ }
+
+}
Added: incubator/directory/ldap/trunk/common/src/java/org/apache/ldap/common/util/EqualsBuilder.java
==============================================================================
--- (empty file)
+++ incubator/directory/ldap/trunk/common/src/java/org/apache/ldap/common/util/EqualsBuilder.java Sat Sep 25 12:11:47 2004
@@ -0,0 +1,754 @@
+/*
+ * Copyright 2002-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.ldap.common.util;
+
+import java.lang.reflect.AccessibleObject;
+import java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
+
+/**
+ * <p>Assists in implementing {@link Object#equals(Object)} methods.</p>
+ *
+ * <p> This class provides methods to build a good equals method for any
+ * class. It follows rules laid out in
+ * <a href="http://java.sun.com/docs/books/effective/index.html">Effective Java</a>
+ * , by Joshua Bloch. In particular the rule for comparing <code>doubles</code>,
+ * <code>floats</code>, and arrays can be tricky. Also, making sure that
+ * <code>equals()</code> and <code>hashCode()</code> are consistent can be
+ * difficult.</p>
+ *
+ * <p>Two Objects that compare as equals must generate the same hash code,
+ * but two Objects with the same hash code do not have to be equal.</p>
+ *
+ * <p>All relevant fields should be included in the calculation of equals.
+ * Derived fields may be ignored. In particular, any field used in
+ * generating a hash code must be used in the equals method, and vice
+ * versa.</p>
+ *
+ * <p>Typical use for the code is as follows:</p>
+ * <pre>
+ * public boolean equals(Object o) {
+ * if ( !(o instanceof MyClass) ) {
+ * return false;
+ * }
+ * MyClass rhs = (MyClass) o;
+ * return new EqualsBuilder()
+ * .appendSuper(super.equals(o))
+ * .append(field1, rhs.field1)
+ * .append(field2, rhs.field2)
+ * .append(field3, rhs.field3)
+ * .isEquals();
+ * }
+ * </pre>
+ *
+ * <p> Alternatively, there is a method that uses reflection to determine
+ * the fields to test. Because these fields are usually private, the method,
+ * <code>reflectionEquals</code>, uses <code>AccessibleObject.setAccessible</code> to
+ * change the visibility of the fields. This will fail under a security
+ * manager, unless the appropriate permissions are set up correctly. It is
+ * also slower than testing explicitly.</p>
+ *
+ * <p> A typical invocation for this method would look like:</p>
+ * <pre>
+ * public boolean equals(Object o) {
+ * return EqualsBuilder.reflectionEquals(this, o);
+ * }
+ * </pre>
+ *
+ * @author <a href="mailto:steve.downey@netfolio.com">Steve Downey</a>
+ * @author Stephen Colebourne
+ * @author Gary Gregory
+ * @author Pete Gieser
+ * @author Arun Mammen Thomas
+ * @since 1.0
+ * @version $Id: EqualsBuilder.java,v 1.26 2004/08/26 05:46:45 ggregory Exp $
+ */
+public class EqualsBuilder {
+
+ /**
+ * If the fields tested are equals.
+ * The default value is <code>true</code>.
+ */
+ private boolean isEquals = true;
+
+ /**
+ * <p>Constructor for EqualsBuilder.</p>
+ *
+ * <p>Starts off assuming that equals is <code>true</code>.</p>
+ * @see Object#equals(Object)
+ */
+ public EqualsBuilder() {
+ // do nothing for now.
+ }
+
+ //-------------------------------------------------------------------------
+
+ /**
+ * <p>This method uses reflection to determine if the two <code>Object</code>s
+ * are equal.</p>
+ *
+ * <p>It uses <code>AccessibleObject.setAccessible</code> to gain access to private
+ * fields. This means that it will throw a security exception if run under
+ * a security manager, if the permissions are not set up correctly. It is also
+ * not as efficient as testing explicitly.</p>
+ *
+ * <p>Transient members will be not be tested, as they are likely derived
+ * fields, and not part of the value of the Object.</p>
+ *
+ * <p>Static fields will not be tested. Superclass fields will be included.</p>
+ *
+ * @param lhs <code>this</code> object
+ * @param rhs the other object
+ * @return <code>true</code> if the two Objects have tested equals.
+ */
+ public static boolean reflectionEquals(Object lhs, Object rhs) {
+ return reflectionEquals(lhs, rhs, false, null);
+ }
+
+ /**
+ * <p>This method uses reflection to determine if the two <code>Object</code>s
+ * are equal.</p>
+ *
+ * <p>It uses <code>AccessibleObject.setAccessible</code> to gain access to private
+ * fields. This means that it will throw a security exception if run under
+ * a security manager, if the permissions are not set up correctly. It is also
+ * not as efficient as testing explicitly.</p>
+ *
+ * <p>If the TestTransients parameter is set to <code>true</code>, transient
+ * members will be tested, otherwise they are ignored, as they are likely
+ * derived fields, and not part of the value of the <code>Object</code>.</p>
+ *
+ * <p>Static fields will not be tested. Superclass fields will be included.</p>
+ *
+ * @param lhs <code>this</code> object
+ * @param rhs the other object
+ * @param testTransients whether to include transient fields
+ * @return <code>true</code> if the two Objects have tested equals.
+ */
+ public static boolean reflectionEquals(Object lhs, Object rhs, boolean testTransients) {
+ return reflectionEquals(lhs, rhs, testTransients, null);
+ }
+
+ /**
+ * <p>This method uses reflection to determine if the two <code>Object</code>s
+ * are equal.</p>
+ *
+ * <p>It uses <code>AccessibleObject.setAccessible</code> to gain access to private
+ * fields. This means that it will throw a security exception if run under
+ * a security manager, if the permissions are not set up correctly. It is also
+ * not as efficient as testing explicitly.</p>
+ *
+ * <p>If the testTransients parameter is set to <code>true</code>, transient
+ * members will be tested, otherwise they are ignored, as they are likely
+ * derived fields, and not part of the value of the <code>Object</code>.</p>
+ *
+ * <p>Static fields will not be included. Superclass fields will be appended
+ * up to and including the specified superclass. A null superclass is treated
+ * as java.lang.Object.</p>
+ *
+ * @param lhs <code>this</code> object
+ * @param rhs the other object
+ * @param testTransients whether to include transient fields
+ * @param reflectUpToClass the superclass to reflect up to (inclusive),
+ * may be <code>null</code>
+ * @return <code>true</code> if the two Objects have tested equals.
+ * @since 2.0
+ */
+ public static boolean reflectionEquals(Object lhs, Object rhs, boolean testTransients, Class reflectUpToClass) {
+ if (lhs == rhs) {
+ return true;
+ }
+ if (lhs == null || rhs == null) {
+ return false;
+ }
+ // Find the leaf class since there may be transients in the leaf
+ // class or in classes between the leaf and root.
+ // If we are not testing transients or a subclass has no ivars,
+ // then a subclass can test equals to a superclass.
+ Class lhsClass = lhs.getClass();
+ Class rhsClass = rhs.getClass();
+ Class testClass;
+ if (lhsClass.isInstance(rhs)) {
+ testClass = lhsClass;
+ if (!rhsClass.isInstance(lhs)) {
+ // rhsClass is a subclass of lhsClass
+ testClass = rhsClass;
+ }
+ } else if (rhsClass.isInstance(lhs)) {
+ testClass = rhsClass;
+ if (!lhsClass.isInstance(rhs)) {
+ // lhsClass is a subclass of rhsClass
+ testClass = lhsClass;
+ }
+ } else {
+ // The two classes are not related.
+ return false;
+ }
+ EqualsBuilder equalsBuilder = new EqualsBuilder();
+ try {
+ reflectionAppend(lhs, rhs, testClass, equalsBuilder, testTransients);
+ while (testClass.getSuperclass() != null && testClass != reflectUpToClass) {
+ testClass = testClass.getSuperclass();
+ reflectionAppend(lhs, rhs, testClass, equalsBuilder, testTransients);
+ }
+ } catch (IllegalArgumentException e) {
+ // In this case, we tried to test a subclass vs. a superclass and
+ // the subclass has ivars or the ivars are transient and
+ // we are testing transients.
+ // If a subclass has ivars that we are trying to test them, we get an
+ // exception and we know that the objects are not equal.
+ return false;
+ }
+ return equalsBuilder.isEquals();
+ }
+
+ /**
+ * <p>Appends the fields and values defined by the given object of the
+ * given Class.</p>
+ *
+ * @param lhs the left hand object
+ * @param rhs the right hand object
+ * @param clazz the class to append details of
+ * @param builder the builder to append to
+ * @param useTransients whether to test transient fields
+ */
+ private static void reflectionAppend(
+ Object lhs,
+ Object rhs,
+ Class clazz,
+ EqualsBuilder builder,
+ boolean useTransients) {
+ Field[] fields = clazz.getDeclaredFields();
+ AccessibleObject.setAccessible(fields, true);
+ for (int i = 0; i < fields.length && builder.isEquals; i++) {
+ Field f = fields[i];
+ if ((f.getName().indexOf('$') == -1)
+ && (useTransients || !Modifier.isTransient(f.getModifiers()))
+ && (!Modifier.isStatic(f.getModifiers()))) {
+ try {
+ builder.append(f.get(lhs), f.get(rhs));
+ } catch (IllegalAccessException e) {
+ //this can't happen. Would get a Security exception instead
+ //throw a runtime exception in case the impossible happens.
+ throw new InternalError("Unexpected IllegalAccessException");
+ }
+ }
+ }
+ }
+
+ //-------------------------------------------------------------------------
+
+ /**
+ * <p>Adds the result of <code>super.equals()</code> to this builder.</p>
+ *
+ * @param superEquals the result of calling <code>super.equals()</code>
+ * @return EqualsBuilder - used to chain calls.
+ * @since 2.0
+ */
+ public EqualsBuilder appendSuper(boolean superEquals) {
+ if (isEquals == false) {
+ return this;
+ }
+ isEquals = superEquals;
+ return this;
+ }
+
+ //-------------------------------------------------------------------------
+
+ /**
+ * <p>Test if two <code>Object</code>s are equal using their
+ * <code>equals</code> method.</p>
+ *
+ * @param lhs the left hand object
+ * @param rhs the right hand object
+ * @return EqualsBuilder - used to chain calls.
+ */
+ public EqualsBuilder append(Object lhs, Object rhs) {
+ if (isEquals == false) {
+ return this;
+ }
+ if (lhs == rhs) {
+ return this;
+ }
+ if (lhs == null || rhs == null) {
+ this.setEquals(false);
+ return this;
+ }
+ Class lhsClass = lhs.getClass();
+ if (!lhsClass.isArray()) {
+ // The simple case, not an array, just test the element
+ isEquals = lhs.equals(rhs);
+ } else if (lhs.getClass() != rhs.getClass()) {
+ // Here when we compare different dimensions, for example: a boolean[][] to a boolean[]
+ this.setEquals(false);
+ }
+ // 'Switch' on type of array, to dispatch to the correct handler
+ // This handles multi dimensional arrays of the same depth
+ else if (lhs instanceof long[]) {
+ append((long[]) lhs, (long[]) rhs);
+ } else if (lhs instanceof int[]) {
+ append((int[]) lhs, (int[]) rhs);
+ } else if (lhs instanceof short[]) {
+ append((short[]) lhs, (short[]) rhs);
+ } else if (lhs instanceof char[]) {
+ append((char[]) lhs, (char[]) rhs);
+ } else if (lhs instanceof byte[]) {
+ append((byte[]) lhs, (byte[]) rhs);
+ } else if (lhs instanceof double[]) {
+ append((double[]) lhs, (double[]) rhs);
+ } else if (lhs instanceof float[]) {
+ append((float[]) lhs, (float[]) rhs);
+ } else if (lhs instanceof boolean[]) {
+ append((boolean[]) lhs, (boolean[]) rhs);
+ } else {
+ // Not an array of primitives
+ append((Object[]) lhs, (Object[]) rhs);
+ }
+ return this;
+ }
+
+ /**
+ * <p>
+ * Test if two <code>long</code> s are equal.
+ * </p>
+ *
+ * @param lhs
+ * the left hand <code>long</code>
+ * @param rhs
+ * the right hand <code>long</code>
+ * @return EqualsBuilder - used to chain calls.
+ */
+ public EqualsBuilder append(long lhs, long rhs) {
+ if (isEquals == false) {
+ return this;
+ }
+ isEquals = (lhs == rhs);
+ return this;
+ }
+
+ /**
+ * <p>Test if two <code>int</code>s are equal.</p>
+ *
+ * @param lhs the left hand <code>int</code>
+ * @param rhs the right hand <code>int</code>
+ * @return EqualsBuilder - used to chain calls.
+ */
+ public EqualsBuilder append(int lhs, int rhs) {
+ if (isEquals == false) {
+ return this;
+ }
+ isEquals = (lhs == rhs);
+ return this;
+ }
+
+ /**
+ * <p>Test if two <code>short</code>s are equal.</p>
+ *
+ * @param lhs the left hand <code>short</code>
+ * @param rhs the right hand <code>short</code>
+ * @return EqualsBuilder - used to chain calls.
+ */
+ public EqualsBuilder append(short lhs, short rhs) {
+ if (isEquals == false) {
+ return this;
+ }
+ isEquals = (lhs == rhs);
+ return this;
+ }
+
+ /**
+ * <p>Test if two <code>char</code>s are equal.</p>
+ *
+ * @param lhs the left hand <code>char</code>
+ * @param rhs the right hand <code>char</code>
+ * @return EqualsBuilder - used to chain calls.
+ */
+ public EqualsBuilder append(char lhs, char rhs) {
+ if (isEquals == false) {
+ return this;
+ }
+ isEquals = (lhs == rhs);
+ return this;
+ }
+
+ /**
+ * <p>Test if two <code>byte</code>s are equal.</p>
+ *
+ * @param lhs the left hand <code>byte</code>
+ * @param rhs the right hand <code>byte</code>
+ * @return EqualsBuilder - used to chain calls.
+ */
+ public EqualsBuilder append(byte lhs, byte rhs) {
+ if (isEquals == false) {
+ return this;
+ }
+ isEquals = (lhs == rhs);
+ return this;
+ }
+
+ /**
+ * <p>Test if two <code>double</code>s are equal by testing that the
+ * pattern of bits returned by <code>doubleToLong</code> are equal.</p>
+ *
+ * <p>This handles NaNs, Infinities, and <code>-0.0</code>.</p>
+ *
+ * <p>It is compatible with the hash code generated by
+ * <code>HashCodeBuilder</code>.</p>
+ *
+ * @param lhs the left hand <code>double</code>
+ * @param rhs the right hand <code>double</code>
+ * @return EqualsBuilder - used to chain calls.
+ */
+ public EqualsBuilder append(double lhs, double rhs) {
+ if (isEquals == false) {
+ return this;
+ }
+ return append(Double.doubleToLongBits(lhs), Double.doubleToLongBits(rhs));
+ }
+
+ /**
+ * <p>Test if two <code>float</code>s are equal byt testing that the
+ * pattern of bits returned by doubleToLong are equal.</p>
+ *
+ * <p>This handles NaNs, Infinities, and <code>-0.0</code>.</p>
+ *
+ * <p>It is compatible with the hash code generated by
+ * <code>HashCodeBuilder</code>.</p>
+ *
+ * @param lhs the left hand <code>float</code>
+ * @param rhs the right hand <code>float</code>
+ * @return EqualsBuilder - used to chain calls.
+ */
+ public EqualsBuilder append(float lhs, float rhs) {
+ if (isEquals == false) {
+ return this;
+ }
+ return append(Float.floatToIntBits(lhs), Float.floatToIntBits(rhs));
+ }
+
+ /**
+ * <p>Test if two <code>booleans</code>s are equal.</p>
+ *
+ * @param lhs the left hand <code>boolean</code>
+ * @param rhs the right hand <code>boolean</code>
+ * @return EqualsBuilder - used to chain calls.
+ */
+ public EqualsBuilder append(boolean lhs, boolean rhs) {
+ if (isEquals == false) {
+ return this;
+ }
+ isEquals = (lhs == rhs);
+ return this;
+ }
+
+ /**
+ * <p>Performs a deep comparison of two <code>Object</code> arrays.</p>
+ *
+ * <p>This also will be called for the top level of
+ * multi-dimensional, ragged, and multi-typed arrays.</p>
+ *
+ * @param lhs the left hand <code>Object[]</code>
+ * @param rhs the right hand <code>Object[]</code>
+ * @return EqualsBuilder - used to chain calls.
+ */
+ public EqualsBuilder append(Object[] lhs, Object[] rhs) {
+ if (isEquals == false) {
+ return this;
+ }
+ if (lhs == rhs) {
+ return this;
+ }
+ if (lhs == null || rhs == null) {
+ this.setEquals(false);
+ return this;
+ }
+ if (lhs.length != rhs.length) {
+ this.setEquals(false);
+ return this;
+ }
+ for (int i = 0; i < lhs.length && isEquals; ++i) {
+ append(lhs[i], rhs[i]);
+ }
+ return this;
+ }
+
+ /**
+ * <p>Deep comparison of array of <code>long</code>. Length and all
+ * values are compared.</p>
+ *
+ * <p>The method {@link #append(long, long)} is used.</p>
+ *
+ * @param lhs the left hand <code>long[]</code>
+ * @param rhs the right hand <code>long[]</code>
+ * @return EqualsBuilder - used to chain calls.
+ */
+ public EqualsBuilder append(long[] lhs, long[] rhs) {
+ if (isEquals == false) {
+ return this;
+ }
+ if (lhs == rhs) {
+ return this;
+ }
+ if (lhs == null || rhs == null) {
+ this.setEquals(false);
+ return this;
+ }
+ if (lhs.length != rhs.length) {
+ this.setEquals(false);
+ return this;
+ }
+ for (int i = 0; i < lhs.length && isEquals; ++i) {
+ append(lhs[i], rhs[i]);
+ }
+ return this;
+ }
+
+ /**
+ * <p>Deep comparison of array of <code>int</code>. Length and all
+ * values are compared.</p>
+ *
+ * <p>The method {@link #append(int, int)} is used.</p>
+ *
+ * @param lhs the left hand <code>int[]</code>
+ * @param rhs the right hand <code>int[]</code>
+ * @return EqualsBuilder - used to chain calls.
+ */
+ public EqualsBuilder append(int[] lhs, int[] rhs) {
+ if (isEquals == false) {
+ return this;
+ }
+ if (lhs == rhs) {
+ return this;
+ }
+ if (lhs == null || rhs == null) {
+ this.setEquals(false);
+ return this;
+ }
+ if (lhs.length != rhs.length) {
+ this.setEquals(false);
+ return this;
+ }
+ for (int i = 0; i < lhs.length && isEquals; ++i) {
+ append(lhs[i], rhs[i]);
+ }
+ return this;
+ }
+
+ /**
+ * <p>Deep comparison of array of <code>short</code>. Length and all
+ * values are compared.</p>
+ *
+ * <p>The method {@link #append(short, short)} is used.</p>
+ *
+ * @param lhs the left hand <code>short[]</code>
+ * @param rhs the right hand <code>short[]</code>
+ * @return EqualsBuilder - used to chain calls.
+ */
+ public EqualsBuilder append(short[] lhs, short[] rhs) {
+ if (isEquals == false) {
+ return this;
+ }
+ if (lhs == rhs) {
+ return this;
+ }
+ if (lhs == null || rhs == null) {
+ this.setEquals(false);
+ return this;
+ }
+ if (lhs.length != rhs.length) {
+ this.setEquals(false);
+ return this;
+ }
+ for (int i = 0; i < lhs.length && isEquals; ++i) {
+ append(lhs[i], rhs[i]);
+ }
+ return this;
+ }
+
+ /**
+ * <p>Deep comparison of array of <code>char</code>. Length and all
+ * values are compared.</p>
+ *
+ * <p>The method {@link #append(char, char)} is used.</p>
+ *
+ * @param lhs the left hand <code>char[]</code>
+ * @param rhs the right hand <code>char[]</code>
+ * @return EqualsBuilder - used to chain calls.
+ */
+ public EqualsBuilder append(char[] lhs, char[] rhs) {
+ if (isEquals == false) {
+ return this;
+ }
+ if (lhs == rhs) {
+ return this;
+ }
+ if (lhs == null || rhs == null) {
+ this.setEquals(false);
+ return this;
+ }
+ if (lhs.length != rhs.length) {
+ this.setEquals(false);
+ return this;
+ }
+ for (int i = 0; i < lhs.length && isEquals; ++i) {
+ append(lhs[i], rhs[i]);
+ }
+ return this;
+ }
+
+ /**
+ * <p>Deep comparison of array of <code>byte</code>. Length and all
+ * values are compared.</p>
+ *
+ * <p>The method {@link #append(byte, byte)} is used.</p>
+ *
+ * @param lhs the left hand <code>byte[]</code>
+ * @param rhs the right hand <code>byte[]</code>
+ * @return EqualsBuilder - used to chain calls.
+ */
+ public EqualsBuilder append(byte[] lhs, byte[] rhs) {
+ if (isEquals == false) {
+ return this;
+ }
+ if (lhs == rhs) {
+ return this;
+ }
+ if (lhs == null || rhs == null) {
+ this.setEquals(false);
+ return this;
+ }
+ if (lhs.length != rhs.length) {
+ this.setEquals(false);
+ return this;
+ }
+ for (int i = 0; i < lhs.length && isEquals; ++i) {
+ append(lhs[i], rhs[i]);
+ }
+ return this;
+ }
+
+ /**
+ * <p>Deep comparison of array of <code>double</code>. Length and all
+ * values are compared.</p>
+ *
+ * <p>The method {@link #append(double, double)} is used.</p>
+ *
+ * @param lhs the left hand <code>double[]</code>
+ * @param rhs the right hand <code>double[]</code>
+ * @return EqualsBuilder - used to chain calls.
+ */
+ public EqualsBuilder append(double[] lhs, double[] rhs) {
+ if (isEquals == false) {
+ return this;
+ }
+ if (lhs == rhs) {
+ return this;
+ }
+ if (lhs == null || rhs == null) {
+ this.setEquals(false);
+ return this;
+ }
+ if (lhs.length != rhs.length) {
+ this.setEquals(false);
+ return this;
+ }
+ for (int i = 0; i < lhs.length && isEquals; ++i) {
+ append(lhs[i], rhs[i]);
+ }
+ return this;
+ }
+
+ /**
+ * <p>Deep comparison of array of <code>float</code>. Length and all
+ * values are compared.</p>
+ *
+ * <p>The method {@link #append(float, float)} is used.</p>
+ *
+ * @param lhs the left hand <code>float[]</code>
+ * @param rhs the right hand <code>float[]</code>
+ * @return EqualsBuilder - used to chain calls.
+ */
+ public EqualsBuilder append(float[] lhs, float[] rhs) {
+ if (isEquals == false) {
+ return this;
+ }
+ if (lhs == rhs) {
+ return this;
+ }
+ if (lhs == null || rhs == null) {
+ this.setEquals(false);
+ return this;
+ }
+ if (lhs.length != rhs.length) {
+ this.setEquals(false);
+ return this;
+ }
+ for (int i = 0; i < lhs.length && isEquals; ++i) {
+ append(lhs[i], rhs[i]);
+ }
+ return this;
+ }
+
+ /**
+ * <p>Deep comparison of array of <code>boolean</code>. Length and all
+ * values are compared.</p>
+ *
+ * <p>The method {@link #append(boolean, boolean)} is used.</p>
+ *
+ * @param lhs the left hand <code>boolean[]</code>
+ * @param rhs the right hand <code>boolean[]</code>
+ * @return EqualsBuilder - used to chain calls.
+ */
+ public EqualsBuilder append(boolean[] lhs, boolean[] rhs) {
+ if (isEquals == false) {
+ return this;
+ }
+ if (lhs == rhs) {
+ return this;
+ }
+ if (lhs == null || rhs == null) {
+ this.setEquals(false);
+ return this;
+ }
+ if (lhs.length != rhs.length) {
+ this.setEquals(false);
+ return this;
+ }
+ for (int i = 0; i < lhs.length && isEquals; ++i) {
+ append(lhs[i], rhs[i]);
+ }
+ return this;
+ }
+
+ /**
+ * <p>Returns <code>true</code> if the fields that have been checked
+ * are all equal.</p>
+ *
+ * @return boolean
+ */
+ public boolean isEquals() {
+ return this.isEquals;
+ }
+
+ /**
+ * Sets the <code>isEquals</code> value.
+ *
+ * @param isEquals The value to set.
+ */
+ protected void setEquals(boolean isEquals) {
+ this.isEquals = isEquals;
+ }
+}
Added: incubator/directory/ldap/trunk/common/src/java/org/apache/ldap/common/util/ExceptionUtils.java
==============================================================================
--- (empty file)
+++ incubator/directory/ldap/trunk/common/src/java/org/apache/ldap/common/util/ExceptionUtils.java Sat Sep 25 12:11:47 2004
@@ -0,0 +1,688 @@
+/*
+ * Copyright 2002-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.ldap.common.util;
+
+import java.io.PrintStream;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.sql.SQLException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.StringTokenizer;
+
+
+/**
+ * <p>Provides utilities for manipulating and examining
+ * <code>Throwable</code> objects.</p>
+ *
+ * @author <a href="mailto:dlr@finemaltcoding.com">Daniel Rall</a>
+ * @author Dmitri Plotnikov
+ * @author Stephen Colebourne
+ * @author <a href="mailto:ggregory@seagullsw.com">Gary Gregory</a>
+ * @author Pete Gieser
+ * @since 1.0
+ * @version $Id: ExceptionUtils.java,v 1.39 2004/07/04 03:24:57 bayard Exp $
+ */
+public class ExceptionUtils {
+
+ /**
+ * <p>Used when printing stack frames to denote the start of a
+ * wrapped exception.</p>
+ *
+ * <p>Package private for accessibility by test suite.</p>
+ */
+ static final String WRAPPED_MARKER = " [wrapped] ";
+
+ /**
+ * <p>The names of methods commonly used to access a wrapped exception.</p>
+ */
+ private static String[] CAUSE_METHOD_NAMES = {
+ "getCause",
+ "getNextException",
+ "getTargetException",
+ "getException",
+ "getSourceException",
+ "getRootCause",
+ "getCausedByException",
+ "getNested",
+ "getLinkedException",
+ "getNestedException",
+ "getLinkedCause",
+ "getThrowable",
+ };
+
+ /**
+ * <p>The Method object for JDK1.4 getCause.</p>
+ */
+ private static final Method THROWABLE_CAUSE_METHOD;
+ static {
+ Method getCauseMethod;
+ try {
+ getCauseMethod = Throwable.class.getMethod("getCause", null);
+ } catch (Exception e) {
+ getCauseMethod = null;
+ }
+ THROWABLE_CAUSE_METHOD = getCauseMethod;
+ }
+
+ /**
+ * <p>Public constructor allows an instance of <code>ExceptionUtils</code>
+ * to be created, although that is not normally necessary.</p>
+ */
+ public ExceptionUtils() {
+ }
+
+ /**
+ * <p>Checks if a String is not empty ("") and not null.</p>
+ *
+ * @param str the String to check, may be null
+ * @return <code>true</code> if the String is not empty and not null
+ */
+ private static boolean isNotEmpty(String str) {
+ return (str != null && str.length() > 0);
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * <p>Adds to the list of method names used in the search for <code>Throwable</code>
+ * objects.</p>
+ *
+ * @param methodName the methodName to add to the list, <code>null</code>
+ * and empty strings are ignored
+ * @since 2.0
+ */
+ public static void addCauseMethodName(String methodName) {
+ if (isNotEmpty(methodName)) {
+ List list = new ArrayList(Arrays.asList(CAUSE_METHOD_NAMES));
+ list.add(methodName);
+ CAUSE_METHOD_NAMES = (String[]) list.toArray(new String[list.size()]);
+ }
+ }
+
+ /**
+ * <p>Introspects the <code>Throwable</code> to obtain the cause.</p>
+ *
+ * <p>The method searches for methods with specific names that return a
+ * <code>Throwable</code> object. This will pick up most wrapping exceptions,
+ * including those from JDK 1.4, and
+ * The method names can be added to using {@link #addCauseMethodName(String)}.</p>
+ *
+ * <p>The default list searched for are:</p>
+ * <ul>
+ * <li><code>getCause()</code></li>
+ * <li><code>getNextException()</code></li>
+ * <li><code>getTargetException()</code></li>
+ * <li><code>getException()</code></li>
+ * <li><code>getSourceException()</code></li>
+ * <li><code>getRootCause()</code></li>
+ * <li><code>getCausedByException()</code></li>
+ * <li><code>getNested()</code></li>
+ * </ul>
+ *
+ * <p>In the absence of any such method, the object is inspected for a
+ * <code>detail</code> field assignable to a <code>Throwable</code>.</p>
+ *
+ * <p>If none of the above is found, returns <code>null</code>.</p>
+ *
+ * @param throwable the throwable to introspect for a cause, may be null
+ * @return the cause of the <code>Throwable</code>,
+ * <code>null</code> if none found or null throwable input
+ * @since 1.0
+ */
+ public static Throwable getCause(Throwable throwable) {
+ return getCause(throwable, CAUSE_METHOD_NAMES);
+ }
+
+ /**
+ * <p>Introspects the <code>Throwable</code> to obtain the cause.</p>
+ *
+ * <ol>
+ * <li>Try known exception types.</li>
+ * <li>Try the supplied array of method names.</li>
+ * <li>Try the field 'detail'.</li>
+ * </ol>
+ *
+ * <p>A <code>null</code> set of method names means use the default set.
+ * A <code>null</code> in the set of method names will be ignored.</p>
+ *
+ * @param throwable the throwable to introspect for a cause, may be null
+ * @param methodNames the method names, null treated as default set
+ * @return the cause of the <code>Throwable</code>,
+ * <code>null</code> if none found or null throwable input
+ * @since 1.0
+ */
+ public static Throwable getCause(Throwable throwable, String[] methodNames) {
+ if (throwable == null) {
+ return null;
+ }
+ Throwable cause = getCauseUsingWellKnownTypes(throwable);
+ if (cause == null) {
+ if (methodNames == null) {
+ methodNames = CAUSE_METHOD_NAMES;
+ }
+ for (int i = 0; i < methodNames.length; i++) {
+ String methodName = methodNames[i];
+ if (methodName != null) {
+ cause = getCauseUsingMethodName(throwable, methodName);
+ if (cause != null) {
+ break;
+ }
+ }
+ }
+
+ if (cause == null) {
+ cause = getCauseUsingFieldName(throwable, "detail");
+ }
+ }
+ return cause;
+ }
+
+ /**
+ * <p>Introspects the <code>Throwable</code> to obtain the root cause.</p>
+ *
+ * <p>This method walks through the exception chain to the last element,
+ * "root" of the tree, using {@link #getCause(Throwable)}, and
+ * returns that exception.</p>
+ *
+ * @param throwable the throwable to get the root cause for, may be null
+ * @return the root cause of the <code>Throwable</code>,
+ * <code>null</code> if none found or null throwable input
+ */
+ public static Throwable getRootCause(Throwable throwable) {
+ Throwable cause = getCause(throwable);
+ if (cause != null) {
+ throwable = cause;
+ while ((throwable = getCause(throwable)) != null) {
+ cause = throwable;
+ }
+ }
+ return cause;
+ }
+
+ /**
+ * <p>Finds a <code>Throwable</code> for known types.</p>
+ *
+ * <p>Uses <code>instanceof</code> checks to examine the exception,
+ * looking for well known types which could contain chained or
+ * wrapped exceptions.</p>
+ *
+ * @param throwable the exception to examine
+ * @return the wrapped exception, or <code>null</code> if not found
+ */
+ private static Throwable getCauseUsingWellKnownTypes(Throwable throwable) {
+ if (throwable instanceof Nestable) {
+ return ((Nestable) throwable).getCause();
+ } else if (throwable instanceof SQLException) {
+ return ((SQLException) throwable).getNextException();
+ } else if (throwable instanceof InvocationTargetException) {
+ return ((InvocationTargetException) throwable).getTargetException();
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * <p>Finds a <code>Throwable</code> by method name.</p>
+ *
+ * @param throwable the exception to examine
+ * @param methodName the name of the method to find and invoke
+ * @return the wrapped exception, or <code>null</code> if not found
+ */
+ private static Throwable getCauseUsingMethodName(Throwable throwable, String methodName) {
+ Method method = null;
+ try {
+ method = throwable.getClass().getMethod(methodName, null);
+ } catch (NoSuchMethodException ignored) {
+ } catch (SecurityException ignored) {
+ }
+
+ if (method != null && Throwable.class.isAssignableFrom(method.getReturnType())) {
+ try {
+ return (Throwable) method.invoke(throwable, ArrayUtils.EMPTY_OBJECT_ARRAY);
+ } catch (IllegalAccessException ignored) {
+ } catch (IllegalArgumentException ignored) {
+ } catch (InvocationTargetException ignored) {
+ }
+ }
+ return null;
+ }
+
+ /**
+ * <p>Finds a <code>Throwable</code> by field name.</p>
+ *
+ * @param throwable the exception to examine
+ * @param fieldName the name of the attribute to examine
+ * @return the wrapped exception, or <code>null</code> if not found
+ */
+ private static Throwable getCauseUsingFieldName(Throwable throwable, String fieldName) {
+ Field field = null;
+ try {
+ field = throwable.getClass().getField(fieldName);
+ } catch (NoSuchFieldException ignored) {
+ } catch (SecurityException ignored) {
+ }
+
+ if (field != null && Throwable.class.isAssignableFrom(field.getType())) {
+ try {
+ return (Throwable) field.get(throwable);
+ } catch (IllegalAccessException ignored) {
+ } catch (IllegalArgumentException ignored) {
+ }
+ }
+ return null;
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * <p>Checks if the Throwable class has a <code>getCause</code> method.</p>
+ *
+ * <p>This is true for JDK 1.4 and above.</p>
+ *
+ * @return true if Throwable is nestable
+ * @since 2.0
+ */
+ public static boolean isThrowableNested() {
+ return (THROWABLE_CAUSE_METHOD != null);
+ }
+
+ /**
+ * <p>Checks whether this <code>Throwable</code> class can store a cause.</p>
+ *
+ * <p>This method does <b>not</b> check whether it actually does store a cause.<p>
+ *
+ * @param throwable the <code>Throwable</code> to examine, may be null
+ * @return boolean <code>true</code> if nested otherwise <code>false</code>
+ * @since 2.0
+ */
+ public static boolean isNestedThrowable(Throwable throwable) {
+ if (throwable == null) {
+ return false;
+ }
+
+ if (throwable instanceof Nestable) {
+ return true;
+ } else if (throwable instanceof SQLException) {
+ return true;
+ } else if (throwable instanceof InvocationTargetException) {
+ return true;
+ } else if (isThrowableNested()) {
+ return true;
+ }
+
+ Class cls = throwable.getClass();
+ for (int i = 0, isize = CAUSE_METHOD_NAMES.length; i < isize; i++) {
+ try {
+ Method method = cls.getMethod(CAUSE_METHOD_NAMES[i], null);
+ if (method != null && Throwable.class.isAssignableFrom(method.getReturnType())) {
+ return true;
+ }
+ } catch (NoSuchMethodException ignored) {
+ } catch (SecurityException ignored) {
+ }
+ }
+
+ try {
+ Field field = cls.getField("detail");
+ if (field != null) {
+ return true;
+ }
+ } catch (NoSuchFieldException ignored) {
+ } catch (SecurityException ignored) {
+ }
+
+ return false;
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * <p>Counts the number of <code>Throwable</code> objects in the
+ * exception chain.</p>
+ *
+ * <p>A throwable without cause will return <code>1</code>.
+ * A throwable with one cause will return <code>2</code> and so on.
+ * A <code>null</code> throwable will return <code>0</code>.</p>
+ *
+ * @param throwable the throwable to inspect, may be null
+ * @return the count of throwables, zero if null input
+ */
+ public static int getThrowableCount(Throwable throwable) {
+ int count = 0;
+ while (throwable != null) {
+ count++;
+ throwable = ExceptionUtils.getCause(throwable);
+ }
+ return count;
+ }
+
+ /**
+ * <p>Returns the list of <code>Throwable</code> objects in the
+ * exception chain.</p>
+ *
+ * <p>A throwable without cause will return an array containing
+ * one element - the input throwable.
+ * A throwable with one cause will return an array containing
+ * two elements. - the input throwable and the cause throwable.
+ * A <code>null</code> throwable will return an array size zero.</p>
+ *
+ * @param throwable the throwable to inspect, may be null
+ * @return the array of throwables, never null
+ */
+ public static Throwable[] getThrowables(Throwable throwable) {
+ List list = new ArrayList();
+ while (throwable != null) {
+ list.add(throwable);
+ throwable = ExceptionUtils.getCause(throwable);
+ }
+ return (Throwable[]) list.toArray(new Throwable[list.size()]);
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * <p>Returns the (zero based) index of the first <code>Throwable</code>
+ * that matches the specified type in the exception chain.</p>
+ *
+ * <p>A <code>null</code> throwable returns <code>-1</code>.
+ * A <code>null</code> type returns <code>-1</code>.
+ * No match in the chain returns <code>-1</code>.</p>
+ *
+ * @param throwable the throwable to inspect, may be null
+ * @param type the type to search for
+ * @return the index into the throwable chain, -1 if no match or null input
+ */
+ public static int indexOfThrowable(Throwable throwable, Class type) {
+ return indexOfThrowable(throwable, type, 0);
+ }
+
+ /**
+ * <p>Returns the (zero based) index of the first <code>Throwable</code>
+ * that matches the specified type in the exception chain from
+ * a specified index.</p>
+ *
+ * <p>A <code>null</code> throwable returns <code>-1</code>.
+ * A <code>null</code> type returns <code>-1</code>.
+ * No match in the chain returns <code>-1</code>.
+ * A negative start index is treated as zero.
+ * A start index greater than the number of throwables returns <code>-1</code>.</p>
+ *
+ * @param throwable the throwable to inspect, may be null
+ * @param type the type to search for
+ * @param fromIndex the (zero based) index of the starting position,
+ * negative treated as zero, larger than chain size returns -1
+ * @return the index into the throwable chain, -1 if no match or null input
+ */
+ public static int indexOfThrowable(Throwable throwable, Class type, int fromIndex) {
+ if (throwable == null) {
+ return -1;
+ }
+ if (fromIndex < 0) {
+ fromIndex = 0;
+ }
+ Throwable[] throwables = ExceptionUtils.getThrowables(throwable);
+ if (fromIndex >= throwables.length) {
+ return -1;
+ }
+ for (int i = fromIndex; i < throwables.length; i++) {
+ if (throwables[i].getClass().equals(type)) {
+ return i;
+ }
+ }
+ return -1;
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * <p>Prints a compact stack trace for the root cause of a throwable
+ * to <code>System.err</code>.</p>
+ *
+ * <p>The compact stack trace starts with the root cause and prints
+ * stack frames up to the place where it was caught and wrapped.
+ * Then it prints the wrapped exception and continues with stack frames
+ * until the wrapper exception is caught and wrapped again, etc.</p>
+ *
+ * <p>The method is equivalent to <code>printStackTrace</code> for throwables
+ * that don't have nested causes.</p>
+ *
+ * @param throwable the throwable to output
+ * @since 2.0
+ */
+ public static void printRootCauseStackTrace(Throwable throwable) {
+ printRootCauseStackTrace(throwable, System.err);
+ }
+
+ /**
+ * <p>Prints a compact stack trace for the root cause of a throwable.</p>
+ *
+ * <p>The compact stack trace starts with the root cause and prints
+ * stack frames up to the place where it was caught and wrapped.
+ * Then it prints the wrapped exception and continues with stack frames
+ * until the wrapper exception is caught and wrapped again, etc.</p>
+ *
+ * <p>The method is equivalent to <code>printStackTrace</code> for throwables
+ * that don't have nested causes.</p>
+ *
+ * @param throwable the throwable to output, may be null
+ * @param stream the stream to output to, may not be null
+ * @throws IllegalArgumentException if the stream is <code>null</code>
+ * @since 2.0
+ */
+ public static void printRootCauseStackTrace(Throwable throwable, PrintStream stream) {
+ if (throwable == null) {
+ return;
+ }
+ if (stream == null) {
+ throw new IllegalArgumentException("The PrintStream must not be null");
+ }
+ String trace[] = getRootCauseStackTrace(throwable);
+ for (int i = 0; i < trace.length; i++) {
+ stream.println(trace[i]);
+ }
+ stream.flush();
+ }
+
+ /**
+ * <p>Prints a compact stack trace for the root cause of a throwable.</p>
+ *
+ * <p>The compact stack trace starts with the root cause and prints
+ * stack frames up to the place where it was caught and wrapped.
+ * Then it prints the wrapped exception and continues with stack frames
+ * until the wrapper exception is caught and wrapped again, etc.</p>
+ *
+ * <p>The method is equivalent to <code>printStackTrace</code> for throwables
+ * that don't have nested causes.</p>
+ *
+ * @param throwable the throwable to output, may be null
+ * @param writer the writer to output to, may not be null
+ * @throws IllegalArgumentException if the writer is <code>null</code>
+ * @since 2.0
+ */
+ public static void printRootCauseStackTrace(Throwable throwable, PrintWriter writer) {
+ if (throwable == null) {
+ return;
+ }
+ if (writer == null) {
+ throw new IllegalArgumentException("The PrintWriter must not be null");
+ }
+ String trace[] = getRootCauseStackTrace(throwable);
+ for (int i = 0; i < trace.length; i++) {
+ writer.println(trace[i]);
+ }
+ writer.flush();
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * <p>Creates a compact stack trace for the root cause of the supplied
+ * <code>Throwable</code>.</p>
+ *
+ * @param throwable the throwable to examine, may be null
+ * @return an array of stack trace frames, never null
+ * @since 2.0
+ */
+ public static String[] getRootCauseStackTrace(Throwable throwable) {
+ if (throwable == null) {
+ return ArrayUtils.EMPTY_STRING_ARRAY;
+ }
+ Throwable throwables[] = getThrowables(throwable);
+ int count = throwables.length;
+ ArrayList frames = new ArrayList();
+ List nextTrace = getStackFrameList(throwables[count - 1]);
+ for (int i = count; --i >= 0;) {
+ List trace = nextTrace;
+ if (i != 0) {
+ nextTrace = getStackFrameList(throwables[i - 1]);
+ removeCommonFrames(trace, nextTrace);
+ }
+ if (i == count - 1) {
+ frames.add(throwables[i].toString());
+ } else {
+ frames.add(WRAPPED_MARKER + throwables[i].toString());
+ }
+ for (int j = 0; j < trace.size(); j++) {
+ frames.add(trace.get(j));
+ }
+ }
+ return (String[]) frames.toArray(new String[0]);
+ }
+
+ /**
+ * <p>Removes common frames from the cause trace given the two stack traces.</p>
+ *
+ * @param causeFrames stack trace of a cause throwable
+ * @param wrapperFrames stack trace of a wrapper throwable
+ * @throws IllegalArgumentException if either argument is null
+ * @since 2.0
+ */
+ public static void removeCommonFrames(List causeFrames, List wrapperFrames) {
+ if (causeFrames == null || wrapperFrames == null) {
+ throw new IllegalArgumentException("The List must not be null");
+ }
+ int causeFrameIndex = causeFrames.size() - 1;
+ int wrapperFrameIndex = wrapperFrames.size() - 1;
+ while (causeFrameIndex >= 0 && wrapperFrameIndex >= 0) {
+ // Remove the frame from the cause trace if it is the same
+ // as in the wrapper trace
+ String causeFrame = (String) causeFrames.get(causeFrameIndex);
+ String wrapperFrame = (String) wrapperFrames.get(wrapperFrameIndex);
+ if (causeFrame.equals(wrapperFrame)) {
+ causeFrames.remove(causeFrameIndex);
+ }
+ causeFrameIndex--;
+ wrapperFrameIndex--;
+ }
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * <p>Gets the stack trace from a Throwable as a String.</p>
+ *
+ * @param throwable the <code>Throwable</code> to be examined
+ * @return the stack trace as generated by the exception's
+ * <code>printStackTrace(PrintWriter)</code> method
+ */
+ public static String getStackTrace(Throwable throwable) {
+ StringWriter sw = new StringWriter();
+ PrintWriter pw = new PrintWriter(sw, true);
+ throwable.printStackTrace(pw);
+ return sw.getBuffer().toString();
+ }
+
+ /**
+ * <p>A way to get the entire nested stack-trace of an throwable.</p>
+ *
+ * @param throwable the <code>Throwable</code> to be examined
+ * @return the nested stack trace, with the root cause first
+ * @since 2.0
+ */
+ public static String getFullStackTrace(Throwable throwable) {
+ StringWriter sw = new StringWriter();
+ PrintWriter pw = new PrintWriter(sw, true);
+ Throwable[] ts = getThrowables(throwable);
+ for (int i = 0; i < ts.length; i++) {
+ ts[i].printStackTrace(pw);
+ if (isNestedThrowable(ts[i])) {
+ break;
+ }
+ }
+ return sw.getBuffer().toString();
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * <p>Captures the stack trace associated with the specified
+ * <code>Throwable</code> object, decomposing it into a list of
+ * stack frames.</p>
+ *
+ * @param throwable the <code>Throwable</code> to examine, may be null
+ * @return an array of strings describing each stack frame, never null
+ */
+ public static String[] getStackFrames(Throwable throwable) {
+ if (throwable == null) {
+ return ArrayUtils.EMPTY_STRING_ARRAY;
+ }
+ return getStackFrames(getStackTrace(throwable));
+ }
+
+ /**
+ * <p>Functionality shared between the
+ * <code>getStackFrames(Throwable)</code> methods of this and the
+ */
+ static String[] getStackFrames(String stackTrace) {
+ String linebreak = SystemUtils.LINE_SEPARATOR;
+ StringTokenizer frames = new StringTokenizer(stackTrace, linebreak);
+ List list = new LinkedList();
+ while (frames.hasMoreTokens()) {
+ list.add(frames.nextToken());
+ }
+ return (String[]) list.toArray(new String[list.size()]);
+ }
+
+ /**
+ * <p>Produces a <code>List</code> of stack frames - the message
+ * is not included.</p>
+ *
+ * <p>This works in most cases - it will only fail if the exception
+ * message contains a line that starts with:
+ * <code>" at".</code></p>
+ *
+ * @param t is any throwable
+ * @return List of stack frames
+ */
+ static List getStackFrameList(Throwable t) {
+ String stackTrace = getStackTrace(t);
+ String linebreak = SystemUtils.LINE_SEPARATOR;
+ StringTokenizer frames = new StringTokenizer(stackTrace, linebreak);
+ List list = new LinkedList();
+ boolean traceStarted = false;
+ while (frames.hasMoreTokens()) {
+ String token = frames.nextToken();
+ // Determine if the line starts with <whitespace>at
+ int at = token.indexOf("at");
+ if (at != -1 && token.substring(0, at).trim().length() == 0) {
+ traceStarted = true;
+ list.add(token);
+ } else if (traceStarted) {
+ break;
+ }
+ }
+ return list;
+ }
+
+}
Added: incubator/directory/ldap/trunk/common/src/java/org/apache/ldap/common/util/HashCodeBuilder.java
==============================================================================
--- (empty file)
+++ incubator/directory/ldap/trunk/common/src/java/org/apache/ldap/common/util/HashCodeBuilder.java Sat Sep 25 12:11:47 2004
@@ -0,0 +1,636 @@
+/*
+ * Copyright 2002-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.ldap.common.util;
+
+import java.lang.reflect.AccessibleObject;
+import java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
+
+/**
+ * <p>Assists in implementing {@link Object#hashCode()} methods.</p>
+ *
+ * <p> This class enables a good <code>hashCode</code> method to be built for any class. It
+ * follows the rules laid out in the book
+ * <a href="http://java.sun.com/docs/books/effective/index.html">Effective Java</a>
+ * by Joshua Bloch. Writing a good <code>hashCode</code> method is actually quite
+ * difficult. This class aims to simplify the process.</p>
+ *
+ * <p>All relevant fields from the object should be included in the
+ * <code>hashCode</code> method. Derived fields may be excluded. In general, any
+ * field used in the <code>equals</code> method must be used in the <code>hashCode</code>
+ * method.</p>
+ *
+ * <p>To use this class write code as follows:</p>
+ * <pre>
+ * public class Person {
+ * String name;
+ * int age;
+ * boolean isSmoker;
+ * ...
+ *
+ * public int hashCode() {
+ * // you pick a hard-coded, randomly chosen, non-zero, odd number
+ * // ideally different for each class
+ * return new HashCodeBuilder(17, 37).
+ * append(name).
+ * append(age).
+ * append(smoker).
+ * toHashCode();
+ * }
+ * }
+ * </pre>
+ *
+ * <p>If required, the superclass <code>hashCode()</code> can be added
+ * using {@link #appendSuper}.</p>
+ *
+ * <p>Alternatively, there is a method that uses reflection to determine
+ * the fields to test. Because these fields are usually private, the method,
+ * <code>reflectionHashCode</code>, uses <code>AccessibleObject.setAccessible</code> to
+ * change the visibility of the fields. This will fail under a security manager,
+ * unless the appropriate permissions are set up correctly. It is also slower
+ * than testing explicitly.</p>
+ *
+ * <p>A typical invocation for this method would look like:</p>
+ * <pre>
+ * public int hashCode() {
+ * return HashCodeBuilder.reflectionHashCode(this);
+ * }
+ * </pre>
+ *
+ * @author Stephen Colebourne
+ * @author Gary Gregory
+ * @author Pete Gieser
+ * @since 1.0
+ * @version $Id: HashCodeBuilder.java,v 1.22 2004/08/15 02:17:13 bayard Exp $
+ */
+public class HashCodeBuilder {
+
+ /**
+ * Constant to use in building the hashCode.
+ */
+ private final int iConstant;
+ /**
+ * Running total of the hashCode.
+ */
+ private int iTotal = 0;
+
+ /**
+ * <p>Constructor.</p>
+ *
+ * <p>This constructor uses two hard coded choices for the constants
+ * needed to build a <code>hashCode</code>.</p>
+ */
+ public HashCodeBuilder() {
+ super();
+ iConstant = 37;
+ iTotal = 17;
+ }
+
+ /**
+ * <p>Constructor.</p>
+ *
+ * <p>Two randomly chosen, non-zero, odd numbers must be passed in.
+ * Ideally these should be different for each class, however this is
+ * not vital.</p>
+ *
+ * <p>Prime numbers are preferred, especially for the multiplier.</p>
+ *
+ * @param initialNonZeroOddNumber a non-zero, odd number used as the initial value
+ * @param multiplierNonZeroOddNumber a non-zero, odd number used as the multiplier
+ * @throws IllegalArgumentException if the number is zero or even
+ */
+ public HashCodeBuilder(int initialNonZeroOddNumber, int multiplierNonZeroOddNumber) {
+ super();
+ if (initialNonZeroOddNumber == 0) {
+ throw new IllegalArgumentException("HashCodeBuilder requires a non zero initial value");
+ }
+ if (initialNonZeroOddNumber % 2 == 0) {
+ throw new IllegalArgumentException("HashCodeBuilder requires an odd initial value");
+ }
+ if (multiplierNonZeroOddNumber == 0) {
+ throw new IllegalArgumentException("HashCodeBuilder requires a non zero multiplier");
+ }
+ if (multiplierNonZeroOddNumber % 2 == 0) {
+ throw new IllegalArgumentException("HashCodeBuilder requires an odd multiplier");
+ }
+ iConstant = multiplierNonZeroOddNumber;
+ iTotal = initialNonZeroOddNumber;
+ }
+
+ //-------------------------------------------------------------------------
+
+ /**
+ * <p>This method uses reflection to build a valid hash code.</p>
+ *
+ * <p>This constructor uses two hard coded choices for the constants
+ * needed to build a hash code.</p>
+ *
+ * <p>It uses <code>AccessibleObject.setAccessible</code> to gain access to private
+ * fields. This means that it will throw a security exception if run under
+ * a security manager, if the permissions are not set up correctly. It is
+ * also not as efficient as testing explicitly.</p>
+ *
+ * <p>Transient members will be not be used, as they are likely derived
+ * fields, and not part of the value of the <code>Object</code>.</p>
+ *
+ * <p>Static fields will not be tested. Superclass fields will be included.</p>
+ *
+ * @param object the Object to create a <code>hashCode</code> for
+ * @return int hash code
+ * @throws IllegalArgumentException if the object is <code>null</code>
+ */
+ public static int reflectionHashCode(Object object) {
+ return reflectionHashCode(17, 37, object, false, null);
+ }
+
+ /**
+ * <p>This method uses reflection to build a valid hash code.</p>
+ *
+ * <p>This constructor uses two hard coded choices for the constants needed
+ * to build a hash code.</p>
+ *
+ * <p> It uses <code>AccessibleObject.setAccessible</code> to gain access to private
+ * fields. This means that it will throw a security exception if run under
+ * a security manager, if the permissions are not set up correctly. It is
+ * also not as efficient as testing explicitly.</p>
+ *
+ * <P>If the TestTransients parameter is set to <code>true</code>, transient
+ * members will be tested, otherwise they are ignored, as they are likely
+ * derived fields, and not part of the value of the <code>Object</code>.</p>
+ *
+ * <p>Static fields will not be tested. Superclass fields will be included.</p>
+ *
+ * @param object the Object to create a <code>hashCode</code> for
+ * @param testTransients whether to include transient fields
+ * @return int hash code
+ * @throws IllegalArgumentException if the object is <code>null</code>
+ */
+ public static int reflectionHashCode(Object object, boolean testTransients) {
+ return reflectionHashCode(17, 37, object, testTransients, null);
+ }
+
+ /**
+ * <p>This method uses reflection to build a valid hash code.</p>
+ *
+ * <p>It uses <code>AccessibleObject.setAccessible</code> to gain access to private
+ * fields. This means that it will throw a security exception if run under
+ * a security manager, if the permissions are not set up correctly. It is
+ * also not as efficient as testing explicitly.</p>
+ *
+ * <p>Transient members will be not be used, as they are likely derived
+ * fields, and not part of the value of the <code>Object</code>.</p>
+ *
+ * <p>Static fields will not be tested. Superclass fields will be included.</p>
+ *
+ * <p>Two randomly chosen, non-zero, odd numbers must be passed in. Ideally
+ * these should be different for each class, however this is not vital.
+ * Prime numbers are preferred, especially for the multiplier.</p>
+ *
+ * @param initialNonZeroOddNumber a non-zero, odd number used as the initial value
+ * @param multiplierNonZeroOddNumber a non-zero, odd number used as the multiplier
+ * @param object the Object to create a <code>hashCode</code> for
+ * @return int hash code
+ * @throws IllegalArgumentException if the Object is <code>null</code>
+ * @throws IllegalArgumentException if the number is zero or even
+ */
+ public static int reflectionHashCode(
+ int initialNonZeroOddNumber, int multiplierNonZeroOddNumber, Object object) {
+ return reflectionHashCode(initialNonZeroOddNumber, multiplierNonZeroOddNumber, object, false, null);
+ }
+
+ /**
+ * <p>This method uses reflection to build a valid hash code.</p>
+ *
+ * <p>It uses <code>AccessibleObject.setAccessible</code> to gain access to private
+ * fields. This means that it will throw a security exception if run under
+ * a security manager, if the permissions are not set up correctly. It is also
+ * not as efficient as testing explicitly.</p>
+ *
+ * <p>If the TestTransients parameter is set to <code>true</code>, transient
+ * members will be tested, otherwise they are ignored, as they are likely
+ * derived fields, and not part of the value of the <code>Object</code>.</p>
+ *
+ * <p>Static fields will not be tested. Superclass fields will be included.</p>
+ *
+ * <p>Two randomly chosen, non-zero, odd numbers must be passed in. Ideally
+ * these should be different for each class, however this is not vital.
+ * Prime numbers are preferred, especially for the multiplier.</p>
+ *
+ * @param initialNonZeroOddNumber a non-zero, odd number used as the initial value
+ * @param multiplierNonZeroOddNumber a non-zero, odd number used as the multiplier
+ * @param object the Object to create a <code>hashCode</code> for
+ * @param testTransients whether to include transient fields
+ * @return int hash code
+ * @throws IllegalArgumentException if the Object is <code>null</code>
+ * @throws IllegalArgumentException if the number is zero or even
+ */
+ public static int reflectionHashCode(
+ int initialNonZeroOddNumber, int multiplierNonZeroOddNumber,
+ Object object, boolean testTransients) {
+ return reflectionHashCode(initialNonZeroOddNumber, multiplierNonZeroOddNumber, object, testTransients, null);
+ }
+
+ /**
+ * <p>This method uses reflection to build a valid hash code.</p>
+ *
+ * <p>It uses <code>AccessibleObject.setAccessible</code> to gain access to private
+ * fields. This means that it will throw a security exception if run under
+ * a security manager, if the permissions are not set up correctly. It is also
+ * not as efficient as testing explicitly.</p>
+ *
+ * <p>If the TestTransients parameter is set to <code>true</code>, transient
+ * members will be tested, otherwise they are ignored, as they are likely
+ * derived fields, and not part of the value of the <code>Object</code>.</p>
+ *
+ * <p>Static fields will not be included. Superclass fields will be included
+ * up to and including the specified superclass. A null superclass is treated
+ * as java.lang.Object.</p>
+ *
+ * <p>Two randomly chosen, non-zero, odd numbers must be passed in. Ideally
+ * these should be different for each class, however this is not vital.
+ * Prime numbers are preferred, especially for the multiplier.</p>
+ *
+ * @param initialNonZeroOddNumber a non-zero, odd number used as the initial value
+ * @param multiplierNonZeroOddNumber a non-zero, odd number used as the multiplier
+ * @param object the Object to create a <code>hashCode</code> for
+ * @param testTransients whether to include transient fields
+ * @param reflectUpToClass the superclass to reflect up to (inclusive),
+ * may be <code>null</code>
+ * @return int hash code
+ * @throws IllegalArgumentException if the Object is <code>null</code>
+ * @throws IllegalArgumentException if the number is zero or even
+ * @since 2.0
+ */
+ public static int reflectionHashCode(
+ int initialNonZeroOddNumber,
+ int multiplierNonZeroOddNumber,
+ Object object,
+ boolean testTransients,
+ Class reflectUpToClass) {
+
+ if (object == null) {
+ throw new IllegalArgumentException("The object to build a hash code for must not be null");
+ }
+ HashCodeBuilder builder = new HashCodeBuilder(initialNonZeroOddNumber, multiplierNonZeroOddNumber);
+ Class clazz = object.getClass();
+ reflectionAppend(object, clazz, builder, testTransients);
+ while (clazz.getSuperclass() != null && clazz != reflectUpToClass) {
+ clazz = clazz.getSuperclass();
+ reflectionAppend(object, clazz, builder, testTransients);
+ }
+ return builder.toHashCode();
+ }
+
+ /**
+ * <p>Appends the fields and values defined by the given object of the
+ * given <code>Class</code>.</p>
+ *
+ * @param object the object to append details of
+ * @param clazz the class to append details of
+ * @param builder the builder to append to
+ * @param useTransients whether to use transient fields
+ */
+ private static void reflectionAppend(Object object, Class clazz, HashCodeBuilder builder, boolean useTransients) {
+ Field[] fields = clazz.getDeclaredFields();
+ AccessibleObject.setAccessible(fields, true);
+ for (int i = 0; i < fields.length; i++) {
+ Field f = fields[i];
+ if ((f.getName().indexOf('$') == -1)
+ && (useTransients || !Modifier.isTransient(f.getModifiers()))
+ && (!Modifier.isStatic(f.getModifiers()))) {
+ try {
+ builder.append(f.get(object));
+ } catch (IllegalAccessException e) {
+ //this can't happen. Would get a Security exception instead
+ //throw a runtime exception in case the impossible happens.
+ throw new InternalError("Unexpected IllegalAccessException");
+ }
+ }
+ }
+ }
+
+ //-------------------------------------------------------------------------
+
+ /**
+ * <p>Adds the result of super.hashCode() to this builder.</p>
+ *
+ * @param superHashCode the result of calling <code>super.hashCode()</code>
+ * @return this HashCodeBuilder, used to chain calls.
+ * @since 2.0
+ */
+ public HashCodeBuilder appendSuper(int superHashCode) {
+ iTotal = iTotal * iConstant + superHashCode;
+ return this;
+ }
+
+ //-------------------------------------------------------------------------
+
+ /**
+ * <p>Append a <code>hashCode</code> for an <code>Object</code>.</p>
+ *
+ * @param object the Object to add to the <code>hashCode</code>
+ * @return this
+ */
+ public HashCodeBuilder append(Object object) {
+ if (object == null) {
+ iTotal = iTotal * iConstant;
+
+ } else {
+ if (object.getClass().isArray() == false) {
+ //the simple case, not an array, just the element
+ iTotal = iTotal * iConstant + object.hashCode();
+
+ } else {
+ //'Switch' on type of array, to dispatch to the correct handler
+ // This handles multi dimensional arrays
+ if (object instanceof long[]) {
+ append((long[]) object);
+ } else if (object instanceof int[]) {
+ append((int[]) object);
+ } else if (object instanceof short[]) {
+ append((short[]) object);
+ } else if (object instanceof char[]) {
+ append((char[]) object);
+ } else if (object instanceof byte[]) {
+ append((byte[]) object);
+ } else if (object instanceof double[]) {
+ append((double[]) object);
+ } else if (object instanceof float[]) {
+ append((float[]) object);
+ } else if (object instanceof boolean[]) {
+ append((boolean[]) object);
+ } else {
+ // Not an array of primitives
+ append((Object[]) object);
+ }
+ }
+ }
+ return this;
+ }
+
+ /**
+ * <p>Append a <code>hashCode</code> for a <code>long</code>.</p>
+ *
+ * @param value the long to add to the <code>hashCode</code>
+ * @return this
+ */
+ public HashCodeBuilder append(long value) {
+ iTotal = iTotal * iConstant + ((int) (value ^ (value >> 32)));
+ return this;
+ }
+
+ /**
+ * <p>Append a <code>hashCode</code> for an <code>int</code>.</p>
+ *
+ * @param value the int to add to the <code>hashCode</code>
+ * @return this
+ */
+ public HashCodeBuilder append(int value) {
+ iTotal = iTotal * iConstant + value;
+ return this;
+ }
+
+ /**
+ * <p>Append a <code>hashCode</code> for a <code>short</code>.</p>
+ *
+ * @param value the short to add to the <code>hashCode</code>
+ * @return this
+ */
+ public HashCodeBuilder append(short value) {
+ iTotal = iTotal * iConstant + value;
+ return this;
+ }
+
+ /**
+ * <p>Append a <code>hashCode</code> for a <code>char</code>.</p>
+ *
+ * @param value the char to add to the <code>hashCode</code>
+ * @return this
+ */
+ public HashCodeBuilder append(char value) {
+ iTotal = iTotal * iConstant + value;
+ return this;
+ }
+
+ /**
+ * <p>Append a <code>hashCode</code> for a <code>byte</code>.</p>
+ *
+ * @param value the byte to add to the <code>hashCode</code>
+ * @return this
+ */
+ public HashCodeBuilder append(byte value) {
+ iTotal = iTotal * iConstant + value;
+ return this;
+ }
+
+ /**
+ * <p>Append a <code>hashCode</code> for a <code>double</code>.</p>
+ *
+ * @param value the double to add to the <code>hashCode</code>
+ * @return this
+ */
+ public HashCodeBuilder append(double value) {
+ return append(Double.doubleToLongBits(value));
+ }
+
+ /**
+ * <p>Append a <code>hashCode</code> for a <code>float</code>.</p>
+ *
+ * @param value the float to add to the <code>hashCode</code>
+ * @return this
+ */
+ public HashCodeBuilder append(float value) {
+ iTotal = iTotal * iConstant + Float.floatToIntBits(value);
+ return this;
+ }
+
+ /**
+ * <p>Append a <code>hashCode</code> for a <code>boolean</code>.</p>
+ * <p>This adds <code>iConstant * 1</code> to the <code>hashCode</code>
+ * and not a <code>1231</code> or <code>1237</code> as done in java.lang.Boolean.
+ * This is in accordance with the Effective Java design. </p>
+ *
+ * @param value the boolean to add to the <code>hashCode</code>
+ * @return this
+ */
+ public HashCodeBuilder append(boolean value) {
+ iTotal = iTotal * iConstant + (value ? 0 : 1);
+ return this;
+ }
+
+ /**
+ * <p>Append a <code>hashCode</code> for an <code>Object</code> array.</p>
+ *
+ * @param array the array to add to the <code>hashCode</code>
+ * @return this
+ */
+ public HashCodeBuilder append(Object[] array) {
+ if (array == null) {
+ iTotal = iTotal * iConstant;
+ } else {
+ for (int i = 0; i < array.length; i++) {
+ append(array[i]);
+ }
+ }
+ return this;
+ }
+
+ /**
+ * <p>Append a <code>hashCode</code> for a <code>long</code> array.</p>
+ *
+ * @param array the array to add to the <code>hashCode</code>
+ * @return this
+ */
+ public HashCodeBuilder append(long[] array) {
+ if (array == null) {
+ iTotal = iTotal * iConstant;
+ } else {
+ for (int i = 0; i < array.length; i++) {
+ append(array[i]);
+ }
+ }
+ return this;
+ }
+
+ /**
+ * <p>Append a <code>hashCode</code> for an <code>int</code> array.</p>
+ *
+ * @param array the array to add to the <code>hashCode</code>
+ * @return this
+ */
+ public HashCodeBuilder append(int[] array) {
+ if (array == null) {
+ iTotal = iTotal * iConstant;
+ } else {
+ for (int i = 0; i < array.length; i++) {
+ append(array[i]);
+ }
+ }
+ return this;
+ }
+
+ /**
+ * <p>Append a <code>hashCode</code> for a <code>short</code> array.</p>
+ *
+ * @param array the array to add to the <code>hashCode</code>
+ * @return this
+ */
+ public HashCodeBuilder append(short[] array) {
+ if (array == null) {
+ iTotal = iTotal * iConstant;
+ } else {
+ for (int i = 0; i < array.length; i++) {
+ append(array[i]);
+ }
+ }
+ return this;
+ }
+
+ /**
+ * <p>Append a <code>hashCode</code> for a <code>char</code> array.</p>
+ *
+ * @param array the array to add to the <code>hashCode</code>
+ * @return this
+ */
+ public HashCodeBuilder append(char[] array) {
+ if (array == null) {
+ iTotal = iTotal * iConstant;
+ } else {
+ for (int i = 0; i < array.length; i++) {
+ append(array[i]);
+ }
+ }
+ return this;
+ }
+
+ /**
+ * <p>Append a <code>hashCode</code> for a <code>byte</code> array.</p>
+ *
+ * @param array the array to add to the <code>hashCode</code>
+ * @return this
+ */
+ public HashCodeBuilder append(byte[] array) {
+ if (array == null) {
+ iTotal = iTotal * iConstant;
+ } else {
+ for (int i = 0; i < array.length; i++) {
+ append(array[i]);
+ }
+ }
+ return this;
+ }
+
+ /**
+ * <p>Append a <code>hashCode</code> for a <code>double</code> array.</p>
+ *
+ * @param array the array to add to the <code>hashCode</code>
+ * @return this
+ */
+ public HashCodeBuilder append(double[] array) {
+ if (array == null) {
+ iTotal = iTotal * iConstant;
+ } else {
+ for (int i = 0; i < array.length; i++) {
+ append(array[i]);
+ }
+ }
+ return this;
+ }
+
+ /**
+ * <p>Append a <code>hashCode</code> for a <code>float</code> array.</p>
+ *
+ * @param array the array to add to the <code>hashCode</code>
+ * @return this
+ */
+ public HashCodeBuilder append(float[] array) {
+ if (array == null) {
+ iTotal = iTotal * iConstant;
+ } else {
+ for (int i = 0; i < array.length; i++) {
+ append(array[i]);
+ }
+ }
+ return this;
+ }
+
+ /**
+ * <p>Append a <code>hashCode</code> for a <code>boolean</code> array.</p>
+ *
+ * @param array the array to add to the <code>hashCode</code>
+ * @return this
+ */
+ public HashCodeBuilder append(boolean[] array) {
+ if (array == null) {
+ iTotal = iTotal * iConstant;
+ } else {
+ for (int i = 0; i < array.length; i++) {
+ append(array[i]);
+ }
+ }
+ return this;
+ }
+
+ /**
+ * <p>Return the computed <code>hashCode</code>.</p>
+ *
+ * @return <code>hashCode</code> based on the fields appended
+ */
+ public int toHashCode() {
+ return iTotal;
+ }
+
+}
Added: incubator/directory/ldap/trunk/common/src/java/org/apache/ldap/common/util/MultiMap.java
==============================================================================
--- (empty file)
+++ incubator/directory/ldap/trunk/common/src/java/org/apache/ldap/common/util/MultiMap.java Sat Sep 25 12:11:47 2004
@@ -0,0 +1,159 @@
+/*
+ * Copyright 2001-2004 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.ldap.common.util;
+
+import java.util.Collection;
+import java.util.Map;
+
+/**
+ * Defines a map that holds a collection of values against each key.
+ * <p>
+ * A <code>MultiMap</code> is a Map with slightly different semantics.
+ * Putting a value into the map will add the value to a Collection at that key.
+ * Getting a value will return a Collection, holding all the values put to that key.
+ * <p>
+ * For example:
+ * <pre>
+ * MultiMap mhm = new MultiHashMap();
+ * mhm.put(key, "A");
+ * mhm.put(key, "B");
+ * mhm.put(key, "C");
+ * Collection coll = (Collection) mhm.get(key);</pre>
+ * <p>
+ * <code>coll</code> will be a collection containing "A", "B", "C".
+ * <p>
+ * NOTE: Additional methods were added to this interface in Commons Collections 3.1.
+ * These were added solely for documentation purposes and do not change the interface
+ * as they were defined in the superinterface <code>Map</code> anyway.
+ *
+ * @since Commons Collections 2.0
+ * @version $Revision: 1.12 $ $Date: 2004/03/14 15:33:57 $
+ *
+ * @author Christopher Berry
+ * @author James Strachan
+ * @author Stephen Colebourne
+ */
+public interface MultiMap extends Map {
+
+ /**
+ * Removes a specific value from map.
+ * <p>
+ * The item is removed from the collection mapped to the specified key.
+ * Other values attached to that key are unaffected.
+ * <p>
+ * If the last value for a key is removed, implementations typically
+ * return <code>null</code> from a subsequant <code>get(Object)</code>, however
+ * they may choose to return an empty collection.
+ *
+ * @param key the key to remove from
+ * @param item the item to remove
+ * @return the value removed (which was passed in), null if nothing removed
+ * @throws UnsupportedOperationException if the map is unmodifiable
+ * @throws ClassCastException if the key or value is of an invalid type
+ * @throws NullPointerException if the key or value is null and null is invalid
+ */
+ public Object remove(Object key, Object item);
+
+ //-----------------------------------------------------------------------
+ /**
+ * Gets the number of keys in this map.
+ * <p>
+ * Implementations typically return only the count of keys in the map
+ * This cannot be mandated due to backwards compatability of this interface.
+ *
+ * @return the number of key-collection mappings in this map
+ */
+ int size();
+
+ /**
+ * Gets the collection of values associated with the specified key.
+ * <p>
+ * The returned value will implement <code>Collection</code>. Implementations
+ * are free to declare that they return <code>Collection</code> subclasses
+ * such as <code>List</code> or <code>Set</code>.
+ * <p>
+ * Implementations typically return <code>null</code> if no values have
+ * been mapped to the key, however the implementation may choose to
+ * return an empty collection.
+ * <p>
+ * Implementations may choose to return a clone of the internal collection.
+ *
+ * @param key the key to retrieve
+ * @return the <code>Collection</code> of values, implementations should
+ * return <code>null</code> for no mapping, but may return an empty collection
+ * @throws ClassCastException if the key is of an invalid type
+ * @throws NullPointerException if the key is null and null keys are invalid
+ */
+ Object get(Object key);
+
+ /**
+ * Checks whether the map contains the value specified.
+ * <p>
+ * Implementations typically check all collections against all keys for the value.
+ * This cannot be mandated due to backwards compatability of this interface.
+ *
+ * @param value the value to search for
+ * @return true if the map contains the value
+ * @throws ClassCastException if the value is of an invalid type
+ * @throws NullPointerException if the value is null and null value are invalid
+ */
+ boolean containsValue(Object value);
+
+ /**
+ * Adds the value to the collection associated with the specified key.
+ * <p>
+ * Unlike a normal <code>Map</code> the previous value is not replaced.
+ * Instead the new value is added to the collection stored against the key.
+ * The collection may be a <code>List</code>, <code>Set</code> or other
+ * collection dependent on implementation.
+ *
+ * @param key the key to store against
+ * @param value the value to add to the collection at the key
+ * @return typically the value added if the map changed and null if the map did not change
+ * @throws UnsupportedOperationException if the map is unmodifiable
+ * @throws ClassCastException if the key or value is of an invalid type
+ * @throws NullPointerException if the key or value is null and null is invalid
+ * @throws IllegalArgumentException if the key or value is invalid
+ */
+ Object put(Object key, Object value);
+
+ /**
+ * Removes all values associated with the specified key.
+ * <p>
+ * Implementations typically return <code>null</code> from a subsequant
+ * <code>get(Object)</code>, however they may choose to return an empty collection.
+ *
+ * @param key the key to remove values from
+ * @return the <code>Collection</code> of values removed, implementations should
+ * return <code>null</code> for no mapping found, but may return an empty collection
+ * @throws UnsupportedOperationException if the map is unmodifiable
+ * @throws ClassCastException if the key is of an invalid type
+ * @throws NullPointerException if the key is null and null keys are invalid
+ */
+ Object remove(Object key);
+
+ /**
+ * Gets a collection containing all the values in the map.
+ * <p>
+ * Inplementations typically return a collection containing the combination
+ * of values from all keys.
+ * This cannot be mandated due to backwards compatability of this interface.
+ *
+ * @return a collection view of the values contained in this map
+ */
+ Collection values();
+
+}
Added: incubator/directory/ldap/trunk/common/src/java/org/apache/ldap/common/util/Nestable.java
==============================================================================
--- (empty file)
+++ incubator/directory/ldap/trunk/common/src/java/org/apache/ldap/common/util/Nestable.java Sat Sep 25 12:11:47 2004
@@ -0,0 +1,165 @@
+/*
+ * Copyright 2002-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.ldap.common.util;
+
+import java.io.PrintStream;
+import java.io.PrintWriter;
+
+/**
+ * An interface to be implemented by {@link java.lang.Throwable}
+ * extensions which would like to be able to nest root exceptions
+ * inside themselves.
+ *
+ * @author <a href="mailto:dlr@collab.net">Daniel Rall</a>
+ * @author <a href="mailto:knielsen@apache.org">Kasper Nielsen</a>
+ * @author <a href="mailto:steven@caswell.name">Steven Caswell</a>
+ * @author Pete Gieser
+ * @since 1.0
+ * @version $Id: Nestable.java,v 1.11 2004/02/18 22:54:04 ggregory Exp $
+ */
+public interface Nestable {
+
+ /**
+ * Returns the reference to the exception or error that caused the
+ * exception implementing the <code>Nestable</code> to be thrown.
+ *
+ * @return throwable that caused the original exception
+ */
+ public Throwable getCause();
+
+ /**
+ * Returns the error message of this and any nested
+ * <code>Throwable</code>.
+ *
+ * @return the error message
+ */
+ public String getMessage();
+
+ /**
+ * Returns the error message of the <code>Throwable</code> in the chain
+ * of <code>Throwable</code>s at the specified index, numbered from 0.
+ *
+ * @param index the index of the <code>Throwable</code> in the chain of
+ * <code>Throwable</code>s
+ * @return the error message, or null if the <code>Throwable</code> at the
+ * specified index in the chain does not contain a message
+ * @throws IndexOutOfBoundsException if the <code>index</code> argument is
+ * negative or not less than the count of <code>Throwable</code>s in the
+ * chain
+ */
+ public String getMessage(int index);
+
+ /**
+ * Returns the error message of this and any nested <code>Throwable</code>s
+ * in an array of Strings, one element for each message. Any
+ * <code>Throwable</code> not containing a message is represented in the
+ * array by a null. This has the effect of cause the length of the returned
+ * array to be equal to the result of the {@link #getThrowableCount()}
+ * operation.
+ *
+ * @return the error messages
+ */
+ public String[] getMessages();
+
+ /**
+ * Returns the <code>Throwable</code> in the chain of
+ * <code>Throwable</code>s at the specified index, numbered from 0.
+ *
+ * @param index the index, numbered from 0, of the <code>Throwable</code> in
+ * the chain of <code>Throwable</code>s
+ * @return the <code>Throwable</code>
+ * @throws IndexOutOfBoundsException if the <code>index</code> argument is
+ * negative or not less than the count of <code>Throwable</code>s in the
+ * chain
+ */
+ public Throwable getThrowable(int index);
+
+ /**
+ * Returns the number of nested <code>Throwable</code>s represented by
+ * this <code>Nestable</code>, including this <code>Nestable</code>.
+ *
+ * @return the throwable count
+ */
+ public int getThrowableCount();
+
+ /**
+ * Returns this <code>Nestable</code> and any nested <code>Throwable</code>s
+ * in an array of <code>Throwable</code>s, one element for each
+ * <code>Throwable</code>.
+ *
+ * @return the <code>Throwable</code>s
+ */
+ public Throwable[] getThrowables();
+
+ /**
+ * Returns the index, numbered from 0, of the first occurrence of the
+ * specified type in the chain of <code>Throwable</code>s, or -1 if the
+ * specified type is not found in the chain.
+ *
+ * @param type <code>Class</code> to be found
+ * @return index of the first occurrence of the type in the chain, or -1 if
+ * the type is not found
+ */
+ public int indexOfThrowable(Class type);
+
+ /**
+ * Returns the index, numbered from 0, of the first <code>Throwable</code>
+ * that matches the specified type in the chain of <code>Throwable</code>s
+ * with an index greater than or equal to the specified index, or -1 if
+ * the type is not found.
+ *
+ * @param type <code>Class</code> to be found
+ * @param fromIndex the index, numbered from 0, of the starting position in
+ * the chain to be searched
+ * @return index of the first occurrence of the type in the chain, or -1 if
+ * the type is not found
+ * @throws IndexOutOfBoundsException if the <code>fromIndex</code> argument
+ * is negative or not less than the count of <code>Throwable</code>s in the
+ * chain
+ */
+ public int indexOfThrowable(Class type, int fromIndex);
+
+ /**
+ * Prints the stack trace of this exception to the specified print
+ * writer. Includes information from the exception, if any,
+ * which caused this exception.
+ *
+ * @param out <code>PrintWriter</code> to use for output.
+ */
+ public void printStackTrace(PrintWriter out);
+
+ /**
+ * Prints the stack trace of this exception to the specified print
+ * stream. Includes information from the exception, if any,
+ * which caused this exception.
+ *
+ * @param out <code>PrintStream</code> to use for output.
+ */
+ public void printStackTrace(PrintStream out);
+
+ /**
+ * Prints the stack trace for this exception only--root cause not
+ * included--using the provided writer. Used by {@link
+ * org.apache.commons.lang.exception.NestableDelegate} to write
+ * individual stack traces to a buffer. The implementation of
+ * this method should call
+ * <code>super.printStackTrace(out);</code> in most cases.
+ *
+ * @param out The writer to use.
+ */
+ public void printPartialStackTrace(PrintWriter out);
+
+}
Added: incubator/directory/ldap/trunk/common/src/java/org/apache/ldap/common/util/NestableDelegate.java
==============================================================================
--- (empty file)
+++ incubator/directory/ldap/trunk/common/src/java/org/apache/ldap/common/util/NestableDelegate.java Sat Sep 25 12:11:47 2004
@@ -0,0 +1,372 @@
+/*
+ * Copyright 2002-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.ldap.common.util;
+
+import java.io.PrintStream;
+import java.io.PrintWriter;
+import java.io.Serializable;
+import java.io.StringWriter;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+
+/**
+ * <p>A shared implementation of the nestable exception functionality.</p>
+ * <p>
+ * The code is shared between
+ * </p>
+ *
+ * @author <a href="mailto:Rafal.Krzewski@e-point.pl">Rafal Krzewski</a>
+ * @author <a href="mailto:dlr@collab.net">Daniel Rall</a>
+ * @author <a href="mailto:knielsen@apache.org">Kasper Nielsen</a>
+ * @author <a href="mailto:steven@caswell.name">Steven Caswell</a>
+ * @author Sean C. Sullivan
+ * @author Stephen Colebourne
+ * @since 1.0
+ * @version $Id: NestableDelegate.java,v 1.23 2004/02/18 22:54:04 ggregory Exp $
+ */
+public class NestableDelegate implements Serializable {
+
+ /**
+ * Constructor error message.
+ */
+ private transient static final String MUST_BE_THROWABLE =
+ "The Nestable implementation passed to the NestableDelegate(Nestable) "
+ + "constructor must extend java.lang.Throwable";
+
+ /**
+ * Holds the reference to the exception or error that we're
+ * wrapping (which must be a {@link
+ * org.apache.commons.lang.exception.Nestable} implementation).
+ */
+ private Throwable nestable = null;
+
+ /**
+ * Whether to print the stack trace top-down.
+ * This public flag may be set by calling code, typically in initialisation.
+ * @since 2.0
+ */
+ public static boolean topDown = true;
+
+ /**
+ * Whether to trim the repeated stack trace.
+ * This public flag may be set by calling code, typically in initialisation.
+ * @since 2.0
+ */
+ public static boolean trimStackFrames = true;
+
+ /**
+ * Constructs a new <code>NestableDelegate</code> instance to manage the
+ * specified <code>Nestable</code>.
+ *
+ * @param nestable the Nestable implementation (<i>must</i> extend
+ * {@link java.lang.Throwable})
+ * @since 2.0
+ */
+ public NestableDelegate(Nestable nestable) {
+ if (nestable instanceof Throwable) {
+ this.nestable = (Throwable) nestable;
+ } else {
+ throw new IllegalArgumentException(MUST_BE_THROWABLE);
+ }
+ }
+
+ /**
+ * Returns the error message of the <code>Throwable</code> in the chain
+ * of <code>Throwable</code>s at the specified index, numbered from 0.
+ *
+ * @param index the index of the <code>Throwable</code> in the chain of
+ * <code>Throwable</code>s
+ * @return the error message, or null if the <code>Throwable</code> at the
+ * specified index in the chain does not contain a message
+ * @throws IndexOutOfBoundsException if the <code>index</code> argument is
+ * negative or not less than the count of <code>Throwable</code>s in the
+ * chain
+ * @since 2.0
+ */
+ public String getMessage(int index) {
+ Throwable t = this.getThrowable(index);
+ if (Nestable.class.isInstance(t)) {
+ return ((Nestable) t).getMessage(0);
+ } else {
+ return t.getMessage();
+ }
+ }
+
+ /**
+ * Returns the full message contained by the <code>Nestable</code>
+ * and any nested <code>Throwable</code>s.
+ *
+ * @param baseMsg the base message to use when creating the full
+ * message. Should be generally be called via
+ * <code>nestableHelper.getMessage(super.getMessage())</code>,
+ * where <code>super</code> is an instance of {@link
+ * java.lang.Throwable}.
+ * @return The concatenated message for this and all nested
+ * <code>Throwable</code>s
+ * @since 2.0
+ */
+ public String getMessage(String baseMsg) {
+ StringBuffer msg = new StringBuffer();
+ if (baseMsg != null) {
+ msg.append(baseMsg);
+ }
+
+ Throwable nestedCause = ExceptionUtils.getCause(this.nestable);
+ if (nestedCause != null) {
+ String causeMsg = nestedCause.getMessage();
+ if (causeMsg != null) {
+ if (baseMsg != null) {
+ msg.append(": ");
+ }
+ msg.append(causeMsg);
+ }
+
+ }
+ return (msg.length() > 0 ? msg.toString() : null);
+ }
+
+ /**
+ * Returns the error message of this and any nested <code>Throwable</code>s
+ * in an array of Strings, one element for each message. Any
+ * <code>Throwable</code> not containing a message is represented in the
+ * array by a null. This has the effect of cause the length of the returned
+ * array to be equal to the result of the {@link #getThrowableCount()}
+ * operation.
+ *
+ * @return the error messages
+ * @since 2.0
+ */
+ public String[] getMessages() {
+ Throwable[] throwables = this.getThrowables();
+ String[] msgs = new String[throwables.length];
+ for (int i = 0; i < throwables.length; i++) {
+ msgs[i] =
+ (Nestable.class.isInstance(throwables[i])
+ ? ((Nestable) throwables[i]).getMessage(0)
+ : throwables[i].getMessage());
+ }
+ return msgs;
+ }
+
+ /**
+ * Returns the <code>Throwable</code> in the chain of
+ * <code>Throwable</code>s at the specified index, numbered from 0.
+ *
+ * @param index the index, numbered from 0, of the <code>Throwable</code> in
+ * the chain of <code>Throwable</code>s
+ * @return the <code>Throwable</code>
+ * @throws IndexOutOfBoundsException if the <code>index</code> argument is
+ * negative or not less than the count of <code>Throwable</code>s in the
+ * chain
+ * @since 2.0
+ */
+ public Throwable getThrowable(int index) {
+ if (index == 0) {
+ return this.nestable;
+ }
+ Throwable[] throwables = this.getThrowables();
+ return throwables[index];
+ }
+
+ /**
+ * Returns the number of <code>Throwable</code>s contained in the
+ * <code>Nestable</code> contained by this delegate.
+ *
+ * @return the throwable count
+ * @since 2.0
+ */
+ public int getThrowableCount() {
+ return ExceptionUtils.getThrowableCount(this.nestable);
+ }
+
+ /**
+ * Returns this delegate's <code>Nestable</code> and any nested
+ * <code>Throwable</code>s in an array of <code>Throwable</code>s, one
+ * element for each <code>Throwable</code>.
+ *
+ * @return the <code>Throwable</code>s
+ * @since 2.0
+ */
+ public Throwable[] getThrowables() {
+ return ExceptionUtils.getThrowables(this.nestable);
+ }
+
+ /**
+ * Returns the index, numbered from 0, of the first <code>Throwable</code>
+ * that matches the specified type in the chain of <code>Throwable</code>s
+ * held in this delegate's <code>Nestable</code> with an index greater than
+ * or equal to the specified index, or -1 if the type is not found.
+ *
+ * @param type <code>Class</code> to be found
+ * @param fromIndex the index, numbered from 0, of the starting position in
+ * the chain to be searched
+ * @return index of the first occurrence of the type in the chain, or -1 if
+ * the type is not found
+ * @throws IndexOutOfBoundsException if the <code>fromIndex</code> argument
+ * is negative or not less than the count of <code>Throwable</code>s in the
+ * chain
+ * @since 2.0
+ */
+ public int indexOfThrowable(Class type, int fromIndex) {
+ if (fromIndex < 0) {
+ throw new IndexOutOfBoundsException("The start index was out of bounds: " + fromIndex);
+ }
+ Throwable[] throwables = ExceptionUtils.getThrowables(this.nestable);
+ if (fromIndex >= throwables.length) {
+ throw new IndexOutOfBoundsException("The start index was out of bounds: "
+ + fromIndex + " >= " + throwables.length);
+ }
+ for (int i = fromIndex; i < throwables.length; i++) {
+ if (throwables[i].getClass().equals(type)) {
+ return i;
+ }
+ }
+ return -1;
+ }
+
+ /**
+ * Prints the stack trace of this exception the the standar error
+ * stream.
+ */
+ public void printStackTrace() {
+ printStackTrace(System.err);
+ }
+
+ /**
+ * Prints the stack trace of this exception to the specified
+ * stream.
+ *
+ * @param out <code>PrintStream</code> to use for output.
+ * @see #printStackTrace(PrintWriter)
+ */
+ public void printStackTrace(PrintStream out) {
+ synchronized (out) {
+ PrintWriter pw = new PrintWriter(out, false);
+ printStackTrace(pw);
+ // Flush the PrintWriter before it's GC'ed.
+ pw.flush();
+ }
+ }
+
+ /**
+ * Prints the stack trace of this exception to the specified
+ * writer. If the Throwable class has a <code>getCause</code>
+ * method (i.e. running on jre1.4 or higher), this method just
+ * uses Throwable's printStackTrace() method. Otherwise, generates
+ * the stack-trace, by taking into account the 'topDown' and
+ * 'trimStackFrames' parameters. The topDown and trimStackFrames
+ * are set to 'true' by default (produces jre1.4-like stack trace).
+ *
+ * @param out <code>PrintWriter</code> to use for output.
+ */
+ public void printStackTrace(PrintWriter out) {
+ Throwable throwable = this.nestable;
+ // if running on jre1.4 or higher, use default printStackTrace
+ if (ExceptionUtils.isThrowableNested()) {
+ if (throwable instanceof Nestable) {
+ ((Nestable)throwable).printPartialStackTrace(out);
+ } else {
+ throwable.printStackTrace(out);
+ }
+ return;
+ }
+
+ // generating the nested stack trace
+ List stacks = new ArrayList();
+ while (throwable != null) {
+ String[] st = getStackFrames(throwable);
+ stacks.add(st);
+ throwable = ExceptionUtils.getCause(throwable);
+ }
+
+ // If NOT topDown, reverse the stack
+ String separatorLine = "Caused by: ";
+ if (!topDown) {
+ separatorLine = "Rethrown as: ";
+ Collections.reverse(stacks);
+ }
+
+ // Remove the repeated lines in the stack
+ if (trimStackFrames) {
+ trimStackFrames(stacks);
+ }
+
+ synchronized (out) {
+ for (Iterator iter=stacks.iterator(); iter.hasNext();) {
+ String[] st = (String[]) iter.next();
+ for (int i=0, len=st.length; i < len; i++) {
+ out.println(st[i]);
+ }
+ if (iter.hasNext()) {
+ out.print(separatorLine);
+ }
+ }
+ }
+ }
+
+ /**
+ * Captures the stack trace associated with the specified
+ * <code>Throwable</code> object, decomposing it into a list of
+ * stack frames.
+ *
+ * @param t The <code>Throwable</code>.
+ * @return An array of strings describing each stack frame.
+ * @since 2.0
+ */
+ protected String[] getStackFrames(Throwable t) {
+ StringWriter sw = new StringWriter();
+ PrintWriter pw = new PrintWriter(sw, true);
+
+ // Avoid infinite loop between decompose() and printStackTrace().
+ if (t instanceof Nestable) {
+ ((Nestable) t).printPartialStackTrace(pw);
+ } else {
+ t.printStackTrace(pw);
+ }
+ return ExceptionUtils.getStackFrames(sw.getBuffer().toString());
+ }
+
+ /**
+ * Trims the stack frames. The first set is left untouched. The rest
+ * of the frames are truncated from the bottom by comparing with
+ * one just on top.
+ *
+ * @param stacks The list containing String[] elements
+ * @since 2.0
+ */
+ protected void trimStackFrames(List stacks) {
+ for (int size=stacks.size(), i=size-1; i > 0; i--) {
+ String[] curr = (String[]) stacks.get(i);
+ String[] next = (String[]) stacks.get(i-1);
+
+ List currList = new ArrayList(Arrays.asList(curr));
+ List nextList = new ArrayList(Arrays.asList(next));
+ ExceptionUtils.removeCommonFrames(currList, nextList);
+
+ int trimmed = curr.length - currList.size();
+ if (trimmed > 0) {
+ currList.add("\t... "+trimmed+" more");
+ stacks.set(
+ i,
+ currList.toArray(new String[currList.size()])
+ );
+ }
+ }
+ }
+}
Added: incubator/directory/ldap/trunk/common/src/java/org/apache/ldap/common/util/NestableError.java
==============================================================================
--- (empty file)
+++ incubator/directory/ldap/trunk/common/src/java/org/apache/ldap/common/util/NestableError.java Sat Sep 25 12:11:47 2004
@@ -0,0 +1,151 @@
+/*
+ * Copyright 2002-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.ldap.common.util;
+
+import java.io.PrintStream;
+import java.io.PrintWriter;
+
+/**
+ * The base class of all errors which can contain other exceptions.
+ *
+ * @author <a href="mailto:dlr@finemaltcoding.com">Daniel Rall</a>
+ * @since 1.0
+ * @version $Id: NestableError.java,v 1.8 2004/02/18 22:54:04 ggregory Exp $
+ */
+public class NestableError extends Error implements Nestable {
+
+ /**
+ * The helper instance which contains much of the code which we
+ * delegate to.
+ */
+ protected NestableDelegate delegate = new NestableDelegate(this);
+
+ /**
+ * Holds the reference to the exception or error that caused
+ * this exception to be thrown.
+ */
+ private Throwable cause = null;
+
+ /**
+ * Constructs a new <code>NestableError</code> without specified
+ * detail message.
+ */
+ public NestableError() {
+ super();
+ }
+
+ /**
+ * Constructs a new <code>NestableError</code> with specified
+ * detail message.
+ *
+ * @param msg The error message.
+ */
+ public NestableError(String msg) {
+ super(msg);
+ }
+
+ /**
+ * Constructs a new <code>NestableError</code> with specified
+ * nested <code>Throwable</code>.
+ *
+ * @param cause the exception or error that caused this exception to be
+ * thrown
+ */
+ public NestableError(Throwable cause) {
+ super();
+ this.cause = cause;
+ }
+
+ /**
+ * Constructs a new <code>NestableError</code> with specified
+ * detail message and nested <code>Throwable</code>.
+ *
+ * @param msg the error message
+ * @param cause the exception or error that caused this exception to be
+ * thrown
+ */
+ public NestableError(String msg, Throwable cause) {
+ super(msg);
+ this.cause = cause;
+ }
+
+ public Throwable getCause() {
+ return cause;
+ }
+
+ /**
+ * Returns the detail message string of this throwable. If it was
+ * created with a null message, returns the following:
+ * (cause==null ? null : cause.toString()).
+ */
+ public String getMessage() {
+ if (super.getMessage() != null) {
+ return super.getMessage();
+ } else if (cause != null) {
+ return cause.toString();
+ } else {
+ return null;
+ }
+ }
+
+ public String getMessage(int index) {
+ if (index == 0) {
+ return super.getMessage();
+ } else {
+ return delegate.getMessage(index);
+ }
+ }
+
+ public String[] getMessages() {
+ return delegate.getMessages();
+ }
+
+ public Throwable getThrowable(int index) {
+ return delegate.getThrowable(index);
+ }
+
+ public int getThrowableCount() {
+ return delegate.getThrowableCount();
+ }
+
+ public Throwable[] getThrowables() {
+ return delegate.getThrowables();
+ }
+
+ public int indexOfThrowable(Class type) {
+ return delegate.indexOfThrowable(type, 0);
+ }
+
+ public int indexOfThrowable(Class type, int fromIndex) {
+ return delegate.indexOfThrowable(type, fromIndex);
+ }
+
+ public void printStackTrace() {
+ delegate.printStackTrace();
+ }
+
+ public void printStackTrace(PrintStream out) {
+ delegate.printStackTrace(out);
+ }
+
+ public void printStackTrace(PrintWriter out) {
+ delegate.printStackTrace(out);
+ }
+
+ public final void printPartialStackTrace(PrintWriter out) {
+ super.printStackTrace(out);
+ }
+}
Added: incubator/directory/ldap/trunk/common/src/java/org/apache/ldap/common/util/NestableException.java
==============================================================================
--- (empty file)
+++ incubator/directory/ldap/trunk/common/src/java/org/apache/ldap/common/util/NestableException.java Sat Sep 25 12:11:47 2004
@@ -0,0 +1,213 @@
+/*
+ * Copyright 2002-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.ldap.common.util;
+
+import java.io.PrintStream;
+import java.io.PrintWriter;
+
+/**
+ * The base class of all exceptions which can contain other exceptions.
+ *
+ * It is intended to ease the debugging by carrying on the information
+ * about the exception which was caught and provoked throwing the
+ * current exception. Catching and rethrowing may occur multiple
+ * times, and provided that all exceptions except the first one
+ * are descendants of <code>NestedException</code>, when the
+ * exception is finally printed out using any of the <code>
+ * printStackTrace()</code> methods, the stack trace will contain
+ * the information about all exceptions thrown and caught on
+ * the way.
+ * <p> Running the following program
+ * <p><blockquote><pre>
+ * 1 import org.apache.commons.lang.exception.NestableException;
+ * 2
+ * 3 public class Test {
+ * 4 public static void main( String[] args ) {
+ * 5 try {
+ * 6 a();
+ * 7 } catch(Exception e) {
+ * 8 e.printStackTrace();
+ * 9 }
+ * 10 }
+ * 11
+ * 12 public static void a() throws Exception {
+ * 13 try {
+ * 14 b();
+ * 15 } catch(Exception e) {
+ * 16 throw new NestableException("foo", e);
+ * 17 }
+ * 18 }
+ * 19
+ * 20 public static void b() throws Exception {
+ * 21 try {
+ * 22 c();
+ * 23 } catch(Exception e) {
+ * 24 throw new NestableException("bar", e);
+ * 25 }
+ * 26 }
+ * 27
+ * 28 public static void c() throws Exception {
+ * 29 throw new Exception("baz");
+ * 30 }
+ * 31 }
+ * </pre></blockquote>
+ * <p>Yields the following stack trace:
+ * <p><blockquote><pre>
+ * org.apache.commons.lang.exception.NestableException: foo
+ * at Test.a(Test.java:16)
+ * at Test.main(Test.java:6)
+ * Caused by: org.apache.commons.lang.exception.NestableException: bar
+ * at Test.b(Test.java:24)
+ * at Test.a(Test.java:14)
+ * ... 1 more
+ * Caused by: java.lang.Exception: baz
+ * at Test.c(Test.java:29)
+ * at Test.b(Test.java:22)
+ * ... 2 more
+ * </pre></blockquote><br>
+ *
+ * @author <a href="mailto:Rafal.Krzewski@e-point.pl">Rafal Krzewski</a>
+ * @author <a href="mailto:dlr@collab.net">Daniel Rall</a>
+ * @author <a href="mailto:knielsen@apache.org">Kasper Nielsen</a>
+ * @author <a href="mailto:steven@caswell.name">Steven Caswell</a>
+ * @since 1.0
+ * @version $Id: NestableException.java,v 1.12 2004/08/04 18:41:09 ggregory Exp $
+ */
+public class NestableException extends Exception implements Nestable {
+
+ /**
+ * The helper instance which contains much of the code which we
+ * delegate to.
+ */
+ protected NestableDelegate delegate = new NestableDelegate(this);
+
+ /**
+ * Holds the reference to the exception or error that caused
+ * this exception to be thrown.
+ */
+ private Throwable cause = null;
+
+ /**
+ * Constructs a new <code>NestableException</code> without specified
+ * detail message.
+ */
+ public NestableException() {
+ super();
+ }
+
+ /**
+ * Constructs a new <code>NestableException</code> with specified
+ * detail message.
+ *
+ * @param msg The error message.
+ */
+ public NestableException(String msg) {
+ super(msg);
+ }
+
+ /**
+ * Constructs a new <code>NestableException</code> with specified
+ * nested <code>Throwable</code>.
+ *
+ * @param cause the exception or error that caused this exception to be
+ * thrown
+ */
+ public NestableException(Throwable cause) {
+ super();
+ this.cause = cause;
+ }
+
+ /**
+ * Constructs a new <code>NestableException</code> with specified
+ * detail message and nested <code>Throwable</code>.
+ *
+ * @param msg the error message
+ * @param cause the exception or error that caused this exception to be
+ * thrown
+ */
+ public NestableException(String msg, Throwable cause) {
+ super(msg);
+ this.cause = cause;
+ }
+
+ public Throwable getCause() {
+ return cause;
+ }
+
+ /**
+ * Returns the detail message string of this throwable. If it was
+ * created with a null message, returns the following:
+ * (cause==null ? null : cause.toString()).
+ */
+ public String getMessage() {
+ if (super.getMessage() != null) {
+ return super.getMessage();
+ } else if (cause != null) {
+ return cause.toString();
+ } else {
+ return null;
+ }
+ }
+
+ public String getMessage(int index) {
+ if (index == 0) {
+ return super.getMessage();
+ } else {
+ return delegate.getMessage(index);
+ }
+ }
+
+ public String[] getMessages() {
+ return delegate.getMessages();
+ }
+
+ public Throwable getThrowable(int index) {
+ return delegate.getThrowable(index);
+ }
+
+ public int getThrowableCount() {
+ return delegate.getThrowableCount();
+ }
+
+ public Throwable[] getThrowables() {
+ return delegate.getThrowables();
+ }
+
+ public int indexOfThrowable(Class type) {
+ return delegate.indexOfThrowable(type, 0);
+ }
+
+ public int indexOfThrowable(Class type, int fromIndex) {
+ return delegate.indexOfThrowable(type, fromIndex);
+ }
+
+ public void printStackTrace() {
+ delegate.printStackTrace();
+ }
+
+ public void printStackTrace(PrintStream out) {
+ delegate.printStackTrace(out);
+ }
+
+ public void printStackTrace(PrintWriter out) {
+ delegate.printStackTrace(out);
+ }
+
+ public final void printPartialStackTrace(PrintWriter out) {
+ super.printStackTrace(out);
+ }
+
+}
Added: incubator/directory/ldap/trunk/common/src/java/org/apache/ldap/common/util/NestableRuntimeException.java
==============================================================================
--- (empty file)
+++ incubator/directory/ldap/trunk/common/src/java/org/apache/ldap/common/util/NestableRuntimeException.java Sat Sep 25 12:11:47 2004
@@ -0,0 +1,156 @@
+/*
+ * Copyright 2002-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.ldap.common.util;
+
+import java.io.PrintStream;
+import java.io.PrintWriter;
+
+/**
+ * The base class of all runtime exceptions which can contain other
+ * exceptions.
+ *
+ * @author <a href="mailto:Rafal.Krzewski@e-point.pl">Rafal Krzewski</a>
+ * @author <a href="mailto:dlr@collab.net">Daniel Rall</a>
+ * @author <a href="mailto:knielsen@apache.org">Kasper Nielsen</a>
+ * @author <a href="mailto:steven@caswell.name">Steven Caswell</a>
+ * @since 1.0
+ * @version $Id: NestableRuntimeException.java,v 1.10 2004/02/18 22:54:04 ggregory Exp $
+ */
+public class NestableRuntimeException extends RuntimeException implements Nestable {
+
+ /**
+ * The helper instance which contains much of the code which we
+ * delegate to.
+ */
+ protected NestableDelegate delegate = new NestableDelegate(this);
+
+ /**
+ * Holds the reference to the exception or error that caused
+ * this exception to be thrown.
+ */
+ private Throwable cause = null;
+
+ /**
+ * Constructs a new <code>NestableRuntimeException</code> without specified
+ * detail message.
+ */
+ public NestableRuntimeException() {
+ super();
+ }
+
+ /**
+ * Constructs a new <code>NestableRuntimeException</code> with specified
+ * detail message.
+ *
+ * @param msg the error message
+ */
+ public NestableRuntimeException(String msg) {
+ super(msg);
+ }
+
+ /**
+ * Constructs a new <code>NestableRuntimeException</code> with specified
+ * nested <code>Throwable</code>.
+ *
+ * @param cause the exception or error that caused this exception to be
+ * thrown
+ */
+ public NestableRuntimeException(Throwable cause) {
+ super();
+ this.cause = cause;
+ }
+
+ /**
+ * Constructs a new <code>NestableRuntimeException</code> with specified
+ * detail message and nested <code>Throwable</code>.
+ *
+ * @param msg the error message
+ * @param cause the exception or error that caused this exception to be
+ * thrown
+ */
+ public NestableRuntimeException(String msg, Throwable cause) {
+ super(msg);
+ this.cause = cause;
+ }
+
+ public Throwable getCause() {
+ return cause;
+ }
+
+ /**
+ * Returns the detail message string of this throwable. If it was
+ * created with a null message, returns the following:
+ * (cause==null ? null : cause.toString()).
+ */
+ public String getMessage() {
+ if (super.getMessage() != null) {
+ return super.getMessage();
+ } else if (cause != null) {
+ return cause.toString();
+ } else {
+ return null;
+ }
+ }
+
+ public String getMessage(int index) {
+ if (index == 0) {
+ return super.getMessage();
+ } else {
+ return delegate.getMessage(index);
+ }
+ }
+
+ public String[] getMessages() {
+ return delegate.getMessages();
+ }
+
+ public Throwable getThrowable(int index) {
+ return delegate.getThrowable(index);
+ }
+
+ public int getThrowableCount() {
+ return delegate.getThrowableCount();
+ }
+
+ public Throwable[] getThrowables() {
+ return delegate.getThrowables();
+ }
+
+ public int indexOfThrowable(Class type) {
+ return delegate.indexOfThrowable(type, 0);
+ }
+
+ public int indexOfThrowable(Class type, int fromIndex) {
+ return delegate.indexOfThrowable(type, fromIndex);
+ }
+
+ public void printStackTrace() {
+ delegate.printStackTrace();
+ }
+
+ public void printStackTrace(PrintStream out) {
+ delegate.printStackTrace(out);
+ }
+
+ public void printStackTrace(PrintWriter out) {
+ delegate.printStackTrace(out);
+ }
+
+ public final void printPartialStackTrace(PrintWriter out) {
+ super.printStackTrace(out);
+ }
+
+}
Added: incubator/directory/ldap/trunk/common/src/java/org/apache/ldap/common/util/ObjectUtils.java
==============================================================================
--- (empty file)
+++ incubator/directory/ldap/trunk/common/src/java/org/apache/ldap/common/util/ObjectUtils.java Sat Sep 25 12:11:47 2004
@@ -0,0 +1,271 @@
+/*
+ * Copyright 2002-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.ldap.common.util;
+
+import java.io.Serializable;
+
+/**
+ * <p>Operations on <code>Object</code>.</p>
+ *
+ * <p>This class tries to handle <code>null</code> input gracefully.
+ * An exception will generally not be thrown for a <code>null</code> input.
+ * Each method documents its behaviour in more detail.</p>
+ *
+ * @author <a href="mailto:nissim@nksystems.com">Nissim Karpenstein</a>
+ * @author <a href="mailto:janekdb@yahoo.co.uk">Janek Bogucki</a>
+ * @author <a href="mailto:dlr@finemaltcoding.com">Daniel Rall</a>
+ * @author Stephen Colebourne
+ * @author Gary Gregory
+ * @author Mario Winterer
+ * @since 1.0
+ * @version $Id: ObjectUtils.java,v 1.24 2004/06/01 21:08:48 scolebourne Exp $
+ */
+public class ObjectUtils {
+
+ /**
+ * <p>Singleton used as a <code>null</code> placeholder where
+ * <code>null</code> has another meaning.</p>
+ *
+ * <p>For example, in a <code>HashMap</code> the
+ * {@link java.util.HashMap#get(java.lang.Object)} method returns
+ * <code>null</code> if the <code>Map</code> contains
+ * <code>null</code> or if there is no matching key. The
+ * <code>Null</code> placeholder can be used to distinguish between
+ * these two cases.</p>
+ *
+ * <p>Another example is <code>Hashtable</code>, where <code>null</code>
+ * cannot be stored.</p>
+ *
+ * <p>This instance is Serializable.</p>
+ */
+ public static final Null NULL = new Null();
+
+ /**
+ * <p><code>ObjectUtils</code> instances should NOT be constructed in
+ * standard programming. Instead, the class should be used as
+ * <code>ObjectUtils.defaultIfNull("a","b");</code>.</p>
+ *
+ * <p>This constructor is public to permit tools that require a JavaBean instance
+ * to operate.</p>
+ */
+ public ObjectUtils() {
+ }
+
+ // Defaulting
+ //-----------------------------------------------------------------------
+ /**
+ * <p>Returns a default value if the object passed is
+ * <code>null</code>.</p>
+ *
+ * <pre>
+ * ObjectUtils.defaultIfNull(null, null) = null
+ * ObjectUtils.defaultIfNull(null, "") = ""
+ * ObjectUtils.defaultIfNull(null, "zz") = "zz"
+ * ObjectUtils.defaultIfNull("abc", *) = "abc"
+ * ObjectUtils.defaultIfNull(Boolean.TRUE, *) = Boolean.TRUE
+ * </pre>
+ *
+ * @param object the <code>Object</code> to test, may be <code>null</code>
+ * @param defaultValue the default value to return, may be <code>null</code>
+ * @return <code>object</code> if it is not <code>null</code>, defaultValue otherwise
+ */
+ public static Object defaultIfNull(Object object, Object defaultValue) {
+ return (object != null ? object : defaultValue);
+ }
+
+ /**
+ * <p>Compares two objects for equality, where either one or both
+ * objects may be <code>null</code>.</p>
+ *
+ * <pre>
+ * ObjectUtils.equals(null, null) = true
+ * ObjectUtils.equals(null, "") = false
+ * ObjectUtils.equals("", null) = false
+ * ObjectUtils.equals("", "") = true
+ * ObjectUtils.equals(Boolean.TRUE, null) = false
+ * ObjectUtils.equals(Boolean.TRUE, "true") = false
+ * ObjectUtils.equals(Boolean.TRUE, Boolean.TRUE) = true
+ * ObjectUtils.equals(Boolean.TRUE, Boolean.FALSE) = false
+ * </pre>
+ *
+ * @param object1 the first object, may be <code>null</code>
+ * @param object2 the second object, may be <code>null</code>
+ * @return <code>true</code> if the values of both objects are the same
+ */
+ public static boolean equals(Object object1, Object object2) {
+ if (object1 == object2) {
+ return true;
+ }
+ if ((object1 == null) || (object2 == null)) {
+ return false;
+ }
+ return object1.equals(object2);
+ }
+
+ /**
+ * <p>Gets the hash code of an object returning zero when the
+ * object is <code>null</code>.</p>
+ *
+ * <pre>
+ * ObjectUtils.hashCode(null) = 0
+ * ObjectUtils.hashCode(obj) = obj.hashCode()
+ * </pre>
+ *
+ * @param obj the object to obtain the hash code of, may be <code>null</code>
+ * @return the hash code of the object, or zero if null
+ * @since 2.1
+ */
+ public static int hashCode(Object obj) {
+ return ((obj == null) ? 0 : obj.hashCode());
+ }
+
+ // Identity ToString
+ //-----------------------------------------------------------------------
+ /**
+ * <p>Gets the toString that would be produced by <code>Object</code>
+ * if a class did not override toString itself. <code>null</code>
+ * will return <code>null</code>.</p>
+ *
+ * <pre>
+ * ObjectUtils.identityToString(null) = null
+ * ObjectUtils.identityToString("") = "java.lang.String@1e23"
+ * ObjectUtils.identityToString(Boolean.TRUE) = "java.lang.Boolean@7fa"
+ * </pre>
+ *
+ * @param object the object to create a toString for, may be
+ * <code>null</code>
+ * @return the default toString text, or <code>null</code> if
+ * <code>null</code> passed in
+ */
+ public static String identityToString(Object object) {
+ if (object == null) {
+ return null;
+ }
+ return appendIdentityToString(null, object).toString();
+ }
+
+ /**
+ * <p>Appends the toString that would be produced by <code>Object</code>
+ * if a class did not override toString itself. <code>null</code>
+ * will return <code>null</code>.</p>
+ *
+ * <pre>
+ * ObjectUtils.appendIdentityToString(*, null) = null
+ * ObjectUtils.appendIdentityToString(null, "") = "java.lang.String@1e23"
+ * ObjectUtils.appendIdentityToString(null, Boolean.TRUE) = "java.lang.Boolean@7fa"
+ * ObjectUtils.appendIdentityToString(buf, Boolean.TRUE) = buf.append("java.lang.Boolean@7fa")
+ * </pre>
+ *
+ * @param buffer the buffer to append to, may be <code>null</code>
+ * @param object the object to create a toString for, may be <code>null</code>
+ * @return the default toString text, or <code>null</code> if
+ * <code>null</code> passed in
+ * @since 2.0
+ */
+ public static StringBuffer appendIdentityToString(StringBuffer buffer, Object object) {
+ if (object == null) {
+ return null;
+ }
+ if (buffer == null) {
+ buffer = new StringBuffer();
+ }
+ return buffer
+ .append(object.getClass().getName())
+ .append('@')
+ .append(Integer.toHexString(System.identityHashCode(object)));
+ }
+
+ // ToString
+ //-----------------------------------------------------------------------
+ /**
+ * <p>Gets the <code>toString</code> of an <code>Object</code> returning
+ * an empty string ("") if <code>null</code> input.</p>
+ *
+ * <pre>
+ * ObjectUtils.toString(null) = ""
+ * ObjectUtils.toString("") = ""
+ * ObjectUtils.toString("bat") = "bat"
+ * ObjectUtils.toString(Boolean.TRUE) = "true"
+ * </pre>
+ *
+ * @see String#valueOf(Object)
+ * @param obj the Object to <code>toString</code>, may be null
+ * @return the passed in Object's toString, or nullStr if <code>null</code> input
+ * @since 2.0
+ */
+ public static String toString(Object obj) {
+ return (obj == null ? "" : obj.toString());
+ }
+
+ /**
+ * <p>Gets the <code>toString</code> of an <code>Object</code> returning
+ * a specified text if <code>null</code> input.</p>
+ *
+ * <pre>
+ * ObjectUtils.toString(null, null) = null
+ * ObjectUtils.toString(null, "null") = "null"
+ * ObjectUtils.toString("", "null") = ""
+ * ObjectUtils.toString("bat", "null") = "bat"
+ * ObjectUtils.toString(Boolean.TRUE, "null") = "true"
+ * </pre>
+ *
+ * @see String#valueOf(Object)
+ * @param obj the Object to <code>toString</code>, may be null
+ * @param nullStr the String to return if <code>null</code> input, may be null
+ * @return the passed in Object's toString, or nullStr if <code>null</code> input
+ * @since 2.0
+ */
+ public static String toString(Object obj, String nullStr) {
+ return (obj == null ? nullStr : obj.toString());
+ }
+
+ // Null
+ //-----------------------------------------------------------------------
+ /**
+ * <p>Class used as a null placeholder where <code>null</code>
+ * has another meaning.</p>
+ *
+ * <p>For example, in a <code>HashMap</code> the
+ * {@link java.util.HashMap#get(java.lang.Object)} method returns
+ * <code>null</code> if the <code>Map</code> contains
+ * <code>null</code> or if there is no matching key. The
+ * <code>Null</code> placeholder can be used to distinguish between
+ * these two cases.</p>
+ *
+ * <p>Another example is <code>Hashtable</code>, where <code>null</code>
+ * cannot be stored.</p>
+ */
+ public static class Null implements Serializable {
+ // declare serialization compatibility with Commons Lang 1.0
+ private static final long serialVersionUID = 7092611880189329093L;
+
+ /**
+ * Restricted constructor - singleton.
+ */
+ Null() {
+ }
+
+ /**
+ * <p>Ensure singleton.</p>
+ *
+ * @return the singleton value
+ */
+ private Object readResolve() {
+ return ObjectUtils.NULL;
+ }
+ }
+
+}
Added: incubator/directory/ldap/trunk/common/src/java/org/apache/ldap/common/util/ReflectionToStringBuilder.java
==============================================================================
--- (empty file)
+++ incubator/directory/ldap/trunk/common/src/java/org/apache/ldap/common/util/ReflectionToStringBuilder.java Sat Sep 25 12:11:47 2004
@@ -0,0 +1,798 @@
+/*
+ * Copyright 2002-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.ldap.common.util;
+
+
+import java.lang.reflect.AccessibleObject;
+import java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
+import java.util.HashSet;
+import java.util.Set;
+
+
+/**
+ * <p>
+ * Assists in implementing {@link Object#toString()}methods using reflection.
+ * </p>
+ *
+ * <p>
+ * This class uses reflection to determine the fields to append. Because these
+ * fields are usually private, the class uses
+ * {@link java.lang.reflect.AccessibleObject#setAccessible(java.lang.reflect.AccessibleObject[], boolean)}
+ * to change the visibility of the fields. This will fail under a security
+ * manager, unless the appropriate permissions are set up correctly.
+ * </p>
+ *
+ * <p>
+ * A typical invocation for this method would look like:
+ * </p>
+ *
+ * <pre>
+ * public String toString() {
+ * return ReflectionToStringBuilder.toString(this);
+ * }</pre>
+ *
+ *
+ *
+ * <p>
+ * You can also use the builder to debug 3rd party objects:
+ * </p>
+ *
+ * <pre>
+ * System.out.println("An object: " + ReflectionToStringBuilder.toString(anObject));</pre>
+ *
+ *
+ *
+ * <p>
+ * A subclass can control field output by overriding the methods:
+ * <ul>
+ * <li>{@link #accept(java.lang.reflect.Field)}</li>
+ * <li>{@link #getValue(java.lang.reflect.Field)}</li>
+ * </ul>
+ * </p>
+ * <p>
+ * For example, this method does <i>not</i> include the <code>password</code>
+ * field in the returned <code>String</code>:
+ * </p>
+ *
+ * <pre>
+ * public String toString() {
+ * return (new ReflectionToStringBuilder(this) {
+ * protected boolean accept(Field f) {
+ * return super.accept(f) && !f.getName().equals("password");
+ * }
+ * }).toString();
+ * }</pre>
+ *
+ *
+ *
+ * <p>
+ * The exact format of the <code>toString</code> is determined by the
+ * {@link ToStringStyle} passed into the constructor.
+ * </p>
+ *
+ * @author Gary Gregory
+ * @author Stephen Colebourne
+ * @author Pete Gieser
+ * @since 2.0
+ * @version $Id: ReflectionToStringBuilder.java,v 1.15 2003/12/02 19:11:58
+ * ggregory Exp $
+ */
+public class ReflectionToStringBuilder extends ToStringBuilder {
+ /**
+ * <p>
+ * A registry of objects used by <code>reflectionToString</code> methods
+ * to detect cyclical object references and avoid infinite loops.
+ * </p>
+ */
+ private static ThreadLocal registry = new ThreadLocal() {
+ protected synchronized Object initialValue() {
+ // The HashSet implementation is not synchronized,
+ // which is just what we need here.
+ return new HashSet();
+ }
+ };
+
+ /**
+ * <p>
+ * Returns the registry of objects being traversed by the <code>reflectionToString</code>
+ * methods in the current thread.
+ * </p>
+ *
+ * @return Set the registry of objects being traversed
+ */
+ static Set getRegistry() {
+ return (Set) registry.get();
+ }
+
+ /**
+ * <p>
+ * Returns <code>true</code> if the registry contains the given object.
+ * Used by the reflection methods to avoid infinite loops.
+ * </p>
+ *
+ * @param value
+ * The object to lookup in the registry.
+ * @return boolean <code>true</code> if the registry contains the given
+ * object.
+ */
+ static boolean isRegistered(Object value) {
+ return getRegistry().contains(value);
+ }
+
+ /**
+ * <p>
+ * Registers the given object. Used by the reflection methods to avoid
+ * infinite loops.
+ * </p>
+ *
+ * @param value
+ * The object to register.
+ */
+ static void register(Object value) {
+ getRegistry().add(value);
+ }
+
+ /**
+ * <p>
+ * This method uses reflection to build a suitable <code>toString</code>
+ * using the default <code>ToStringStyle</code>.
+ *
+ * <p>
+ * It uses <code>AccessibleObject.setAccessible</code> to gain access to
+ * private fields. This means that it will throw a security exception if
+ * run under a security manager, if the permissions are not set up
+ * correctly. It is also not as efficient as testing explicitly.
+ * </p>
+ *
+ * <p>
+ * Transient members will be not be included, as they are likely derived.
+ * Static fields will not be included. Superclass fields will be appended.
+ * </p>
+ *
+ * @param object
+ * the Object to be output
+ * @return the String result
+ * @throws IllegalArgumentException
+ * if the Object is <code>null</code>
+ */
+ public static String toString(Object object) {
+ return toString(object, null, false, false, null);
+ }
+
+ /**
+ * <p>
+ * This method uses reflection to build a suitable <code>toString</code>.
+ * </p>
+ *
+ * <p>
+ * It uses <code>AccessibleObject.setAccessible</code> to gain access to
+ * private fields. This means that it will throw a security exception if
+ * run under a security manager, if the permissions are not set up
+ * correctly. It is also not as efficient as testing explicitly.
+ * </p>
+ *
+ * <p>
+ * Transient members will be not be included, as they are likely derived.
+ * Static fields will not be included. Superclass fields will be appended.
+ * </p>
+ *
+ * <p>
+ * If the style is <code>null</code>, the default <code>ToStringStyle</code>
+ * is used.
+ * </p>
+ *
+ * @param object
+ * the Object to be output
+ * @param style
+ * the style of the <code>toString</code> to create, may be
+ * <code>null</code>
+ * @return the String result
+ * @throws IllegalArgumentException
+ * if the Object or <code>ToStringStyle</code> is <code>null</code>
+ */
+ public static String toString(Object object, ToStringStyle style) {
+ return toString(object, style, false, false, null);
+ }
+
+ /**
+ * <p>
+ * This method uses reflection to build a suitable <code>toString</code>.
+ * </p>
+ *
+ * <p>
+ * It uses <code>AccessibleObject.setAccessible</code> to gain access to
+ * private fields. This means that it will throw a security exception if
+ * run under a security manager, if the permissions are not set up
+ * correctly. It is also not as efficient as testing explicitly.
+ * </p>
+ *
+ * <p>
+ * If the <code>outputTransients</code> is <code>true</code>,
+ * transient members will be output, otherwise they are ignored, as they
+ * are likely derived fields, and not part of the value of the Object.
+ * </p>
+ *
+ * <p>
+ * Static fields will not be included. Superclass fields will be appended.
+ * </p>
+ *
+ * <p>
+ * If the style is <code>null</code>, the default <code>ToStringStyle</code>
+ * is used.
+ * </p>
+ *
+ * @param object
+ * the Object to be output
+ * @param style
+ * the style of the <code>toString</code> to create, may be
+ * <code>null</code>
+ * @param outputTransients
+ * whether to include transient fields
+ * @return the String result
+ * @throws IllegalArgumentException
+ * if the Object is <code>null</code>
+ */
+ public static String toString(Object object, ToStringStyle style, boolean outputTransients) {
+ return toString(object, style, outputTransients, false, null);
+ }
+
+ /**
+ * <p>
+ * This method uses reflection to build a suitable <code>toString</code>.
+ * </p>
+ *
+ * <p>
+ * It uses <code>AccessibleObject.setAccessible</code> to gain access to
+ * private fields. This means that it will throw a security exception if
+ * run under a security manager, if the permissions are not set up
+ * correctly. It is also not as efficient as testing explicitly.
+ * </p>
+ *
+ * <p>
+ * If the <code>outputTransients</code> is <code>true</code>,
+ * transient fields will be output, otherwise they are ignored, as they are
+ * likely derived fields, and not part of the value of the Object.
+ * </p>
+ *
+ * <p>
+ * If the <code>outputStatics</code> is <code>true</code>, static
+ * fields will be output, otherwise they are ignored.
+ * </p>
+ *
+ * <p>
+ * Static fields will not be included. Superclass fields will be appended.
+ * </p>
+ *
+ * <p>
+ * If the style is <code>null</code>, the default <code>ToStringStyle</code>
+ * is used.
+ * </p>
+ *
+ * @param object
+ * the Object to be output
+ * @param style
+ * the style of the <code>toString</code> to create, may be
+ * <code>null</code>
+ * @param outputTransients
+ * whether to include transient fields
+ * @param outputStatics
+ * whether to include transient fields
+ * @return the String result
+ * @throws IllegalArgumentException
+ * if the Object is <code>null</code>
+ */
+ public static String toString(Object object, ToStringStyle style, boolean outputTransients, boolean outputStatics) {
+ return toString(object, style, outputTransients, outputStatics, null);
+ }
+
+ /**
+ * <p>
+ * This method uses reflection to build a suitable <code>toString</code>.
+ * </p>
+ *
+ * <p>
+ * It uses <code>AccessibleObject.setAccessible</code> to gain access to
+ * private fields. This means that it will throw a security exception if
+ * run under a security manager, if the permissions are not set up
+ * correctly. It is also not as efficient as testing explicitly.
+ * </p>
+ *
+ * <p>
+ * If the <code>outputTransients</code> is <code>true</code>,
+ * transient fields will be output, otherwise they are ignored, as they are
+ * likely derived fields, and not part of the value of the Object.
+ * </p>
+ *
+ * <p>
+ * If the <code>outputStatics</code> is <code>true</code>, static
+ * fields will be output, otherwise they are ignored.
+ * </p>
+ *
+ * <p>
+ * Superclass fields will be appended up to and including the specified
+ * superclass. A null superclass is treated as <code>java.lang.Object</code>.
+ * </p>
+ *
+ * <p>
+ * If the style is <code>null</code>, the default <code>ToStringStyle</code>
+ * is used.
+ * </p>
+ *
+ * @param object
+ * the Object to be output
+ * @param style
+ * the style of the <code>toString</code> to create, may be
+ * <code>null</code>
+ * @param outputTransients
+ * whether to include transient fields
+ * @param outputStatics
+ * whether to include static fields
+ * @param reflectUpToClass
+ * the superclass to reflect up to (inclusive), may be <code>null</code>
+ * @return the String result
+ * @throws IllegalArgumentException
+ * if the Object is <code>null</code>
+ */
+ public static String toString(Object object, ToStringStyle style, boolean outputTransients, boolean outputStatics,
+ Class reflectUpToClass) {
+ return new ReflectionToStringBuilder(object, style, null, reflectUpToClass, outputTransients, outputStatics)
+ .toString();
+ }
+
+ /**
+ * <p>
+ * This method uses reflection to build a suitable <code>toString</code>.
+ * </p>
+ *
+ * <p>
+ * It uses <code>AccessibleObject.setAccessible</code> to gain access to
+ * private fields. This means that it will throw a security exception if
+ * run under a security manager, if the permissions are not set up
+ * correctly. It is also not as efficient as testing explicitly.
+ * </p>
+ *
+ * <p>
+ * If the <code>outputTransients</code> is <code>true</code>,
+ * transient members will be output, otherwise they are ignored, as they
+ * are likely derived fields, and not part of the value of the Object.
+ * </p>
+ *
+ * <p>
+ * Static fields will not be included. Superclass fields will be appended
+ * up to and including the specified superclass. A null superclass is
+ * treated as <code>java.lang.Object</code>.
+ * </p>
+ *
+ * <p>
+ * If the style is <code>null</code>, the default <code>ToStringStyle</code>
+ * is used.
+ * </p>
+ *
+ * @deprecated Use
+ * {@link #toString(Object,ToStringStyle,boolean,boolean,Class)}
+ *
+ * @param object
+ * the Object to be output
+ * @param style
+ * the style of the <code>toString</code> to create, may be
+ * <code>null</code>
+ * @param outputTransients
+ * whether to include transient fields
+ * @param reflectUpToClass
+ * the superclass to reflect up to (inclusive), may be <code>null</code>
+ * @return the String result
+ * @throws IllegalArgumentException
+ * if the Object is <code>null</code>
+ */
+ public static String toString(Object object, ToStringStyle style, boolean outputTransients, Class reflectUpToClass) {
+ return new ReflectionToStringBuilder(object, style, null, reflectUpToClass, outputTransients).toString();
+ }
+
+ /**
+ * <p>
+ * Unregisters the given object.
+ * </p>
+ *
+ * <p>
+ * Used by the reflection methods to avoid infinite loops.
+ * </p>
+ *
+ * @param value
+ * The object to unregister.
+ */
+ static void unregister(Object value) {
+ getRegistry().remove(value);
+ }
+
+ /**
+ * Whether or not to append static fields.
+ */
+ private boolean appendStatics = false;
+
+ /**
+ * Whether or not to append transient fields.
+ */
+ private boolean appendTransients = false;
+
+ /**
+ * The last super class to stop appending fields for.
+ */
+ private Class upToClass = null;
+
+ /**
+ * <p>
+ * Constructor.
+ * </p>
+ *
+ * <p>
+ * This constructor outputs using the default style set with <code>setDefaultStyle</code>.
+ * </p>
+ *
+ * @param object
+ * the Object to build a <code>toString</code> for, must not
+ * be <code>null</code>
+ * @throws IllegalArgumentException
+ * if the Object passed in is <code>null</code>
+ */
+ public ReflectionToStringBuilder(Object object) {
+ super(object);
+ }
+
+ /**
+ * <p>
+ * Constructor.
+ * </p>
+ *
+ * <p>
+ * If the style is <code>null</code>, the default style is used.
+ * </p>
+ *
+ * @param object
+ * the Object to build a <code>toString</code> for, must not
+ * be <code>null</code>
+ * @param style
+ * the style of the <code>toString</code> to create, may be
+ * <code>null</code>
+ * @throws IllegalArgumentException
+ * if the Object passed in is <code>null</code>
+ */
+ public ReflectionToStringBuilder(Object object, ToStringStyle style) {
+ super(object, style);
+ }
+
+ /**
+ * <p>
+ * Constructor.
+ * </p>
+ *
+ * <p>
+ * If the style is <code>null</code>, the default style is used.
+ * </p>
+ *
+ * <p>
+ * If the buffer is <code>null</code>, a new one is created.
+ * </p>
+ *
+ * @param object
+ * the Object to build a <code>toString</code> for
+ * @param style
+ * the style of the <code>toString</code> to create, may be
+ * <code>null</code>
+ * @param buffer
+ * the <code>StringBuffer</code> to populate, may be <code>null</code>
+ * @throws IllegalArgumentException
+ * if the Object passed in is <code>null</code>
+ */
+ public ReflectionToStringBuilder(Object object, ToStringStyle style, StringBuffer buffer) {
+ super(object, style, buffer);
+ }
+
+ /**
+ * Constructor.
+ *
+ * @deprecated Use
+ * {@link #ReflectionToStringBuilder(Object,ToStringStyle,StringBuffer,Class,boolean,boolean)}.
+ *
+ * @param object
+ * the Object to build a <code>toString</code> for
+ * @param style
+ * the style of the <code>toString</code> to create, may be
+ * <code>null</code>
+ * @param buffer
+ * the <code>StringBuffer</code> to populate, may be <code>null</code>
+ * @param reflectUpToClass
+ * the superclass to reflect up to (inclusive), may be <code>null</code>
+ * @param outputTransients
+ * whether to include transient fields
+ */
+ public ReflectionToStringBuilder(Object object, ToStringStyle style, StringBuffer buffer, Class reflectUpToClass,
+ boolean outputTransients) {
+ super(object, style, buffer);
+ this.setUpToClass(reflectUpToClass);
+ this.setAppendTransients(outputTransients);
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param object
+ * the Object to build a <code>toString</code> for
+ * @param style
+ * the style of the <code>toString</code> to create, may be
+ * <code>null</code>
+ * @param buffer
+ * the <code>StringBuffer</code> to populate, may be <code>null</code>
+ * @param reflectUpToClass
+ * the superclass to reflect up to (inclusive), may be <code>null</code>
+ * @param outputTransients
+ * whether to include transient fields
+ * @param outputStatics
+ * whether to include static fields
+ */
+ public ReflectionToStringBuilder(Object object, ToStringStyle style, StringBuffer buffer, Class reflectUpToClass,
+ boolean outputTransients, boolean outputStatics) {
+ super(object, style, buffer);
+ this.setUpToClass(reflectUpToClass);
+ this.setAppendTransients(outputTransients);
+ this.setAppendStatics(outputStatics);
+ }
+
+ /**
+ * Returns whether or not to append the given <code>Field</code>.
+ * <ul>
+ * <li>Transient fields are appended only if {@link #isAppendTransients()}
+ * returns <code>true</code>.
+ * <li>Static fields are appended only if {@link #isAppendStatics()}
+ * returns <code>true</code>.
+ * <li>Inner class fields are not appened.</li>
+ * </ul>
+ *
+ * @param field
+ * The Field to test.
+ * @return Whether or not to append the given <code>Field</code>.
+ */
+ protected boolean accept(Field field) {
+ if (field.getName().indexOf('$') != -1) {
+ // Reject field from inner class.
+ return false;
+ }
+ if (Modifier.isTransient(field.getModifiers()) && !this.isAppendTransients()) {
+ // transients.
+ return false;
+ }
+ if (Modifier.isStatic(field.getModifiers()) && !this.isAppendStatics()) {
+ // transients.
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * <p>
+ * Appends the fields and values defined by the given object of the given
+ * Class.
+ * </p>
+ *
+ * <p>
+ * If a cycle is detected as an object is "toString()'ed", such
+ * an object is rendered as if <code>Object.toString()</code> had been
+ * called and not implemented by the object.
+ * </p>
+ *
+ * @param clazz
+ * The class of object parameter
+ */
+ protected void appendFieldsIn(Class clazz) {
+ if (isRegistered(this.getObject())) {
+ // The object has already been appended, therefore we have an
+ // object cycle.
+ // Append a simple Object.toString style string. The field name is
+ // already appended at this point.
+ this.appendAsObjectToString(this.getObject());
+ return;
+ }
+ try {
+ this.registerObject();
+ if (clazz.isArray()) {
+ this.reflectionAppendArray(this.getObject());
+ return;
+ }
+ Field[] fields = clazz.getDeclaredFields();
+ AccessibleObject.setAccessible(fields, true);
+ for (int i = 0; i < fields.length; i++) {
+ Field field = fields[i];
+ String fieldName = field.getName();
+ if (this.accept(field)) {
+ try {
+ // Warning: Field.get(Object) creates wrappers objects
+ // for primitive types.
+ Object fieldValue = this.getValue(field);
+ if (isRegistered(fieldValue) && !field.getType().isPrimitive()) {
+ // A known field value has already been appended,
+ // therefore we have an object cycle,
+ // append a simple Object.toString style string.
+ this.getStyle().appendFieldStart(this.getStringBuffer(), fieldName);
+ this.appendAsObjectToString(fieldValue);
+ // The recursion out of
+ // builder.append(fieldName, fieldValue);
+ // below will append the field
+ // end marker.
+ } else {
+ try {
+ this.registerObject();
+ this.append(fieldName, fieldValue);
+ } finally {
+ this.unregisterObject();
+ }
+ }
+ } catch (IllegalAccessException ex) {
+ //this can't happen. Would get a Security exception
+ // instead
+ //throw a runtime exception in case the impossible
+ // happens.
+ throw new InternalError("Unexpected IllegalAccessException: " + ex.getMessage());
+ }
+ }
+ }
+ } finally {
+ this.unregisterObject();
+ }
+ }
+
+ /**
+ * <p>
+ * Gets the last super class to stop appending fields for.
+ * </p>
+ *
+ * @return The last super class to stop appending fields for.
+ */
+ public Class getUpToClass() {
+ return this.upToClass;
+ }
+
+ /**
+ * <p>
+ * Calls <code>java.lang.reflect.Field.get(Object)</code>.
+ * </p>
+ *
+ * @param field
+ * The Field to query.
+ * @return The Object from the given Field.
+ *
+ * @throws IllegalArgumentException
+ * see {@link java.lang.reflect.Field#get(Object)}
+ * @throws IllegalAccessException
+ * see {@link java.lang.reflect.Field#get(Object)}
+ *
+ * @see java.lang.reflect.Field#get(Object)
+ */
+ protected Object getValue(Field field) throws IllegalArgumentException, IllegalAccessException {
+ return field.get(this.getObject());
+ }
+
+ /**
+ * <p>
+ * Gets whether or not to append static fields.
+ * </p>
+ *
+ * @return Whether or not to append static fields.
+ */
+ public boolean isAppendStatics() {
+ return this.appendStatics;
+ }
+
+ /**
+ * <p>
+ * Gets whether or not to append transient fields.
+ * </p>
+ *
+ * @return Whether or not to append transient fields.
+ */
+ public boolean isAppendTransients() {
+ return this.appendTransients;
+ }
+
+ /**
+ * <p>
+ * Append to the <code>toString</code> an <code>Object</code> array.
+ * </p>
+ *
+ * @param array
+ * the array to add to the <code>toString</code>
+ * @return this
+ */
+ public ToStringBuilder reflectionAppendArray(Object array) {
+ this.getStyle().reflectionAppendArrayDetail(this.getStringBuffer(), null, array);
+ return this;
+ }
+
+ /**
+ * <p>
+ * Registers this builder's source object to avoid infinite loops when
+ * processing circular object references.
+ * </p>
+ */
+ void registerObject() {
+ register(this.getObject());
+ }
+
+ /**
+ * <p>
+ * Sets whether or not to append static fields.
+ * </p>
+ *
+ * @param appendStatics
+ * Whether or not to append static fields.
+ */
+ public void setAppendStatics(boolean appendStatics) {
+ this.appendStatics = appendStatics;
+ }
+
+ /**
+ * <p>
+ * Sets whether or not to append transient fields.
+ * </p>
+ *
+ * @param appendTransients
+ * Whether or not to append transient fields.
+ */
+ public void setAppendTransients(boolean appendTransients) {
+ this.appendTransients = appendTransients;
+ }
+
+ /**
+ * <p>
+ * Sets the last super class to stop appending fields for.
+ * </p>
+ *
+ * @param clazz
+ * The last super class to stop appending fields for.
+ */
+ public void setUpToClass(Class clazz) {
+ this.upToClass = clazz;
+ }
+
+ /**
+ * <p>
+ * Gets the String built by this builder.
+ * </p>
+ *
+ * @return the built string
+ */
+ public String toString() {
+ if (this.getObject() == null) {
+ return this.getStyle().getNullText();
+ }
+ Class clazz = this.getObject().getClass();
+ this.appendFieldsIn(clazz);
+ while (clazz.getSuperclass() != null && clazz != this.getUpToClass()) {
+ clazz = clazz.getSuperclass();
+ this.appendFieldsIn(clazz);
+ }
+ return super.toString();
+ }
+
+ /**
+ * <p>
+ * Unregisters this builder's source object to avoid infinite loops when
+ * processing circular object references.
+ * </p>
+ */
+ void unregisterObject() {
+ unregister(this.getObject());
+ }
+}
Added: incubator/directory/ldap/trunk/common/src/java/org/apache/ldap/common/util/SystemUtils.java
==============================================================================
--- (empty file)
+++ incubator/directory/ldap/trunk/common/src/java/org/apache/ldap/common/util/SystemUtils.java Sat Sep 25 12:11:47 2004
@@ -0,0 +1,1296 @@
+/*
+ * Copyright 2002-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.ldap.common.util;
+
+import java.io.File;
+
+/**
+ * <p>Helpers for <code>java.lang.System</code>.</p>
+ *
+ * <p>If a system property cannot be read due to security restrictions,
+ * the corresponding field in this class will be set to <code>null</code>
+ * and a message will be written to <code>System.err</code>.</p>
+ *
+ * @author Based on code from Avalon Excalibur
+ * @author Based on code from Lucene
+ * @author Stephen Colebourne
+ * @author <a href="mailto:sdowney@panix.com">Steve Downey</a>
+ * @author Gary Gregory
+ * @author Michael Becke
+ * @author Tetsuya Kaneuchi
+ * @author Rafal Krupinski
+ * @since 1.0
+ * @version $Id: SystemUtils.java,v 1.35 2004/08/30 21:21:18 ggregory Exp $
+ */
+public class SystemUtils {
+
+ /**
+ * The prefix String for all Windows OS.
+ */
+ private static final String OS_NAME_WINDOWS_PREFIX = "Windows";
+
+ // System property constants
+ //-----------------------------------------------------------------------
+ // These MUST be declared first. Other constants depend on this.
+
+ /**
+ * The System property key for the user home directory.
+ */
+ private static final String USER_HOME_KEY = "user.home";
+
+ /**
+ * The System property key for the user directory.
+ */
+ private static final String USER_DIR_KEY = "user.dir";
+
+ /**
+ * The System property key for the Java IO temporary directory.
+ */
+ private static final String JAVA_IO_TMPDIR_KEY = "java.io.tmpdir";
+
+ /**
+ * The System property key for the Java home directory.
+ */
+ private static final String JAVA_HOME_KEY = "java.home";
+
+ /**
+ * <p>The <code>awt.toolkit</code> System Property.</p>
+ * <p>Holds a class name, on Windows XP this is <code>sun.awt.windows.WToolkit</code>.</p>
+ * <p><b>On platforms without a GUI, this value is <code>null</code>.</b></p>
+ *
+ * <p>Defaults to <code>null</code> if the runtime does not have
+ * security access to read this property or the property does not exist.</p>
+ *
+ * <p>
+ * This value is initialized when the class is loaded. If {@link System#setProperty(String,String)}
+ * or {@link System#setProperties(java.util.Properties)} is called after this class is loaded, the value
+ * will be out of sync with that System property.
+ * </p>
+ *
+ * @since 2.1
+ */
+ public static final String AWT_TOOLKIT = getSystemProperty("awt.toolkit");
+
+ /**
+ * <p>The <code>file.encoding</code> System Property.</p>
+ * <p>File encoding, such as <code>Cp1252</code>.</p>
+ *
+ * <p>Defaults to <code>null</code> if the runtime does not have
+ * security access to read this property or the property does not exist.</p>
+ *
+ * <p>
+ * This value is initialized when the class is loaded. If {@link System#setProperty(String,String)}
+ * or {@link System#setProperties(java.util.Properties)} is called after this class is loaded, the value
+ * will be out of sync with that System property.
+ * </p>
+ *
+ * @since 2.0
+ * @since Java 1.2
+ */
+ public static final String FILE_ENCODING = getSystemProperty("file.encoding");
+
+ /**
+ * <p>The <code>file.separator</code> System Property.
+ * File separator (<code>"/"</code> on UNIX).</p>
+ *
+ * <p>Defaults to <code>null</code> if the runtime does not have
+ * security access to read this property or the property does not exist.</p>
+ *
+ * <p>
+ * This value is initialized when the class is loaded. If {@link System#setProperty(String,String)}
+ * or {@link System#setProperties(java.util.Properties)} is called after this class is loaded, the value
+ * will be out of sync with that System property.
+ * </p>
+ *
+ * @since Java 1.1
+ */
+ public static final String FILE_SEPARATOR = getSystemProperty("file.separator");
+
+ /**
+ * <p>The <code>java.awt.fonts</code> System Property.</p>
+ *
+ * <p>Defaults to <code>null</code> if the runtime does not have
+ * security access to read this property or the property does not exist.</p>
+ *
+ * <p>
+ * This value is initialized when the class is loaded. If {@link System#setProperty(String,String)}
+ * or {@link System#setProperties(java.util.Properties)} is called after this class is loaded, the value
+ * will be out of sync with that System property.
+ * </p>
+ *
+ * @since 2.1
+ */
+ public static final String JAVA_AWT_FONTS = getSystemProperty("java.awt.fonts");
+
+ /**
+ * <p>The <code>java.awt.graphicsenv</code> System Property.</p>
+ *
+ * <p>Defaults to <code>null</code> if the runtime does not have
+ * security access to read this property or the property does not exist.</p>
+ *
+ * <p>
+ * This value is initialized when the class is loaded. If {@link System#setProperty(String,String)}
+ * or {@link System#setProperties(java.util.Properties)} is called after this class is loaded, the value
+ * will be out of sync with that System property.
+ * </p>
+ *
+ * @since 2.1
+ */
+ public static final String JAVA_AWT_GRAPHICSENV = getSystemProperty("java.awt.graphicsenv");
+
+ /**
+ * <p>
+ * The <code>java.awt.headless</code> System Property.
+ * The value of this property is the String <code>"true"</code> or <code>"false"</code>.
+ * </p>
+ *
+ * <p>Defaults to <code>null</code> if the runtime does not have
+ * security access to read this property or the property does not exist.</p>
+ *
+ * <p>
+ * This value is initialized when the class is loaded. If {@link System#setProperty(String,String)}
+ * or {@link System#setProperties(java.util.Properties)} is called after this class is loaded, the value
+ * will be out of sync with that System property.
+ * </p>
+ *
+ * @see #isJavaAwtHeadless()
+ * @since 2.1
+ * @since Java 1.4
+ */
+ public static final String JAVA_AWT_HEADLESS = getSystemProperty("java.awt.headless");
+
+ /**
+ * <p>The <code>java.awt.printerjob</code> System Property.</p>
+ *
+ * <p>Defaults to <code>null</code> if the runtime does not have
+ * security access to read this property or the property does not exist.</p>
+ *
+ * <p>
+ * This value is initialized when the class is loaded. If {@link System#setProperty(String,String)}
+ * or {@link System#setProperties(java.util.Properties)} is called after this class is loaded, the value
+ * will be out of sync with that System property.
+ * </p>
+ *
+ * @since 2.1
+ */
+ public static final String JAVA_AWT_PRINTERJOB = getSystemProperty("java.awt.printerjob");
+
+ /**
+ * <p>The <code>java.class.path</code> System Property. Java class path.</p>
+ *
+ * <p>Defaults to <code>null</code> if the runtime does not have
+ * security access to read this property or the property does not exist.</p>
+ *
+ * <p>
+ * This value is initialized when the class is loaded. If {@link System#setProperty(String,String)}
+ * or {@link System#setProperties(java.util.Properties)} is called after this class is loaded, the value
+ * will be out of sync with that System property.
+ * </p>
+ *
+ * @since Java 1.1
+ */
+ public static final String JAVA_CLASS_PATH = getSystemProperty("java.class.path");
+
+ /**
+ * <p>The <code>java.class.version</code> System Property.
+ * Java class format version number.</p>
+ *
+ * <p>Defaults to <code>null</code> if the runtime does not have
+ * security access to read this property or the property does not exist.</p>
+ *
+ * <p>
+ * This value is initialized when the class is loaded. If {@link System#setProperty(String,String)}
+ * or {@link System#setProperties(java.util.Properties)} is called after this class is loaded, the value
+ * will be out of sync with that System property.
+ * </p>
+ *
+ * @since Java 1.1
+ */
+ public static final String JAVA_CLASS_VERSION = getSystemProperty("java.class.version");
+
+ /**
+ * <p>The <code>java.compiler</code> System Property. Name of JIT compiler to use.
+ * First in JDK version 1.2. Not used in Sun JDKs after 1.2.</p>
+ *
+ * <p>Defaults to <code>null</code> if the runtime does not have
+ * security access to read this property or the property does not exist.</p>
+ *
+ * <p>
+ * This value is initialized when the class is loaded. If {@link System#setProperty(String,String)}
+ * or {@link System#setProperties(java.util.Properties)} is called after this class is loaded, the value
+ * will be out of sync with that System property.
+ * </p>
+ *
+ * @since Java 1.2. Not used in Sun versions after 1.2.
+ */
+ public static final String JAVA_COMPILER = getSystemProperty("java.compiler");
+
+ /**
+ * <p>The <code>java.endorsed.dirs</code> System Property. Path of endorsed directory
+ * or directories.</p>
+ *
+ * <p>Defaults to <code>null</code> if the runtime does not have
+ * security access to read this property or the property does not exist.</p>
+ *
+ * <p>
+ * This value is initialized when the class is loaded. If {@link System#setProperty(String,String)}
+ * or {@link System#setProperties(java.util.Properties)} is called after this class is loaded, the value
+ * will be out of sync with that System property.
+ * </p>
+ *
+ * @since Java 1.4
+ */
+ public static final String JAVA_ENDORSED_DIRS = getSystemProperty("java.endorsed.dirs");
+
+ /**
+ * <p>The <code>java.ext.dirs</code> System Property. Path of extension directory
+ * or directories.</p>
+ *
+ * <p>Defaults to <code>null</code> if the runtime does not have
+ * security access to read this property or the property does not exist.</p>
+ *
+ * <p>
+ * This value is initialized when the class is loaded. If {@link System#setProperty(String,String)}
+ * or {@link System#setProperties(java.util.Properties)} is called after this class is loaded, the value
+ * will be out of sync with that System property.
+ * </p>
+ *
+ * @since Java 1.3
+ */
+ public static final String JAVA_EXT_DIRS = getSystemProperty("java.ext.dirs");
+
+ /**
+ * <p>The <code>java.home</code> System Property. Java installation directory.</p>
+ *
+ * <p>Defaults to <code>null</code> if the runtime does not have
+ * security access to read this property or the property does not exist.</p>
+ *
+ * <p>
+ * This value is initialized when the class is loaded. If {@link System#setProperty(String,String)}
+ * or {@link System#setProperties(java.util.Properties)} is called after this class is loaded, the value
+ * will be out of sync with that System property.
+ * </p>
+ *
+ * @since Java 1.1
+ */
+ public static final String JAVA_HOME = getSystemProperty(JAVA_HOME_KEY);
+
+ /**
+ * <p>The <code>java.io.tmpdir</code> System Property. Default temp file path.</p>
+ *
+ * <p>Defaults to <code>null</code> if the runtime does not have
+ * security access to read this property or the property does not exist.</p>
+ *
+ * <p>
+ * This value is initialized when the class is loaded. If {@link System#setProperty(String,String)}
+ * or {@link System#setProperties(java.util.Properties)} is called after this class is loaded, the value
+ * will be out of sync with that System property.
+ * </p>
+ *
+ * @since Java 1.2
+ */
+ public static final String JAVA_IO_TMPDIR = getSystemProperty(JAVA_IO_TMPDIR_KEY);
+
+ /**
+ * <p>The <code>java.library.path</code> System Property. List of paths to search
+ * when loading libraries.</p>
+ *
+ * <p>Defaults to <code>null</code> if the runtime does not have
+ * security access to read this property or the property does not exist.</p>
+ *
+ * <p>
+ * This value is initialized when the class is loaded. If {@link System#setProperty(String,String)}
+ * or {@link System#setProperties(java.util.Properties)} is called after this class is loaded, the value
+ * will be out of sync with that System property.
+ * </p>
+ *
+ * @since Java 1.2
+ */
+ public static final String JAVA_LIBRARY_PATH = getSystemProperty("java.library.path");
+
+ /**
+ * <p>The <code>java.runtime.name</code> System Property. Java Runtime Environment
+ * name.</p>
+ *
+ * <p>Defaults to <code>null</code> if the runtime does not have
+ * security access to read this property or the property does not exist.</p>
+ *
+ * <p>
+ * This value is initialized when the class is loaded. If {@link System#setProperty(String,String)}
+ * or {@link System#setProperties(java.util.Properties)} is called after this class is loaded, the value
+ * will be out of sync with that System property.
+ * </p>
+ *
+ * @since 2.0
+ * @since Java 1.3
+ */
+ public static final String JAVA_RUNTIME_NAME = getSystemProperty("java.runtime.name");
+
+ /**
+ * <p>The <code>java.runtime.version</code> System Property. Java Runtime Environment
+ * version.</p>
+ *
+ * <p>Defaults to <code>null</code> if the runtime does not have
+ * security access to read this property or the property does not exist.</p>
+ *
+ * <p>
+ * This value is initialized when the class is loaded. If {@link System#setProperty(String,String)}
+ * or {@link System#setProperties(java.util.Properties)} is called after this class is loaded, the value
+ * will be out of sync with that System property.
+ * </p>
+ *
+ * @since 2.0
+ * @since Java 1.3
+ */
+ public static final String JAVA_RUNTIME_VERSION = getSystemProperty("java.runtime.version");
+
+ /**
+ * <p>The <code>java.specification.name</code> System Property. Java Runtime Environment
+ * specification name.</p>
+ *
+ * <p>Defaults to <code>null</code> if the runtime does not have
+ * security access to read this property or the property does not exist.</p>
+ *
+ * <p>
+ * This value is initialized when the class is loaded. If {@link System#setProperty(String,String)}
+ * or {@link System#setProperties(java.util.Properties)} is called after this class is loaded, the value
+ * will be out of sync with that System property.
+ * </p>
+ *
+ * @since Java 1.2
+ */
+ public static final String JAVA_SPECIFICATION_NAME = getSystemProperty("java.specification.name");
+
+ /**
+ * <p>The <code>java.specification.vendor</code> System Property. Java Runtime Environment
+ * specification vendor.</p>
+ *
+ * <p>Defaults to <code>null</code> if the runtime does not have
+ * security access to read this property or the property does not exist.</p>
+ *
+ * <p>
+ * This value is initialized when the class is loaded. If {@link System#setProperty(String,String)}
+ * or {@link System#setProperties(java.util.Properties)} is called after this class is loaded, the value
+ * will be out of sync with that System property.
+ * </p>
+ *
+ * @since Java 1.2
+ */
+ public static final String JAVA_SPECIFICATION_VENDOR = getSystemProperty("java.specification.vendor");
+
+ /**
+ * <p>The <code>java.specification.version</code> System Property. Java Runtime Environment
+ * specification version.</p>
+ *
+ * <p>Defaults to <code>null</code> if the runtime does not have
+ * security access to read this property or the property does not exist.</p>
+ *
+ * <p>
+ * This value is initialized when the class is loaded. If {@link System#setProperty(String,String)}
+ * or {@link System#setProperties(java.util.Properties)} is called after this class is loaded, the value
+ * will be out of sync with that System property.
+ * </p>
+ *
+ * @since Java 1.3
+ */
+ public static final String JAVA_SPECIFICATION_VERSION = getSystemProperty("java.specification.version");
+
+ /**
+ * <p>The <code>java.util.prefs.PreferencesFactory</code> System Property. A class name.</p>
+ *
+ * <p>Defaults to <code>null</code> if the runtime does not have
+ * security access to read this property or the property does not exist.</p>
+ *
+ * <p>
+ * This value is initialized when the class is loaded. If {@link System#setProperty(String,String)}
+ * or {@link System#setProperties(java.util.Properties)} is called after this class is loaded, the value
+ * will be out of sync with that System property.
+ * </p>
+ *
+ * @since 2.1
+ * @since Java 1.4
+ */
+ public static final String JAVA_UTIL_PREFS_PREFERENCES_FACTORY = getSystemProperty("java.util.prefs.PreferencesFactory");
+
+ /**
+ * <p>The <code>java.vendor</code> System Property. Java vendor-specific string.</p>
+ *
+ * <p>Defaults to <code>null</code> if the runtime does not have
+ * security access to read this property or the property does not exist.</p>
+ *
+ * <p>
+ * This value is initialized when the class is loaded. If {@link System#setProperty(String,String)}
+ * or {@link System#setProperties(java.util.Properties)} is called after this class is loaded, the value
+ * will be out of sync with that System property.
+ * </p>
+ *
+ * @since Java 1.1
+ */
+ public static final String JAVA_VENDOR = getSystemProperty("java.vendor");
+
+ /**
+ * <p>The <code>java.vendor.url</code> System Property. Java vendor URL.</p>
+ *
+ * <p>Defaults to <code>null</code> if the runtime does not have
+ * security access to read this property or the property does not exist.</p>
+ *
+ * <p>
+ * This value is initialized when the class is loaded. If {@link System#setProperty(String,String)}
+ * or {@link System#setProperties(java.util.Properties)} is called after this class is loaded, the value
+ * will be out of sync with that System property.
+ * </p>
+ *
+ * @since Java 1.1
+ */
+ public static final String JAVA_VENDOR_URL = getSystemProperty("java.vendor.url");
+
+ /**
+ * <p>The <code>java.version</code> System Property. Java version number.</p>
+ *
+ * <p>Defaults to <code>null</code> if the runtime does not have
+ * security access to read this property or the property does not exist.</p>
+ *
+ * <p>
+ * This value is initialized when the class is loaded. If {@link System#setProperty(String,String)}
+ * or {@link System#setProperties(java.util.Properties)} is called after this class is loaded, the value
+ * will be out of sync with that System property.
+ * </p>
+ *
+ * @since Java 1.1
+ */
+ public static final String JAVA_VERSION = getSystemProperty("java.version");
+
+ /**
+ * <p>The <code>java.vm.info</code> System Property. Java Virtual Machine implementation
+ * info.</p>
+ *
+ * <p>Defaults to <code>null</code> if the runtime does not have
+ * security access to read this property or the property does not exist.</p>
+ *
+ * <p>
+ * This value is initialized when the class is loaded. If {@link System#setProperty(String,String)}
+ * or {@link System#setProperties(java.util.Properties)} is called after this class is loaded, the value
+ * will be out of sync with that System property.
+ * </p>
+ *
+ * @since 2.0
+ * @since Java 1.2
+ */
+ public static final String JAVA_VM_INFO = getSystemProperty("java.vm.info");
+
+ /**
+ * <p>The <code>java.vm.name</code> System Property. Java Virtual Machine implementation
+ * name.</p>
+ *
+ * <p>Defaults to <code>null</code> if the runtime does not have
+ * security access to read this property or the property does not exist.</p>
+ *
+ * <p>
+ * This value is initialized when the class is loaded. If {@link System#setProperty(String,String)}
+ * or {@link System#setProperties(java.util.Properties)} is called after this class is loaded, the value
+ * will be out of sync with that System property.
+ * </p>
+ *
+ * @since Java 1.2
+ */
+ public static final String JAVA_VM_NAME = getSystemProperty("java.vm.name");
+
+ /**
+ * <p>The <code>java.vm.specification.name</code> System Property. Java Virtual Machine
+ * specification name.</p>
+ *
+ * <p>Defaults to <code>null</code> if the runtime does not have
+ * security access to read this property or the property does not exist.</p>
+ *
+ * <p>
+ * This value is initialized when the class is loaded. If {@link System#setProperty(String,String)}
+ * or {@link System#setProperties(java.util.Properties)} is called after this class is loaded, the value
+ * will be out of sync with that System property.
+ * </p>
+ *
+ * @since Java 1.2
+ */
+ public static final String JAVA_VM_SPECIFICATION_NAME = getSystemProperty("java.vm.specification.name");
+
+ /**
+ * <p>The <code>java.vm.specification.vendor</code> System Property. Java Virtual
+ * Machine specification vendor.</p>
+ *
+ * <p>Defaults to <code>null</code> if the runtime does not have
+ * security access to read this property or the property does not exist.</p>
+ *
+ * <p>
+ * This value is initialized when the class is loaded. If {@link System#setProperty(String,String)}
+ * or {@link System#setProperties(java.util.Properties)} is called after this class is loaded, the value
+ * will be out of sync with that System property.
+ * </p>
+ *
+ * @since Java 1.2
+ */
+ public static final String JAVA_VM_SPECIFICATION_VENDOR = getSystemProperty("java.vm.specification.vendor");
+
+ /**
+ * <p>The <code>java.vm.specification.version</code> System Property. Java Virtual Machine
+ * specification version.</p>
+ *
+ * <p>Defaults to <code>null</code> if the runtime does not have
+ * security access to read this property or the property does not exist.</p>
+ *
+ * <p>
+ * This value is initialized when the class is loaded. If {@link System#setProperty(String,String)}
+ * or {@link System#setProperties(java.util.Properties)} is called after this class is loaded, the value
+ * will be out of sync with that System property.
+ * </p>
+ *
+ * @since Java 1.2
+ */
+ public static final String JAVA_VM_SPECIFICATION_VERSION = getSystemProperty("java.vm.specification.version");
+
+ /**
+ * <p>The <code>java.vm.vendor</code> System Property. Java Virtual Machine implementation
+ * vendor.</p>
+ *
+ * <p>Defaults to <code>null</code> if the runtime does not have
+ * security access to read this property or the property does not exist.</p>
+ *
+ * <p>
+ * This value is initialized when the class is loaded. If {@link System#setProperty(String,String)}
+ * or {@link System#setProperties(java.util.Properties)} is called after this class is loaded, the value
+ * will be out of sync with that System property.
+ * </p>
+ *
+ * @since Java 1.2
+ */
+ public static final String JAVA_VM_VENDOR = getSystemProperty("java.vm.vendor");
+
+ /**
+ * <p>The <code>java.vm.version</code> System Property. Java Virtual Machine
+ * implementation version.</p>
+ *
+ * <p>Defaults to <code>null</code> if the runtime does not have
+ * security access to read this property or the property does not exist.</p>
+ *
+ * <p>
+ * This value is initialized when the class is loaded. If {@link System#setProperty(String,String)}
+ * or {@link System#setProperties(java.util.Properties)} is called after this class is loaded, the value
+ * will be out of sync with that System property.
+ * </p>
+ *
+ * @since Java 1.2
+ */
+ public static final String JAVA_VM_VERSION = getSystemProperty("java.vm.version");
+
+ /**
+ * <p>The <code>line.separator</code> System Property. Line separator
+ * (<code>"\n<"</code> on UNIX).</p>
+ *
+ * <p>Defaults to <code>null</code> if the runtime does not have
+ * security access to read this property or the property does not exist.</p>
+ *
+ * <p>
+ * This value is initialized when the class is loaded. If {@link System#setProperty(String,String)}
+ * or {@link System#setProperties(java.util.Properties)} is called after this class is loaded, the value
+ * will be out of sync with that System property.
+ * </p>
+ *
+ * @since Java 1.1
+ */
+ public static final String LINE_SEPARATOR = getSystemProperty("line.separator");
+
+ /**
+ * <p>The <code>os.arch</code> System Property. Operating system architecture.</p>
+ *
+ * <p>Defaults to <code>null</code> if the runtime does not have
+ * security access to read this property or the property does not exist.</p>
+ *
+ * <p>
+ * This value is initialized when the class is loaded. If {@link System#setProperty(String,String)}
+ * or {@link System#setProperties(java.util.Properties)} is called after this class is loaded, the value
+ * will be out of sync with that System property.
+ * </p>
+ *
+ * @since Java 1.1
+ */
+ public static final String OS_ARCH = getSystemProperty("os.arch");
+
+ /**
+ * <p>The <code>os.name</code> System Property. Operating system name.</p>
+ *
+ * <p>Defaults to <code>null</code> if the runtime does not have
+ * security access to read this property or the property does not exist.</p>
+ *
+ * <p>
+ * This value is initialized when the class is loaded. If {@link System#setProperty(String,String)}
+ * or {@link System#setProperties(java.util.Properties)} is called after this class is loaded, the value
+ * will be out of sync with that System property.
+ * </p>
+ *
+ * @since Java 1.1
+ */
+ public static final String OS_NAME = getSystemProperty("os.name");
+
+ /**
+ * <p>The <code>os.version</code> System Property. Operating system version.</p>
+ *
+ * <p>Defaults to <code>null</code> if the runtime does not have
+ * security access to read this property or the property does not exist.</p>
+ *
+ * <p>
+ * This value is initialized when the class is loaded. If {@link System#setProperty(String,String)}
+ * or {@link System#setProperties(java.util.Properties)} is called after this class is loaded, the value
+ * will be out of sync with that System property.
+ * </p>
+ *
+ * @since Java 1.1
+ */
+ public static final String OS_VERSION = getSystemProperty("os.version");
+
+ /**
+ * <p>The <code>path.separator</code> System Property. Path separator
+ * (<code>":"</code> on UNIX).</p>
+ *
+ * <p>Defaults to <code>null</code> if the runtime does not have
+ * security access to read this property or the property does not exist.</p>
+ *
+ * <p>
+ * This value is initialized when the class is loaded. If {@link System#setProperty(String,String)}
+ * or {@link System#setProperties(java.util.Properties)} is called after this class is loaded, the value
+ * will be out of sync with that System property.
+ * </p>
+ *
+ * @since Java 1.1
+ */
+ public static final String PATH_SEPARATOR = getSystemProperty("path.separator");
+
+ /**
+ * <p>The <code>user.country</code> or <code>user.region</code> System Property.
+ * User's country code, such as <code>GB</code>. First in JDK version 1.2 as
+ * <code>user.region</code>. Renamed to <code>user.country</code> in 1.4</p>
+ *
+ * <p>Defaults to <code>null</code> if the runtime does not have
+ * security access to read this property or the property does not exist.</p>
+ *
+ * <p>
+ * This value is initialized when the class is loaded. If {@link System#setProperty(String,String)}
+ * or {@link System#setProperties(java.util.Properties)} is called after this class is loaded, the value
+ * will be out of sync with that System property.
+ * </p>
+ *
+ * @since 2.0
+ * @since Java 1.2
+ */
+ public static final String USER_COUNTRY =
+ (getSystemProperty("user.country") == null ?
+ getSystemProperty("user.region") : getSystemProperty("user.country"));
+
+ /**
+ * <p>The <code>user.dir</code> System Property. User's current working
+ * directory.</p>
+ *
+ * <p>Defaults to <code>null</code> if the runtime does not have
+ * security access to read this property or the property does not exist.</p>
+ *
+ * <p>
+ * This value is initialized when the class is loaded. If {@link System#setProperty(String,String)}
+ * or {@link System#setProperties(java.util.Properties)} is called after this class is loaded, the value
+ * will be out of sync with that System property.
+ * </p>
+ *
+ * @since Java 1.1
+ */
+ public static final String USER_DIR = getSystemProperty(USER_DIR_KEY);
+
+ /**
+ * <p>The <code>user.home</code> System Property. User's home directory.</p>
+ *
+ * <p>Defaults to <code>null</code> if the runtime does not have
+ * security access to read this property or the property does not exist.</p>
+ *
+ * <p>
+ * This value is initialized when the class is loaded. If {@link System#setProperty(String,String)}
+ * or {@link System#setProperties(java.util.Properties)} is called after this class is loaded, the value
+ * will be out of sync with that System property.
+ * </p>
+ *
+ * @since Java 1.1
+ */
+ public static final String USER_HOME = getSystemProperty(USER_HOME_KEY);
+
+ /**
+ * <p>The <code>user.language</code> System Property. User's language code,
+ * such as <code>"en"</code>.</p>
+ *
+ * <p>Defaults to <code>null</code> if the runtime does not have
+ * security access to read this property or the property does not exist.</p>
+ *
+ * <p>
+ * This value is initialized when the class is loaded. If {@link System#setProperty(String,String)}
+ * or {@link System#setProperties(java.util.Properties)} is called after this class is loaded, the value
+ * will be out of sync with that System property.
+ * </p>
+ *
+ * @since 2.0
+ * @since Java 1.2
+ */
+ public static final String USER_LANGUAGE = getSystemProperty("user.language");
+
+ /**
+ * <p>The <code>user.name</code> System Property. User's account name.</p>
+ *
+ * <p>Defaults to <code>null</code> if the runtime does not have
+ * security access to read this property or the property does not exist.</p>
+ *
+ * <p>
+ * This value is initialized when the class is loaded. If {@link System#setProperty(String,String)}
+ * or {@link System#setProperties(java.util.Properties)} is called after this class is loaded, the value
+ * will be out of sync with that System property.
+ * </p>
+ *
+ * @since Java 1.1
+ */
+ public static final String USER_NAME = getSystemProperty("user.name");
+
+ /**
+ * <p>The <code>user.timezone</code> System Property.
+ * For example: <code>"America/Los_Angeles"</code>.</p>
+ *
+ * <p>Defaults to <code>null</code> if the runtime does not have
+ * security access to read this property or the property does not exist.</p>
+ *
+ * <p>
+ * This value is initialized when the class is loaded. If {@link System#setProperty(String,String)}
+ * or {@link System#setProperties(java.util.Properties)} is called after this class is loaded, the value
+ * will be out of sync with that System property.
+ * </p>
+ *
+ * @since 2.1
+ */
+ public static final String USER_TIMEZONE = getSystemProperty("user.timezone");
+
+ // Java version
+ //-----------------------------------------------------------------------
+ // These MUST be declared after those above as they depend on the
+ // values being set up
+
+ /**
+ * <p>Gets the Java version as a <code>float</code>.</p>
+ *
+ * <p>Example return values:</p>
+ * <ul>
+ * <li><code>1.2f</code> for JDK 1.2
+ * <li><code>1.31f</code> for JDK 1.3.1
+ * </ul>
+ *
+ * <p>The field will return zero if {@link #JAVA_VERSION} is <code>null</code>.</p>
+ *
+ * @since 2.0
+ */
+ public static final float JAVA_VERSION_FLOAT = getJavaVersionAsFloat();
+
+ /**
+ * <p>Gets the Java version as an <code>int</code>.</p>
+ *
+ * <p>Example return values:</p>
+ * <ul>
+ * <li><code>120</code> for JDK 1.2
+ * <li><code>131</code> for JDK 1.3.1
+ * </ul>
+ *
+ * <p>The field will return zero if {@link #JAVA_VERSION} is <code>null</code>.</p>
+ *
+ * @since 2.0
+ */
+ public static final int JAVA_VERSION_INT = getJavaVersionAsInt();
+
+ // Java version checks
+ //-----------------------------------------------------------------------
+ // These MUST be declared after those above as they depend on the
+ // values being set up
+
+ /**
+ * <p>Is <code>true</code> if this is Java version 1.1 (also 1.1.x versions).</p>
+ *
+ * <p>The field will return <code>false</code> if {@link #JAVA_VERSION} is
+ * <code>null</code>.</p>
+ */
+ public static final boolean IS_JAVA_1_1 = getJavaVersionMatches("1.1");
+
+ /**
+ * <p>Is <code>true</code> if this is Java version 1.2 (also 1.2.x versions).</p>
+ *
+ * <p>The field will return <code>false</code> if {@link #JAVA_VERSION} is
+ * <code>null</code>.</p>
+ */
+ public static final boolean IS_JAVA_1_2 = getJavaVersionMatches("1.2");
+
+ /**
+ * <p>Is <code>true</code> if this is Java version 1.3 (also 1.3.x versions).</p>
+ *
+ * <p>The field will return <code>false</code> if {@link #JAVA_VERSION} is
+ * <code>null</code>.</p>
+ */
+ public static final boolean IS_JAVA_1_3 = getJavaVersionMatches("1.3");
+
+ /**
+ * <p>Is <code>true</code> if this is Java version 1.4 (also 1.4.x versions).</p>
+ *
+ * <p>The field will return <code>false</code> if {@link #JAVA_VERSION} is
+ * <code>null</code>.</p>
+ */
+ public static final boolean IS_JAVA_1_4 = getJavaVersionMatches("1.4");
+
+ /**
+ * <p>Is <code>true</code> if this is Java version 1.5 (also 1.5.x versions).</p>
+ *
+ * <p>The field will return <code>false</code> if {@link #JAVA_VERSION} is
+ * <code>null</code>.</p>
+ */
+ public static final boolean IS_JAVA_1_5 = getJavaVersionMatches("1.5");
+
+ // Operating system checks
+ //-----------------------------------------------------------------------
+ // These MUST be declared after those above as they depend on the
+ // values being set up
+ // OS names from http://www.vamphq.com/os.html
+ // Selected ones included - please advise commons-dev@jakarta.apache.org
+ // if you want another added or a mistake corrected
+
+ /**
+ * <p>Is <code>true</code> if this is AIX.</p>
+ *
+ * <p>The field will return <code>false</code> if <code>OS_NAME</code> is
+ * <code>null</code>.</p>
+ *
+ * @since 2.0
+ */
+ public static final boolean IS_OS_AIX = getOSMatches("AIX");
+
+ /**
+ * <p>Is <code>true</code> if this is HP-UX.</p>
+ *
+ * <p>The field will return <code>false</code> if <code>OS_NAME</code> is
+ * <code>null</code>.</p>
+ *
+ * @since 2.0
+ */
+ public static final boolean IS_OS_HP_UX = getOSMatches("HP-UX");
+
+ /**
+ * <p>Is <code>true</code> if this is Irix.</p>
+ *
+ * <p>The field will return <code>false</code> if <code>OS_NAME</code> is
+ * <code>null</code>.</p>
+ *
+ * @since 2.0
+ */
+ public static final boolean IS_OS_IRIX = getOSMatches("Irix");
+
+ /**
+ * <p>Is <code>true</code> if this is Linux.</p>
+ *
+ * <p>The field will return <code>false</code> if <code>OS_NAME</code> is
+ * <code>null</code>.</p>
+ *
+ * @since 2.0
+ */
+ public static final boolean IS_OS_LINUX = getOSMatches("Linux") || getOSMatches("LINUX");
+
+ /**
+ * <p>Is <code>true</code> if this is Mac.</p>
+ *
+ * <p>The field will return <code>false</code> if <code>OS_NAME</code> is
+ * <code>null</code>.</p>
+ *
+ * @since 2.0
+ */
+ public static final boolean IS_OS_MAC = getOSMatches("Mac");
+
+ /**
+ * <p>Is <code>true</code> if this is Mac.</p>
+ *
+ * <p>The field will return <code>false</code> if <code>OS_NAME</code> is
+ * <code>null</code>.</p>
+ *
+ * @since 2.0
+ */
+ public static final boolean IS_OS_MAC_OSX = getOSMatches("Mac OS X");
+
+ /**
+ * <p>Is <code>true</code> if this is OS/2.</p>
+ *
+ * <p>The field will return <code>false</code> if <code>OS_NAME</code> is
+ * <code>null</code>.</p>
+ *
+ * @since 2.0
+ */
+ public static final boolean IS_OS_OS2 = getOSMatches("OS/2");
+
+ /**
+ * <p>Is <code>true</code> if this is Solaris.</p>
+ *
+ * <p>The field will return <code>false</code> if <code>OS_NAME</code> is
+ * <code>null</code>.</p>
+ *
+ * @since 2.0
+ */
+ public static final boolean IS_OS_SOLARIS = getOSMatches("Solaris");
+
+ /**
+ * <p>Is <code>true</code> if this is SunOS.</p>
+ *
+ * <p>The field will return <code>false</code> if <code>OS_NAME</code> is
+ * <code>null</code>.</p>
+ *
+ * @since 2.0
+ */
+ public static final boolean IS_OS_SUN_OS = getOSMatches("SunOS");
+
+ /**
+ * <p>Is <code>true</code> if this is a POSIX compilant system,
+ * as in any of AIX, HP-UX, Irix, Linux, MacOSX, Solaris or SUN OS.</p>
+ *
+ * <p>The field will return <code>false</code> if <code>OS_NAME</code> is
+ * <code>null</code>.</p>
+ *
+ * @since 2.1
+ */
+ public static final boolean IS_OS_UNIX =
+ IS_OS_AIX || IS_OS_HP_UX || IS_OS_IRIX || IS_OS_LINUX ||
+ IS_OS_MAC_OSX || IS_OS_SOLARIS || IS_OS_SUN_OS;
+
+ /**
+ * <p>Is <code>true</code> if this is Windows.</p>
+ *
+ * <p>The field will return <code>false</code> if <code>OS_NAME</code> is
+ * <code>null</code>.</p>
+ *
+ * @since 2.0
+ */
+ public static final boolean IS_OS_WINDOWS = getOSMatches(OS_NAME_WINDOWS_PREFIX);
+
+ /**
+ * <p>Is <code>true</code> if this is Windows 2000.</p>
+ *
+ * <p>The field will return <code>false</code> if <code>OS_NAME</code> is
+ * <code>null</code>.</p>
+ *
+ * @since 2.0
+ */
+ public static final boolean IS_OS_WINDOWS_2000 = getOSMatches(OS_NAME_WINDOWS_PREFIX, "5.0");
+
+ /**
+ * <p>Is <code>true</code> if this is Windows 95.</p>
+ *
+ * <p>The field will return <code>false</code> if <code>OS_NAME</code> is
+ * <code>null</code>.</p>
+ *
+ * @since 2.0
+ */
+ public static final boolean IS_OS_WINDOWS_95 = getOSMatches(OS_NAME_WINDOWS_PREFIX + " 9", "4.0");
+ // JDK 1.2 running on Windows98 returns 'Windows 95', hence the above
+
+ /**
+ * <p>Is <code>true</code> if this is Windows 98.</p>
+ *
+ * <p>The field will return <code>false</code> if <code>OS_NAME</code> is
+ * <code>null</code>.</p>
+ *
+ * @since 2.0
+ */
+ public static final boolean IS_OS_WINDOWS_98 = getOSMatches(OS_NAME_WINDOWS_PREFIX + " 9", "4.1");
+ // JDK 1.2 running on Windows98 returns 'Windows 95', hence the above
+
+ /**
+ * <p>Is <code>true</code> if this is Windows ME.</p>
+ *
+ * <p>The field will return <code>false</code> if <code>OS_NAME</code> is
+ * <code>null</code>.</p>
+ *
+ * @since 2.0
+ */
+ public static final boolean IS_OS_WINDOWS_ME = getOSMatches(OS_NAME_WINDOWS_PREFIX, "4.9");
+ // JDK 1.2 running on WindowsME may return 'Windows 95', hence the above
+
+ /**
+ * <p>Is <code>true</code> if this is Windows NT.</p>
+ *
+ * <p>The field will return <code>false</code> if <code>OS_NAME</code> is
+ * <code>null</code>.</p>
+ *
+ * @since 2.0
+ */
+ public static final boolean IS_OS_WINDOWS_NT = getOSMatches(OS_NAME_WINDOWS_PREFIX + " NT");
+ // Windows 2000 returns 'Windows 2000' but may suffer from same JDK1.2 problem
+
+ /**
+ * <p>Is <code>true</code> if this is Windows XP.</p>
+ *
+ * <p>The field will return <code>false</code> if <code>OS_NAME</code> is
+ * <code>null</code>.</p>
+ *
+ * @since 2.0
+ */
+ public static final boolean IS_OS_WINDOWS_XP = getOSMatches(OS_NAME_WINDOWS_PREFIX, "5.1");
+
+ //-----------------------------------------------------------------------
+ /**
+ * <p>SystemUtils instances should NOT be constructed in standard
+ * programming. Instead, the class should be used as
+ * <code>SystemUtils.FILE_SEPARATOR</code>.</p>
+ *
+ * <p>This constructor is public to permit tools that require a JavaBean
+ * instance to operate.</p>
+ */
+ public SystemUtils() {
+ // no init.
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * <p>Gets the Java version number as a <code>float</code>.</p>
+ *
+ * <p>Example return values:</p>
+ * <ul>
+ * <li><code>1.2f</code> for JDK 1.2
+ * <li><code>1.31f</code> for JDK 1.3.1
+ * </ul>
+ *
+ * @return the version, for example 1.31f for JDK 1.3.1
+ * @deprecated Use {@link #JAVA_VERSION_FLOAT} instead.
+ * Method will be removed in Commons Lang 3.0.
+ */
+ public static float getJavaVersion() {
+ return JAVA_VERSION_FLOAT;
+ }
+
+ /**
+ * <p>Gets the Java version number as a <code>float</code>.</p>
+ *
+ * <p>Example return values:</p>
+ * <ul>
+ * <li><code>1.2f</code> for JDK 1.2
+ * <li><code>1.31f</code> for JDK 1.3.1
+ * </ul>
+ *
+ * <p>Patch releases are not reported.
+ * Zero is returned if {@link #JAVA_VERSION} is <code>null</code>.</p>
+ *
+ * @return the version, for example 1.31f for JDK 1.3.1
+ */
+ private static float getJavaVersionAsFloat() {
+ if (JAVA_VERSION == null) {
+ return 0f;
+ }
+ String str = JAVA_VERSION.substring(0, 3);
+ if (JAVA_VERSION.length() >= 5) {
+ str = str + JAVA_VERSION.substring(4, 5);
+ }
+ return Float.parseFloat(str);
+ }
+
+ /**
+ * <p>Gets the Java version number as an <code>int</code>.</p>
+ *
+ * <p>Example return values:</p>
+ * <ul>
+ * <li><code>120</code> for JDK 1.2
+ * <li><code>131</code> for JDK 1.3.1
+ * </ul>
+ *
+ * <p>Patch releases are not reported.
+ * Zero is returned if {@link #JAVA_VERSION} is <code>null</code>.</p>
+ *
+ * @return the version, for example 131 for JDK 1.3.1
+ */
+ private static int getJavaVersionAsInt() {
+ if (JAVA_VERSION == null) {
+ return 0;
+ }
+ String str = JAVA_VERSION.substring(0, 1);
+ str = str + JAVA_VERSION.substring(2, 3);
+ if (JAVA_VERSION.length() >= 5) {
+ str = str + JAVA_VERSION.substring(4, 5);
+ } else {
+ str = str + "0";
+ }
+ return Integer.parseInt(str);
+ }
+
+ /**
+ * <p>Decides if the java version matches.</p>
+ *
+ * @param versionPrefix the prefix for the java version
+ * @return true if matches, or false if not or can't determine
+ */
+ private static boolean getJavaVersionMatches(String versionPrefix) {
+ if (JAVA_VERSION == null) {
+ return false;
+ }
+ return JAVA_VERSION.startsWith(versionPrefix);
+ }
+
+ /**
+ * <p>Decides if the operating system matches.</p>
+ *
+ * @param osNamePrefix the prefix for the os name
+ * @return true if matches, or false if not or can't determine
+ */
+ private static boolean getOSMatches(String osNamePrefix) {
+ if (OS_NAME == null) {
+ return false;
+ }
+ return OS_NAME.startsWith(osNamePrefix);
+ }
+
+ /**
+ * <p>Decides if the operating system matches.</p>
+ *
+ * @param osNamePrefix the prefix for the os name
+ * @param osVersionPrefix the prefix for the version
+ * @return true if matches, or false if not or can't determine
+ */
+ private static boolean getOSMatches(String osNamePrefix, String osVersionPrefix) {
+ if (OS_NAME == null || OS_VERSION == null) {
+ return false;
+ }
+ return OS_NAME.startsWith(osNamePrefix) && OS_VERSION.startsWith(osVersionPrefix);
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * <p>Gets a System property, defaulting to <code>null</code> if the property
+ * cannot be read.</p>
+ *
+ * <p>If a <code>SecurityException</code> is caught, the return
+ * value is <code>null</code> and a message is written to <code>System.err</code>.</p>
+ *
+ * @param property the system property name
+ * @return the system property value or <code>null</code> if a security problem occurs
+ */
+ private static String getSystemProperty(String property) {
+ try {
+ return System.getProperty(property);
+ } catch (SecurityException ex) {
+ // we are not allowed to look at this property
+ System.err.println(
+ "Caught a SecurityException reading the system property '" + property
+ + "'; the SystemUtils property value will default to null."
+ );
+ return null;
+ }
+ }
+
+ /**
+ * <p>Is the Java version at least the requested version.</p>
+ *
+ * <p>Example input:</p>
+ * <ul>
+ * <li><code>1.2f</code> to test for JDK 1.2</li>
+ * <li><code>1.31f</code> to test for JDK 1.3.1</li>
+ * </ul>
+ *
+ * @param requiredVersion the required version, for example 1.31f
+ * @return <code>true</code> if the actual version is equal or greater
+ * than the required version
+ */
+ public static boolean isJavaVersionAtLeast(float requiredVersion) {
+ return (JAVA_VERSION_FLOAT >= requiredVersion);
+ }
+
+ /**
+ * <p>Is the Java version at least the requested version.</p>
+ *
+ * <p>Example input:</p>
+ * <ul>
+ * <li><code>120</code> to test for JDK 1.2 or greater</li>
+ * <li><code>131</code> to test for JDK 1.3.1 or greater</li>
+ * </ul>
+ *
+ * @param requiredVersion the required version, for example 131
+ * @return <code>true</code> if the actual version is equal or greater
+ * than the required version
+ * @since 2.0
+ */
+ public static boolean isJavaVersionAtLeast(int requiredVersion) {
+ return (JAVA_VERSION_INT >= requiredVersion);
+ }
+
+ /**
+ * Returns whether the {@link #JAVA_AWT_HEADLESS} value is <code>true</code>.
+ *
+ * @return <code>true</code> if <code>JAVA_AWT_HEADLESS</code> is <code>"true"</code>,
+ * <code>false</code> otherwise.
+ *
+ * @see #JAVA_AWT_HEADLESS
+ * @since 2.1
+ * @since Java 1.4
+ */
+ public static boolean isJavaAwtHeadless() {
+ return JAVA_AWT_HEADLESS != null ? JAVA_AWT_HEADLESS.equals(Boolean.TRUE.toString()) : false;
+ }
+ /**
+ * <p>Gets the Java home directory as a <code>File</code>.</p>
+ *
+ * @return a directory
+ * @throws SecurityException if a security manager exists and its
+ * <code>checkPropertyAccess</code> method doesn't allow
+ * access to the specified system property.
+ * @see System#getProperty(String)
+ */
+ public static File getJavaHome() {
+ return new File(System.getProperty(JAVA_HOME_KEY));
+ }
+
+ /**
+ * <p>Gets the Java IO temporary directory as a <code>File</code>.</p>
+ *
+ * @return a directory
+ * @throws SecurityException if a security manager exists and its
+ * <code>checkPropertyAccess</code> method doesn't allow
+ * access to the specified system property.
+ * @see System#getProperty(String)
+ */
+ public static File getJavaIoTmpDir() {
+ return new File(System.getProperty(JAVA_IO_TMPDIR_KEY));
+ }
+
+ /**
+ * <p>Gets the user directory as a <code>File</code>.</p>
+ *
+ * @return a directory
+ * @throws SecurityException if a security manager exists and its
+ * <code>checkPropertyAccess</code> method doesn't allow
+ * access to the specified system property.
+ * @see System#getProperty(String)
+ */
+ public static File getUserDir() {
+ return new File(System.getProperty(USER_DIR_KEY));
+ }
+
+ /**
+ * <p>Gets the user home directory as a <code>File</code>.</p>
+ *
+ * @return a directory
+ * @throws SecurityException if a security manager exists and its
+ * <code>checkPropertyAccess</code> method doesn't allow
+ * access to the specified system property.
+ * @see System#getProperty(String)
+ */
+ public static File getUserHome() {
+ return new File(System.getProperty(USER_HOME_KEY));
+ }
+
+}
Added: incubator/directory/ldap/trunk/common/src/java/org/apache/ldap/common/util/ToStringBuilder.java
==============================================================================
--- (empty file)
+++ incubator/directory/ldap/trunk/common/src/java/org/apache/ldap/common/util/ToStringBuilder.java Sat Sep 25 12:11:47 2004
@@ -0,0 +1,1041 @@
+/*
+ * Copyright 2002-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.ldap.common.util;
+
+
+
+/**
+ * <p>Assists in implementing {@link Object#toString()} methods.</p>
+ *
+ * <p>This class enables a good and consistent <code>toString()</code> to be built for any
+ * class or object. This class aims to simplify the process by:</p>
+ * <ul>
+ * <li>allowing field names</li>
+ * <li>handling all types consistently</li>
+ * <li>handling nulls consistently</li>
+ * <li>outputting arrays and multi-dimensional arrays</li>
+ * <li>enabling the detail level to be controlled for Objects and Collections</li>
+ * <li>handling class hierarchies</li>
+ * </ul>
+ *
+ * <p>To use this class write code as follows:</p>
+ *
+ * <pre>
+ * public class Person {
+ * String name;
+ * int age;
+ * boolean isSmoker;
+ *
+ * ...
+ *
+ * public String toString() {
+ * return new ToStringBuilder(this).
+ * append("name", name).
+ * append("age", age).
+ * append("smoker", smoker).
+ * toString();
+ * }
+ * }
+ * </pre>
+ *
+ * <p>This will produce a toString of the format:
+ * <code>Person@7f54[name=Stephen,age=29,smoker=false]</code></p>
+ *
+ * <p>To add the superclass <code>toString</code>, use {@link #appendSuper}.
+ * To append the <code>toString</code> from an object that is delegated
+ * to (or any other object), use {@link #appendToString}.</p>
+ *
+ * <p>Alternatively, there is a method that uses reflection to determine
+ * the fields to test. Because these fields are usually private, the method,
+ * <code>reflectionToString</code>, uses <code>AccessibleObject.setAccessible</code> to
+ * change the visibility of the fields. This will fail under a security manager,
+ * unless the appropriate permissions are set up correctly. It is also
+ * slower than testing explicitly.</p>
+ *
+ * <p>A typical invocation for this method would look like:</p>
+ *
+ * <pre>
+ * public String toString() {
+ * return ToStringBuilder.reflectionToString(this);
+ * }
+ * </pre>
+ *
+ * <p>You can also use the builder to debug 3rd party objects:</p>
+ *
+ * <pre>
+ * System.out.println("An object: " + ToStringBuilder.reflectionToString(anObject));
+ * </pre>
+ *
+ * <p>The exact format of the <code>toString</code> is determined by
+ * the {@link ToStringStyle} passed into the constructor.</p>
+ *
+ * @author Stephen Colebourne
+ * @author Gary Gregory
+ * @author Pete Gieser
+ * @since 1.0
+ * @version $Id: ToStringBuilder.java,v 1.35 2004/07/01 17:40:10 ggregory Exp $
+ */
+public class ToStringBuilder {
+
+ /**
+ * The default style of output to use.
+ */
+ private static ToStringStyle defaultStyle = ToStringStyle.DEFAULT_STYLE;
+
+ //----------------------------------------------------------------------------
+
+ /**
+ * <p>Gets the default <code>ToStringStyle</code> to use.</p>
+ *
+ * <p>This could allow the <code>ToStringStyle</code> to be
+ * controlled for an entire application with one call.</p>
+ *
+ * <p>This might be used to have a verbose
+ * <code>ToStringStyle</code> during development and a compact
+ * <code>ToStringStyle</code> in production.</p>
+ *
+ * @return the default <code>ToStringStyle</code>
+ */
+ public static ToStringStyle getDefaultStyle() {
+ return defaultStyle;
+ }
+
+ /**
+ * <p>Forwards to <code>ReflectionToStringBuilder</code>.</p>
+ *
+ * @see ReflectionToStringBuilder#toString(Object)
+ */
+ public static String reflectionToString(Object object) {
+ return ReflectionToStringBuilder.toString(object);
+ }
+
+ /**
+ * <p>Forwards to <code>ReflectionToStringBuilder</code>.</p>
+ *
+ * @see ReflectionToStringBuilder#toString(Object,ToStringStyle)
+ */
+ public static String reflectionToString(Object object, ToStringStyle style) {
+ return ReflectionToStringBuilder.toString(object, style);
+ }
+
+ /**
+ * <p>Forwards to <code>ReflectionToStringBuilder</code>.</p>
+ *
+ * @see ReflectionToStringBuilder#toString(Object,ToStringStyle,boolean)
+ */
+ public static String reflectionToString(Object object, ToStringStyle style, boolean outputTransients) {
+ return ReflectionToStringBuilder.toString(object, style, outputTransients, false, null);
+ }
+
+ /**
+ * <p>Forwards to <code>ReflectionToStringBuilder</code>.</p>
+ *
+ * @see ReflectionToStringBuilder#toString(Object,ToStringStyle,boolean,boolean,Class)
+ * @since 2.0
+ */
+ public static String reflectionToString(
+ Object object,
+ ToStringStyle style,
+ boolean outputTransients,
+ Class reflectUpToClass) {
+ return ReflectionToStringBuilder.toString(object, style, outputTransients, false, reflectUpToClass);
+ }
+
+ /**
+ * <p>Sets the default <code>ToStringStyle</code> to use.</p>
+ *
+ * @param style the default <code>ToStringStyle</code>
+ * @throws IllegalArgumentException if the style is <code>null</code>
+ */
+ public static void setDefaultStyle(ToStringStyle style) {
+ if (style == null) {
+ throw new IllegalArgumentException("The style must not be null");
+ }
+ defaultStyle = style;
+ }
+
+ /**
+ * Current toString buffer.
+ */
+ private final StringBuffer buffer;
+
+ /**
+ * The object being output.
+ */
+ private final Object object;
+
+ /**
+ * The style of output to use.
+ */
+ private final ToStringStyle style;
+
+ /**
+ * <p>Constructor for <code>ToStringBuilder</code>.</p>
+ *
+ * <p>This constructor outputs using the default style set with
+ * <code>setDefaultStyle</code>.</p>
+ *
+ * @param object the Object to build a <code>toString</code> for
+ * @throws IllegalArgumentException if the Object passed in is
+ * <code>null</code>
+ */
+ public ToStringBuilder(Object object) {
+ this(object, getDefaultStyle(), null);
+ }
+
+ /**
+ * <p>Constructor for <code>ToStringBuilder</code> specifying the
+ * output style.</p>
+ *
+ * <p>If the style is <code>null</code>, the default style is used.</p>
+ *
+ * @param object the Object to build a <code>toString</code> for
+ * @param style the style of the <code>toString</code> to create,
+ * may be <code>null</code>
+ * @throws IllegalArgumentException if the Object passed in is
+ * <code>null</code>
+ */
+ public ToStringBuilder(Object object, ToStringStyle style) {
+ this(object, style, null);
+ }
+
+ /**
+ * <p>Constructor for <code>ToStringBuilder</code>.</p>
+ *
+ * <p>If the style is <code>null</code>, the default style is used.</p>
+ *
+ * <p>If the buffer is <code>null</code>, a new one is created.</p>
+ *
+ * @param object the Object to build a <code>toString</code> for
+ * @param style the style of the <code>toString</code> to create,
+ * may be <code>null</code>
+ * @param buffer the <code>StringBuffer</code> to populate, may be
+ * <code>null</code>
+ */
+ public ToStringBuilder(Object object, ToStringStyle style, StringBuffer buffer) {
+ if (style == null) {
+ style = getDefaultStyle();
+ }
+ if (buffer == null) {
+ buffer = new StringBuffer(512);
+ }
+ this.buffer = buffer;
+ this.style = style;
+ this.object = object;
+
+ style.appendStart(buffer, object);
+ }
+
+ //----------------------------------------------------------------------------
+
+ /**
+ * <p>Append to the <code>toString</code> a <code>boolean</code>
+ * value.</p>
+ *
+ * @param value the value to add to the <code>toString</code>
+ * @return this
+ */
+ public ToStringBuilder append(boolean value) {
+ style.append(buffer, null, value);
+ return this;
+ }
+
+ //----------------------------------------------------------------------------
+
+ /**
+ * <p>Append to the <code>toString</code> a <code>boolean</code>
+ * array.</p>
+ *
+ * @param array the array to add to the <code>toString</code>
+ * @return this
+ */
+ public ToStringBuilder append(boolean[] array) {
+ style.append(buffer, null, array, null);
+ return this;
+ }
+
+ //----------------------------------------------------------------------------
+
+ /**
+ * <p>Append to the <code>toString</code> a <code>byte</code>
+ * value.</p>
+ *
+ * @param value the value to add to the <code>toString</code>
+ * @return this
+ */
+ public ToStringBuilder append(byte value) {
+ style.append(buffer, null, value);
+ return this;
+ }
+
+ //----------------------------------------------------------------------------
+
+ /**
+ * <p>Append to the <code>toString</code> a <code>byte</code>
+ * array.</p>
+ *
+ * @param array the array to add to the <code>toString</code>
+ * @return this
+ */
+ public ToStringBuilder append(byte[] array) {
+ style.append(buffer, null, array, null);
+ return this;
+ }
+
+ //----------------------------------------------------------------------------
+
+ /**
+ * <p>Append to the <code>toString</code> a <code>char</code>
+ * value.</p>
+ *
+ * @param value the value to add to the <code>toString</code>
+ * @return this
+ */
+ public ToStringBuilder append(char value) {
+ style.append(buffer, null, value);
+ return this;
+ }
+
+ //----------------------------------------------------------------------------
+
+ /**
+ * <p>Append to the <code>toString</code> a <code>char</code>
+ * array.</p>
+ *
+ * @param array the array to add to the <code>toString</code>
+ * @return this
+ */
+ public ToStringBuilder append(char[] array) {
+ style.append(buffer, null, array, null);
+ return this;
+ }
+
+ //----------------------------------------------------------------------------
+
+ /**
+ * <p>Append to the <code>toString</code> a <code>double</code>
+ * value.</p>
+ *
+ * @param value the value to add to the <code>toString</code>
+ * @return this
+ */
+ public ToStringBuilder append(double value) {
+ style.append(buffer, null, value);
+ return this;
+ }
+
+ //----------------------------------------------------------------------------
+
+ /**
+ * <p>Append to the <code>toString</code> a <code>double</code>
+ * array.</p>
+ *
+ * @param array the array to add to the <code>toString</code>
+ * @return this
+ */
+ public ToStringBuilder append(double[] array) {
+ style.append(buffer, null, array, null);
+ return this;
+ }
+
+ //----------------------------------------------------------------------------
+
+ /**
+ * <p>Append to the <code>toString</code> a <code>float</code>
+ * value.</p>
+ *
+ * @param value the value to add to the <code>toString</code>
+ * @return this
+ */
+ public ToStringBuilder append(float value) {
+ style.append(buffer, null, value);
+ return this;
+ }
+
+ //----------------------------------------------------------------------------
+
+ /**
+ * <p>Append to the <code>toString</code> a <code>float</code>
+ * array.</p>
+ *
+ * @param array the array to add to the <code>toString</code>
+ * @return this
+ */
+ public ToStringBuilder append(float[] array) {
+ style.append(buffer, null, array, null);
+ return this;
+ }
+
+ //----------------------------------------------------------------------------
+
+ /**
+ * <p>Append to the <code>toString</code> an <code>int</code>
+ * value.</p>
+ *
+ * @param value the value to add to the <code>toString</code>
+ * @return this
+ */
+ public ToStringBuilder append(int value) {
+ style.append(buffer, null, value);
+ return this;
+ }
+
+ //----------------------------------------------------------------------------
+
+ /**
+ * <p>Append to the <code>toString</code> an <code>int</code>
+ * array.</p>
+ *
+ * @param array the array to add to the <code>toString</code>
+ * @return this
+ */
+ public ToStringBuilder append(int[] array) {
+ style.append(buffer, null, array, null);
+ return this;
+ }
+
+ //----------------------------------------------------------------------------
+
+ /**
+ * <p>Append to the <code>toString</code> a <code>long</code>
+ * value.</p>
+ *
+ * @param value the value to add to the <code>toString</code>
+ * @return this
+ */
+ public ToStringBuilder append(long value) {
+ style.append(buffer, null, value);
+ return this;
+ }
+
+ //----------------------------------------------------------------------------
+
+ /**
+ * <p>Append to the <code>toString</code> a <code>long</code>
+ * array.</p>
+ *
+ * @param array the array to add to the <code>toString</code>
+ * @return this
+ */
+ public ToStringBuilder append(long[] array) {
+ style.append(buffer, null, array, null);
+ return this;
+ }
+
+ //----------------------------------------------------------------------------
+
+ /**
+ * <p>Append to the <code>toString</code> an <code>Object</code>
+ * value.</p>
+ *
+ * @param object the value to add to the <code>toString</code>
+ * @return this
+ */
+ public ToStringBuilder append(Object object) {
+ style.append(buffer, null, object, null);
+ return this;
+ }
+
+ //----------------------------------------------------------------------------
+
+ /**
+ * <p>Append to the <code>toString</code> an <code>Object</code>
+ * array.</p>
+ *
+ * @param array the array to add to the <code>toString</code>
+ * @return this
+ */
+ public ToStringBuilder append(Object[] array) {
+ style.append(buffer, null, array, null);
+ return this;
+ }
+
+ //----------------------------------------------------------------------------
+
+ /**
+ * <p>Append to the <code>toString</code> a <code>short</code>
+ * value.</p>
+ *
+ * @param value the value to add to the <code>toString</code>
+ * @return this
+ */
+ public ToStringBuilder append(short value) {
+ style.append(buffer, null, value);
+ return this;
+ }
+
+ //----------------------------------------------------------------------------
+
+ /**
+ * <p>Append to the <code>toString</code> a <code>short</code>
+ * array.</p>
+ *
+ * @param array the array to add to the <code>toString</code>
+ * @return this
+ */
+ public ToStringBuilder append(short[] array) {
+ style.append(buffer, null, array, null);
+ return this;
+ }
+
+ /**
+ * <p>Append to the <code>toString</code> a <code>boolean</code>
+ * value.</p>
+ *
+ * @param fieldName the field name
+ * @param value the value to add to the <code>toString</code>
+ * @return this
+ */
+ public ToStringBuilder append(String fieldName, boolean value) {
+ style.append(buffer, fieldName, value);
+ return this;
+ }
+
+ /**
+ * <p>Append to the <code>toString</code> a <code>boolean</code>
+ * array.</p>
+ *
+ * @param fieldName the field name
+ * @param array the array to add to the <code>hashCode</code>
+ * @return this
+ */
+ public ToStringBuilder append(String fieldName, boolean[] array) {
+ style.append(buffer, fieldName, array, null);
+ return this;
+ }
+
+ /**
+ * <p>Append to the <code>toString</code> a <code>boolean</code>
+ * array.</p>
+ *
+ * <p>A boolean parameter controls the level of detail to show.
+ * Setting <code>true</code> will output the array in full. Setting
+ * <code>false</code> will output a summary, typically the size of
+ * the array.</p>
+ *
+ * @param fieldName the field name
+ * @param array the array to add to the <code>toString</code>
+ * @param fullDetail <code>true</code> for detail, <code>false</code>
+ * for summary info
+ * @return this
+ */
+ public ToStringBuilder append(String fieldName, boolean[] array, boolean fullDetail) {
+ style.append(buffer, fieldName, array, BooleanUtils.toBooleanObject(fullDetail));
+ return this;
+ }
+
+ /**
+ * <p>Append to the <code>toString</code> an <code>byte</code>
+ * value.</p>
+ *
+ * @param fieldName the field name
+ * @param value the value to add to the <code>toString</code>
+ * @return this
+ */
+ public ToStringBuilder append(String fieldName, byte value) {
+ style.append(buffer, fieldName, value);
+ return this;
+ }
+
+ /**
+ * <p>Append to the <code>toString</code> a <code>byte</code> array.</p>
+ *
+ * @param fieldName the field name
+ * @param array the array to add to the <code>toString</code>
+ * @return this
+ */
+ public ToStringBuilder append(String fieldName, byte[] array) {
+ style.append(buffer, fieldName, array, null);
+ return this;
+ }
+
+ /**
+ * <p>Append to the <code>toString</code> a <code>byte</code>
+ * array.</p>
+ *
+ * <p>A boolean parameter controls the level of detail to show.
+ * Setting <code>true</code> will output the array in full. Setting
+ * <code>false</code> will output a summary, typically the size of
+ * the array.
+ *
+ * @param fieldName the field name
+ * @param array the array to add to the <code>toString</code>
+ * @param fullDetail <code>true</code> for detail, <code>false</code>
+ * for summary info
+ * @return this
+ */
+ public ToStringBuilder append(String fieldName, byte[] array, boolean fullDetail) {
+ style.append(buffer, fieldName, array, BooleanUtils.toBooleanObject(fullDetail));
+ return this;
+ }
+
+ /**
+ * <p>Append to the <code>toString</code> a <code>char</code>
+ * value.</p>
+ *
+ * @param fieldName the field name
+ * @param value the value to add to the <code>toString</code>
+ * @return this
+ */
+ public ToStringBuilder append(String fieldName, char value) {
+ style.append(buffer, fieldName, value);
+ return this;
+ }
+
+ /**
+ * <p>Append to the <code>toString</code> a <code>char</code>
+ * array.</p>
+ *
+ * @param fieldName the field name
+ * @param array the array to add to the <code>toString</code>
+ * @return this
+ */
+ public ToStringBuilder append(String fieldName, char[] array) {
+ style.append(buffer, fieldName, array, null);
+ return this;
+ }
+
+ /**
+ * <p>Append to the <code>toString</code> a <code>char</code>
+ * array.</p>
+ *
+ * <p>A boolean parameter controls the level of detail to show.
+ * Setting <code>true</code> will output the array in full. Setting
+ * <code>false</code> will output a summary, typically the size of
+ * the array.</p>
+ *
+ * @param fieldName the field name
+ * @param array the array to add to the <code>toString</code>
+ * @param fullDetail <code>true</code> for detail, <code>false</code>
+ * for summary info
+ * @return this
+ */
+ public ToStringBuilder append(String fieldName, char[] array, boolean fullDetail) {
+ style.append(buffer, fieldName, array, BooleanUtils.toBooleanObject(fullDetail));
+ return this;
+ }
+
+ /**
+ * <p>Append to the <code>toString</code> a <code>double</code>
+ * value.</p>
+ *
+ * @param fieldName the field name
+ * @param value the value to add to the <code>toString</code>
+ * @return this
+ */
+ public ToStringBuilder append(String fieldName, double value) {
+ style.append(buffer, fieldName, value);
+ return this;
+ }
+
+ /**
+ * <p>Append to the <code>toString</code> a <code>double</code>
+ * array.</p>
+ *
+ * @param fieldName the field name
+ * @param array the array to add to the <code>toString</code>
+ * @return this
+ */
+ public ToStringBuilder append(String fieldName, double[] array) {
+ style.append(buffer, fieldName, array, null);
+ return this;
+ }
+
+ /**
+ * <p>Append to the <code>toString</code> a <code>double</code>
+ * array.</p>
+ *
+ * <p>A boolean parameter controls the level of detail to show.
+ * Setting <code>true</code> will output the array in full. Setting
+ * <code>false</code> will output a summary, typically the size of
+ * the array.</p>
+ *
+ * @param fieldName the field name
+ * @param array the array to add to the <code>toString</code>
+ * @param fullDetail <code>true</code> for detail, <code>false</code>
+ * for summary info
+ * @return this
+ */
+ public ToStringBuilder append(String fieldName, double[] array, boolean fullDetail) {
+ style.append(buffer, fieldName, array, BooleanUtils.toBooleanObject(fullDetail));
+ return this;
+ }
+
+ /**
+ * <p>Append to the <code>toString</code> an <code>float</code>
+ * value.</p>
+ *
+ * @param fieldName the field name
+ * @param value the value to add to the <code>toString</code>
+ * @return this
+ */
+ public ToStringBuilder append(String fieldName, float value) {
+ style.append(buffer, fieldName, value);
+ return this;
+ }
+
+ /**
+ * <p>Append to the <code>toString</code> a <code>float</code>
+ * array.</p>
+ *
+ * @param fieldName the field name
+ * @param array the array to add to the <code>toString</code>
+ * @return this
+ */
+ public ToStringBuilder append(String fieldName, float[] array) {
+ style.append(buffer, fieldName, array, null);
+ return this;
+ }
+
+ /**
+ * <p>Append to the <code>toString</code> a <code>float</code>
+ * array.</p>
+ *
+ * <p>A boolean parameter controls the level of detail to show.
+ * Setting <code>true</code> will output the array in full. Setting
+ * <code>false</code> will output a summary, typically the size of
+ * the array.</p>
+ *
+ * @param fieldName the field name
+ * @param array the array to add to the <code>toString</code>
+ * @param fullDetail <code>true</code> for detail, <code>false</code>
+ * for summary info
+ * @return this
+ */
+ public ToStringBuilder append(String fieldName, float[] array, boolean fullDetail) {
+ style.append(buffer, fieldName, array, BooleanUtils.toBooleanObject(fullDetail));
+ return this;
+ }
+
+ /**
+ * <p>Append to the <code>toString</code> an <code>int</code>
+ * value.</p>
+ *
+ * @param fieldName the field name
+ * @param value the value to add to the <code>toString</code>
+ * @return this
+ */
+ public ToStringBuilder append(String fieldName, int value) {
+ style.append(buffer, fieldName, value);
+ return this;
+ }
+
+ /**
+ * <p>Append to the <code>toString</code> an <code>int</code>
+ * array.</p>
+ *
+ * @param fieldName the field name
+ * @param array the array to add to the <code>toString</code>
+ * @return this
+ */
+ public ToStringBuilder append(String fieldName, int[] array) {
+ style.append(buffer, fieldName, array, null);
+ return this;
+ }
+
+ /**
+ * <p>Append to the <code>toString</code> an <code>int</code>
+ * array.</p>
+ *
+ * <p>A boolean parameter controls the level of detail to show.
+ * Setting <code>true</code> will output the array in full. Setting
+ * <code>false</code> will output a summary, typically the size of
+ * the array.</p>
+ *
+ * @param fieldName the field name
+ * @param array the array to add to the <code>toString</code>
+ * @param fullDetail <code>true</code> for detail, <code>false</code>
+ * for summary info
+ * @return this
+ */
+ public ToStringBuilder append(String fieldName, int[] array, boolean fullDetail) {
+ style.append(buffer, fieldName, array, BooleanUtils.toBooleanObject(fullDetail));
+ return this;
+ }
+
+ /**
+ * <p>Append to the <code>toString</code> a <code>long</code>
+ * value.</p>
+ *
+ * @param fieldName the field name
+ * @param value the value to add to the <code>toString</code>
+ * @return this
+ */
+ public ToStringBuilder append(String fieldName, long value) {
+ style.append(buffer, fieldName, value);
+ return this;
+ }
+
+ /**
+ * <p>Append to the <code>toString</code> a <code>long</code>
+ * array.</p>
+ *
+ * @param fieldName the field name
+ * @param array the array to add to the <code>toString</code>
+ * @return this
+ */
+ public ToStringBuilder append(String fieldName, long[] array) {
+ style.append(buffer, fieldName, array, null);
+ return this;
+ }
+
+ /**
+ * <p>Append to the <code>toString</code> a <code>long</code>
+ * array.</p>
+ *
+ * <p>A boolean parameter controls the level of detail to show.
+ * Setting <code>true</code> will output the array in full. Setting
+ * <code>false</code> will output a summary, typically the size of
+ * the array.</p>
+ *
+ * @param fieldName the field name
+ * @param array the array to add to the <code>toString</code>
+ * @param fullDetail <code>true</code> for detail, <code>false</code>
+ * for summary info
+ * @return this
+ */
+ public ToStringBuilder append(String fieldName, long[] array, boolean fullDetail) {
+ style.append(buffer, fieldName, array, BooleanUtils.toBooleanObject(fullDetail));
+ return this;
+ }
+
+ /**
+ * <p>Append to the <code>toString</code> an <code>Object</code>
+ * value.</p>
+ *
+ * @param fieldName the field name
+ * @param object the value to add to the <code>toString</code>
+ * @return this
+ */
+ public ToStringBuilder append(String fieldName, Object object) {
+ style.append(buffer, fieldName, object, null);
+ return this;
+ }
+
+ /**
+ * <p>Append to the <code>toString</code> an <code>Object</code>
+ * value.</p>
+ *
+ * @param fieldName the field name
+ * @param object the value to add to the <code>toString</code>
+ * @param fullDetail <code>true</code> for detail,
+ * <code>false</code> for summary info
+ * @return this
+ */
+ public ToStringBuilder append(String fieldName, Object object, boolean fullDetail) {
+ style.append(buffer, fieldName, object, BooleanUtils.toBooleanObject(fullDetail));
+ return this;
+ }
+
+ /**
+ * <p>Append to the <code>toString</code> an <code>Object</code>
+ * array.</p>
+ *
+ * @param fieldName the field name
+ * @param array the array to add to the <code>toString</code>
+ * @return this
+ */
+ public ToStringBuilder append(String fieldName, Object[] array) {
+ style.append(buffer, fieldName, array, null);
+ return this;
+ }
+
+ /**
+ * <p>Append to the <code>toString</code> an <code>Object</code>
+ * array.</p>
+ *
+ * <p>A boolean parameter controls the level of detail to show.
+ * Setting <code>true</code> will output the array in full. Setting
+ * <code>false</code> will output a summary, typically the size of
+ * the array.</p>
+ *
+ * @param fieldName the field name
+ * @param array the array to add to the <code>toString</code>
+ * @param fullDetail <code>true</code> for detail, <code>false</code>
+ * for summary info
+ * @return this
+ */
+ public ToStringBuilder append(String fieldName, Object[] array, boolean fullDetail) {
+ style.append(buffer, fieldName, array, BooleanUtils.toBooleanObject(fullDetail));
+ return this;
+ }
+
+ /**
+ * <p>Append to the <code>toString</code> an <code>short</code>
+ * value.</p>
+ *
+ * @param fieldName the field name
+ * @param value the value to add to the <code>toString</code>
+ * @return this
+ */
+ public ToStringBuilder append(String fieldName, short value) {
+ style.append(buffer, fieldName, value);
+ return this;
+ }
+
+ /**
+ * <p>Append to the <code>toString</code> a <code>short</code>
+ * array.</p>
+ *
+ * @param fieldName the field name
+ * @param array the array to add to the <code>toString</code>
+ * @return this
+ */
+ public ToStringBuilder append(String fieldName, short[] array) {
+ style.append(buffer, fieldName, array, null);
+ return this;
+ }
+
+ /**
+ * <p>Append to the <code>toString</code> a <code>short</code>
+ * array.</p>
+ *
+ * <p>A boolean parameter controls the level of detail to show.
+ * Setting <code>true</code> will output the array in full. Setting
+ * <code>false</code> will output a summary, typically the size of
+ * the array.
+ *
+ * @param fieldName the field name
+ * @param array the array to add to the <code>toString</code>
+ * @param fullDetail <code>true</code> for detail, <code>false</code>
+ * for summary info
+ * @return this
+ */
+ public ToStringBuilder append(String fieldName, short[] array, boolean fullDetail) {
+ style.append(buffer, fieldName, array, BooleanUtils.toBooleanObject(fullDetail));
+ return this;
+ }
+
+ /**
+ * <p>Appends with the same format as the default <code>Object toString()
+ * </code> method. Appends the class name followed by
+ * {@link System#identityHashCode(java.lang.Object)}.</p>
+ *
+ * @param object the <code>Object</code> whose class name and id to output
+ * @return this
+ * @since 2.0
+ */
+ public ToStringBuilder appendAsObjectToString(Object object) {
+ ObjectUtils.appendIdentityToString(this.getStringBuffer(), object);
+ return this;
+ }
+
+ //----------------------------------------------------------------------------
+
+ /**
+ * <p>Append the <code>toString</code> from the superclass.</p>
+ *
+ * <p>This method assumes that the superclass uses the same <code>ToStringStyle</code>
+ * as this one.</p>
+ *
+ * <p>If <code>superToString</code> is <code>null</code>, no change is made.</p>
+ *
+ * @param superToString the result of <code>super.toString()</code>
+ * @return this
+ * @since 2.0
+ */
+ public ToStringBuilder appendSuper(String superToString) {
+ if (superToString != null) {
+ style.appendSuper(buffer, superToString);
+ }
+ return this;
+ }
+
+ /**
+ * <p>Append the <code>toString</code> from another object.</p>
+ *
+ * <p>This method is useful where a class delegates most of the implementation of
+ * its properties to another class. You can then call <code>toString()</code> on
+ * the other class and pass the result into this method.</p>
+ *
+ * <pre>
+ * private AnotherObject delegate;
+ * private String fieldInThisClass;
+ *
+ * public String toString() {
+ * return new ToStringBuilder(this).
+ * appendToString(delegate.toString()).
+ * append(fieldInThisClass).
+ * toString();
+ * }</pre>
+ *
+ * <p>This method assumes that the other object uses the same <code>ToStringStyle</code>
+ * as this one.</p>
+ *
+ * <p>If the <code>toString</code> is <code>null</code>, no change is made.</p>
+ *
+ * @param toString the result of <code>toString()</code> on another object
+ * @return this
+ * @since 2.0
+ */
+ public ToStringBuilder appendToString(String toString) {
+ if (toString != null) {
+ style.appendToString(buffer, toString);
+ }
+ return this;
+ }
+
+ /**
+ * <p>Returns the <code>Object</code> being output.</p>
+ *
+ * @return The object being output.
+ * @since 2.0
+ */
+ public Object getObject() {
+ return object;
+ }
+
+ /**
+ * <p>Gets the <code>StringBuffer</code> being populated.</p>
+ *
+ * @return the <code>StringBuffer</code> being populated
+ */
+ public StringBuffer getStringBuffer() {
+ return buffer;
+ }
+
+ //----------------------------------------------------------------------------
+
+ /**
+ * <p>Gets the <code>ToStringStyle</code> being used.</p>
+ *
+ * @return the <code>ToStringStyle</code> being used
+ * @since 2.0
+ */
+ public ToStringStyle getStyle() {
+ return style;
+ }
+
+ /**
+ * <p>Returns the built <code>toString</code>.</p>
+ *
+ * <p>This method appends the end of data indicator, and can only be called once.
+ * Use {@link #getStringBuffer} to get the current string state.</p>
+ *
+ * <p>If the object is <code>null</code>, return the style's <code>nullText</code></p>
+ *
+ * @return the String <code>toString</code>
+ */
+ public String toString() {
+ if (this.getObject() == null) {
+ this.getStringBuffer().append(this.getStyle().getNullText());
+ } else {
+ style.appendEnd(this.getStringBuffer(), this.getObject());
+ }
+ return this.getStringBuffer().toString();
+ }
+
+}
Added: incubator/directory/ldap/trunk/common/src/java/org/apache/ldap/common/util/ToStringStyle.java
==============================================================================
--- (empty file)
+++ incubator/directory/ldap/trunk/common/src/java/org/apache/ldap/common/util/ToStringStyle.java Sat Sep 25 12:11:47 2004
@@ -0,0 +1,2186 @@
+/*
+ * Copyright 2002-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.ldap.common.util;
+
+
+import java.io.Serializable;
+import java.lang.reflect.Array;
+import java.util.Collection;
+import java.util.Map;
+
+
+/**
+ * <p>Controls <code>String</code> formatting for {@link ToStringBuilder}.
+ * The main public interface is always via <code>ToStringBuilder</code>.</p>
+ *
+ * <p>These classes are intended to be used as <code>Singletons</code>.
+ * There is no need to instantiate a new style each time. A program
+ * will generally use one of the predefined constants on this class.
+ * Alternatively, the {@link } class can be used
+ * to set the individual settings. Thus most styles can be achieved
+ * without subclassing.</p>
+ *
+ * <p>If required, a subclass can override as many or as few of the
+ * methods as it requires. Each object type (from <code>boolean</code>
+ * to <code>long</code> to <code>Object</code> to <code>int[]</code>) has
+ * its own methods to output it. Most have two versions, detail and summary.
+ *
+ * <p>For example, the detail version of the array based methods will
+ * output the whole array, whereas the summary method will just output
+ * the array length.</p>
+ *
+ * @author Stephen Colebourne
+ * @author Gary Gregory
+ * @author Pete Gieser
+ * @since 1.0
+ * @version $Id: ToStringStyle.java,v 1.32 2004/07/01 17:40:10 ggregory Exp $
+ */
+public abstract class ToStringStyle implements Serializable {
+
+ /**
+ * The default toString style.
+ */
+ public static final ToStringStyle DEFAULT_STYLE = new DefaultToStringStyle();
+
+ /**
+ * The multi line toString style.
+ */
+ public static final ToStringStyle MULTI_LINE_STYLE = new MultiLineToStringStyle();
+
+ /**
+ * The no field names toString style.
+ */
+ public static final ToStringStyle NO_FIELD_NAMES_STYLE = new NoFieldNameToStringStyle();
+
+ /**
+ * The short prefix toString style.
+ */
+ public static final ToStringStyle SHORT_PREFIX_STYLE = new ShortPrefixToStringStyle();
+
+ /**
+ * The simple toString style.
+ */
+ public static final ToStringStyle SIMPLE_STYLE = new SimpleToStringStyle();
+
+ /**
+ * Whether to use the field names, the default is <code>true</code>.
+ */
+ private boolean useFieldNames = true;
+
+ /**
+ * Whether to use the class name, the default is <code>true</code>.
+ */
+ private boolean useClassName = true;
+
+ /**
+ * Whether to use short class names, the default is <code>false</code>.
+ */
+ private boolean useShortClassName = false;
+
+ /**
+ * Whether to use the identity hash code, the default is <code>true</code>.
+ */
+ private boolean useIdentityHashCode = true;
+
+ /**
+ * The content start <code>'['</code>.
+ */
+ private String contentStart = "[";
+
+ /**
+ * The content end <code>']'</code>.
+ */
+ private String contentEnd = "]";
+
+ /**
+ * The field name value separator <code>'='</code>.
+ */
+ private String fieldNameValueSeparator = "=";
+
+ /**
+ * Whether the field separator should be added before any other fields.
+ */
+ private boolean fieldSeparatorAtStart = false;
+
+ /**
+ * Whether the field separator should be added after any other fields.
+ */
+ private boolean fieldSeparatorAtEnd = false;
+
+ /**
+ * The field separator <code>','</code>.
+ */
+ private String fieldSeparator = ",";
+
+ /**
+ * The array start <code>'{'</code>.
+ */
+ private String arrayStart = "{";
+
+ /**
+ * The array separator <code>','</code>.
+ */
+ private String arraySeparator = ",";
+
+ /**
+ * The detail for array content.
+ */
+ private boolean arrayContentDetail = true;
+
+ /**
+ * The array end <code>'}'</code>.
+ */
+ private String arrayEnd = "}";
+
+ /**
+ * The value to use when fullDetail is <code>null</code>,
+ * the default value is <code>true</code>.
+ */
+ private boolean defaultFullDetail = true;
+
+ /**
+ * The <code>null</code> text <code>'<null>'</code>.
+ */
+ private String nullText = "<null>";
+
+ /**
+ * The summary size text start <code>'<size'</code>.
+ */
+ private String sizeStartText = "<size=";
+
+ /**
+ * The summary size text start <code>'>'</code>.
+ */
+ private String sizeEndText = ">";
+
+ /**
+ * The summary object text start <code>'<'</code>.
+ */
+ private String summaryObjectStartText = "<";
+
+ /**
+ * The summary object text start <code>'>'</code>.
+ */
+ private String summaryObjectEndText = ">";
+
+ //----------------------------------------------------------------------------
+
+ /**
+ * <p>Constructor.</p>
+ */
+ protected ToStringStyle() {
+ super();
+ }
+
+ //----------------------------------------------------------------------------
+
+ /**
+ * <p>Append to the <code>toString</code> the superclass toString.</p>
+ *
+ * <p>A <code>null</code> <code>superToString</code> is ignored.</p>
+ *
+ * @param buffer the <code>StringBuffer</code> to populate
+ * @param superToString the <code>super.toString()</code>
+ * @since 2.0
+ */
+ public void appendSuper(StringBuffer buffer, String superToString) {
+ appendToString(buffer, superToString);
+ }
+
+ /**
+ * <p>Append to the <code>toString</code> another toString.</p>
+ *
+ * <p>A <code>null</code> <code>toString</code> is ignored.</p>
+ *
+ * @param buffer the <code>StringBuffer</code> to populate
+ * @param toString the additional <code>toString</code>
+ * @since 2.0
+ */
+ public void appendToString(StringBuffer buffer, String toString) {
+ if (toString != null) {
+ int pos1 = toString.indexOf(contentStart) + contentStart.length();
+ int pos2 = toString.lastIndexOf(contentEnd);
+ if (pos1 != pos2 && pos1 >= 0 && pos2 >= 0) {
+ String data = toString.substring(pos1, pos2);
+ if (fieldSeparatorAtStart) {
+ removeLastFieldSeparator(buffer);
+ }
+ buffer.append(data);
+ appendFieldSeparator(buffer);
+ }
+ }
+ }
+
+ /**
+ * <p>Append to the <code>toString</code> the start of data indicator.</p>
+ *
+ * @param buffer the <code>StringBuffer</code> to populate
+ * @param object the <code>Object</code> to build a <code>toString</code> for
+ */
+ public void appendStart(StringBuffer buffer, Object object) {
+ if (object != null) {
+ appendClassName(buffer, object);
+ appendIdentityHashCode(buffer, object);
+ appendContentStart(buffer);
+ if (fieldSeparatorAtStart) {
+ appendFieldSeparator(buffer);
+ }
+ }
+ }
+
+ /**
+ * <p>Append to the <code>toString</code> the end of data indicator.</p>
+ *
+ * @param buffer the <code>StringBuffer</code> to populate
+ * @param object the <code>Object</code> to build a
+ * <code>toString</code> for.
+ */
+ public void appendEnd(StringBuffer buffer, Object object) {
+ if (this.fieldSeparatorAtEnd == false) {
+ removeLastFieldSeparator(buffer);
+ }
+ appendContentEnd(buffer);
+ }
+
+ /**
+ * <p>Remove the last field separator from the buffer.</p>
+ *
+ * @param buffer the <code>StringBuffer</code> to populate
+ * @since 2.0
+ */
+ protected void removeLastFieldSeparator(StringBuffer buffer) {
+ int len = buffer.length();
+ int sepLen = fieldSeparator.length();
+ if (len > 0 && sepLen > 0 && len >= sepLen) {
+ boolean match = true;
+ for (int i = 0; i < sepLen; i++) {
+ if (buffer.charAt(len - 1 - i) != fieldSeparator.charAt(sepLen - 1 - i)) {
+ match = false;
+ break;
+ }
+ }
+ if (match) {
+ buffer.setLength(len - sepLen);
+ }
+ }
+ }
+
+ //----------------------------------------------------------------------------
+
+ /**
+ * <p>Append to the <code>toString</code> an <code>Object</code>
+ * value, printing the full <code>toString</code> of the
+ * <code>Object</code> passed in.</p>
+ *
+ * @param buffer the <code>StringBuffer</code> to populate
+ * @param fieldName the field name
+ * @param value the value to add to the <code>toString</code>
+ * @param fullDetail <code>true</code> for detail, <code>false</code>
+ * for summary info, <code>null</code> for style decides
+ */
+ public void append(StringBuffer buffer, String fieldName, Object value, Boolean fullDetail) {
+ appendFieldStart(buffer, fieldName);
+
+ if (value == null) {
+ appendNullText(buffer, fieldName);
+
+ } else {
+ appendInternal(buffer, fieldName, value, isFullDetail(fullDetail));
+ }
+
+ appendFieldEnd(buffer, fieldName);
+ }
+
+ /**
+ * <p>Append to the <code>toString</code> an <code>Object</code>,
+ * correctly interpreting its type.</p>
+ *
+ * <p>This method performs the main lookup by Class type to correctly
+ * route arrays, <code>Collections</code>, <code>Maps</code> and
+ * <code>Objects</code> to the appropriate method.</p>
+ *
+ * <p>Either detail or summary views can be specified.</p>
+ *
+ * <p>If a cycle is detected, an object will be appended with the
+ * <code>Object.toString()</code> format.</p>
+ *
+ * @param buffer the <code>StringBuffer</code> to populate
+ * @param fieldName the field name, typically not used as already appended
+ * @param value the value to add to the <code>toString</code>,
+ * not <code>null</code>
+ * @param detail output detail or not
+ */
+ protected void appendInternal(StringBuffer buffer, String fieldName, Object value, boolean detail) {
+ if (ReflectionToStringBuilder.isRegistered(value)
+ && !(value instanceof Number || value instanceof Boolean || value instanceof Character)) {
+ ObjectUtils.appendIdentityToString(buffer, value);
+
+ } else if (value instanceof Collection) {
+ if (detail) {
+ appendDetail(buffer, fieldName, (Collection) value);
+ } else {
+ appendSummarySize(buffer, fieldName, ((Collection) value).size());
+ }
+
+ } else if (value instanceof Map) {
+ if (detail) {
+ appendDetail(buffer, fieldName, (Map) value);
+ } else {
+ appendSummarySize(buffer, fieldName, ((Map) value).size());
+ }
+
+ } else if (value instanceof long[]) {
+ if (detail) {
+ appendDetail(buffer, fieldName, (long[]) value);
+ } else {
+ appendSummary(buffer, fieldName, (long[]) value);
+ }
+
+ } else if (value instanceof int[]) {
+ if (detail) {
+ appendDetail(buffer, fieldName, (int[]) value);
+ } else {
+ appendSummary(buffer, fieldName, (int[]) value);
+ }
+
+ } else if (value instanceof short[]) {
+ if (detail) {
+ appendDetail(buffer, fieldName, (short[]) value);
+ } else {
+ appendSummary(buffer, fieldName, (short[]) value);
+ }
+
+ } else if (value instanceof byte[]) {
+ if (detail) {
+ appendDetail(buffer, fieldName, (byte[]) value);
+ } else {
+ appendSummary(buffer, fieldName, (byte[]) value);
+ }
+
+ } else if (value instanceof char[]) {
+ if (detail) {
+ appendDetail(buffer, fieldName, (char[]) value);
+ } else {
+ appendSummary(buffer, fieldName, (char[]) value);
+ }
+
+ } else if (value instanceof double[]) {
+ if (detail) {
+ appendDetail(buffer, fieldName, (double[]) value);
+ } else {
+ appendSummary(buffer, fieldName, (double[]) value);
+ }
+
+ } else if (value instanceof float[]) {
+ if (detail) {
+ appendDetail(buffer, fieldName, (float[]) value);
+ } else {
+ appendSummary(buffer, fieldName, (float[]) value);
+ }
+
+ } else if (value instanceof boolean[]) {
+ if (detail) {
+ appendDetail(buffer, fieldName, (boolean[]) value);
+ } else {
+ appendSummary(buffer, fieldName, (boolean[]) value);
+ }
+
+ } else if (value.getClass().isArray()) {
+ if (detail) {
+ appendDetail(buffer, fieldName, (Object[]) value);
+ } else {
+ appendSummary(buffer, fieldName, (Object[]) value);
+ }
+
+ } else {
+ if (detail) {
+ appendDetail(buffer, fieldName, value);
+ } else {
+ appendSummary(buffer, fieldName, value);
+ }
+ }
+ }
+
+ /**
+ * <p>Append to the <code>toString</code> an <code>Object</code>
+ * value, printing the full detail of the <code>Object</code>.</p>
+ *
+ * @param buffer the <code>StringBuffer</code> to populate
+ * @param fieldName the field name, typically not used as already appended
+ * @param value the value to add to the <code>toString</code>,
+ * not <code>null</code>
+ */
+ protected void appendDetail(StringBuffer buffer, String fieldName, Object value) {
+ buffer.append(value);
+ }
+
+ /**
+ * <p>Append to the <code>toString</code> a <code>Collection</code>.</p>
+ *
+ * @param buffer the <code>StringBuffer</code> to populate
+ * @param fieldName the field name, typically not used as already appended
+ * @param coll the <code>Collection</code> to add to the
+ * <code>toString</code>, not <code>null</code>
+ */
+ protected void appendDetail(StringBuffer buffer, String fieldName, Collection coll) {
+ buffer.append(coll);
+ }
+
+ /**
+ * <p>Append to the <code>toString</code> a <code>Map<code>.</p>
+ *
+ * @param buffer the <code>StringBuffer</code> to populate
+ * @param fieldName the field name, typically not used as already appended
+ * @param map the <code>Map</code> to add to the <code>toString</code>,
+ * not <code>null</code>
+ */
+ protected void appendDetail(StringBuffer buffer, String fieldName, Map map) {
+ buffer.append(map);
+ }
+
+ /**
+ * <p>Append to the <code>toString</code> an <code>Object</code>
+ * value, printing a summary of the <code>Object</code>.</P>
+ *
+ * @param buffer the <code>StringBuffer</code> to populate
+ * @param fieldName the field name, typically not used as already appended
+ * @param value the value to add to the <code>toString</code>,
+ * not <code>null</code>
+ */
+ protected void appendSummary(StringBuffer buffer, String fieldName, Object value) {
+ buffer.append(summaryObjectStartText);
+ buffer.append(getShortClassName(value.getClass()));
+ buffer.append(summaryObjectEndText);
+ }
+
+ //----------------------------------------------------------------------------
+
+ /**
+ * <p>Append to the <code>toString</code> a <code>long</code>
+ * value.</p>
+ *
+ * @param buffer the <code>StringBuffer</code> to populate
+ * @param fieldName the field name
+ * @param value the value to add to the <code>toString</code>
+ */
+ public void append(StringBuffer buffer, String fieldName, long value) {
+ appendFieldStart(buffer, fieldName);
+ appendDetail(buffer, fieldName, value);
+ appendFieldEnd(buffer, fieldName);
+ }
+
+ /**
+ * <p>Append to the <code>toString</code> a <code>long</code>
+ * value.</p>
+ *
+ * @param buffer the <code>StringBuffer</code> to populate
+ * @param fieldName the field name, typically not used as already appended
+ * @param value the value to add to the <code>toString</code>
+ */
+ protected void appendDetail(StringBuffer buffer, String fieldName, long value) {
+ buffer.append(value);
+ }
+
+ //----------------------------------------------------------------------------
+
+ /**
+ * <p>Append to the <code>toString</code> an <code>int</code>
+ * value.</p>
+ *
+ * @param buffer the <code>StringBuffer</code> to populate
+ * @param fieldName the field name
+ * @param value the value to add to the <code>toString</code>
+ */
+ public void append(StringBuffer buffer, String fieldName, int value) {
+ appendFieldStart(buffer, fieldName);
+ appendDetail(buffer, fieldName, value);
+ appendFieldEnd(buffer, fieldName);
+ }
+
+ /**
+ * <p>Append to the <code>toString</code> an <code>int</code>
+ * value.</p>
+ *
+ * @param buffer the <code>StringBuffer</code> to populate
+ * @param fieldName the field name, typically not used as already appended
+ * @param value the value to add to the <code>toString</code>
+ */
+ protected void appendDetail(StringBuffer buffer, String fieldName, int value) {
+ buffer.append(value);
+ }
+
+ //----------------------------------------------------------------------------
+
+ /**
+ * <p>Append to the <code>toString</code> a <code>short</code>
+ * value.</p>
+ *
+ * @param buffer the <code>StringBuffer</code> to populate
+ * @param fieldName the field name
+ * @param value the value to add to the <code>toString</code>
+ */
+ public void append(StringBuffer buffer, String fieldName, short value) {
+ appendFieldStart(buffer, fieldName);
+ appendDetail(buffer, fieldName, value);
+ appendFieldEnd(buffer, fieldName);
+ }
+
+ /**
+ * <p>Append to the <code>toString</code> a <code>short</code>
+ * value.</p>
+ *
+ * @param buffer the <code>StringBuffer</code> to populate
+ * @param fieldName the field name, typically not used as already appended
+ * @param value the value to add to the <code>toString</code>
+ */
+ protected void appendDetail(StringBuffer buffer, String fieldName, short value) {
+ buffer.append(value);
+ }
+
+ //----------------------------------------------------------------------------
+
+ /**
+ * <p>Append to the <code>toString</code> a <code>byte</code>
+ * value.</p>
+ *
+ * @param buffer the <code>StringBuffer</code> to populate
+ * @param fieldName the field name
+ * @param value the value to add to the <code>toString</code>
+ */
+ public void append(StringBuffer buffer, String fieldName, byte value) {
+ appendFieldStart(buffer, fieldName);
+ appendDetail(buffer, fieldName, value);
+ appendFieldEnd(buffer, fieldName);
+ }
+
+ /**
+ * <p>Append to the <code>toString</code> a <code>byte</code>
+ * value.</p>
+ *
+ * @param buffer the <code>StringBuffer</code> to populate
+ * @param fieldName the field name, typically not used as already appended
+ * @param value the value to add to the <code>toString</code>
+ */
+ protected void appendDetail(StringBuffer buffer, String fieldName, byte value) {
+ buffer.append(value);
+ }
+
+ //----------------------------------------------------------------------------
+
+ /**
+ * <p>Append to the <code>toString</code> a <code>char</code>
+ * value.</p>
+ *
+ * @param buffer the <code>StringBuffer</code> to populate
+ * @param fieldName the field name
+ * @param value the value to add to the <code>toString</code>
+ */
+ public void append(StringBuffer buffer, String fieldName, char value) {
+ appendFieldStart(buffer, fieldName);
+ appendDetail(buffer, fieldName, value);
+ appendFieldEnd(buffer, fieldName);
+ }
+
+ /**
+ * <p>Append to the <code>toString</code> a <code>char</code>
+ * value.</p>
+ *
+ * @param buffer the <code>StringBuffer</code> to populate
+ * @param fieldName the field name, typically not used as already appended
+ * @param value the value to add to the <code>toString</code>
+ */
+ protected void appendDetail(StringBuffer buffer, String fieldName, char value) {
+ buffer.append(value);
+ }
+
+ //----------------------------------------------------------------------------
+
+ /**
+ * <p>Append to the <code>toString</code> a <code>double</code>
+ * value.</p>
+ *
+ * @param buffer the <code>StringBuffer</code> to populate
+ * @param fieldName the field name
+ * @param value the value to add to the <code>toString</code>
+ */
+ public void append(StringBuffer buffer, String fieldName, double value) {
+ appendFieldStart(buffer, fieldName);
+ appendDetail(buffer, fieldName, value);
+ appendFieldEnd(buffer, fieldName);
+ }
+
+ /**
+ * <p>Append to the <code>toString</code> a <code>double</code>
+ * value.</p>
+ *
+ * @param buffer the <code>StringBuffer</code> to populate
+ * @param fieldName the field name, typically not used as already appended
+ * @param value the value to add to the <code>toString</code>
+ */
+ protected void appendDetail(StringBuffer buffer, String fieldName, double value) {
+ buffer.append(value);
+ }
+
+ //----------------------------------------------------------------------------
+
+ /**
+ * <p>Append to the <code>toString</code> a <code>float</code>
+ * value.</p>
+ *
+ * @param buffer the <code>StringBuffer</code> to populate
+ * @param fieldName the field name
+ * @param value the value to add to the <code>toString</code>
+ */
+ public void append(StringBuffer buffer, String fieldName, float value) {
+ appendFieldStart(buffer, fieldName);
+ appendDetail(buffer, fieldName, value);
+ appendFieldEnd(buffer, fieldName);
+ }
+
+ /**
+ * <p>Append to the <code>toString</code> a <code>float</code>
+ * value.</p>
+ *
+ * @param buffer the <code>StringBuffer</code> to populate
+ * @param fieldName the field name, typically not used as already appended
+ * @param value the value to add to the <code>toString</code>
+ */
+ protected void appendDetail(StringBuffer buffer, String fieldName, float value) {
+ buffer.append(value);
+ }
+
+ //----------------------------------------------------------------------------
+
+ /**
+ * <p>Append to the <code>toString</code> a <code>boolean</code>
+ * value.</p>
+ *
+ * @param buffer the <code>StringBuffer</code> to populate
+ * @param fieldName the field name
+ * @param value the value to add to the <code>toString</code>
+ */
+ public void append(StringBuffer buffer, String fieldName, boolean value) {
+ appendFieldStart(buffer, fieldName);
+ appendDetail(buffer, fieldName, value);
+ appendFieldEnd(buffer, fieldName);
+ }
+
+ /**
+ * <p>Append to the <code>toString</code> a <code>boolean</code>
+ * value.</p>
+ *
+ * @param buffer the <code>StringBuffer</code> to populate
+ * @param fieldName the field name, typically not used as already appended
+ * @param value the value to add to the <code>toString</code>
+ */
+ protected void appendDetail(StringBuffer buffer, String fieldName, boolean value) {
+ buffer.append(value);
+ }
+
+ /**
+ * <p>Append to the <code>toString</code> an <code>Object</code>
+ * array.</p>
+ *
+ * @param buffer the <code>StringBuffer</code> to populate
+ * @param fieldName the field name
+ * @param array the array to add to the toString
+ * @param fullDetail <code>true</code> for detail, <code>false</code>
+ * for summary info, <code>null</code> for style decides
+ */
+ public void append(StringBuffer buffer, String fieldName, Object[] array, Boolean fullDetail) {
+ appendFieldStart(buffer, fieldName);
+
+ if (array == null) {
+ appendNullText(buffer, fieldName);
+
+ } else if (isFullDetail(fullDetail)) {
+ appendDetail(buffer, fieldName, array);
+
+ } else {
+ appendSummary(buffer, fieldName, array);
+ }
+
+ appendFieldEnd(buffer, fieldName);
+ }
+
+ //----------------------------------------------------------------------------
+
+ /**
+ * <p>Append to the <code>toString</code> the detail of an
+ * <code>Object</code> array.</p>
+ *
+ * @param buffer the <code>StringBuffer</code> to populate
+ * @param fieldName the field name, typically not used as already appended
+ * @param array the array to add to the <code>toString</code>,
+ * not <code>null</code>
+ */
+ protected void appendDetail(StringBuffer buffer, String fieldName, Object[] array) {
+ buffer.append(arrayStart);
+ for (int i = 0; i < array.length; i++) {
+ Object item = array[i];
+ if (i > 0) {
+ buffer.append(arraySeparator);
+ }
+ if (item == null) {
+ appendNullText(buffer, fieldName);
+
+ } else {
+ appendInternal(buffer, fieldName, item, arrayContentDetail);
+ }
+ }
+ buffer.append(arrayEnd);
+ }
+
+ /**
+ * <p>Append to the <code>toString</code> the detail of an array type.</p>
+ *
+ * @param buffer the <code>StringBuffer</code> to populate
+ * @param fieldName the field name, typically not used as already appended
+ * @param array the array to add to the <code>toString</code>,
+ * not <code>null</code>
+ * @since 2.0
+ */
+ protected void reflectionAppendArrayDetail(StringBuffer buffer, String fieldName, Object array) {
+ buffer.append(arrayStart);
+ int length = Array.getLength(array);
+ for (int i = 0; i < length; i++) {
+ Object item = Array.get(array, i);
+ if (i > 0) {
+ buffer.append(arraySeparator);
+ }
+ if (item == null) {
+ appendNullText(buffer, fieldName);
+
+ } else {
+ appendInternal(buffer, fieldName, item, arrayContentDetail);
+ }
+ }
+ buffer.append(arrayEnd);
+ }
+
+ /**
+ * <p>Append to the <code>toString</code> a summary of an
+ * <code>Object</code> array.</p>
+ *
+ * @param buffer the <code>StringBuffer</code> to populate
+ * @param fieldName the field name, typically not used as already appended
+ * @param array the array to add to the <code>toString</code>,
+ * not <code>null</code>
+ */
+ protected void appendSummary(StringBuffer buffer, String fieldName, Object[] array) {
+ appendSummarySize(buffer, fieldName, array.length);
+ }
+
+ //----------------------------------------------------------------------------
+
+ /**
+ * <p>Append to the <code>toString</code> a <code>long</code>
+ * array.</p>
+ *
+ * @param buffer the <code>StringBuffer</code> to populate
+ * @param fieldName the field name
+ * @param array the array to add to the <code>toString</code>
+ * @param fullDetail <code>true</code> for detail, <code>false</code>
+ * for summary info, <code>null</code> for style decides
+ */
+ public void append(StringBuffer buffer, String fieldName, long[] array, Boolean fullDetail) {
+ appendFieldStart(buffer, fieldName);
+
+ if (array == null) {
+ appendNullText(buffer, fieldName);
+
+ } else if (isFullDetail(fullDetail)) {
+ appendDetail(buffer, fieldName, array);
+
+ } else {
+ appendSummary(buffer, fieldName, array);
+ }
+
+ appendFieldEnd(buffer, fieldName);
+ }
+
+ /**
+ * <p>Append to the <code>toString</code> the detail of a
+ * <code>long</code> array.</p>
+ *
+ * @param buffer the <code>StringBuffer</code> to populate
+ * @param fieldName the field name, typically not used as already appended
+ * @param array the array to add to the <code>toString</code>,
+ * not <code>null</code>
+ */
+ protected void appendDetail(StringBuffer buffer, String fieldName, long[] array) {
+ buffer.append(arrayStart);
+ for (int i = 0; i < array.length; i++) {
+ if (i > 0) {
+ buffer.append(arraySeparator);
+ }
+ appendDetail(buffer, fieldName, array[i]);
+ }
+ buffer.append(arrayEnd);
+ }
+
+ /**
+ * <p>Append to the <code>toString</code> a summary of a
+ * <code>long</code> array.</p>
+ *
+ * @param buffer the <code>StringBuffer</code> to populate
+ * @param fieldName the field name, typically not used as already appended
+ * @param array the array to add to the <code>toString</code>,
+ * not <code>null</code>
+ */
+ protected void appendSummary(StringBuffer buffer, String fieldName, long[] array) {
+ appendSummarySize(buffer, fieldName, array.length);
+ }
+
+ //----------------------------------------------------------------------------
+
+ /**
+ * <p>Append to the <code>toString</code> an <code>int</code>
+ * array.</p>
+ *
+ * @param buffer the <code>StringBuffer</code> to populate
+ * @param fieldName the field name
+ * @param array the array to add to the <code>toString</code>
+ * @param fullDetail <code>true</code> for detail, <code>false</code>
+ * for summary info, <code>null</code> for style decides
+ */
+ public void append(StringBuffer buffer, String fieldName, int[] array, Boolean fullDetail) {
+ appendFieldStart(buffer, fieldName);
+
+ if (array == null) {
+ appendNullText(buffer, fieldName);
+
+ } else if (isFullDetail(fullDetail)) {
+ appendDetail(buffer, fieldName, array);
+
+ } else {
+ appendSummary(buffer, fieldName, array);
+ }
+
+ appendFieldEnd(buffer, fieldName);
+ }
+
+ /**
+ * <p>Append to the <code>toString</code> the detail of an
+ * <code>int</code> array.</p>
+ *
+ * @param buffer the <code>StringBuffer</code> to populate
+ * @param fieldName the field name, typically not used as already appended
+ * @param array the array to add to the <code>toString</code>,
+ * not <code>null</code>
+ */
+ protected void appendDetail(StringBuffer buffer, String fieldName, int[] array) {
+ buffer.append(arrayStart);
+ for (int i = 0; i < array.length; i++) {
+ if (i > 0) {
+ buffer.append(arraySeparator);
+ }
+ appendDetail(buffer, fieldName, array[i]);
+ }
+ buffer.append(arrayEnd);
+ }
+
+ /**
+ * <p>Append to the <code>toString</code> a summary of an
+ * <code>int</code> array.</p>
+ *
+ * @param buffer the <code>StringBuffer</code> to populate
+ * @param fieldName the field name, typically not used as already appended
+ * @param array the array to add to the <code>toString</code>,
+ * not <code>null</code>
+ */
+ protected void appendSummary(StringBuffer buffer, String fieldName, int[] array) {
+ appendSummarySize(buffer, fieldName, array.length);
+ }
+
+ //----------------------------------------------------------------------------
+
+ /**
+ * <p>Append to the <code>toString</code> a <code>short</code>
+ * array.</p>
+ *
+ * @param buffer the <code>StringBuffer</code> to populate
+ * @param fieldName the field name
+ * @param array the array to add to the <code>toString</code>
+ * @param fullDetail <code>true</code> for detail, <code>false</code>
+ * for summary info, <code>null</code> for style decides
+ */
+ public void append(StringBuffer buffer, String fieldName, short[] array, Boolean fullDetail) {
+ appendFieldStart(buffer, fieldName);
+
+ if (array == null) {
+ appendNullText(buffer, fieldName);
+
+ } else if (isFullDetail(fullDetail)) {
+ appendDetail(buffer, fieldName, array);
+
+ } else {
+ appendSummary(buffer, fieldName, array);
+ }
+
+ appendFieldEnd(buffer, fieldName);
+ }
+
+ /**
+ * <p>Append to the <code>toString</code> the detail of a
+ * <code>short</code> array.</p>
+ *
+ * @param buffer the <code>StringBuffer</code> to populate
+ * @param fieldName the field name, typically not used as already appended
+ * @param array the array to add to the <code>toString</code>,
+ * not <code>null</code>
+ */
+ protected void appendDetail(StringBuffer buffer, String fieldName, short[] array) {
+ buffer.append(arrayStart);
+ for (int i = 0; i < array.length; i++) {
+ if (i > 0) {
+ buffer.append(arraySeparator);
+ }
+ appendDetail(buffer, fieldName, array[i]);
+ }
+ buffer.append(arrayEnd);
+ }
+
+ /**
+ * <p>Append to the <code>toString</code> a summary of a
+ * <code>short</code> array.</p>
+ *
+ * @param buffer the <code>StringBuffer</code> to populate
+ * @param fieldName the field name, typically not used as already appended
+ * @param array the array to add to the <code>toString</code>,
+ * not <code>null</code>
+ */
+ protected void appendSummary(StringBuffer buffer, String fieldName, short[] array) {
+ appendSummarySize(buffer, fieldName, array.length);
+ }
+
+ //----------------------------------------------------------------------------
+
+ /**
+ * <p>Append to the <code>toString</code> a <code>byte</code>
+ * array.</p>
+ *
+ * @param buffer the <code>StringBuffer</code> to populate
+ * @param fieldName the field name
+ * @param array the array to add to the <code>toString</code>
+ * @param fullDetail <code>true</code> for detail, <code>false</code>
+ * for summary info, <code>null</code> for style decides
+ */
+ public void append(StringBuffer buffer, String fieldName, byte[] array, Boolean fullDetail) {
+ appendFieldStart(buffer, fieldName);
+
+ if (array == null) {
+ appendNullText(buffer, fieldName);
+
+ } else if (isFullDetail(fullDetail)) {
+ appendDetail(buffer, fieldName, array);
+
+ } else {
+ appendSummary(buffer, fieldName, array);
+ }
+
+ appendFieldEnd(buffer, fieldName);
+ }
+
+ /**
+ * <p>Append to the <code>toString</code> the detail of a
+ * <code>byte</code> array.</p>
+ *
+ * @param buffer the <code>StringBuffer</code> to populate
+ * @param fieldName the field name, typically not used as already appended
+ * @param array the array to add to the <code>toString</code>,
+ * not <code>null</code>
+ */
+ protected void appendDetail(StringBuffer buffer, String fieldName, byte[] array) {
+ buffer.append(arrayStart);
+ for (int i = 0; i < array.length; i++) {
+ if (i > 0) {
+ buffer.append(arraySeparator);
+ }
+ appendDetail(buffer, fieldName, array[i]);
+ }
+ buffer.append(arrayEnd);
+ }
+
+ /**
+ * <p>Append to the <code>toString</code> a summary of a
+ * <code>byte</code> array.</p>
+ *
+ * @param buffer the <code>StringBuffer</code> to populate
+ * @param fieldName the field name, typically not used as already appended
+ * @param array the array to add to the <code>toString</code>,
+ * not <code>null</code>
+ */
+ protected void appendSummary(StringBuffer buffer, String fieldName, byte[] array) {
+ appendSummarySize(buffer, fieldName, array.length);
+ }
+
+ //----------------------------------------------------------------------------
+
+ /**
+ * <p>Append to the <code>toString</code> a <code>char</code>
+ * array.</p>
+ *
+ * @param buffer the <code>StringBuffer</code> to populate
+ * @param fieldName the field name
+ * @param array the array to add to the <code>toString</code>
+ * @param fullDetail <code>true</code> for detail, <code>false</code>
+ * for summary info, <code>null</code> for style decides
+ */
+ public void append(StringBuffer buffer, String fieldName, char[] array, Boolean fullDetail) {
+ appendFieldStart(buffer, fieldName);
+
+ if (array == null) {
+ appendNullText(buffer, fieldName);
+
+ } else if (isFullDetail(fullDetail)) {
+ appendDetail(buffer, fieldName, array);
+
+ } else {
+ appendSummary(buffer, fieldName, array);
+ }
+
+ appendFieldEnd(buffer, fieldName);
+ }
+
+ /**
+ * <p>Append to the <code>toString</code> the detail of a
+ * <code>char</code> array.</p>
+ *
+ * @param buffer the <code>StringBuffer</code> to populate
+ * @param fieldName the field name, typically not used as already appended
+ * @param array the array to add to the <code>toString</code>,
+ * not <code>null</code>
+ */
+ protected void appendDetail(StringBuffer buffer, String fieldName, char[] array) {
+ buffer.append(arrayStart);
+ for (int i = 0; i < array.length; i++) {
+ if (i > 0) {
+ buffer.append(arraySeparator);
+ }
+ appendDetail(buffer, fieldName, array[i]);
+ }
+ buffer.append(arrayEnd);
+ }
+
+ /**
+ * <p>Append to the <code>toString</code> a summary of a
+ * <code>char</code> array.</p>
+ *
+ * @param buffer the <code>StringBuffer</code> to populate
+ * @param fieldName the field name, typically not used as already appended
+ * @param array the array to add to the <code>toString</code>,
+ * not <code>null</code>
+ */
+ protected void appendSummary(StringBuffer buffer, String fieldName, char[] array) {
+ appendSummarySize(buffer, fieldName, array.length);
+ }
+
+ //----------------------------------------------------------------------------
+
+ /**
+ * <p>Append to the <code>toString</code> a <code>double</code>
+ * array.</p>
+ *
+ * @param buffer the <code>StringBuffer</code> to populate
+ * @param fieldName the field name
+ * @param array the array to add to the toString
+ * @param fullDetail <code>true</code> for detail, <code>false</code>
+ * for summary info, <code>null</code> for style decides
+ */
+ public void append(StringBuffer buffer, String fieldName, double[] array, Boolean fullDetail) {
+ appendFieldStart(buffer, fieldName);
+
+ if (array == null) {
+ appendNullText(buffer, fieldName);
+
+ } else if (isFullDetail(fullDetail)) {
+ appendDetail(buffer, fieldName, array);
+
+ } else {
+ appendSummary(buffer, fieldName, array);
+ }
+
+ appendFieldEnd(buffer, fieldName);
+ }
+
+ /**
+ * <p>Append to the <code>toString</code> the detail of a
+ * <code>double</code> array.</p>
+ *
+ * @param buffer the <code>StringBuffer</code> to populate
+ * @param fieldName the field name, typically not used as already appended
+ * @param array the array to add to the <code>toString</code>,
+ * not <code>null</code>
+ */
+ protected void appendDetail(StringBuffer buffer, String fieldName, double[] array) {
+ buffer.append(arrayStart);
+ for (int i = 0; i < array.length; i++) {
+ if (i > 0) {
+ buffer.append(arraySeparator);
+ }
+ appendDetail(buffer, fieldName, array[i]);
+ }
+ buffer.append(arrayEnd);
+ }
+
+ /**
+ * <p>Append to the <code>toString</code> a summary of a
+ * <code>double</code> array.</p>
+ *
+ * @param buffer the <code>StringBuffer</code> to populate
+ * @param fieldName the field name, typically not used as already appended
+ * @param array the array to add to the <code>toString</code>,
+ * not <code>null</code>
+ */
+ protected void appendSummary(StringBuffer buffer, String fieldName, double[] array) {
+ appendSummarySize(buffer, fieldName, array.length);
+ }
+
+ //----------------------------------------------------------------------------
+
+ /**
+ * <p>Append to the <code>toString</code> a <code>float</code>
+ * array.</p>
+ *
+ * @param buffer the <code>StringBuffer</code> to populate
+ * @param fieldName the field name
+ * @param array the array to add to the toString
+ * @param fullDetail <code>true</code> for detail, <code>false</code>
+ * for summary info, <code>null</code> for style decides
+ */
+ public void append(StringBuffer buffer, String fieldName, float[] array, Boolean fullDetail) {
+ appendFieldStart(buffer, fieldName);
+
+ if (array == null) {
+ appendNullText(buffer, fieldName);
+
+ } else if (isFullDetail(fullDetail)) {
+ appendDetail(buffer, fieldName, array);
+
+ } else {
+ appendSummary(buffer, fieldName, array);
+ }
+
+ appendFieldEnd(buffer, fieldName);
+ }
+
+ /**
+ * <p>Append to the <code>toString</code> the detail of a
+ * <code>float</code> array.</p>
+ *
+ * @param buffer the <code>StringBuffer</code> to populate
+ * @param fieldName the field name, typically not used as already appended
+ * @param array the array to add to the <code>toString</code>,
+ * not <code>null</code>
+ */
+ protected void appendDetail(StringBuffer buffer, String fieldName, float[] array) {
+ buffer.append(arrayStart);
+ for (int i = 0; i < array.length; i++) {
+ if (i > 0) {
+ buffer.append(arraySeparator);
+ }
+ appendDetail(buffer, fieldName, array[i]);
+ }
+ buffer.append(arrayEnd);
+ }
+
+ /**
+ * <p>Append to the <code>toString</code> a summary of a
+ * <code>float</code> array.</p>
+ *
+ * @param buffer the <code>StringBuffer</code> to populate
+ * @param fieldName the field name, typically not used as already appended
+ * @param array the array to add to the <code>toString</code>,
+ * not <code>null</code>
+ */
+ protected void appendSummary(StringBuffer buffer, String fieldName, float[] array) {
+ appendSummarySize(buffer, fieldName, array.length);
+ }
+
+ //----------------------------------------------------------------------------
+
+ /**
+ * <p>Append to the <code>toString</code> a <code>boolean</code>
+ * array.</p>
+ *
+ * @param buffer the <code>StringBuffer</code> to populate
+ * @param fieldName the field name
+ * @param array the array to add to the toString
+ * @param fullDetail <code>true</code> for detail, <code>false</code>
+ * for summary info, <code>null</code> for style decides
+ */
+ public void append(StringBuffer buffer, String fieldName, boolean[] array, Boolean fullDetail) {
+ appendFieldStart(buffer, fieldName);
+
+ if (array == null) {
+ appendNullText(buffer, fieldName);
+
+ } else if (isFullDetail(fullDetail)) {
+ appendDetail(buffer, fieldName, array);
+
+ } else {
+ appendSummary(buffer, fieldName, array);
+ }
+
+ appendFieldEnd(buffer, fieldName);
+ }
+
+ /**
+ * <p>Append to the <code>toString</code> the detail of a
+ * <code>boolean</code> array.</p>
+ *
+ * @param buffer the <code>StringBuffer</code> to populate
+ * @param fieldName the field name, typically not used as already appended
+ * @param array the array to add to the <code>toString</code>,
+ * not <code>null</code>
+ */
+ protected void appendDetail(StringBuffer buffer, String fieldName, boolean[] array) {
+ buffer.append(arrayStart);
+ for (int i = 0; i < array.length; i++) {
+ if (i > 0) {
+ buffer.append(arraySeparator);
+ }
+ appendDetail(buffer, fieldName, array[i]);
+ }
+ buffer.append(arrayEnd);
+ }
+
+ /**
+ * <p>Append to the <code>toString</code> a summary of a
+ * <code>boolean</code> array.</p>
+ *
+ * @param buffer the <code>StringBuffer</code> to populate
+ * @param fieldName the field name, typically not used as already appended
+ * @param array the array to add to the <code>toString</code>,
+ * not <code>null</code>
+ */
+ protected void appendSummary(StringBuffer buffer, String fieldName, boolean[] array) {
+ appendSummarySize(buffer, fieldName, array.length);
+ }
+
+ //----------------------------------------------------------------------------
+
+ /**
+ * <p>Append to the <code>toString</code> the class name.</p>
+ *
+ * @param buffer the <code>StringBuffer</code> to populate
+ * @param object the <code>Object</code> whose name to output
+ */
+ protected void appendClassName(StringBuffer buffer, Object object) {
+ if (useClassName && object != null) {
+ if (useShortClassName) {
+ buffer.append(getShortClassName(object.getClass()));
+ } else {
+ buffer.append(object.getClass().getName());
+ }
+ }
+ }
+
+ /**
+ * <p>Append the {@link System#identityHashCode(java.lang.Object)}.</p>
+ *
+ * @param buffer the <code>StringBuffer</code> to populate
+ * @param object the <code>Object</code> whose id to output
+ */
+ protected void appendIdentityHashCode(StringBuffer buffer, Object object) {
+ if (this.isUseIdentityHashCode() && object!=null) {
+ buffer.append('@');
+ buffer.append(Integer.toHexString(System.identityHashCode(object)));
+ }
+ }
+
+ /**
+ * <p>Append to the <code>toString</code> the content start.</p>
+ *
+ * @param buffer the <code>StringBuffer</code> to populate
+ */
+ protected void appendContentStart(StringBuffer buffer) {
+ buffer.append(contentStart);
+ }
+
+ /**
+ * <p>Append to the <code>toString</code> the content end.</p>
+ *
+ * @param buffer the <code>StringBuffer</code> to populate
+ */
+ protected void appendContentEnd(StringBuffer buffer) {
+ buffer.append(contentEnd);
+ }
+
+ /**
+ * <p>Append to the <code>toString</code> an indicator for <code>null</code>.</p>
+ *
+ * <p>The default indicator is <code>'<null>'</code>.</p>
+ *
+ * @param buffer the <code>StringBuffer</code> to populate
+ * @param fieldName the field name, typically not used as already appended
+ */
+ protected void appendNullText(StringBuffer buffer, String fieldName) {
+ buffer.append(nullText);
+ }
+
+ /**
+ * <p>Append to the <code>toString</code> the field separator.</p>
+ *
+ * @param buffer the <code>StringBuffer</code> to populate
+ */
+ protected void appendFieldSeparator(StringBuffer buffer) {
+ buffer.append(fieldSeparator);
+ }
+
+ /**
+ * <p>Append to the <code>toString</code> the field start.</p>
+ *
+ * @param buffer the <code>StringBuffer</code> to populate
+ * @param fieldName the field name
+ */
+ protected void appendFieldStart(StringBuffer buffer, String fieldName) {
+ if (useFieldNames && fieldName != null) {
+ buffer.append(fieldName);
+ buffer.append(fieldNameValueSeparator);
+ }
+ }
+
+ /**
+ * <p>Append to the <code>toString<code> the field end.</p>
+ *
+ * @param buffer the <code>StringBuffer</code> to populate
+ * @param fieldName the field name, typically not used as already appended
+ */
+ protected void appendFieldEnd(StringBuffer buffer, String fieldName) {
+ appendFieldSeparator(buffer);
+ }
+
+ /**
+ * <p>Append to the <code>toString</code> a size summary.</p>
+ *
+ * <p>The size summary is used to summarize the contents of
+ * <code>Collections</code>, <code>Maps</code> and arrays.</p>
+ *
+ * <p>The output consists of a prefix, the passed in size
+ * and a suffix.</p>
+ *
+ * <p>The default format is <code>'<size=n>'<code>.</p>
+ *
+ * @param buffer the <code>StringBuffer</code> to populate
+ * @param fieldName the field name, typically not used as already appended
+ * @param size the size to append
+ */
+ protected void appendSummarySize(StringBuffer buffer, String fieldName, int size) {
+ buffer.append(sizeStartText);
+ buffer.append(size);
+ buffer.append(sizeEndText);
+ }
+
+ /**
+ * <p>Is this field to be output in full detail.</p>
+ *
+ * <p>This method converts a detail request into a detail level.
+ * The calling code may request full detail (<code>true</code>),
+ * but a subclass might ignore that and always return
+ * <code>false</code>. The calling code may pass in
+ * <code>null</code> indicating that it doesn't care about
+ * the detail level. In this case the default detail level is
+ * used.</p>
+ *
+ * @param fullDetailRequest the detail level requested
+ * @return whether full detail is to be shown
+ */
+ protected boolean isFullDetail(Boolean fullDetailRequest) {
+ if (fullDetailRequest == null) {
+ return defaultFullDetail;
+ }
+ return fullDetailRequest.booleanValue();
+ }
+
+ /**
+ * <p>Gets the short class name for a class.</p>
+ *
+ * <p>The short class name is the classname excluding
+ * the package name.</p>
+ *
+ * @param cls the <code>Class</code> to get the short name of
+ * @return the short name
+ */
+ protected String getShortClassName(Class cls) {
+ return ClassUtils.getShortClassName(cls);
+ }
+
+ // Setters and getters for the customizable parts of the style
+ // These methods are not expected to be overridden, except to make public
+ // (They are not public so that immutable subclasses can be written)
+ //---------------------------------------------------------------------
+
+ /**
+ * <p>Gets whether to use the class name.</p>
+ *
+ * @return the current useClassName flag
+ */
+ protected boolean isUseClassName() {
+ return useClassName;
+ }
+
+ /**
+ * <p>Sets whether to use the class name.</p>
+ *
+ * @param useClassName the new useClassName flag
+ */
+ protected void setUseClassName(boolean useClassName) {
+ this.useClassName = useClassName;
+ }
+
+ //---------------------------------------------------------------------
+
+ /**
+ * <p>Gets whether to output short or long class names.</p>
+ *
+ * @return the current useShortClassName flag
+ * @since 2.0
+ */
+ protected boolean isUseShortClassName() {
+ return useShortClassName;
+ }
+
+ /**
+ * <p>Gets whether to output short or long class names.</p>
+ *
+ * @return the current shortClassName flag
+ * @deprecated Use {@link #isUseShortClassName()}
+ * Method will be removed in Commons Lang 3.0.
+ */
+ protected boolean isShortClassName() {
+ return useShortClassName;
+ }
+
+ /**
+ * <p>Sets whether to output short or long class names.</p>
+ *
+ * @param useShortClassName the new useShortClassName flag
+ * @since 2.0
+ */
+ protected void setUseShortClassName(boolean useShortClassName) {
+ this.useShortClassName = useShortClassName;
+ }
+
+ /**
+ * <p>Sets whether to output short or long class names.</p>
+ *
+ * @param shortClassName the new shortClassName flag
+ * @deprecated Use {@link #setUseShortClassName(boolean)}
+ * Method will be removed in Commons Lang 3.0.
+ */
+ protected void setShortClassName(boolean shortClassName) {
+ this.useShortClassName = shortClassName;
+ }
+
+ //---------------------------------------------------------------------
+
+ /**
+ * <p>Gets whether to use the identity hash code.</p>
+ *
+ * @return the current useIdentityHashCode flag
+ */
+ protected boolean isUseIdentityHashCode() {
+ return useIdentityHashCode;
+ }
+
+ /**
+ * <p>Sets whether to use the identity hash code.</p>
+ *
+ * @param useIdentityHashCode the new useIdentityHashCode flag
+ */
+ protected void setUseIdentityHashCode(boolean useIdentityHashCode) {
+ this.useIdentityHashCode = useIdentityHashCode;
+ }
+
+ //---------------------------------------------------------------------
+
+ /**
+ * <p>Gets whether to use the field names passed in.</p>
+ *
+ * @return the current useFieldNames flag
+ */
+ protected boolean isUseFieldNames() {
+ return useFieldNames;
+ }
+
+ /**
+ * <p>Sets whether to use the field names passed in.</p>
+ *
+ * @param useFieldNames the new useFieldNames flag
+ */
+ protected void setUseFieldNames(boolean useFieldNames) {
+ this.useFieldNames = useFieldNames;
+ }
+
+ //---------------------------------------------------------------------
+
+ /**
+ * <p>Gets whether to use full detail when the caller doesn't
+ * specify.</p>
+ *
+ * @return the current defaultFullDetail flag
+ */
+ protected boolean isDefaultFullDetail() {
+ return defaultFullDetail;
+ }
+
+ /**
+ * <p>Sets whether to use full detail when the caller doesn't
+ * specify.</p>
+ *
+ * @param defaultFullDetail the new defaultFullDetail flag
+ */
+ protected void setDefaultFullDetail(boolean defaultFullDetail) {
+ this.defaultFullDetail = defaultFullDetail;
+ }
+
+ //---------------------------------------------------------------------
+
+ /**
+ * <p>Gets whether to output array content detail.</p>
+ *
+ * @return the current array content detail setting
+ */
+ protected boolean isArrayContentDetail() {
+ return arrayContentDetail;
+ }
+
+ /**
+ * <p>Sets whether to output array content detail.</p>
+ *
+ * @param arrayContentDetail the new arrayContentDetail flag
+ */
+ protected void setArrayContentDetail(boolean arrayContentDetail) {
+ this.arrayContentDetail = arrayContentDetail;
+ }
+
+ //---------------------------------------------------------------------
+
+ /**
+ * <p>Gets the array start text.</p>
+ *
+ * @return the current array start text
+ */
+ protected String getArrayStart() {
+ return arrayStart;
+ }
+
+ /**
+ * <p>Sets the array start text.</p>
+ *
+ * <p><code>null</code> is accepted, but will be converted to
+ * an empty String.</p>
+ *
+ * @param arrayStart the new array start text
+ */
+ protected void setArrayStart(String arrayStart) {
+ if (arrayStart == null) {
+ arrayStart = "";
+ }
+ this.arrayStart = arrayStart;
+ }
+
+ //---------------------------------------------------------------------
+
+ /**
+ * <p>Gets the array end text.</p>
+ *
+ * @return the current array end text
+ */
+ protected String getArrayEnd() {
+ return arrayEnd;
+ }
+
+ /**
+ * <p>Sets the array end text.</p>
+ *
+ * <p><code>null</code> is accepted, but will be converted to
+ * an empty String.</p>
+ *
+ * @param arrayEnd the new array end text
+ */
+ protected void setArrayEnd(String arrayEnd) {
+ if (arrayStart == null) {
+ arrayStart = "";
+ }
+ this.arrayEnd = arrayEnd;
+ }
+
+ //---------------------------------------------------------------------
+
+ /**
+ * <p>Gets the array separator text.</p>
+ *
+ * @return the current array separator text
+ */
+ protected String getArraySeparator() {
+ return arraySeparator;
+ }
+
+ /**
+ * <p>Sets the array separator text.</p>
+ *
+ * <p><code>null</code> is accepted, but will be converted to
+ * an empty String.</p>
+ *
+ * @param arraySeparator the new array separator text
+ */
+ protected void setArraySeparator(String arraySeparator) {
+ if (arraySeparator == null) {
+ arraySeparator = "";
+ }
+ this.arraySeparator = arraySeparator;
+ }
+
+ //---------------------------------------------------------------------
+
+ /**
+ * <p>Gets the content start text.</p>
+ *
+ * @return the current content start text
+ */
+ protected String getContentStart() {
+ return contentStart;
+ }
+
+ /**
+ * <p>Sets the content start text.</p>
+ *
+ * <p><code>null</code> is accepted, but will be converted to
+ * an empty String.</p>
+ *
+ * @param contentStart the new content start text
+ */
+ protected void setContentStart(String contentStart) {
+ if (contentStart == null) {
+ contentStart = "";
+ }
+ this.contentStart = contentStart;
+ }
+
+ //---------------------------------------------------------------------
+
+ /**
+ * <p>Gets the content end text.</p>
+ *
+ * @return the current content end text
+ */
+ protected String getContentEnd() {
+ return contentEnd;
+ }
+
+ /**
+ * <p>Sets the content end text.</p>
+ *
+ * <p><code>null</code> is accepted, but will be converted to
+ * an empty String.</p>
+ *
+ * @param contentEnd the new content end text
+ */
+ protected void setContentEnd(String contentEnd) {
+ if (contentEnd == null) {
+ contentEnd = "";
+ }
+ this.contentEnd = contentEnd;
+ }
+
+ //---------------------------------------------------------------------
+
+ /**
+ * <p>Gets the field name value separator text.</p>
+ *
+ * @return the current field name value separator text
+ */
+ protected String getFieldNameValueSeparator() {
+ return fieldNameValueSeparator;
+ }
+
+ /**
+ * <p>Sets the field name value separator text.</p>
+ *
+ * <p><code>null</code> is accepted, but will be converted to
+ * an empty String.</p>
+ *
+ * @param fieldNameValueSeparator the new field name value separator text
+ */
+ protected void setFieldNameValueSeparator(String fieldNameValueSeparator) {
+ if (fieldNameValueSeparator == null) {
+ fieldNameValueSeparator = "";
+ }
+ this.fieldNameValueSeparator = fieldNameValueSeparator;
+ }
+
+ //---------------------------------------------------------------------
+
+ /**
+ * <p>Gets the field separator text.</p>
+ *
+ * @return the current field separator text
+ */
+ protected String getFieldSeparator() {
+ return fieldSeparator;
+ }
+
+ /**
+ * <p>Sets the field separator text.</p>
+ *
+ * <p><code>null</code> is accepted, but will be converted to
+ * an empty String.</p>
+ *
+ * @param fieldSeparator the new field separator text
+ */
+ protected void setFieldSeparator(String fieldSeparator) {
+ if (fieldSeparator == null) {
+ fieldSeparator = "";
+ }
+ this.fieldSeparator = fieldSeparator;
+ }
+
+ //---------------------------------------------------------------------
+
+ /**
+ * <p>Gets whether the field separator should be added at the start
+ * of each buffer.</p>
+ *
+ * @return the fieldSeparatorAtStart flag
+ * @since 2.0
+ */
+ protected boolean isFieldSeparatorAtStart() {
+ return fieldSeparatorAtStart;
+ }
+
+ /**
+ * <p>Sets whether the field separator should be added at the start
+ * of each buffer.</p>
+ *
+ * @param fieldSeparatorAtStart the fieldSeparatorAtStart flag
+ * @since 2.0
+ */
+ protected void setFieldSeparatorAtStart(boolean fieldSeparatorAtStart) {
+ this.fieldSeparatorAtStart = fieldSeparatorAtStart;
+ }
+
+ //---------------------------------------------------------------------
+
+ /**
+ * <p>Gets whether the field separator should be added at the end
+ * of each buffer.</p>
+ *
+ * @return fieldSeparatorAtEnd flag
+ * @since 2.0
+ */
+ protected boolean isFieldSeparatorAtEnd() {
+ return fieldSeparatorAtEnd;
+ }
+
+ /**
+ * <p>Sets whether the field separator should be added at the end
+ * of each buffer.</p>
+ *
+ * @param fieldSeparatorAtEnd the fieldSeparatorAtEnd flag
+ * @since 2.0
+ */
+ protected void setFieldSeparatorAtEnd(boolean fieldSeparatorAtEnd) {
+ this.fieldSeparatorAtEnd = fieldSeparatorAtEnd;
+ }
+
+ //---------------------------------------------------------------------
+
+ /**
+ * <p>Gets the text to output when <code>null</code> found.</p>
+ *
+ * @return the current text to output when null found
+ */
+ protected String getNullText() {
+ return nullText;
+ }
+
+ /**
+ * <p>Sets the text to output when <code>null</code> found.</p>
+ *
+ * <p><code>null</code> is accepted, but will be converted to
+ * an empty String.</p>
+ *
+ * @param nullText the new text to output when null found
+ */
+ protected void setNullText(String nullText) {
+ if (nullText == null) {
+ nullText = "";
+ }
+ this.nullText = nullText;
+ }
+
+ //---------------------------------------------------------------------
+
+ /**
+ * <p>Gets the start text to output when a <code>Collection</code>,
+ * <code>Map</code> or array size is output.</p>
+ *
+ * <p>This is output before the size value.</p>
+ *
+ * @return the current start of size text
+ */
+ protected String getSizeStartText() {
+ return sizeStartText;
+ }
+
+ /**
+ * <p>Sets the start text to output when a <code>Collection</code>,
+ * <code>Map</code> or array size is output.</p>
+ *
+ * <p>This is output before the size value.</p>
+ *
+ * <p><code>null</code> is accepted, but will be converted to
+ * an empty String.</p>
+ *
+ * @param sizeStartText the new start of size text
+ */
+ protected void setSizeStartText(String sizeStartText) {
+ if (sizeStartText == null) {
+ sizeStartText = "";
+ }
+ this.sizeStartText = sizeStartText;
+ }
+
+ //---------------------------------------------------------------------
+
+ /**
+ * <p>Gets the end text to output when a <code>Collection</code>,
+ * <code>Map</code> or array size is output.</p>
+ *
+ * <p>This is output after the size value.</p>
+ *
+ * @return the current end of size text
+ */
+ protected String getSizeEndText() {
+ return sizeEndText;
+ }
+
+ /**
+ * <p>Sets the end text to output when a <code>Collection</code>,
+ * <code>Map</code> or array size is output.</p>
+ *
+ * <p>This is output after the size value.</p>
+ *
+ * <p><code>null</code> is accepted, but will be converted to
+ * an empty String.</p>
+ *
+ * @param sizeEndText the new end of size text
+ */
+ protected void setSizeEndText(String sizeEndText) {
+ if (sizeEndText == null) {
+ sizeEndText = "";
+ }
+ this.sizeEndText = sizeEndText;
+ }
+
+ //---------------------------------------------------------------------
+
+ /**
+ * <p>Gets the start text to output when an <code>Object</code> is
+ * output in summary mode.</p>
+ *
+ * <p>This is output before the size value.</p>
+ *
+ * @return the current start of summary text
+ */
+ protected String getSummaryObjectStartText() {
+ return summaryObjectStartText;
+ }
+
+ /**
+ * <p>Sets the start text to output when an <code>Object</code> is
+ * output in summary mode.</p>
+ *
+ * <p>This is output before the size value.</p>
+ *
+ * <p><code>null</code> is accepted, but will be converted to
+ * an empty String.</p>
+ *
+ * @param summaryObjectStartText the new start of summary text
+ */
+ protected void setSummaryObjectStartText(String summaryObjectStartText) {
+ if (summaryObjectStartText == null) {
+ summaryObjectStartText = "";
+ }
+ this.summaryObjectStartText = summaryObjectStartText;
+ }
+
+ //---------------------------------------------------------------------
+
+ /**
+ * <p>Gets the end text to output when an <code>Object</code> is
+ * output in summary mode.</p>
+ *
+ * <p>This is output after the size value.</p>
+ *
+ * @return the current end of summary text
+ */
+ protected String getSummaryObjectEndText() {
+ return summaryObjectEndText;
+ }
+
+ /**
+ * <p>Sets the end text to output when an <code>Object</code> is
+ * output in summary mode.</p>
+ *
+ * <p>This is output after the size value.</p>
+ *
+ * <p><code>null</code> is accepted, but will be converted to
+ * an empty String.</p>
+ *
+ * @param summaryObjectEndText the new end of summary text
+ */
+ protected void setSummaryObjectEndText(String summaryObjectEndText) {
+ if (summaryObjectEndText == null) {
+ summaryObjectEndText = "";
+ }
+ this.summaryObjectEndText = summaryObjectEndText;
+ }
+
+ //----------------------------------------------------------------------------
+
+ /**
+ * <p>Default <code>ToStringStyle</code>.</p>
+ *
+ * <p>This is an inner class rather than using
+ * <code>StandardToStringStyle</code> to ensure its immutability.</p>
+ */
+ private static final class DefaultToStringStyle extends ToStringStyle {
+
+ /**
+ * <p>Constructor.</p>
+ *
+ * <p>Use the static constant rather than instantiating.</p>
+ */
+ private DefaultToStringStyle() {
+ super();
+ }
+
+ /**
+ * <p>Ensure <code>Singleton</code> after serialization.</p>
+ *
+ * @return the singleton
+ */
+ private Object readResolve() {
+ return ToStringStyle.DEFAULT_STYLE;
+ }
+
+ }
+
+ //----------------------------------------------------------------------------
+
+ /**
+ * <p><code>ToStringStyle</code> that does not print out
+ * the field names.</p>
+ *
+ * <p>This is an inner class rather than using
+ * <code>StandardToStringStyle</code> to ensure its immutability.
+ */
+ private static final class NoFieldNameToStringStyle extends ToStringStyle {
+
+ /**
+ * <p>Constructor.</p>
+ *
+ * <p>Use the static constant rather than instantiating.</p>
+ */
+ private NoFieldNameToStringStyle() {
+ super();
+ this.setUseFieldNames(false);
+ }
+
+ /**
+ * <p>Ensure <code>Singleton</code> after serialization.</p>
+ *
+ * @return the singleton
+ */
+ private Object readResolve() {
+ return ToStringStyle.NO_FIELD_NAMES_STYLE;
+ }
+
+ }
+
+ //----------------------------------------------------------------------------
+
+ /**
+ * <p><code>ToStringStyle</code> that prints out the short
+ * class name and no identity hashcode.</p>
+ *
+ * <p>This is an inner class rather than using
+ * <code>StandardToStringStyle</code> to ensure its immutability.</p>
+ */
+ private static final class ShortPrefixToStringStyle extends ToStringStyle {
+
+ /**
+ * <p>Constructor.</p>
+ *
+ * <p>Use the static constant rather than instantiating.</p>
+ */
+ private ShortPrefixToStringStyle() {
+ super();
+ this.setUseShortClassName(true);
+ this.setUseIdentityHashCode(false);
+ }
+
+ /**
+ * <p>Ensure <code>Singleton</ode> after serialization.</p>
+ * @return the singleton
+ */
+ private Object readResolve() {
+ return ToStringStyle.SHORT_PREFIX_STYLE;
+ }
+
+ }
+
+ /**
+ * <p><code>ToStringStyle</code> that does not print out the
+ * classname, identity hashcode, content start or field name.</p>
+ *
+ * <p>This is an inner class rather than using
+ * <code>StandardToStringStyle</code> to ensure its immutability.</p>
+ */
+ private static final class SimpleToStringStyle extends ToStringStyle {
+
+ /**
+ * <p>Constructor.</p>
+ *
+ * <p>Use the static constant rather than instantiating.</p>
+ */
+ private SimpleToStringStyle() {
+ super();
+ this.setUseClassName(false);
+ this.setUseIdentityHashCode(false);
+ this.setUseFieldNames(false);
+ this.setContentStart("");
+ this.setContentEnd("");
+ }
+
+ /**
+ * <p>Ensure <code>Singleton</ode> after serialization.</p>
+ * @return the singleton
+ */
+ private Object readResolve() {
+ return ToStringStyle.SIMPLE_STYLE;
+ }
+
+ }
+
+ //----------------------------------------------------------------------------
+
+ /**
+ * <p><code>ToStringStyle</code> that outputs on multiple lines.</p>
+ *
+ * <p>This is an inner class rather than using
+ * <code>StandardToStringStyle</code> to ensure its immutability.</p>
+ */
+ private static final class MultiLineToStringStyle extends ToStringStyle {
+
+ /**
+ * <p>Constructor.</p>
+ *
+ * <p>Use the static constant rather than instantiating.</p>
+ */
+ private MultiLineToStringStyle() {
+ super();
+ this.setContentStart("[");
+ this.setFieldSeparator(SystemUtils.LINE_SEPARATOR + " ");
+ this.setFieldSeparatorAtStart(true);
+ this.setContentEnd(SystemUtils.LINE_SEPARATOR + "]");
+ }
+
+ /**
+ * <p>Ensure <code>Singleton</code> after serialization.</p>
+ *
+ * @return the singleton
+ */
+ private Object readResolve() {
+ return ToStringStyle.MULTI_LINE_STYLE;
+ }
+
+ }
+
+ //----------------------------------------------------------------------------
+
+// Removed, as the XML style needs more work for escaping characters, arrays,
+// collections, maps and embedded beans.
+// /**
+// * ToStringStyle that outputs in XML style
+// */
+// private static class XMLToStringStyle extends ToStringStyle {
+//
+// /**
+// * Constructor - use the static constant rather than instantiating.
+// */
+// private XMLToStringStyle() {
+// super();
+// nullText = "null";
+// sizeStartText = "size=";
+// sizeEndText = "";
+// }
+//
+// /**
+// * @see ToStringStyle#appendStart(StringBuffer, Object)
+// */
+// public void appendStart(StringBuffer buffer, Object object) {
+// buffer.append('<');
+// buffer.append(getShortClassName(object.getClass()));
+// buffer.append(" class=\"");
+// appendClassName(buffer, object);
+// buffer.append("\" hashCode=\"");
+// appendIdentityHashCode(buffer, object);
+// buffer.append("\">");
+// buffer.append(SystemUtils.LINE_SEPARATOR);
+// buffer.append(" ");
+// }
+//
+// /**
+// * @see ToStringStyle#appendFieldStart(StringBuffer, String)
+// */
+// protected void appendFieldStart(StringBuffer buffer, String fieldName) {
+// buffer.append('<');
+// buffer.append(fieldName);
+// buffer.append('>');
+// }
+//
+// /**
+// * @see ToStringStyle#appendFieldEnd(StringBuffer, String)
+// */
+// protected void appendFieldEnd(StringBuffer buffer, String fieldName) {
+// buffer.append("</");
+// buffer.append(fieldName);
+// buffer.append('>');
+// buffer.append(SystemUtils.LINE_SEPARATOR);
+// buffer.append(" ");
+// }
+//
+// /**
+// * @see ToStringStyle#appendEnd(StringBuffer, Object)
+// */
+// public void appendEnd(StringBuffer buffer, Object object) {
+// int len = buffer.length();
+// if (len > 2 && buffer.charAt(len - 1) == ' ' && buffer.charAt(len - 2) == ' ') {
+// buffer.setLength(len - 2);
+// }
+// buffer.append("</");
+// buffer.append(getShortClassName(object.getClass()));
+// buffer.append("\">");
+// }
+//
+// }
+
+}
Added: incubator/directory/ldap/trunk/common/src/java/org/apache/ldap/common/util/ValuedEnum.java
==============================================================================
--- (empty file)
+++ incubator/directory/ldap/trunk/common/src/java/org/apache/ldap/common/util/ValuedEnum.java Sat Sep 25 12:11:47 2004
@@ -0,0 +1,185 @@
+/*
+ * Copyright 2002-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.ldap.common.util;
+
+import java.util.Iterator;
+import java.util.List;
+
+/**
+ * <p>Abstract superclass for type-safe enums with integer values suitable
+ * for use in <code>switch</code> statements.</p>
+ *
+ * <p><em>NOTE:</em>Due to the way in which Java ClassLoaders work, comparing
+ * <code>Enum</code> objects should always be done using the equals() method,
+ * not <code>==</code>. The equals() method will try <code>==</code> first so
+ * in most cases the effect is the same.</p>
+ *
+ * <p>To use this class, it must be subclassed. For example:</p>
+ *
+ * <pre>
+ * public final class JavaVersionEnum extends ValuedEnum {
+ * //standard enums for version of JVM
+ * public static final int JAVA1_0_VALUE = 100;
+ * public static final int JAVA1_1_VALUE = 110;
+ * public static final int JAVA1_2_VALUE = 120;
+ * public static final int JAVA1_3_VALUE = 130;
+ * public static final JavaVersionEnum JAVA1_0 = new JavaVersionEnum( "Java 1.0", JAVA1_0_VALUE );
+ * public static final JavaVersionEnum JAVA1_1 = new JavaVersionEnum( "Java 1.1", JAVA1_1_VALUE );
+ * public static final JavaVersionEnum JAVA1_2 = new JavaVersionEnum( "Java 1.2", JAVA1_2_VALUE );
+ * public static final JavaVersionEnum JAVA1_3 = new JavaVersionEnum( "Java 1.3", JAVA1_3_VALUE );
+ *
+ * private JavaVersionEnum(String name, int value) {
+ * super( name, value );
+ * }
+ *
+ * public static JavaVersionEnum getEnum(String javaVersion) {
+ * return (JavaVersionEnum) getEnum(JavaVersionEnum.class, javaVersion);
+ * }
+ *
+ * public static JavaVersionEnum getEnum(int javaVersion) {
+ * return (JavaVersionEnum) getEnum(JavaVersionEnum.class, javaVersion);
+ * }
+ *
+ * public static Map getEnumMap() {
+ * return getEnumMap(JavaVersionEnum.class);
+ * }
+ *
+ * public static List getEnumList() {
+ * return getEnumList(JavaVersionEnum.class);
+ * }
+ *
+ * public static Iterator iterator() {
+ * return iterator(JavaVersionEnum.class);
+ * }
+ * }
+ * </pre>
+ *
+ * <p>The above class could then be used as follows:</p>
+ *
+ * <pre>
+ * public void doSomething(JavaVersion ver) {
+ * switch (ver.getValue()) {
+ * case JAVA1_0_VALUE:
+ * // ...
+ * break;
+ * case JAVA1_1_VALUE:
+ * // ...
+ * break;
+ * //...
+ * }
+ * }
+ * </pre>
+ *
+ * <p>As shown, each enum has a name and a value. These can be accessed using
+ * <code>getName</code> and <code>getValue</code>.</p>
+ *
+ * <p>The <code>getEnum</code> and <code>iterator</code> methods are recommended.
+ * Unfortunately, Java restrictions require these to be coded as shown in each subclass.
+ * An alternative choice is to use the {@link } class.</p>
+ *
+ * @author Apache Avalon project
+ * @author Stephen Colebourne
+ * @since 1.0
+ * @version $Id: ValuedEnum.java,v 1.16 2004/02/23 04:34:20 ggregory Exp $
+ */
+public abstract class ValuedEnum extends Enum {
+
+ /** Lang version 1.0.1 serial compatibility */
+ private static final long serialVersionUID = -7129650521543789085L;
+
+ /**
+ * The value contained in enum.
+ */
+ private final int iValue;
+
+ /**
+ * Constructor for enum item.
+ *
+ * @param name the name of enum item
+ * @param value the value of enum item
+ */
+ protected ValuedEnum(String name, int value) {
+ super(name);
+ iValue = value;
+ }
+
+ /**
+ * <p>Gets an <code>Enum</code> object by class and value.</p>
+ *
+ * <p>This method loops through the list of <code>Enum</code>,
+ * thus if there are many <code>Enum</code>s this will be
+ * slow.</p>
+ *
+ * @param enumClass the class of the <code>Enum</code> to get
+ * @param value the value of the <code>Enum</code> to get
+ * @return the enum object, or null if the enum does not exist
+ * @throws IllegalArgumentException if the enum class is <code>null</code>
+ */
+ protected static Enum getEnum(Class enumClass, int value) {
+ if (enumClass == null) {
+ throw new IllegalArgumentException("The Enum Class must not be null");
+ }
+ List list = Enum.getEnumList(enumClass);
+ for (Iterator it = list.iterator(); it.hasNext();) {
+ ValuedEnum enum = (ValuedEnum) it.next();
+ if (enum.getValue() == value) {
+ return enum;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * <p>Get value of enum item.</p>
+ *
+ * @return the enum item's value.
+ */
+ public final int getValue() {
+ return iValue;
+ }
+
+ /**
+ * <p>Tests for order.</p>
+ *
+ * <p>The default ordering is numeric by value, but this
+ * can be overridden by subclasses.</p>
+ *
+ * @see java.lang.Comparable#compareTo(Object)
+ * @param other the other object to compare to
+ * @return -ve if this is less than the other object, +ve if greater than,
+ * <code>0</code> of equal
+ * @throws ClassCastException if other is not an <code>Enum</code>
+ * @throws NullPointerException if other is <code>null</code>
+ */
+ public int compareTo(Object other) {
+ return iValue - ((ValuedEnum) other).iValue;
+ }
+
+ /**
+ * <p>Human readable description of this <code>Enum</code> item.</p>
+ *
+ * @return String in the form <code>type[name=value]</code>, for example:
+ * <code>JavaVersion[Java 1.0=100]</code>. Note that the package name is
+ * stripped from the type name.
+ */
+ public String toString() {
+ if (iToString == null) {
+ String shortName = ClassUtils.getShortClassName(getEnumClass());
+ iToString = shortName + "[" + getName() + "=" + getValue() + "]";
+ }
+ return iToString;
+ }
+}