/* * Copyright (C) 2011 Laurent Caillette * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation, either * version 3 of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package org.novelang.novelist; import java.util.Locale; import java.util.Random; /** * Endless iterator creating {@link org.novelang.novelist.Word} instances. * * @author Laurent Caillette */ public class WordGenerator implements Generator.ForWord { private final Random random ; private final Bounded.IntegerInclusiveExclusive signCount ; private final LetterDistribution distribution ; private final Bounded.Percentage circumflex ; public WordGenerator( final Configuration configuration ) { this.random = configuration.getRandom() ; this.signCount = configuration.getSignCount() ; this.distribution = LetterDistribution.getFrequency( configuration.getLocale() ) ; this.circumflex = configuration.getCircumflex() ; } @Override public Word generate() { final int letterCount = signCount.boundInteger( random ) ; final StringBuilder builder = new StringBuilder() ; for( int letterIndex = 1 ; letterIndex <= letterCount ; letterIndex ++ ) { Character c = distribution.get( Bounded.newPercentage( random ) ); if( letterIndex == 1 && testAndClearCapitalize() ) { c = Character.toTitleCase( c ) ; } if( letterIndex > 1 && letterIndex < letterCount && circumflex.hit( random ) ) { builder.append( "^" ) ; } builder.append( c ) ; } return new Word( builder.toString() ) ; } private boolean capitalizeNext = false ; @Override public void capitalizeNext() { capitalizeNext = true ; } private boolean testAndClearCapitalize() { final boolean value = capitalizeNext ; capitalizeNext = false ; return value ; } @org.novelang.outfit.Husk.Converter( converterClass = Bounded.class ) public interface Configuration { Locale getLocale() ; Configuration withLocale( Locale locale ) ; Random getRandom() ; Configuration withRandom( Random random ) ; Bounded.IntegerInclusiveExclusive getSignCount() ; Configuration withSignCount( int lowerBound, int upperBound ) ; Bounded.Percentage getCircumflex() ; Configuration withCircumflex( float probability ) ; } }