/*license*\
XBN-Java: Copyright (C) 2014, Jeff Epstein (aliteralmind __DASH__ github __AT__ yahoo __DOT__ com)
This software is dual-licensed under the:
- Lesser General Public License (LGPL) version 3.0 or, at your option, any later version;
- Apache Software License (ASL) version 2.0.
Either license may be applied at your discretion. More information may be found at
- http://en.wikipedia.org/wiki/Multi-licensing.
The text of both licenses is available in the root directory of this project, under the names "LICENSE_lgpl-3.0.txt" and "LICENSE_asl-2.0.txt". The latest copies may be downloaded at:
- LGPL 3.0: https://www.gnu.org/licenses/lgpl-3.0.txt
- ASL 2.0: http://www.apache.org/licenses/LICENSE-2.0.txt
\*license*/
package com.github.xbn.text;
import com.github.xbn.io.RTIOException;
import com.github.xbn.lang.CrashIfObject;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Iterator;
import java.util.NoSuchElementException;
import org.apache.commons.io.LineIterator;
/**
<p>Duplicate a str_obj, append a str_obj if a condition is met, get a "visible index mask", and other str_obj-related utilities.</p>
* @since 0.1.0
* @author Copyright (C) 2014, Jeff Epstein ({@code aliteralmind __DASH__ github __AT__ yahoo __DOT__ com}), dual-licensed under the LGPL (version 3.0 or later) or the ASL (version 2.0). See source code for details. <a href="http://xbnjava.aliteralmind.com">{@code http://xbnjava.aliteralmind.com}</a>, <a href="https://github.com/aliteralmind/xbnjava">{@code https://github.com/aliteralmind/xbnjava}</a>
**/
public class StringUtil extends StringUtilBase {
private StringUtil() {
throw new IllegalStateException("Do not instantiate");
}
/**
<p>An iterator for the characters in a str_obj.</p>
*/
public static final Iterator<Character> getCharIterator(Object str_toPad) {
return (new CharIteratorForQ(str_toPad));
}
/**
<p>Get one str_obj if a condition is met, another if it's not.</p>
* @return <code>{@link #appendIfTrueFalse(Appendable, Object, boolean, Object) appendIfTrueFalse}((new StringBuilder()), true_oString, condition, oString_ifFalse).toString()</code>
*/
public static final String getIfTrueFalse(Object true_oString, boolean condition, Object oString_ifFalse) {
return appendIfTrueFalse((new StringBuilder()), true_oString, condition, oString_ifFalse).toString();
}
/**
<p>Get one str_obj if a condition is met, another if it's not.</p>
* @param to_appendTo May not be {@code null}.
* @param true_oString Returned if {@code condition} is {@code true}.
* @param oString_ifFalse Returned if {@code condition} is {@code false}.
* @exception RTIOException If an {@link java.io.IOException IOException} is thrown
* @see #getIfTrueFalse(Object, boolean, Object) getIfTrueFalse(O,b,O)
*/
public static final Appendable appendIfTrueFalse(Appendable to_appendTo, Object true_oString, boolean condition, Object oString_ifFalse) {
try {
if(condition) {
if(true_oString != null) {
to_appendTo.append(true_oString.toString());
}
} else if(oString_ifFalse != null) {
to_appendTo.append(oString_ifFalse.toString());
}
} catch(IOException iox) {
throw new RTIOException("appendIfTrueFalse", iox);
} catch(RuntimeException rx) {
throw CrashIfObject.nullOrReturnCause(to_appendTo, "to_appendTo", null, rx);
}
return to_appendTo;
}
/**
<p>Get one str_obj (with a prefix and postfix) if a condition is met, or another if it's not.</p>
* @return <code>{@link #appendPreTruePostOrFalse(Appendable, String, Object, String, boolean, Object) appendPreTruePostOrFalse}((new StringBuilder()), prefix_ifTrue, true_oString, postfix_ifTrue, condition, oString_ifFalse).toString()</code>
*/
public static final String getPreTruePostOrFalse(String prefix_ifTrue, Object true_oString, String postfix_ifTrue, boolean condition, Object oString_ifFalse) {
return appendPreTruePostOrFalse((new StringBuilder()), prefix_ifTrue, true_oString, postfix_ifTrue, condition, oString_ifFalse).toString();
}
/**
<p>Append one str_obj (with a prefix and postfix) if a condition is met, or another if it's not.</p>
* @exception RTIOException If an {@link java.io.IOException IOException} is thrown
*/
public static final Appendable appendPreTruePostOrFalse(Appendable to_appendTo, String prefix_ifTrue, Object true_oString, String postfix_ifTrue, boolean condition, Object oString_ifFalse) {
try {
if(condition) {
if(prefix_ifTrue != null) {
to_appendTo.append(prefix_ifTrue);
}
if(true_oString != null) {
to_appendTo.append(true_oString.toString());
}
if(postfix_ifTrue != null) {
to_appendTo.append(postfix_ifTrue);
}
} else if(oString_ifFalse != null) {
to_appendTo.append(oString_ifFalse.toString());
}
} catch(IOException iox) {
throw new RTIOException("appendPreTruePostOrFalse", iox);
} catch(RuntimeException rx) {
throw CrashIfObject.nullOrReturnCause(to_appendTo, "to_appendTo", null, rx);
}
return to_appendTo;
}
/**
<p>Eliminate whitespace from the left side of a str_obj.</p>
<p>The idea for this and {@code rtrim(str_toPad)} is from
<br/> <code><a href="http://stackoverflow.com/questions/15567010/what-is-a-good-alternative-of-ltrim-and-rtrim-in-java">http://stackoverflow.com/questions/15567010/what-is-a-good-alternative-of-ltrim-and-rtrim-in-java</a></code>
<br/>and
<br/> <code><a href="http://www.fromdev.com/2009/07/playing-with-java-str_obj-trim-basics.html">http://www.fromdev.com/2009/07/playing-with-java-str_obj-trim-basics.html</a></code>
<br/>(viewed 11/18/2013)</p>
* @param str_toPad May not be {@code null}.
* @see #rtrim(Object) rtrim(o)
*/
public static String ltrim(Object str_toPad) {
String s = null;
try {
s = str_toPad.toString();
} catch(RuntimeException rx) {
throw CrashIfObject.nullOrReturnCause(str_toPad, "str_toPad", null, rx);
}
int i = 0;
while (i < s.length() && Character.isWhitespace(s.charAt(i))) {
i++;
}
return s.substring(i);
}
/**
<p>Eliminate whitespace from the right side of a str_obj.</p>
* @param str_toPad May not be {@code null}.
* @see #ltrim(Object) ltrim(o)
*/
public static String rtrim(Object str_toPad) {
String s = null;
try {
s = str_toPad.toString();
} catch(RuntimeException rx) {
throw CrashIfObject.nullOrReturnCause(str_toPad, "str_toPad", null, rx);
}
int i = s.length()-1;
while (i >= 0 && Character.isWhitespace(s.charAt(i))) {
i--;
}
return s.substring(0, (i + 1));
}
/**
<p>Creates a string where every element is the same character.</p>
* @param length The length of the returned string.
* @param char_toDup The character to duplicate.
* @param length_varName Descriptive name of {@code length}. <i>Should</i> not be {@code null} or empty.
* @return <code>new String(new char[length]).java.lang.String#replace(CharSequence, CharSequence)("\0", (new Character(char_toDup)).toString())</code>
* @see <code><a href="http://stackoverflow.com/questions/1235179/simple-way-to-repeat-a-string-in-java/4903603#4903603">http://stackoverflow.com/questions/1235179/simple-way-to-repeat-a-string-in-java/4903603#4903603</a></code>
* @exception NegativeArraySizeException If {@code length} is less than zero.
*/
public static final String getStringOfLengthAllCharsEqualTo(int length, char char_toDup, String length_varName) {
try {
return new String(new char[length]).replace("\0", (new Character(char_toDup)).toString());
} catch(NegativeArraySizeException nasx) {
throw new NegativeArraySizeException(length_varName + "=" + length);
}
}
/**
<p>For visibly indicating the index or index-range of a str_obj on the immediately-above line.</p>
{@.codelet.and.out com.github.xbn.examples.text.VisibleIndexMaskXmpl%eliminateCommentBlocksAndPackageDecl()}
* @param str_toPadForLen The str_obj to mask.
* @param idx_start The mask-start index. <i>Should</i> be between 0 and
<br/> {@code (str_toPadForLen.toString().length() - 1)}
* @param idx_endX The mask-end index. <i>Should</i> be between {@code (idx_start + 1)} and
<br/> {@code str_toPadForLen.toString().length()}.
*/
public static final String getVisibleIndexMask(Object str_toPadForLen, int idx_start, int idx_endX) {
StringBuilder sd = new StringBuilder(getDuped(" ", idx_start));
if(idx_start == idx_endX) {
sd.append("^");
} else {
sd.append("|").
append(getDuped("-", (idx_endX - idx_start - 1))).
append("|");
}
try {
sd.append(getDuped(" ", (str_toPadForLen.toString().length() - idx_endX)));
} catch(RuntimeException rx) {
throw CrashIfObject.nullOrReturnCause(str_toPadForLen, "str_toPadForLen", null, rx);
}
return sd.toString();
}
/**
<p>Get a str_obj, duplicated.</p>
* @param str_toDup The str_obj to duplicate. May not be {@code null} or empty.
* @param dup_count The number of times to duplicate {@code str_toDup}. May not be less than zero. If zero, an empty str_obj is returned.
* @return <code>{@link #appendDuped(Appendable, Object, int) appendDuped}((new StringBuilder()), str_toDup, dup_count).toString()</code>
*/
public static final String getDuped(Object str_toDup, int dup_count) {
return appendDuped((new StringBuilder()), str_toDup, dup_count).toString();
}
/**
<p>Append a str_obj, duplicated.</p>
* @param to_appendTo May not be {@code null}.
* @param str_toDup Descriptive name of {@code to_appendTo}. <i>Should</i> not be {@code null} or empty.
* @param dup_count <i>Should</i> be greater than zero.
* @exception RTIOException If an {@link java.io.IOException IOException} is thrown.
* @see #getDuped(Object, int) getDuped(O,i)
*/
public static final Appendable appendDuped(Appendable to_appendTo, Object str_toDup, int dup_count) {
try {
CrashIfString.nullEmpty(str_toDup, "str_toDup", null);
String s = str_toDup.toString();
for(int i = 0; i < dup_count; i++) {
to_appendTo.append(s);
}
} catch(IOException iox) {
throw new RTIOException(iox);
} catch(RuntimeException rx) {
throw CrashIfObject.nullOrReturnCause(to_appendTo, "to_appendTo", null, rx);
}
return to_appendTo;
}
public static final Iterator<String> getLineIterator(Object string_obj) {
BufferedReader br = null;
try {
br = new BufferedReader(new InputStreamReader(new ByteArrayInputStream(string_obj.toString().getBytes())));
} catch(RuntimeException rx) {
throw CrashIfObject.nullOrReturnCause(string_obj, "string_obj", null, rx);
}
return new LineIterator(br);
}
/*
public static final boolean isEqualToExactlyOneElement(String to_test, String[] all_possibleValues, IgnoreCase ignore_case) {
try {
to_test = ignore_case.toUpperCaseIfYes(to_test, "to_test");
} catch(RuntimeException rx) {
throw CrashIfObject.nullOrReturnCause(ignore_case, "ignore_case", null, rx);
}
int i = 0;
try {
for(; i < all_possibleValues.length; i++) {
if(ignore_case.toUpperCaseIfYes(all_possibleValues[i], null).equals(to_test)) {
return true;
}
}
} catch(RuntimeException rx) {
CrashIfObject.nnull(all_possibleValues, "all_possibleValues", null);
throw CrashIfObject.nullOrReturnCause(all_possibleValues[i], "all_possibleValues[" + i + "]", null, rx);
}
return false;
}
*/
}
class CharIteratorForQ implements Iterator<Character> {
private CharSequence q = null;
private int ix = -1;
//constructors...START
public CharIteratorForQ(Object str_toPad) {
this((String)str_toPad);
}
public CharIteratorForQ(CharSequence cs) {
if(cs == null) {
throw new NullPointerException("cs");
}
q = cs;
ix = 0;
}
//constructors...END
public boolean hasNext() {
return (ix < q.length());
}
public Character next() {
if (!hasNext()) {
throw new NoSuchElementException("The length of the str_obj is " + q.length() + ". The str_obj: \"" + q + "\"");
}
return q.charAt(ix++);
}
/**
<p><i>Do not use.</i></p>
* @exception UnsupportedOperationException
*/
public void remove() {
throw new UnsupportedOperationException("remove()");
}
}