001/**
002 * Copyright (C) 2006-2020 Talend Inc. - www.talend.com
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 * http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016package org.talend.sdk.component.server.lang;
017
018import java.util.ArrayList;
019import java.util.Collection;
020import java.util.NoSuchElementException;
021
022public class StringPropertiesTokenizer {
023
024    private String input;
025
026    private char[] delim;
027
028    private int pos = 0;
029
030    private char lastDelimiter = 0;
031
032    private boolean isDelimiter = false;
033
034    public StringPropertiesTokenizer(final String str) {
035        input = str;
036        delim = ", \t\r\n\f".toCharArray();
037    }
038
039    public Collection<String> tokens() {
040        final Collection<String> out = new ArrayList<>();
041        while (hasMoreTokens()) {
042            out.add(nextToken());
043        }
044        return out;
045    }
046
047    private boolean hasMoreTokens() {
048        final int oldpos = pos;
049        final char olddelim = lastDelimiter;
050        try {
051            nextToken();
052            return true;
053        } catch (final NoSuchElementException nsee) {
054            return false;
055        } finally {
056            pos = oldpos;
057            lastDelimiter = olddelim;
058        }
059    }
060
061    private String nextToken() {
062        if (pos >= input.length()) {
063            throw new NoSuchElementException();
064        }
065
066        final StringBuilder sb = new StringBuilder();
067        char prevch = 0;
068        char ch;
069        while (pos < input.length()) {
070            lastDelimiter = ch = input.charAt(pos);
071            if (isDelimiter(ch, prevch)) {
072                break;
073            }
074            if (isDelimiter(ch, (char) 0) && prevch == '\\') {
075                sb.setLength(sb.length() - 1);
076            }
077
078            sb.append(ch);
079            prevch = ch;
080            pos++;
081        }
082        isDelimiter = false;
083        if (sb.length() == 0) {
084            pos++;
085            return nextToken();
086        }
087
088        return sb.toString();
089    }
090
091    public String nextToken(final String delim) {
092        this.delim = delim.toCharArray();
093        return nextToken();
094    }
095
096    public boolean isDelimiter() {
097        return isDelimiter;
098    }
099
100    private boolean isDelimiter(final char ch, final char prevch) {
101        for (char currentChar : delim) {
102            if (ch == currentChar && prevch != '\\') {
103                return true;
104            }
105        }
106        return false;
107    }
108}