mirror of
https://github.com/sismics/docs.git
synced 2025-02-13 03:22:44 +01:00
Initial commit
This commit is contained in:
parent
41cb6dd9ae
commit
9b74bd8194
15
.gitattributes
vendored
Normal file
15
.gitattributes
vendored
Normal file
@ -0,0 +1,15 @@
|
||||
# Set default behaviour, in case users don't have core.autocrlf set.
|
||||
* text=auto
|
||||
|
||||
# Explicitly declare text files we want to always be normalized and converted
|
||||
# to native line endings on checkout.
|
||||
*.c text
|
||||
*.h text
|
||||
|
||||
# Declare files that will always have CRLF line endings on checkout.
|
||||
*.sln text eol=crlf
|
||||
|
||||
# Denote all files that are truly binary and should not be modified.
|
||||
*.png binary
|
||||
*.jpg binary
|
||||
|
7
.gitignore
vendored
Normal file
7
.gitignore
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
/*/.classpath
|
||||
/*/.project
|
||||
/*/.settings
|
||||
/*/bin
|
||||
/*/gen
|
||||
/*/target
|
||||
/*/*.iml
|
185
docs-core/pom.xml
Normal file
185
docs-core/pom.xml
Normal file
@ -0,0 +1,185 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||
|
||||
<parent>
|
||||
<groupId>com.sismics.docs</groupId>
|
||||
<artifactId>docs-parent</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
<relativePath>../docs-parent</relativePath>
|
||||
</parent>
|
||||
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<artifactId>docs-core</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
<name>Docs Core</name>
|
||||
|
||||
<dependencies>
|
||||
<!-- Persistence layer dependencies -->
|
||||
<dependency>
|
||||
<groupId>org.hibernate</groupId>
|
||||
<artifactId>hibernate-core</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.hibernate</groupId>
|
||||
<artifactId>hibernate-entitymanager</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- Other external dependencies -->
|
||||
<dependency>
|
||||
<groupId>joda-time</groupId>
|
||||
<artifactId>joda-time</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.google.guava</groupId>
|
||||
<artifactId>guava</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-compress</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>commons-lang</groupId>
|
||||
<artifactId>commons-lang</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>log4j</groupId>
|
||||
<artifactId>log4j</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-log4j12</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-api</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>jcl-over-slf4j</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.mindrot</groupId>
|
||||
<artifactId>jbcrypt</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.codehaus.jackson</groupId>
|
||||
<artifactId>jackson-core-asl</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.codehaus.jackson</groupId>
|
||||
<artifactId>jackson-mapper-asl</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.ccil.cowan.tagsoup</groupId>
|
||||
<artifactId>tagsoup</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.googlecode.owasp-java-html-sanitizer</groupId>
|
||||
<artifactId>owasp-java-html-sanitizer</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.lucene</groupId>
|
||||
<artifactId>lucene-core</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.lucene</groupId>
|
||||
<artifactId>lucene-analyzers-common</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.lucene</groupId>
|
||||
<artifactId>lucene-queryparser</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.lucene</groupId>
|
||||
<artifactId>lucene-highlighter</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.bitlet</groupId>
|
||||
<artifactId>weupnp</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- Test dependencies -->
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.hsqldb</groupId>
|
||||
<artifactId>hsqldb</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<profiles>
|
||||
<!-- Development profile (active by default) -->
|
||||
<profile>
|
||||
<id>dev</id>
|
||||
<activation>
|
||||
<activeByDefault>true</activeByDefault>
|
||||
<property>
|
||||
<name>env</name>
|
||||
<value>dev</value>
|
||||
</property>
|
||||
</activation>
|
||||
|
||||
<build>
|
||||
<resources>
|
||||
<resource>
|
||||
<directory>src/dev/resources</directory>
|
||||
<filtering>true</filtering>
|
||||
</resource>
|
||||
</resources>
|
||||
</build>
|
||||
</profile>
|
||||
|
||||
<!-- Production profile -->
|
||||
<profile>
|
||||
<id>prod</id>
|
||||
</profile>
|
||||
|
||||
<!-- Demo profile -->
|
||||
<profile>
|
||||
<id>demo</id>
|
||||
|
||||
<build>
|
||||
<resources>
|
||||
<resource>
|
||||
<directory>src/demo/resources</directory>
|
||||
<filtering>true</filtering>
|
||||
</resource>
|
||||
</resources>
|
||||
</build>
|
||||
</profile>
|
||||
</profiles>
|
||||
|
||||
<build>
|
||||
<resources>
|
||||
<resource>
|
||||
<directory>src/main/resources</directory>
|
||||
<filtering>false</filtering>
|
||||
</resource>
|
||||
</resources>
|
||||
</build>
|
||||
|
||||
</project>
|
@ -0,0 +1,13 @@
|
||||
package com.sismics.docs.core.constant;
|
||||
|
||||
/**
|
||||
* Configuration parameters.
|
||||
*
|
||||
* @author jtremeaux
|
||||
*/
|
||||
public enum ConfigType {
|
||||
/**
|
||||
* Lucene directory storage type.
|
||||
*/
|
||||
LUCENE_DIRECTORY_STORAGE,
|
||||
}
|
@ -0,0 +1,43 @@
|
||||
package com.sismics.docs.core.constant;
|
||||
|
||||
/**
|
||||
* Application constants.
|
||||
*
|
||||
* @author jtremeaux
|
||||
*/
|
||||
public class Constants {
|
||||
/**
|
||||
* Default locale.
|
||||
*/
|
||||
public static final String DEFAULT_LOCALE_ID = "en";
|
||||
|
||||
/**
|
||||
* Default timezone ID.
|
||||
*/
|
||||
public static final String DEFAULT_TIMEZONE_ID = "Europe/London";
|
||||
|
||||
/**
|
||||
* Default theme ID.
|
||||
*/
|
||||
public static final String DEFAULT_THEME_ID = "default.less";
|
||||
|
||||
/**
|
||||
* Administrator's default password ("admin").
|
||||
*/
|
||||
public static final String DEFAULT_ADMIN_PASSWORD = "$2a$05$6Ny3TjrW3aVAL1or2SlcR.fhuDgPKp5jp.P9fBXwVNePgeLqb4i3C";
|
||||
|
||||
/**
|
||||
* RAM Lucene directory storage.
|
||||
*/
|
||||
public static final String LUCENE_DIRECTORY_STORAGE_RAM = "RAM";
|
||||
|
||||
/**
|
||||
* File Lucene directory storage.
|
||||
*/
|
||||
public static final String LUCENE_DIRECTORY_STORAGE_FILE = "FILE";
|
||||
|
||||
/**
|
||||
* Default generic user role.
|
||||
*/
|
||||
public static final String DEFAULT_USER_ROLE = "admin";
|
||||
}
|
@ -0,0 +1,38 @@
|
||||
package com.sismics.docs.core.dao.file.theme;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FilenameFilter;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import com.sismics.docs.core.util.DirectoryUtil;
|
||||
|
||||
/**
|
||||
* Theme DAO.
|
||||
*
|
||||
* @author jtremeaux
|
||||
*/
|
||||
public class ThemeDao {
|
||||
private final static FilenameFilter CSS_FILTER = new FilenameFilter() {
|
||||
@Override
|
||||
public boolean accept(File dir, String name) {
|
||||
return name.endsWith(".css") || name.endsWith(".less");
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Return the list of all themes.
|
||||
*
|
||||
* @return List of themes
|
||||
*/
|
||||
public List<String> findAll() {
|
||||
final File themeDirectory = DirectoryUtil.getThemeDirectory();
|
||||
if (themeDirectory != null) {
|
||||
return Lists.newArrayList(themeDirectory.list(CSS_FILTER));
|
||||
} else {
|
||||
return new ArrayList<String>();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,99 @@
|
||||
package com.sismics.docs.core.dao.jpa;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.UUID;
|
||||
|
||||
import javax.persistence.EntityManager;
|
||||
import javax.persistence.Query;
|
||||
|
||||
import org.joda.time.DateTime;
|
||||
|
||||
import com.sismics.docs.core.model.jpa.AuthenticationToken;
|
||||
import com.sismics.util.context.ThreadLocalContext;
|
||||
|
||||
/**
|
||||
* Authentication token DAO.
|
||||
*
|
||||
* @author jtremeaux
|
||||
*/
|
||||
public class AuthenticationTokenDao {
|
||||
/**
|
||||
* Gets an authentication token.
|
||||
*
|
||||
* @param id Authentication token ID
|
||||
* @return Authentication token
|
||||
*/
|
||||
public AuthenticationToken get(String id) {
|
||||
EntityManager em = ThreadLocalContext.get().getEntityManager();
|
||||
return em.find(AuthenticationToken.class, id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new authentication token.
|
||||
*
|
||||
* @param authenticationToken Authentication token
|
||||
* @return Authentication token ID
|
||||
*/
|
||||
public String create(AuthenticationToken authenticationToken) {
|
||||
EntityManager em = ThreadLocalContext.get().getEntityManager();
|
||||
|
||||
authenticationToken.setId(UUID.randomUUID().toString());
|
||||
authenticationToken.setCreationDate(new Date());
|
||||
em.persist(authenticationToken);
|
||||
|
||||
return authenticationToken.getId();
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes the authentication token.
|
||||
*
|
||||
* @param authenticationTokenId Authentication token ID
|
||||
* @throws Exception
|
||||
*/
|
||||
public void delete(String authenticationTokenId) throws Exception {
|
||||
EntityManager em = ThreadLocalContext.get().getEntityManager();
|
||||
AuthenticationToken authenticationToken = em.find(AuthenticationToken.class, authenticationTokenId);
|
||||
if (authenticationToken != null) {
|
||||
em.remove(authenticationToken);
|
||||
} else {
|
||||
throw new Exception("Token not found: " + authenticationTokenId);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes old short lived tokens.
|
||||
*
|
||||
* @param userId User ID
|
||||
* @throws Exception
|
||||
*/
|
||||
public void deleteOldSessionToken(String userId) {
|
||||
StringBuilder sb = new StringBuilder("delete from T_AUTHENTICATION_TOKEN AS ato ");
|
||||
sb.append(" where ato.AUT_IDUSER_C = :userId and ato.AUT_LONGLASTED_B = :longLasted");
|
||||
sb.append(" and ato.AUT_LASTCONNECTIONDATE_D < :minDate ");
|
||||
|
||||
EntityManager em = ThreadLocalContext.get().getEntityManager();
|
||||
Query q = em.createNativeQuery(sb.toString());
|
||||
q.setParameter("userId", userId);
|
||||
q.setParameter("longLasted", false);
|
||||
q.setParameter("minDate", DateTime.now().minusDays(1).toDate());
|
||||
q.executeUpdate();
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes old short lived tokens.
|
||||
*
|
||||
* @param id Token id
|
||||
* @throws Exception
|
||||
*/
|
||||
public void updateLastConnectionDate(String id) {
|
||||
StringBuilder sb = new StringBuilder("update T_AUTHENTICATION_TOKEN ato ");
|
||||
sb.append(" set ato.AUT_LASTCONNECTIONDATE_D = :currentDate ");
|
||||
sb.append(" where ato.AUT_ID_C = :id");
|
||||
|
||||
EntityManager em = ThreadLocalContext.get().getEntityManager();
|
||||
Query q = em.createNativeQuery(sb.toString());
|
||||
q.setParameter("currentDate", new Date());
|
||||
q.setParameter("id", id);
|
||||
q.executeUpdate();
|
||||
}
|
||||
}
|
@ -0,0 +1,36 @@
|
||||
package com.sismics.docs.core.dao.jpa;
|
||||
|
||||
import javax.persistence.EntityManager;
|
||||
import javax.persistence.NoResultException;
|
||||
|
||||
import com.sismics.docs.core.constant.ConfigType;
|
||||
import com.sismics.docs.core.model.jpa.Config;
|
||||
import com.sismics.util.context.ThreadLocalContext;
|
||||
|
||||
/**
|
||||
* Configuration parameter DAO.
|
||||
*
|
||||
* @author jtremeaux
|
||||
*/
|
||||
public class ConfigDao {
|
||||
/**
|
||||
* Gets a configuration parameter by its ID.
|
||||
*
|
||||
* @param id Configuration parameter ID
|
||||
* @return Configuration parameter
|
||||
*/
|
||||
public Config getById(ConfigType id) {
|
||||
EntityManager em = ThreadLocalContext.get().getEntityManager();
|
||||
|
||||
// Prevents from getting parameters outside of a transactional context (e.g. jUnit)
|
||||
if (em == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
return em.find(Config.class, id);
|
||||
} catch (NoResultException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,147 @@
|
||||
package com.sismics.docs.core.dao.jpa;
|
||||
|
||||
import java.sql.Timestamp;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
import javax.persistence.EntityManager;
|
||||
import javax.persistence.NoResultException;
|
||||
import javax.persistence.Query;
|
||||
|
||||
import com.google.common.base.Joiner;
|
||||
import com.sismics.docs.core.dao.jpa.criteria.DocumentCriteria;
|
||||
import com.sismics.docs.core.dao.jpa.dto.DocumentDto;
|
||||
import com.sismics.docs.core.model.jpa.Document;
|
||||
import com.sismics.docs.core.util.jpa.PaginatedList;
|
||||
import com.sismics.docs.core.util.jpa.PaginatedLists;
|
||||
import com.sismics.docs.core.util.jpa.QueryParam;
|
||||
import com.sismics.docs.core.util.jpa.SortCriteria;
|
||||
import com.sismics.util.context.ThreadLocalContext;
|
||||
|
||||
/**
|
||||
* Document DAO.
|
||||
*
|
||||
* @author bgamard
|
||||
*/
|
||||
public class DocumentDao {
|
||||
/**
|
||||
* Creates a new document.
|
||||
*
|
||||
* @param document Document
|
||||
* @return New ID
|
||||
* @throws Exception
|
||||
*/
|
||||
public String create(Document document) {
|
||||
// Create the UUID
|
||||
document.setId(UUID.randomUUID().toString());
|
||||
|
||||
// Create the document
|
||||
EntityManager em = ThreadLocalContext.get().getEntityManager();
|
||||
document.setCreateDate(new Date());
|
||||
em.persist(document);
|
||||
|
||||
return document.getId();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an active document.
|
||||
*
|
||||
* @param id Document ID
|
||||
* @param userId User ID
|
||||
* @return Document
|
||||
*/
|
||||
public Document getDocument(String id, String userId) {
|
||||
EntityManager em = ThreadLocalContext.get().getEntityManager();
|
||||
Query q = em.createQuery("select d from Document d where d.id = :id and d.userId = :userId and d.deleteDate is null");
|
||||
q.setParameter("id", id);
|
||||
q.setParameter("userId", userId);
|
||||
return (Document) q.getSingleResult();
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes a document.
|
||||
*
|
||||
* @param id Document ID
|
||||
*/
|
||||
public void delete(String id) {
|
||||
EntityManager em = ThreadLocalContext.get().getEntityManager();
|
||||
|
||||
// Get the document
|
||||
Query q = em.createQuery("select d from Document d where d.id = :id and d.deleteDate is null");
|
||||
q.setParameter("id", id);
|
||||
Document documentDb = (Document) q.getSingleResult();
|
||||
|
||||
// Delete the document
|
||||
Date dateNow = new Date();
|
||||
documentDb.setDeleteDate(dateNow);
|
||||
|
||||
// Delete linked data
|
||||
q = em.createQuery("update File f set f.deleteDate = :dateNow where f.documentId = :documentId and f.deleteDate is null");
|
||||
q.setParameter("documentId", documentDb.getId());
|
||||
q.setParameter("dateNow", dateNow);
|
||||
q.executeUpdate();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a document by its ID.
|
||||
*
|
||||
* @param id Document ID
|
||||
* @return Document
|
||||
*/
|
||||
public Document getById(String id) {
|
||||
EntityManager em = ThreadLocalContext.get().getEntityManager();
|
||||
try {
|
||||
return em.find(Document.class, id);
|
||||
} catch (NoResultException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Searches documents by criteria.
|
||||
*
|
||||
* @param paginatedList List of documents (updated by side effects)
|
||||
* @param criteria Search criteria
|
||||
* @return List of document
|
||||
*/
|
||||
public void findByCriteria(PaginatedList<DocumentDto> paginatedList, DocumentCriteria criteria, SortCriteria sortCriteria) {
|
||||
Map<String, Object> parameterMap = new HashMap<String, Object>();
|
||||
|
||||
StringBuilder sb = new StringBuilder("select d.DOC_ID_C c0, d.DOC_TITLE_C c1, d.DOC_DESCRIPTION_C c2, d.DOC_CREATEDATE_D c3");
|
||||
sb.append(" from T_DOCUMENT d ");
|
||||
|
||||
// Adds search criteria
|
||||
List<String> criteriaList = new ArrayList<String>();
|
||||
if (criteria.getUserId() != null) {
|
||||
criteriaList.add("d.DOC_IDUSER_C = :userId");
|
||||
parameterMap.put("userId", criteria.getUserId());
|
||||
}
|
||||
|
||||
if (!criteriaList.isEmpty()) {
|
||||
sb.append(" where ");
|
||||
sb.append(Joiner.on(" and ").join(criteriaList));
|
||||
}
|
||||
|
||||
// Perform the search
|
||||
QueryParam queryParam = new QueryParam(sb.toString(), parameterMap);
|
||||
List<Object[]> l = PaginatedLists.executePaginatedQuery(paginatedList, queryParam, sortCriteria);
|
||||
|
||||
// Assemble results
|
||||
List<DocumentDto> documentDtoList = new ArrayList<DocumentDto>();
|
||||
for (Object[] o : l) {
|
||||
int i = 0;
|
||||
DocumentDto documentDto = new DocumentDto();
|
||||
documentDto.setId((String) o[i++]);
|
||||
documentDto.setTitle((String) o[i++]);
|
||||
documentDto.setDescription((String) o[i++]);
|
||||
documentDto.setCreateTimestamp(((Timestamp) o[i++]).getTime());
|
||||
documentDtoList.add(documentDto);
|
||||
}
|
||||
|
||||
paginatedList.setResultList(documentDtoList);
|
||||
}
|
||||
}
|
@ -0,0 +1,102 @@
|
||||
package com.sismics.docs.core.dao.jpa;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
import javax.persistence.EntityManager;
|
||||
import javax.persistence.NoResultException;
|
||||
import javax.persistence.Query;
|
||||
|
||||
import com.sismics.docs.core.model.jpa.File;
|
||||
import com.sismics.util.context.ThreadLocalContext;
|
||||
|
||||
/**
|
||||
* File DAO.
|
||||
*
|
||||
* @author bgamard
|
||||
*/
|
||||
public class FileDao {
|
||||
/**
|
||||
* Creates a new file.
|
||||
*
|
||||
* @param file File
|
||||
* @return New ID
|
||||
* @throws Exception
|
||||
*/
|
||||
public String create(File file) {
|
||||
// Create the UUID
|
||||
file.setId(UUID.randomUUID().toString());
|
||||
|
||||
// Create the file
|
||||
EntityManager em = ThreadLocalContext.get().getEntityManager();
|
||||
file.setCreateDate(new Date());
|
||||
em.persist(file);
|
||||
|
||||
return file.getId();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an active file.
|
||||
*
|
||||
* @param id File ID
|
||||
* @return Document
|
||||
*/
|
||||
public File getFile(String id) {
|
||||
EntityManager em = ThreadLocalContext.get().getEntityManager();
|
||||
Query q = em.createQuery("select f from File f where f.id = :id and f.deleteDate is null");
|
||||
q.setParameter("id", id);
|
||||
return (File) q.getSingleResult();
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes a file.
|
||||
*
|
||||
* @param id File ID
|
||||
*/
|
||||
public void delete(String id) {
|
||||
EntityManager em = ThreadLocalContext.get().getEntityManager();
|
||||
|
||||
// Get the document
|
||||
Query q = em.createQuery("select f from File f where f.id = :id and f.deleteDate is null");
|
||||
q.setParameter("id", id);
|
||||
File fileDb = (File) q.getSingleResult();
|
||||
|
||||
// Delete the document
|
||||
Date dateNow = new Date();
|
||||
fileDb.setDeleteDate(dateNow);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a file by its ID.
|
||||
*
|
||||
* @param id Document ID
|
||||
* @return Document
|
||||
*/
|
||||
public File getById(String id) {
|
||||
EntityManager em = ThreadLocalContext.get().getEntityManager();
|
||||
try {
|
||||
return em.find(File.class, id);
|
||||
} catch (NoResultException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get files by document ID.
|
||||
*
|
||||
* @param documentId Document ID
|
||||
* @return List of files
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public List<File> getByDocumentId(String documentId) {
|
||||
EntityManager em = ThreadLocalContext.get().getEntityManager();
|
||||
|
||||
// Get the files
|
||||
Query q = em.createQuery("select f from File f where f.documentId = :documentId and f.deleteDate is null");
|
||||
q.setParameter("documentId", documentId);
|
||||
List<File> files = (List<File>) q.getResultList();
|
||||
|
||||
return files;
|
||||
}
|
||||
}
|
@ -0,0 +1,44 @@
|
||||
package com.sismics.docs.core.dao.jpa;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import javax.persistence.EntityManager;
|
||||
import javax.persistence.NoResultException;
|
||||
import javax.persistence.Query;
|
||||
|
||||
import com.sismics.docs.core.model.jpa.Locale;
|
||||
import com.sismics.util.context.ThreadLocalContext;
|
||||
|
||||
/**
|
||||
* Locale DAO.
|
||||
*
|
||||
* @author jtremeaux
|
||||
*/
|
||||
public class LocaleDao {
|
||||
/**
|
||||
* Gets a locale by its ID.
|
||||
*
|
||||
* @param id Locale ID
|
||||
* @return Locale
|
||||
*/
|
||||
public Locale getById(String id) {
|
||||
EntityManager em = ThreadLocalContext.get().getEntityManager();
|
||||
try {
|
||||
return em.find(Locale.class, id);
|
||||
} catch (NoResultException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the list of all locales.
|
||||
*
|
||||
* @return List of locales
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public List<Locale> findAll() {
|
||||
EntityManager em = ThreadLocalContext.get().getEntityManager();
|
||||
Query q = em.createQuery("select l from Locale l order by l.id");
|
||||
return q.getResultList();
|
||||
}
|
||||
}
|
@ -0,0 +1,33 @@
|
||||
package com.sismics.docs.core.dao.jpa;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
import javax.persistence.EntityManager;
|
||||
import javax.persistence.Query;
|
||||
|
||||
import com.google.common.collect.Sets;
|
||||
import com.sismics.util.context.ThreadLocalContext;
|
||||
|
||||
/**
|
||||
* Role base functions DAO.
|
||||
*
|
||||
* @author jtremeaux
|
||||
*/
|
||||
public class RoleBaseFunctionDao {
|
||||
/**
|
||||
* Find the set of base functions of a role.
|
||||
*
|
||||
* @param roleId Role ID
|
||||
* @return Set of base functions
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public Set<String> findByRoleId(String roleId) {
|
||||
EntityManager em = ThreadLocalContext.get().getEntityManager();
|
||||
StringBuilder sb = new StringBuilder("select rbf.RBF_IDBASEFUNCTION_C from T_ROLE_BASE_FUNCTION rbf, T_ROLE r");
|
||||
sb.append(" where rbf.RBF_IDROLE_C = :roleId and rbf.RBF_DELETEDATE_D is null");
|
||||
sb.append(" and r.ROL_ID_C = rbf.RBF_IDROLE_C and r.ROL_DELETEDATE_D is null");
|
||||
Query q = em.createNativeQuery(sb.toString());
|
||||
q.setParameter("roleId", roleId);
|
||||
return Sets.newHashSet(q.getResultList());
|
||||
}
|
||||
}
|
@ -0,0 +1,246 @@
|
||||
package com.sismics.docs.core.dao.jpa;
|
||||
|
||||
import java.sql.Timestamp;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
import javax.persistence.EntityManager;
|
||||
import javax.persistence.NoResultException;
|
||||
import javax.persistence.Query;
|
||||
|
||||
import org.mindrot.jbcrypt.BCrypt;
|
||||
|
||||
import com.google.common.base.Joiner;
|
||||
import com.sismics.docs.core.constant.Constants;
|
||||
import com.sismics.docs.core.dao.jpa.dto.UserDto;
|
||||
import com.sismics.docs.core.model.jpa.User;
|
||||
import com.sismics.docs.core.util.jpa.PaginatedList;
|
||||
import com.sismics.docs.core.util.jpa.PaginatedLists;
|
||||
import com.sismics.docs.core.util.jpa.QueryParam;
|
||||
import com.sismics.docs.core.util.jpa.SortCriteria;
|
||||
import com.sismics.util.context.ThreadLocalContext;
|
||||
|
||||
/**
|
||||
* User DAO.
|
||||
*
|
||||
* @author jtremeaux
|
||||
*/
|
||||
public class UserDao {
|
||||
/**
|
||||
* Authenticates an user.
|
||||
*
|
||||
* @param username User login
|
||||
* @param password User password
|
||||
* @return ID of the authenticated user or null
|
||||
*/
|
||||
public String authenticate(String username, String password) {
|
||||
EntityManager em = ThreadLocalContext.get().getEntityManager();
|
||||
Query q = em.createQuery("select u from User u where u.username = :username and u.deleteDate is null");
|
||||
q.setParameter("username", username);
|
||||
try {
|
||||
User user = (User) q.getSingleResult();
|
||||
if (!BCrypt.checkpw(password, user.getPassword())) {
|
||||
return null;
|
||||
}
|
||||
return user.getId();
|
||||
} catch (NoResultException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new user.
|
||||
*
|
||||
* @param user User to create
|
||||
* @return User ID
|
||||
* @throws Exception
|
||||
*/
|
||||
public String create(User user) throws Exception {
|
||||
// Create the user UUID
|
||||
user.setId(UUID.randomUUID().toString());
|
||||
|
||||
// Checks for user unicity
|
||||
EntityManager em = ThreadLocalContext.get().getEntityManager();
|
||||
Query q = em.createQuery("select u from User u where u.username = :username and u.deleteDate is null");
|
||||
q.setParameter("username", user.getUsername());
|
||||
List<?> l = q.getResultList();
|
||||
if (l.size() > 0) {
|
||||
throw new Exception("AlreadyExistingUsername");
|
||||
}
|
||||
|
||||
user.setCreateDate(new Date());
|
||||
user.setPassword(hashPassword(user.getPassword()));
|
||||
user.setTheme(Constants.DEFAULT_THEME_ID);
|
||||
em.persist(user);
|
||||
|
||||
return user.getId();
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates a user.
|
||||
*
|
||||
* @param user User to update
|
||||
* @return Updated user
|
||||
*/
|
||||
public User update(User user) {
|
||||
EntityManager em = ThreadLocalContext.get().getEntityManager();
|
||||
|
||||
// Get the user
|
||||
Query q = em.createQuery("select u from User u where u.id = :id and u.deleteDate is null");
|
||||
q.setParameter("id", user.getId());
|
||||
User userFromDb = (User) q.getSingleResult();
|
||||
|
||||
// Update the user
|
||||
userFromDb.setLocaleId(user.getLocaleId());
|
||||
userFromDb.setEmail(user.getEmail());
|
||||
userFromDb.setTheme(user.getTheme());
|
||||
userFromDb.setFirstConnection(user.isFirstConnection());
|
||||
|
||||
return user;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the user password.
|
||||
*
|
||||
* @param user User to update
|
||||
* @return Updated user
|
||||
*/
|
||||
public User updatePassword(User user) {
|
||||
EntityManager em = ThreadLocalContext.get().getEntityManager();
|
||||
|
||||
// Get the user
|
||||
Query q = em.createQuery("select u from User u where u.id = :id and u.deleteDate is null");
|
||||
q.setParameter("id", user.getId());
|
||||
User userFromDb = (User) q.getSingleResult();
|
||||
|
||||
// Update the user
|
||||
userFromDb.setPassword(hashPassword(user.getPassword()));
|
||||
|
||||
return user;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a user by its ID.
|
||||
*
|
||||
* @param id User ID
|
||||
* @return User
|
||||
*/
|
||||
public User getById(String id) {
|
||||
EntityManager em = ThreadLocalContext.get().getEntityManager();
|
||||
try {
|
||||
return em.find(User.class, id);
|
||||
} catch (NoResultException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an active user by its username.
|
||||
*
|
||||
* @param username User's username
|
||||
* @return User
|
||||
*/
|
||||
public User getActiveByUsername(String username) {
|
||||
EntityManager em = ThreadLocalContext.get().getEntityManager();
|
||||
try {
|
||||
Query q = em.createQuery("select u from User u where u.username = :username and u.deleteDate is null");
|
||||
q.setParameter("username", username);
|
||||
return (User) q.getSingleResult();
|
||||
} catch (NoResultException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an active user by its password recovery token.
|
||||
*
|
||||
* @param passwordResetKey Password recovery token
|
||||
* @return User
|
||||
*/
|
||||
public User getActiveByPasswordResetKey(String passwordResetKey) {
|
||||
EntityManager em = ThreadLocalContext.get().getEntityManager();
|
||||
try {
|
||||
Query q = em.createQuery("select u from User u where u.passwordResetKey = :passwordResetKey and u.deleteDate is null");
|
||||
q.setParameter("passwordResetKey", passwordResetKey);
|
||||
return (User) q.getSingleResult();
|
||||
} catch (NoResultException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes a user.
|
||||
*
|
||||
* @param username User's username
|
||||
*/
|
||||
public void delete(String username) {
|
||||
EntityManager em = ThreadLocalContext.get().getEntityManager();
|
||||
|
||||
// Get the user
|
||||
Query q = em.createQuery("select u from User u where u.username = :username and u.deleteDate is null");
|
||||
q.setParameter("username", username);
|
||||
User userFromDb = (User) q.getSingleResult();
|
||||
|
||||
// Delete the user
|
||||
Date dateNow = new Date();
|
||||
userFromDb.setDeleteDate(dateNow);
|
||||
|
||||
// Delete linked data
|
||||
q = em.createQuery("delete from AuthenticationToken at where at.userId = :userId");
|
||||
q.setParameter("userId", userFromDb.getId());
|
||||
q.executeUpdate();
|
||||
}
|
||||
|
||||
/**
|
||||
* Hash the user's password.
|
||||
*
|
||||
* @param password Clear password
|
||||
* @return Hashed password
|
||||
*/
|
||||
protected String hashPassword(String password) {
|
||||
return BCrypt.hashpw(password, BCrypt.gensalt());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the list of all users.
|
||||
*
|
||||
* @param paginatedList List of users (updated by side effects)
|
||||
* @param sortCriteria Sort criteria
|
||||
*/
|
||||
public void findAll(PaginatedList<UserDto> paginatedList, SortCriteria sortCriteria) {
|
||||
Map<String, Object> parameterMap = new HashMap<String, Object>();
|
||||
StringBuilder sb = new StringBuilder("select u.USE_ID_C as c0, u.USE_USERNAME_C as c1, u.USE_EMAIL_C as c2, u.USE_CREATEDATE_D as c3, u.USE_IDLOCALE_C as c4");
|
||||
sb.append(" from T_USER u ");
|
||||
|
||||
// Add search criterias
|
||||
List<String> criteriaList = new ArrayList<String>();
|
||||
criteriaList.add("u.USE_DELETEDATE_D is null");
|
||||
|
||||
if (!criteriaList.isEmpty()) {
|
||||
sb.append(" where ");
|
||||
sb.append(Joiner.on(" and ").join(criteriaList));
|
||||
}
|
||||
|
||||
// Perform the search
|
||||
QueryParam queryParam = new QueryParam(sb.toString(), parameterMap);
|
||||
List<Object[]> l = PaginatedLists.executePaginatedQuery(paginatedList, queryParam, sortCriteria);
|
||||
|
||||
// Assemble results
|
||||
List<UserDto> userDtoList = new ArrayList<UserDto>();
|
||||
for (Object[] o : l) {
|
||||
int i = 0;
|
||||
UserDto userDto = new UserDto();
|
||||
userDto.setId((String) o[i++]);
|
||||
userDto.setUsername((String) o[i++]);
|
||||
userDto.setEmail((String) o[i++]);
|
||||
userDto.setCreateTimestamp(((Timestamp) o[i++]).getTime());
|
||||
userDto.setLocaleId((String) o[i++]);
|
||||
userDtoList.add(userDto);
|
||||
}
|
||||
paginatedList.setResultList(userDtoList);
|
||||
}
|
||||
}
|
@ -0,0 +1,32 @@
|
||||
package com.sismics.docs.core.dao.jpa.criteria;
|
||||
|
||||
|
||||
/**
|
||||
* Document criteria.
|
||||
*
|
||||
* @author bgamard
|
||||
*/
|
||||
public class DocumentCriteria {
|
||||
/**
|
||||
* User ID.
|
||||
*/
|
||||
private String userId;
|
||||
|
||||
/**
|
||||
* Getter of userId.
|
||||
*
|
||||
* @return userId
|
||||
*/
|
||||
public String getUserId() {
|
||||
return userId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Setter of userId.
|
||||
*
|
||||
* @param userId userId
|
||||
*/
|
||||
public void setUserId(String userId) {
|
||||
this.userId = userId;
|
||||
}
|
||||
}
|
@ -0,0 +1,103 @@
|
||||
package com.sismics.docs.core.dao.jpa.dto;
|
||||
|
||||
import javax.persistence.Id;
|
||||
|
||||
/**
|
||||
* Document DTO.
|
||||
*
|
||||
* @author jtremeaux
|
||||
*/
|
||||
public class DocumentDto {
|
||||
/**
|
||||
* Document ID.
|
||||
*/
|
||||
@Id
|
||||
private String id;
|
||||
|
||||
/**
|
||||
* Title.
|
||||
*/
|
||||
private String title;
|
||||
|
||||
/**
|
||||
* Description.
|
||||
*/
|
||||
private String description;
|
||||
|
||||
/**
|
||||
* Creation date.
|
||||
*/
|
||||
private Long createTimestamp;
|
||||
|
||||
/**
|
||||
* Getter de id.
|
||||
*
|
||||
* @return the id
|
||||
*/
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Setter de id.
|
||||
*
|
||||
* @param id id
|
||||
*/
|
||||
public void setId(String id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Getter de title.
|
||||
*
|
||||
* @return the title
|
||||
*/
|
||||
public String getTitle() {
|
||||
return title;
|
||||
}
|
||||
|
||||
/**
|
||||
* Setter de title.
|
||||
*
|
||||
* @param title title
|
||||
*/
|
||||
public void setTitle(String title) {
|
||||
this.title = title;
|
||||
}
|
||||
|
||||
/**
|
||||
* Getter de description.
|
||||
*
|
||||
* @return the description
|
||||
*/
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
/**
|
||||
* Setter de description.
|
||||
*
|
||||
* @param description description
|
||||
*/
|
||||
public void setDescription(String description) {
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
/**
|
||||
* Getter de createTimestamp.
|
||||
*
|
||||
* @return the createTimestamp
|
||||
*/
|
||||
public Long getCreateTimestamp() {
|
||||
return createTimestamp;
|
||||
}
|
||||
|
||||
/**
|
||||
* Setter of createTimestamp.
|
||||
*
|
||||
* @param createTimestamp createTimestamp
|
||||
*/
|
||||
public void setCreateTimestamp(Long createTimestamp) {
|
||||
this.createTimestamp = createTimestamp;
|
||||
}
|
||||
}
|
@ -0,0 +1,123 @@
|
||||
package com.sismics.docs.core.dao.jpa.dto;
|
||||
|
||||
/**
|
||||
* User DTO.
|
||||
*
|
||||
* @author jtremeaux
|
||||
*/
|
||||
public class UserDto {
|
||||
/**
|
||||
* User ID.
|
||||
*/
|
||||
private String id;
|
||||
|
||||
/**
|
||||
* Locale ID.
|
||||
*/
|
||||
private String localeId;
|
||||
|
||||
/**
|
||||
* Username.
|
||||
*/
|
||||
private String username;
|
||||
|
||||
/**
|
||||
* Email address.
|
||||
*/
|
||||
private String email;
|
||||
|
||||
/**
|
||||
* Creation date of this user.
|
||||
*/
|
||||
private Long createTimestamp;
|
||||
|
||||
/**
|
||||
* Getter of id.
|
||||
*
|
||||
* @return id
|
||||
*/
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Setter of id.
|
||||
*
|
||||
* @param id id
|
||||
*/
|
||||
public void setId(String id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Getter of localeId.
|
||||
*
|
||||
* @return localeId
|
||||
*/
|
||||
public String getLocaleId() {
|
||||
return localeId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Setter of localeId.
|
||||
*
|
||||
* @param localeId localeId
|
||||
*/
|
||||
public void setLocaleId(String localeId) {
|
||||
this.localeId = localeId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Getter of username.
|
||||
*
|
||||
* @return username
|
||||
*/
|
||||
public String getUsername() {
|
||||
return username;
|
||||
}
|
||||
|
||||
/**
|
||||
* Setter of username.
|
||||
*
|
||||
* @param username username
|
||||
*/
|
||||
public void setUsername(String username) {
|
||||
this.username = username;
|
||||
}
|
||||
|
||||
/**
|
||||
* Getter of email.
|
||||
*
|
||||
* @return email
|
||||
*/
|
||||
public String getEmail() {
|
||||
return email;
|
||||
}
|
||||
|
||||
/**
|
||||
* Setter of email.
|
||||
*
|
||||
* @param email email
|
||||
*/
|
||||
public void setEmail(String email) {
|
||||
this.email = email;
|
||||
}
|
||||
|
||||
/**
|
||||
* Getter of createTimestamp.
|
||||
*
|
||||
* @return createTimestamp
|
||||
*/
|
||||
public Long getCreateTimestamp() {
|
||||
return createTimestamp;
|
||||
}
|
||||
|
||||
/**
|
||||
* Setter of createTimestamp.
|
||||
*
|
||||
* @param createTimestamp createTimestamp
|
||||
*/
|
||||
public void setCreateTimestamp(Long createTimestamp) {
|
||||
this.createTimestamp = createTimestamp;
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
package com.sismics.docs.core.dao.lucene;
|
||||
|
||||
|
||||
/**
|
||||
* Lucene Article DAO.
|
||||
*
|
||||
* @author bgamard
|
||||
*/
|
||||
public class ArticleDao {
|
||||
|
||||
}
|
@ -0,0 +1,135 @@
|
||||
package com.sismics.docs.core.dao.lucene;
|
||||
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.Reader;
|
||||
|
||||
import org.apache.lucene.analysis.TokenStream;
|
||||
import org.apache.lucene.analysis.charfilter.HTMLStripCharFilter;
|
||||
import org.apache.lucene.analysis.core.LowerCaseFilter;
|
||||
import org.apache.lucene.analysis.core.StopAnalyzer;
|
||||
import org.apache.lucene.analysis.core.StopFilter;
|
||||
import org.apache.lucene.analysis.standard.ClassicAnalyzer;
|
||||
import org.apache.lucene.analysis.standard.ClassicTokenizer;
|
||||
import org.apache.lucene.analysis.standard.StandardFilter;
|
||||
import org.apache.lucene.analysis.standard.StandardTokenizer;
|
||||
import org.apache.lucene.analysis.util.CharArraySet;
|
||||
import org.apache.lucene.analysis.util.StopwordAnalyzerBase;
|
||||
import org.apache.lucene.util.Version;
|
||||
|
||||
/**
|
||||
* Filters {@link StandardTokenizer} with {@link StandardFilter}, {@link
|
||||
* LowerCaseFilter} and {@link StopFilter}, using a list of
|
||||
* English stop words.
|
||||
*
|
||||
* <a name="version"/>
|
||||
* <p>You must specify the required {@link Version}
|
||||
* compatibility when creating StandardAnalyzer:
|
||||
* <ul>
|
||||
* <li> As of 3.4, Hiragana and Han characters are no longer wrongly split
|
||||
* from their combining characters. If you use a previous version number,
|
||||
* you get the exact broken behavior for backwards compatibility.
|
||||
* <li> As of 3.1, StandardTokenizer implements Unicode text segmentation,
|
||||
* and StopFilter correctly handles Unicode 4.0 supplementary characters
|
||||
* in stopwords. {@link ClassicTokenizer} and {@link ClassicAnalyzer}
|
||||
* are the pre-3.1 implementations of StandardTokenizer and
|
||||
* StandardAnalyzer.
|
||||
* <li> As of 2.9, StopFilter preserves position increments
|
||||
* <li> As of 2.4, Tokens incorrectly identified as acronyms
|
||||
* are corrected (see <a href="https://issues.apache.org/jira/browse/LUCENE-1068">LUCENE-1068</a>)
|
||||
* </ul>
|
||||
*/
|
||||
public final class DocsStandardAnalyzer extends StopwordAnalyzerBase {
|
||||
|
||||
/** Default maximum allowed token length */
|
||||
public static final int DEFAULT_MAX_TOKEN_LENGTH = 255;
|
||||
|
||||
private int maxTokenLength = DEFAULT_MAX_TOKEN_LENGTH;
|
||||
|
||||
/** An unmodifiable set containing some common English words that are usually not
|
||||
useful for searching. */
|
||||
public static final CharArraySet STOP_WORDS_SET = StopAnalyzer.ENGLISH_STOP_WORDS_SET;
|
||||
|
||||
/** Builds an analyzer with the given stop |