/*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.list.lister; import com.github.xbn.analyze.validate.ValidatorComposer; import com.github.xbn.analyze.validate.ValueValidator; import com.github.xbn.io.RTIOException; import com.github.xbn.lang.CrashIfObject; import com.github.xbn.lang.Null; import com.github.xbn.lang.RuleType; import com.github.xbn.lang.ToStringAppendable; import com.github.xbn.list.lister.z.ListLister_Fieldable; import com.github.xbn.text.CrashIfString; import com.github.xbn.text.StringUtil; import com.github.xbn.text.StringWithNullDefault; import com.github.xbn.regexutil.RegexReplacer; import com.github.xbn.regexutil.z.RegexReplacer_Cfg; import java.io.IOException; import java.util.List; import org.apache.commons.lang3.StringUtils; import static com.github.xbn.lang.XbnConstants.*; /** <p>Highly-configurable printing of a {@code java.util.List}.</p> <A NAME="cfg"></a><h3>Builder Configuration: {@link com.github.xbn.list.lister.z.ListLister_Cfg ListLister_Cfg}</h3> <p><ul> <li><b>Sub configs:</b><ul> <li><b><a href="LLCfgElement.html#cfg">LLCfgElement</a>:</b> {@link com.github.xbn.list.lister.z.ListLister_CfgForNeeder#cfgElement() cfgElement}{@code ()}</li> <li><b><a href="LLCfgOverall.html#cfg">LLCfgOverall</a>:</b> {@link com.github.xbn.list.lister.z.ListLister_CfgForNeeder#cfgOverall() cfgOverall}{@code ()}</li> </ul></li> <li><b>Between:</b> {@link com.github.xbn.list.lister.z.ListLister_CfgForNeeder#between(String) between}{@code (s)}, {@link com.github.xbn.list.lister.z.ListLister_CfgForNeeder#commaSpaceBetween() commaSpaceBetween}{@code ()}, {@link com.github.xbn.list.lister.z.ListLister_CfgForNeeder#newLineBetween() newLineBetween}{@code ()}</li> <li><b>Display only valid indexes:</b> {@link com.github.xbn.list.lister.z.ListLister_CfgForNeeder#indexFilter(ValueValidator) indexFilter}{@code (vv)}, {@link com.github.xbn.list.lister.z.ListLister_CfgForNeeder#keepAllIndexes() keepAllIndexes}{@code ()}, {@link com.github.xbn.list.lister.z.ListLister_CfgForNeeder#keepIndexesBelow(int) keepIndexesBelow}{@code (i)}, {@link com.github.xbn.list.lister.z.ListLister_CfgForNeeder#keepIndexesBetween(int, int) keepIndexesBetween}{@code (i,i)}</li> <li><b>Display only valid values:</b> {@link com.github.xbn.list.lister.z.ListLister_CfgForNeeder#valueFilter(ValueValidator) valueFilter}{@code (vv)}, {@link com.github.xbn.list.lister.z.ListLister_CfgForNeeder#filterNullValues() filterNullValues}{@code ()}</li> </ul></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 ListLister<E> implements ToStringAppendable { //state private final LLCfgOverall<E> llco ; private final LLCfgElement<E> llce ; private final ValueValidator<Integer> vvIdxFltr; private final ValueValidator<E> vValFltr ; private final String sBtw ; //internal //"": Replace withs to be determined private static final RegexReplacer lr4SZ_MRK = new RegexReplacer_Cfg().first().directLiteral(LLCfgForLengthItems.sDISPLAY_SIZE_MARKER, "").build(); private static final RegexReplacer lr4IDX_MRK = new RegexReplacer_Cfg().first().directLiteral(LLCfgElement.sDISPLAY_IDX_MARKER, "").build(); //constructor...START public ListLister(ListLister_Fieldable<E> fieldable) { llco = fieldable.getOverallConfig(); llce = fieldable.getElementConfig(); vvIdxFltr = fieldable.getIndexFilter(); vValFltr = fieldable.getValueFilter(); sBtw = fieldable.getBetween(); if(llco == null) { throw new NullPointerException("fieldable.getOverallConfig()"); } if(llce == null) { throw new NullPointerException("fieldable.getElementConfig()"); } ValidatorComposer.ciForbiddenRuleType(vvIdxFltr, RuleType.IMPOSSIBLE, "fieldable.getIndexFilter()", null); ValidatorComposer.ciForbiddenRuleType(vValFltr, RuleType.IMPOSSIBLE, "fieldable.getValueFilter()", null); CrashIfString.empty(Null.OK, sBtw, "fieldable.getBetween()", LLConfigBase.s4ES_USE_NUL); } public ListLister(ListLister<E> to_copy) { try { llco = to_copy.getOverallConfig(); } catch(RuntimeException rx) { throw CrashIfObject.nullOrReturnCause(to_copy, "to_copy", null, rx); } llce = to_copy.getElementConfig(); vvIdxFltr = to_copy.getIndexFilter(); vValFltr = to_copy.getValueFilter(); sBtw = to_copy.getBetween(); } //constructor...END //getters...START public LLCfgOverall<E> getOverallConfig() { return llco; } public LLCfgElement<E> getElementConfig() { return llce; } public ValueValidator<Integer> getIndexFilter() { return vvIdxFltr; } public ValueValidator<E> getValueFilter() { return vValFltr; } public String getBetween() { return sBtw; } //getters...END public String get(List<E> list) { return append(this, (new StringBuilder()), list).toString(); } public Appendable append(Appendable to_appendTo, List<E> list) { return ListLister.append(this, to_appendTo, list); } public Appendable appendX(Appendable to_appendTo, List<E> list) throws IOException { return ListLister.append(this, to_appendTo, list); } public String toString() { return appendToString(new StringBuilder()).toString(); } public StringBuilder appendToString(StringBuilder to_appendTo) { try { StringUtil.appendPreTruePostOrFalse(to_appendTo, ", getIndexFilter()=[", getIndexFilter(), "]", (!getIndexFilter().getRuleType().isUnrestricted()), null); } catch(RuntimeException rx) { throw CrashIfObject.nullOrReturnCause(to_appendTo, "to_appendTo", null, rx); } StringUtil.appendPreTruePostOrFalse(to_appendTo, ", getValueFilter()=[", getValueFilter(), "]", (!getValueFilter().getRuleType().isUnrestricted()), null); to_appendTo.append(LINE_SEP).append("--getOverallConfig()--").append(LINE_SEP); getOverallConfig().appendToString(to_appendTo). append(getOverallConfig()).append(LINE_SEP). append("--getElementConfig()--").append(LINE_SEP); getElementConfig().appendToString(to_appendTo); return to_appendTo; } //static...START /** <p>YYY</p> * @exception RTIOException If an {@link java.io.IOException IOException} is thrown */ public static final <E> Appendable append(ListLister<E> lister, Appendable to_appendTo, List<E> list) { try { return appendX(lister, to_appendTo, list); } catch(IOException iox) { throw new RTIOException("Attempting appendX(lister, to_appendTo, list). to_appendTo=[" + to_appendTo + "], list=[" + StringUtils.join(list, ", ") + "], lister=[" + lister + "]"); } } /** <pre>getOverallConfig() getIfNull() <i>(short circuit)</i> getIfNonNull() <i>(short circuit)</i> getVVForElementLength() <i>(short circuit)</i> getIfElementLength() getIndexFilter() getValueFilter() getElementConfig() getOverallConfig() getVPCFinalOutput() getPrefix() getPostfix()</pre> */ public static final <E> Appendable appendX(ListLister<E> lister, Appendable to_appendTo, List<E> list) throws IOException { LLCfgOverall<E> llco = null; try { llco = lister.getOverallConfig(); } catch(RuntimeException rx) { throw CrashIfObject.nullOrReturnCause(lister, "lister", null, rx); } if(list == null) { return StringWithNullDefault.append(to_appendTo, llco.getIfNull(), null); } ListLister.lr4SZ_MRK.replaceWith(list.size()); StringWithNullDefault.append(to_appendTo, llco.getPrefix(), null); Appendable apblTmp = (llco.getVPCFinalOutput().doesNothing() ? to_appendTo : new StringBuilder()); if(llco.getIfNonNull() != null) { return lr4SZ_MRK.appendReplaced(apblTmp, llco.getIfNonNull()); } if(llco.getVVForElementLength().getRuleType().isRestricted() && llco.getVVForElementLength().isValid(list.size())) { return lr4SZ_MRK.appendReplaced(apblTmp, llco.getIfElementLength()); } String sBetween = StringWithNullDefault.get(lister.getBetween(), null); boolean bFilterUsed = (lister.getIndexFilter().getRuleType().isRestricted() || lister.getValueFilter().getRuleType().isRestricted()); int ix = -1; if(!bFilterUsed) { boolean b1stLmntWritten = false; for(E e : list) { ix++; //First iteration: Was -1, now 0 if(!lister.getIndexFilter().isValid(ix) || !lister.getValueFilter().isValid(e)) { continue; } if(b1stLmntWritten) { apblTmp.append(sBetween); } else { b1stLmntWritten = true; } appendElement(lister.getElementConfig(), apblTmp, ix, e); } //ELSE: bFilterUsed is false } else { for(E e : list) { if(ix > -1) { apblTmp.append(sBetween); } //First iteration: Was -1, now 0 appendElement(lister.getElementConfig(), apblTmp, ++ix, e); } } if(!llco.getVPCFinalOutput().doesNothing()) { llco.getVPCFinalOutput().append(to_appendTo, apblTmp.toString()); } return StringWithNullDefault.append(to_appendTo, llco.getPostfix(), null); } /** <p>YYY</p> * @exception RTIOException If an {@link java.io.IOException IOException} is thrown */ public static final <E> Appendable appendElement(LLCfgElement<E> llc_e, Appendable to_appendTo, int index, E obj) { try { return appendElementX(llc_e, to_appendTo, index, obj); } catch(IOException iox) { throw new RTIOException("Attempting appendElementX(llc_e, to_appendTo, index, obj). index=" + index + ", obj=[" + obj + "], to_appendTo=[" + to_appendTo + "], llc_e=[" + llc_e + "]"); } } /** <pre>getElementConfig() getIfNull() <i>(short circuit)</i> getIfNonNull() <i>(short circuit)</i> getAlterIndex() getAlterValue() getPrefix() getPostfix() getVPCFinalOutput() getOverallConfig() getBetween()</pre> */ public static final <E> Appendable appendElementX(LLCfgElement<E> llc_e, Appendable to_appendTo, int index, E obj) throws IOException { try { if(obj == null) { return StringWithNullDefault.append(to_appendTo, llc_e.getIfNull(), null); } lr4IDX_MRK.replaceWith(index); } catch(RuntimeException rx) { throw CrashIfObject.nullOrReturnCause(llc_e, "llc_e", null, rx); } if(llc_e.getIfNonNull() != null) { return lr4IDX_MRK.appendReplaced(to_appendTo, llc_e.getIfNonNull()); } if(!llc_e.getAlterIndex().isExpired()) { index = llc_e.getAlterIndex().getAltered(index, index); } if(!llc_e.getAlterValue().isExpired()) { obj = llc_e.getAlterValue().getAltered(obj, obj); } StringWithNullDefault.append(to_appendTo, llc_e.getPrefix(), null); llc_e.getVPCFinalOutput().appendX(to_appendTo, obj); return StringWithNullDefault.append(to_appendTo, llc_e.getPostfix(), null); } //static...END }