/* * This file is part of NucleusFramework for Bukkit, licensed under the MIT License (MIT). * * Copyright (c) JCThePants (www.jcwhatever.com) * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package com.jcwhatever.nucleus.utils.text; import com.jcwhatever.nucleus.utils.PreCon; import com.jcwhatever.nucleus.utils.text.TextFormat.TextFormats; import java.util.ArrayDeque; import java.util.ArrayList; import java.util.Deque; import java.util.Iterator; import java.util.List; /** * A collection of {@link TextComponent} instances. */ public class TextComponents implements Iterable<TextComponent> { private final String _text; private final List<TextComponent> _components; private final Object _sync = new Object(); private String _formatted; /** * Constructor. * * <p>Generates {@link TextComponent} collection from text.</p> * * @param text The text. */ public TextComponents(CharSequence text) { PreCon.notNull(text); _text = text.toString(); _components = getTextComponents(_text); } /** * Constructor. * * @param textComponents The text components to clone. */ public TextComponents(TextComponents textComponents) { PreCon.notNull(textComponents); _text = textComponents._text; _components = new ArrayList<>(textComponents._components); } /** * Get the text used to generate the {@link TextComponent}'s in * the collection. */ public String getText() { return _text; } /** * Get text generated from the components. */ public String getFormatted() { if (_formatted == null) { synchronized (_sync) { if (_formatted != null) return _formatted; StringBuilder buffer = new StringBuilder(_components.size() * 15); for (TextComponent component : this) { buffer.append(component.getFormatted()); } _formatted = buffer.toString(); } } return _formatted; } /** * Get the number of {@link TextComponent}'s in the collection. */ public int size() { return _components.size(); } /** * Get the {@link TextComponent} at the specified index location. * * @param index The index. */ public TextComponent get(int index) { return _components.get(index); } @Override public Iterator<TextComponent> iterator() { return new Iterator<TextComponent>() { int index =0; @Override public boolean hasNext() { return index <= _components.size(); } @Override public TextComponent next() { TextComponent n = _components.get(index); index ++; return n; } @Override public void remove() { throw new UnsupportedOperationException(); } }; } /** * Parse the given text into a list of {@link TextComponents}. * * @param text The text to parse. */ private static List<TextComponent> getTextComponents(String text) { PreCon.notNull(text); text = TextUtils.format(text).toString(); StringBuilder buffer = new StringBuilder(text.length()); Deque<TextComponent> result = new ArrayDeque<>(10); for (int i = 0; i < text.length(); i++) { char ch = text.charAt(i); boolean hasFormat = false; int startIndex = i; while (ch == TextFormat.CHAR && i < text.length() - 1 && TextFormat.isFormatChar(text.charAt(i + 1))) { hasFormat = true; i += 1; ch = text.charAt(i); } if (hasFormat) { if (buffer.length() > 0) { TextFormats formats = TextFormat.getFormatAt(startIndex - 1, text); TextComponent textComponent = new TextComponent(buffer.toString(), formats); buffer.setLength(0); if (textComponent.getText().length() > 0) result.addLast(textComponent); } } else { buffer.append(ch); } } if (buffer.length() > 0) { TextFormats formats = TextFormat.getFormatAt(text.length() - 1, text); TextComponent textComponent = new TextComponent(buffer.toString(), formats); result.addLast(textComponent); } return new ArrayList<>(result); } }