View Javadoc

1   /*
2    * Copyright (C) 2017-2019 Centre National d'Etudes Spatiales (CNES).
3    *
4    * This library is free software; you can redistribute it and/or
5    * modify it under the terms of the GNU Lesser General Public
6    * License as published by the Free Software Foundation; either
7    * version 3.0 of the License, or (at your option) any later version.
8    *
9    * This library is distributed in the hope that it will be useful,
10   * but WITHOUT ANY WARRANTY; without even the implied warranty of
11   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12   * Lesser General Public License for more details.
13   *
14   * You should have received a copy of the GNU Lesser General Public
15   * License along with this library; if not, write to the Free Software
16   * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
17   * MA 02110-1301  USA
18   */
19  package fr.cnes.doi.utils;
20  
21  import fr.cnes.doi.db.model.DOIProject;
22  import fr.cnes.doi.exception.DOIDbException;
23  import fr.cnes.doi.exception.DoiRuntimeException;
24  import fr.cnes.doi.plugin.PluginFactory;
25  import fr.cnes.doi.utils.spec.Requirement;
26  import java.util.List;
27  import java.util.Random;
28  import org.apache.logging.log4j.LogManager;
29  import org.apache.logging.log4j.Logger;
30  
31  /**
32   * Utils class to generate a unique number from the project name
33   *
34   */
35  @Requirement(reqId = Requirement.DOI_INTER_030, reqName = Requirement.DOI_INTER_030_NAME)
36  public final class UniqueProjectName {
37  
38      /**
39       * logger.
40       */
41      private static final Logger LOGGER = LogManager.getLogger(UniqueProjectName.class.getName());
42  
43      /**
44       * Constructor
45       */
46      private UniqueProjectName() {
47      }
48  
49      /**
50       * Access to unique INSTANCE of Settings
51       *
52       * @return the configuration instance.
53       */
54      public static UniqueProjectName getInstance() {
55          return UniqueProjectNameHolder.INSTANCE;
56      }
57  
58      /**
59       * Returns the projects from the database.
60       *
61       * @return the projects
62       * @throws fr.cnes.doi.exception.DOIDbException When a problem occurs
63       */
64      public List<DOIProject> getProjects() throws DOIDbException {
65          LOGGER.traceEntry();
66          final List<DOIProject> projects = PluginFactory.getProjectSuffix().getProjects();
67          return LOGGER.traceExit("List of projects", projects);
68      }
69  
70      /**
71       * Returns the projects associated to an user from the database.
72       *
73       * @param userName user name
74       * @return the projects
75       * @throws fr.cnes.doi.exception.DOIDbException When a problem occurs
76       */
77      public List<DOIProject> getProjectsFromUser(final String userName) throws DOIDbException {
78          LOGGER.traceEntry("Parameter\n  userName:{}", userName);
79          final List<DOIProject> projects = PluginFactory.getProjectSuffix().getProjectsFromUser(
80                  userName);
81          return LOGGER.traceExit("Projects for userName", projects);
82      }
83  
84      /**
85       * Creates an Id with an uniform distribution.
86       *
87       * @param maxNumber Number max to generate
88       *
89       * @return the IdRequirement.DOI_AUTH_010
90       */
91      private int generateId(final int maxNumber) {
92          LOGGER.traceEntry("Parameter\n   maxNumber: {}", maxNumber);
93          final Random rand = new Random();
94          final int identifier = Math.abs(rand.nextInt(maxNumber));
95          return LOGGER.traceExit("ID", identifier);
96      }
97  
98      /**
99       * Convert the project name into unique long
100      *
101      * @param input Identifier to convert
102      * @param projectName the project name to convert
103      * @param maxNumber Number max to generate
104      * @return the input that is converted to the base
105      */
106     private int convert(final long input, final String projectName, final int maxNumber) {
107         LOGGER.traceEntry("Parameters\n  input:{}\n  projectName:{}\n  maxNumer:{}", input,
108                 projectName, maxNumber);
109         int result = (int) input;
110         do {
111             result = (int) (result ^ (projectName.hashCode() % maxNumber));
112         } while (result > maxNumber || result < 0 || !isIdUnique(result, projectName));
113         return LOGGER.traceExit("ID", result);
114     }
115 
116     /**
117      * Build a unique String from the project name
118      *
119      * @param project the project name
120      * @param length length of the short name to generate (the short name must
121      * be an int to the length cannot be up to 9)
122      * @return the unique string
123      * @throws fr.cnes.doi.exception.DOIDbException When a problem occurs
124      */
125     public int getShortName(final String project, final int length) throws DOIDbException {
126         LOGGER.traceEntry("Parameters\n project:{}\n  length:{}", project, length);
127         int suffixID;
128         if (length > 9) {
129             final DoiRuntimeException doiEx = new DoiRuntimeException(
130                     "The short name cannot be build because the length requested is too big");
131             throw LOGGER.throwing(doiEx);
132         } else if (PluginFactory.getProjectSuffix().isExistProjectName(project)) {
133             // Si le projet a déjà un identifiant on ne le recalcule pas
134             suffixID = PluginFactory.getProjectSuffix().getIDFrom(project);
135             LOGGER.warn("The project {} has already an id : {}", project, suffixID);
136         } else {
137             final int maxNumber = (int) Math.pow(10.0, length);
138             final long idRandom = generateId(maxNumber);
139             suffixID = convert(idRandom, project, maxNumber);
140             LOGGER.warn("The project {} has an id : {}", project, suffixID);
141         }
142         return LOGGER.traceExit(suffixID);
143     }
144 
145     /**
146      * Check if the generated suffixID is unique (does not already exists) or
147      * not. If not add it associated with the project
148      *
149      * @param idToCheck the identifier to check
150      * @param projectName Project associated to the suffixID
151      * @return true if the Id is OK, false otherwise
152      */
153     private synchronized boolean isIdUnique(final int idToCheck, final String projectName) {
154         LOGGER.traceEntry("Parameters\n  idToCheck:{}\n  projectName:{}\n", idToCheck, projectName);
155         final boolean result;
156         if (PluginFactory.getProjectSuffix().isExistID(idToCheck)) {
157             result = false;
158         } else {
159             result = PluginFactory.getProjectSuffix().addProjectSuffix(idToCheck, projectName);
160         }
161         return LOGGER.traceExit(result);
162     }
163 
164     /**
165      * Class to handle the instance
166      *
167      */
168     private static class UniqueProjectNameHolder {
169 
170         /**
171          * Unique Instance unique
172          */
173         private static final UniqueProjectName INSTANCE = new UniqueProjectName();
174     }
175 
176 }