001/* Copyright (C) 2013 TU Dortmund 002 * This file is part of AutomataLib, http://www.automatalib.net/. 003 * 004 * AutomataLib is free software; you can redistribute it and/or 005 * modify it under the terms of the GNU Lesser General Public 006 * License version 3.0 as published by the Free Software Foundation. 007 * 008 * AutomataLib is distributed in the hope that it will be useful, 009 * but WITHOUT ANY WARRANTY; without even the implied warranty of 010 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 011 * Lesser General Public License for more details. 012 * 013 * You should have received a copy of the GNU Lesser General Public 014 * License along with AutomataLib; if not, see 015 * http://www.gnu.de/documents/lgpl.en.html. 016 */ 017package net.automatalib.words.impl; 018 019import java.util.NoSuchElementException; 020import java.util.Objects; 021 022import net.automatalib.words.Word; 023 024public class ExtensionWord<I> extends Word<I> { 025 026 private static final class Iterator<I> implements java.util.Iterator<I> { 027 private final java.util.Iterator<I> wordIt; 028 private final I letter; 029 private boolean next = true; 030 031 public Iterator(java.util.Iterator<I> wordIt, I letter) { 032 this.wordIt = wordIt; 033 this.letter = letter; 034 } 035 036 @Override 037 public boolean hasNext() { 038 return next; 039 } 040 @Override 041 public I next() { 042 if(wordIt.hasNext()) 043 return wordIt.next(); 044 if(!next) 045 throw new NoSuchElementException(); 046 next = false; 047 return letter; 048 } 049 050 @Override 051 public void remove() { 052 throw new UnsupportedOperationException(); 053 } 054 055 056 } 057 058 private final Word<I> word; 059 private final I letter; 060 061 public ExtensionWord(Word<I> word, I letter) { 062 this.word = word; 063 this.letter = letter; 064 } 065 066 @Override 067 public I getSymbol(int index) { 068 if(index == word.length()) 069 return letter; 070 return word.getSymbol(index); 071 } 072 073 @Override 074 public int length() { 075 return word.length() + 1; 076 } 077 078 @Override 079 protected Word<I> _subWord(int fromIndex, int toIndex) { 080 int wLen = word.length(); 081 if(fromIndex < wLen) { 082 if(toIndex <= wLen) 083 word.subWord(fromIndex, toIndex); 084 return new ExtensionWord<>(word.subWord(fromIndex, wLen), letter); 085 } 086 else if(fromIndex == wLen) 087 return Word.fromLetter(letter); 088 return Word.epsilon(); 089 } 090 091 @Override 092 public java.util.Iterator<I> iterator() { 093 return new Iterator<I>(word.iterator(), letter); 094 } 095 096 @Override 097 public void writeToArray(int offset, Object[] array, int tgtOffset, 098 int length) { 099 int wordLen = word.length(); 100 boolean writeLetter = (offset + length > wordLen); 101 if(offset < wordLen) { 102 if(writeLetter) 103 length--; 104 word.writeToArray(offset, array, tgtOffset, length); 105 } 106 if(writeLetter) 107 array[tgtOffset+length] = letter; 108 } 109 110 @Override 111 public Word<I> prepend(I symbol) { 112 return new ExtensionWord<>(word.prepend(symbol), letter); 113 } 114 115 @Override 116 public boolean isPrefixOf(Word<I> other) { 117 int wordLen = word.length(); 118 if(wordLen >= other.length()) 119 return false; 120 121 if(!word.isPrefixOf(other)) 122 return false; 123 return Objects.equals(other.getSymbol(wordLen), letter); 124 } 125 126}