001/*
002 * Copyright c 2018 Rusi Popov, MDA Tools.net All rights reserved.
003 *
004 * This program and the accompanying materials are made available under the terms of the
005 * Eclipse Public License v2.0 which accompanies this distribution, and is available at
006 * http://www.eclipse.org/legal/epl-v20.html
007 */
008package net.mdatools.modelant.core.operation.format;
009
010import java.util.Iterator;
011
012import net.mdatools.modelant.core.api.Operation;
013import net.mdatools.modelant.core.util.NameTokenizer;
014
015/**
016 * Extract the words from the string, format them ad concatenate them according
017 * @author Rusi Popov (popovr@mdatools.net)
018 */
019public abstract class FormatWordsString implements Operation<String> {
020
021  private final String separator;
022
023  /**
024   * @param separator not null, possibly empty string to use as a separator between the result words
025   */
026  protected FormatWordsString(String separator) {
027    if ( separator == null) {
028      throw new IllegalArgumentException("Expected a non-null separator string");
029    }
030    this.separator = separator;
031  }
032
033
034  /**
035   * @param source not null string to parse
036   * @return string of the formatted words from the source string, concatenated with the separator string provided
037   * @throws RuntimeException
038   * @throws IllegalArgumentException
039   * @see net.mdatools.modelant.core.api.Function#execute(java.lang.Object)
040   */
041  public final String execute(String source) throws RuntimeException, IllegalArgumentException {
042    StringBuilder result;
043    Iterator<String> wordIterator;
044    String word;
045
046    assert source != null : "Expected a non-null source";
047
048    result = new StringBuilder(source.length());
049
050    source = prepare(source);
051
052    wordIterator = new NameTokenizer( source );
053    while ( wordIterator.hasNext() ) {
054      word = wordIterator.next();
055
056      if ( result.length() == 0 ) {
057        formatFirstWord( result, word, wordIterator.hasNext() );
058
059      } else {
060        result.append( separator );
061        formatNextWord( result, word, wordIterator.hasNext() );
062      }
063    }
064    return result.toString();
065  }
066
067  /**
068   * Implement any pre-processing of the source string, before parsing it into words
069   * @param source the not-null string to format
070   * @return the sanitized string to parse into words
071   */
072  protected abstract String prepare(String source);
073
074
075  /**
076   * Concatenate the formatted word into the result builder
077   * @param result non null store of the produced word, result.lenght() = 0
078   * @param word not null, not empty word of letters and digits, which is NOT the first word identified in the source string
079   * @param nextWordExists true, if there are more words to be formatted, false when this is the only word to format
080   */
081  protected abstract void formatFirstWord(StringBuilder result, String word, boolean nextWordExists);
082
083
084  /**
085   * Concatenate the formatted word into the result builder
086   * @param result non null store of the produced word, result.lenght() != 0
087   * @param word not null, not empty word of letters and digits, which is the first word identified in the source string
088   * @param nextWordExists true, if there are more words to be formatted, false when this is the last word to format
089   */
090  protected abstract void formatNextWord(StringBuilder result, String word, boolean nextWordExists);
091
092
093  /**
094   * Append to result the string provided, with first letter capitalized and all next in lower case
095   *
096   * @param name not null to capitalize
097   * @param result not null result/output parameter
098   */
099  protected final void formatFirstCapitalAllLower(StringBuilder result, String name) {
100    if ( name.length() > 0 ) {
101      result.append(Character.toUpperCase( name.charAt( 0 ) ) );
102      result.append(name.substring( 1 ).toLowerCase() );
103    }
104  }
105}