1   /**
2    * Copyright (c) 2000-2010 Liferay, Inc. All rights reserved.
3    *
4    * This library is free software; you can redistribute it and/or modify it under
5    * the terms of the GNU Lesser General Public License as published by the Free
6    * Software Foundation; either version 2.1 of the License, or (at your option)
7    * any later version.
8    *
9    * This library is distributed in the hope that it will be useful, but WITHOUT
10   * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11   * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
12   * details.
13   */
14  
15  package com.liferay.portal.kernel.util;
16  
17  import java.util.HashMap;
18  import java.util.Map;
19  
20  /**
21   * <a href="DeterminateKeyGenerator.java.html"><b><i>View Source</i></b></a>
22   *
23   * <p>
24   * See http://issues.liferay.com/browse/LPS-6872.
25   * </p>
26   *
27   * @author Shuyang Zhou
28   * @author Brian Wing Shun Chan
29   */
30  public class DeterminateKeyGenerator {
31  
32      public static String generate(String input) {
33          return generate(input, _DEFAULT_LENGTH);
34      }
35  
36      public static String generate(String input, int length) {
37          if (input == null) {
38              throw new IllegalArgumentException("Input is null");
39          }
40  
41          if (length <= 0) {
42              throw new IllegalArgumentException(
43                  "Length is less than or equal to 0");
44          }
45  
46          Map<String, Integer> seedMap = _seedMap.get();
47  
48          Integer previousSeed = seedMap.get(input);
49  
50          int seed = 0;
51  
52          if (previousSeed == null) {
53              seed = input.hashCode();
54          }
55          else {
56              seed = previousSeed;
57          }
58  
59          StringBuilder sb = new StringBuilder(length);
60  
61          for (int i = 0; i < length; i++) {
62              int index = 0;
63  
64              if (seed > 0) {
65                  index = seed % 26;
66              }
67              else {
68                  index = -seed % 26;
69              }
70  
71              sb.append(_CHARACTERS[index]);
72  
73              seed = _nextRandom(seed);
74          }
75  
76          seedMap.put(input, seed);
77  
78          return sb.toString();
79      }
80  
81      public static void reset() {
82          Map<String, Integer> seedMap = _seedMap.get();
83  
84          seedMap.clear();
85      }
86  
87      public static void reset(String key) {
88          Map<String, Integer> seedMap = _seedMap.get();
89  
90          seedMap.remove(key);
91      }
92  
93      private static int _nextRandom(int seed) {
94          return (seed % 127773) * 16807 - (seed / 127773) * 2836;
95      }
96  
97      private static char[] _CHARACTERS =
98          "abcdefghijklmnopqrstuvwxyz".toCharArray();
99  
100     private static final int _DEFAULT_LENGTH = 4;
101 
102     private static ThreadLocal<Map<String, Integer>> _seedMap =
103         new AutoResetThreadLocal<Map<String, Integer>>(
104             new HashMap<String, Integer>());
105 
106 }