001/*
002 * (C) Copyright 2006-2008 Nuxeo SA (http://nuxeo.com/) and others.
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 *
016 * Contributors:
017 *     Nuxeo - initial API and implementation
018 *
019 * $Id$
020 */
021
022package org.nuxeo.ecm.platform.importer.random;
023
024import java.io.IOException;
025import java.util.HashMap;
026import java.util.Map;
027import java.util.Random;
028
029import org.nuxeo.ecm.core.api.NuxeoException;
030
031/**
032 * Random text generator to be used for load testing
033 *
034 * @author Thierry Delprat
035 */
036public class RandomTextGenerator {
037
038    protected DictionaryHolder dictionaryHolder;
039
040    protected Map<String, String> paragraphCache = new HashMap<String, String>();
041
042    protected Map<String, String> pageCache = new HashMap<String, String>();
043
044    protected Map<String, String> blockCache = new HashMap<String, String>();
045
046    protected static final int PARAGRAPH_CACHE_SIZE = 100;
047
048    protected static final int PARAGRAPH_CACHE_HIT = 100;
049
050    protected static final int PAGE_CACHE_SIZE = 50;
051
052    protected static final int PAGE_CACHE_HIT = 30;
053
054    protected static final int BLOC_CACHE_SIZE = 30;
055
056    protected static final int BLOC_CACHE_HIT = 20;
057
058    protected static final int BLOC_SIZE = 10 * 1024;
059
060    protected static final int NB_WORDS_PER_LINE = 20;
061
062    protected static final int NB_LINES_PER_PARAGRAPH = 40;
063
064    protected static final int NB_PARAGRAPH_PER_PAGE = 8;
065
066    protected static final int NB_PAGE_PER_BLOC = 3;
067
068    protected static final Random RANDOM = new Random(); // NOSONAR (doesn't need cryptographic strength)
069
070    public RandomTextGenerator(DictionaryHolder dictionary) {
071        dictionaryHolder = dictionary;
072    }
073
074    protected int getTargetPageMaxSizeB() {
075        return (int) (1.2 * (BLOC_SIZE / NB_PAGE_PER_BLOC));
076    }
077
078    protected int getTargetParagraphMaxSizeB() {
079        return (int) (1.2 * (getTargetPageMaxSizeB() / NB_PARAGRAPH_PER_PAGE));
080    }
081
082    public String getRandomTitle(int nbWord) {
083        StringBuffer sb = new StringBuffer();
084        for (int i = 0; i < nbWord; i++) {
085            sb.append(dictionaryHolder.getRandomWord());
086        }
087        return sb.toString();
088
089    }
090
091    public String getRandomLine() {
092        int nbW = 10 + RANDOM.nextInt(NB_WORDS_PER_LINE);
093        StringBuffer sb = new StringBuffer();
094
095        for (int i = 0; i < nbW; i++) {
096            sb.append(dictionaryHolder.getRandomWord());
097        }
098        sb.append(".\n");
099        return sb.toString();
100    }
101
102    public String generateParagraph() {
103        int nbL = 10 + RANDOM.nextInt(NB_LINES_PER_PARAGRAPH);
104        StringBuffer sb = new StringBuffer();
105
106        int maxSize = getTargetParagraphMaxSizeB();
107
108        for (int i = 0; i < nbL; i++) {
109            sb.append(getRandomLine());
110            if (sb.length() > maxSize) {
111                break;
112            }
113        }
114        sb.append("\n\n");
115        return sb.toString();
116    }
117
118    public void prefilCache() {
119
120        try {
121            dictionaryHolder.init();
122        } catch (IOException e) {
123            throw new NuxeoException(e);
124        }
125
126        for (int i = 0; i < PARAGRAPH_CACHE_SIZE; i++) {
127            paragraphCache.put("P" + i, generateParagraph());
128        }
129
130        for (int i = 0; i < PAGE_CACHE_SIZE; i++) {
131            String page = generatePage();
132            pageCache.put("P" + i, page);
133        }
134
135        for (int i = 0; i < BLOC_CACHE_SIZE; i++) {
136            String page = generateBloc();
137            blockCache.put("B" + i, page);
138        }
139
140    }
141
142    public String getRandomParagraph() {
143        int rand = RANDOM.nextInt();
144        int idx = RANDOM.nextInt(PARAGRAPH_CACHE_SIZE);
145        String paragraph = null;
146        if (rand % PARAGRAPH_CACHE_HIT != 0) {
147            paragraph = paragraphCache.get("P" + idx);
148        }
149        if (paragraph == null) {
150            paragraph = generateParagraph();
151            paragraphCache.put("P" + idx, paragraph);
152        }
153        return paragraph;
154    }
155
156    public String generatePage() {
157        int nbL = RANDOM.nextInt(NB_PARAGRAPH_PER_PAGE) + 1;
158        StringBuffer sb = new StringBuffer();
159
160        int maxTargetPageSize = getTargetPageMaxSizeB();
161        for (int i = 0; i < nbL; i++) {
162            sb.append(getRandomParagraph());
163            if (sb.length() > maxTargetPageSize) {
164                break;
165            }
166        }
167        sb.append("\n\n");
168        return sb.toString();
169    }
170
171    public String getRandomPage() {
172        int rand = RANDOM.nextInt();
173        int idx = RANDOM.nextInt(PAGE_CACHE_SIZE);
174        String page = null;
175        if (rand % PAGE_CACHE_HIT != 0) {
176            page = pageCache.get("P" + idx);
177        }
178        if (page == null) {
179            page = generatePage();
180            pageCache.put("P" + idx, page);
181        }
182        return page;
183    }
184
185    public String generateBloc() {
186        StringBuffer sb = new StringBuffer();
187
188        while (sb.length() < BLOC_SIZE) {
189            sb.append(getRandomPage());
190        }
191        return sb.toString();
192    }
193
194    public String getRandomBloc() {
195        int rand = RANDOM.nextInt();
196        int idx = RANDOM.nextInt(BLOC_CACHE_SIZE);
197        String bloc = null;
198        if (rand % BLOC_CACHE_HIT != 0) {
199            bloc = blockCache.get("B" + idx);
200        }
201        if (bloc == null) {
202            bloc = generateBloc();
203            blockCache.put("B" + idx, bloc);
204        }
205        return bloc;
206    }
207
208    public String getRandomText(int avSizeInK) {
209        if (avSizeInK == 0) {
210            return "";
211        }
212        StringBuffer sb = new StringBuffer();
213        int minSize = (int) (avSizeInK * 1024 * (0.8 + 0.4 * RANDOM.nextFloat()));
214        while (sb.length() < (minSize - BLOC_SIZE)) {
215            String p = getRandomBloc();
216            sb.append(p);
217        }
218        while (sb.length() < minSize) {
219            String p = getRandomPage();
220            sb.append(p);
221        }
222        return sb.toString();
223    }
224
225    public String getRandomText() {
226        int sizeK = RANDOM.nextInt(500) + 1;
227        return getRandomText(sizeK);
228    }
229
230}