Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
J
jh-boot
Project
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Jan Hrabal
jh-boot
Commits
13ec164f
Commit
13ec164f
authored
Aug 08, 2019
by
jhrabal
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
work in progress
parent
e7571522
Show whitespace changes
Inline
Side-by-side
Showing
20 changed files
with
1285 additions
and
43 deletions
+1285
-43
pom.xml
pom.xml
+12
-0
init.sql
sql/init.sql
+38
-0
Email.java
src/main/java/com/jh/common/email/Email.java
+0
-22
JhMailConfig.java
src/main/java/com/jh/common/email/JhMailConfig.java
+15
-0
LocalEmailService.java
src/main/java/com/jh/common/email/LocalEmailService.java
+0
-2
I18nContext.java
src/main/java/com/jh/common/i18n/I18nContext.java
+51
-0
I18nUtils.java
src/main/java/com/jh/common/i18n/I18nUtils.java
+264
-0
JhTemplateConfig.java
src/main/java/com/jh/common/template/JhTemplateConfig.java
+18
-0
Template.java
src/main/java/com/jh/common/template/Template.java
+67
-0
TemplateEngine.java
src/main/java/com/jh/common/template/TemplateEngine.java
+31
-0
TemplateLoader.java
src/main/java/com/jh/common/template/TemplateLoader.java
+8
-0
TemplateService.java
src/main/java/com/jh/common/template/TemplateService.java
+2
-19
CustomizableLabelsRepository.java
...n/template/customizable/CustomizableLabelsRepository.java
+55
-0
CustomizableLabelsService.java
...mmon/template/customizable/CustomizableLabelsService.java
+239
-0
CustomizableTemplateLabel.java
...mmon/template/customizable/CustomizableTemplateLabel.java
+120
-0
TemplateLabels.java
...a/com/jh/common/template/customizable/TemplateLabels.java
+16
-0
TemplateParam.java
...va/com/jh/common/template/customizable/TemplateParam.java
+70
-0
TemplateParamValue.java
...m/jh/common/template/customizable/TemplateParamValue.java
+24
-0
TemplateSettings.java
...com/jh/common/template/customizable/TemplateSettings.java
+33
-0
HandlebarsTemplateService.java
...common/template/handlebars/HandlebarsTemplateService.java
+222
-0
No files found.
pom.xml
View file @
13ec164f
...
...
@@ -82,6 +82,18 @@
<artifactId>
spring-boot-starter-mail
</artifactId>
</dependency>
<!-- handlebars -->
<dependency>
<groupId>
com.github.jknack
</groupId>
<artifactId>
handlebars
</artifactId>
<version>
4.1.2
</version>
</dependency>
<dependency>
<groupId>
com.github.jknack
</groupId>
<artifactId>
handlebars-helpers
</artifactId>
<version>
4.1.2
</version>
</dependency>
<dependency>
<groupId>
commons-httpclient
</groupId>
...
...
sql/init.sql
View file @
13ec164f
...
...
@@ -107,6 +107,7 @@ CREATE TABLE RESET_PASSWORD_TOKEN (
);
CREATE
INDEX
RESET_PASSWORD_TOKEN_LOGIN_IDX
ON
RESET_PASSWORD_TOKEN
(
LOGIN
);
-- EMAILS
CREATE
TABLE
EMAIL
(
ID
INT8
NOT
NULL
,
...
...
@@ -167,3 +168,39 @@ CREATE TABLE EMAIL_ATTACHMENT (
);
CREATE
INDEX
EMAIL_ATTACHMENT_IDX
ON
EMAIL_ATTACHMENT
(
EMAIL_ID
);
-- CUSTOMIZABLE TEMPLATES
CREATE
TABLE
CUSTOMIZABLE_TEMPLATE
(
ID
INT8
NOT
NULL
,
CODE
VARCHAR
(
250
),
NAME
VARCHAR
(
100
),
TEMPLATE
TEXT
,
CONSTRAINT
PK_CUSTOMIZABLE_TEMPLATE
PRIMARY
KEY
(
ID
)
);
CREATE
INDEX
CUSTOMIZABLE_TEMPLATE_CODE_IDX
ON
CUSTOMIZABLE_TEMPLATE
(
CODE
);
CREATE
TABLE
CUSTOMIZABLE_TEMPLATE_LABEL
(
ID
INT8
NOT
NULL
,
TEMPLATE_ID
INT8
NOT
NULL
,
UNIT_ID
INT8
,
CODE
VARCHAR
(
1000
)
NOT
NULL
,
LANG
VARCHAR
(
10
),
LABEL
VARCHAR
,
POSITION
NUMERIC
(
19
,
0
),
CONSTRAINT
PK_CUSTOMIZABLE_TEMPLATE_LABEL
PRIMARY
KEY
(
ID
),
CONSTRAINT
FK_CUSTOMIZABLE_TEMPLATE_LABEL_TEMPLATE
FOREIGN
KEY
(
TEMPLATE_ID
)
REFERENCES
CUSTOMIZABLE_TEMPLATE
(
ID
)
);
CREATE
INDEX
CUSTOMIZABLE_TEMPLATE_LABEL_TEMPLATE_IDX
ON
CUSTOMIZABLE_TEMPLATE_LABEL
(
TEMPLATE_ID
);
CREATE
INDEX
CUSTOMIZABLE_TEMPLATE_LABEL_UNIT_IDX
ON
CUSTOMIZABLE_TEMPLATE_LABEL
(
UNIT_ID
);
-- TODO
\ No newline at end of file
src/main/java/com/jh/common/email/Email.java
View file @
13ec164f
...
...
@@ -22,10 +22,6 @@ public class Email extends AbstractIdEntity {
@Column
(
name
=
"LOCKED"
)
private
Boolean
locked
;
/** The unit id. */
@Column
(
name
=
"UNIT_ID"
)
private
Long
unitId
;
/** The email from. */
@Column
(
name
=
"EMAIL_FROM"
)
private
String
emailFrom
;
...
...
@@ -85,24 +81,6 @@ public class Email extends AbstractIdEntity {
}
/**
* Gets the unit id.
*
* @return the unit id
*/
public
Long
getUnitId
()
{
return
unitId
;
}
/**
* Sets the unit id.
*
* @param unitId the new unit id
*/
public
void
setUnitId
(
Long
unitId
)
{
this
.
unitId
=
unitId
;
}
/**
* Gets the from.
*
* @return the from
...
...
src/main/java/com/jh/common/email/JhMailConfig.java
0 → 100644
View file @
13ec164f
package
com
.
jh
.
common
.
email
;
import
org.springframework.context.annotation.Bean
;
//TODO
public
class
JhMailConfig
{
@Bean
public
EmailService
emailService
()
{
return
new
LocalEmailService
();
}
}
src/main/java/com/jh/common/email/LocalEmailService.java
View file @
13ec164f
...
...
@@ -147,7 +147,6 @@ public class LocalEmailService implements EmailService {
helper
.
setText
(
email
.
getHtml
(),
true
);
}
if
(
email
.
getAttachments
()
!=
null
)
{
for
(
EmailAttachment
a
:
email
.
getAttachments
())
{
if
(
a
.
getData
()
!=
null
)
{
...
...
@@ -164,7 +163,6 @@ public class LocalEmailService implements EmailService {
mailSender
.
send
(
msg
);
email
.
setStatus
(
"SENT"
);
}
catch
(
Exception
e
)
{
e
.
printStackTrace
();
email
.
setStatus
(
"FAILED"
);
...
...
src/main/java/com/jh/common/i18n/I18nContext.java
0 → 100644
View file @
13ec164f
package
com
.
jh
.
common
.
i18n
;
/**
* The Interface I18nContext.
*/
public
interface
I18nContext
{
/**
* Gets the date format.
*
* @return the date format
*/
public
String
getDateFormat
();
/**
* Gets the currency format.
*
* @return the currency format
*/
public
String
getCurrencyFormat
();
/**
* Gets the thousand delimiter.
*
* @return the thousand delimiter
*/
public
String
getThousandDelimiter
();
/**
* Gets the decimal delimiter.
*
* @return the decimal delimiter
*/
public
String
getDecimalDelimiter
();
/**
* Gets the currency.
*
* @return the currency
*/
public
String
getCurrency
();
/**
* Gets the currency symbol.
*
* @return the currency symbol
*/
public
String
getCurrencySymbol
();
}
src/main/java/com/jh/common/i18n/I18nUtils.java
0 → 100644
View file @
13ec164f
package
com
.
jh
.
common
.
i18n
;
import
java.text.DecimalFormat
;
import
java.text.DecimalFormatSymbols
;
import
java.text.NumberFormat
;
import
java.text.SimpleDateFormat
;
import
java.time.LocalDate
;
import
java.time.format.DateTimeFormatter
;
import
java.util.Date
;
import
java.util.HashMap
;
import
java.util.Map
;
import
java.util.Objects
;
/**
* TODO comment.
*
* @author jh
*/
public
class
I18nUtils
{
/** The date formats. */
private
Map
<
String
,
SimpleDateFormat
>
dateFormats
;
/** The date formatters. */
private
Map
<
String
,
DateTimeFormatter
>
dateFormatters
;
/** The number formats. */
private
Map
<
NumberFormatKey
,
NumberFormat
>
numberFormats
;
/** The instance. */
private
static
I18nUtils
instance
=
new
I18nUtils
();
private
I18nContext
defaultI18n
=
new
I18nContext
()
{
@Override
public
String
getThousandDelimiter
()
{
return
","
;
}
@Override
public
String
getDecimalDelimiter
()
{
return
"."
;
}
@Override
public
String
getDateFormat
()
{
return
"MM/DD/YYYY"
;
}
@Override
public
String
getCurrencySymbol
()
{
return
"$"
;
}
@Override
public
String
getCurrencyFormat
()
{
return
"left"
;
}
@Override
public
String
getCurrency
()
{
return
"USD"
;
}
};
/**
* Instantiates a new i 18 n utils.
*/
private
I18nUtils
()
{
dateFormats
=
new
HashMap
<>();
numberFormats
=
new
HashMap
<>();
dateFormatters
=
new
HashMap
<>();
}
/**
* Format number.
*
* @param number the number
* @param i18n the i 18 n
* @return the string
*/
public
String
formatNumber
(
Number
number
,
I18nContext
i18n
)
{
return
formatNumber
(
number
,
3
,
i18n
);
}
/**
* Format number.
*
* @param number the number
* @param fixed the fixed
* @param i18n the i 18 n
* @return the string
*/
public
String
formatNumber
(
Number
number
,
int
fixed
,
I18nContext
i18n
)
{
if
(
number
==
null
)
{
return
""
;
}
if
(
i18n
==
null
)
{
i18n
=
defaultI18n
;
}
NumberFormatKey
nfk
=
new
NumberFormatKey
(
i18n
.
getDecimalDelimiter
(),
i18n
.
getThousandDelimiter
(),
fixed
);
NumberFormat
nf
=
numberFormats
.
get
(
nfk
);
if
(
nf
==
null
)
{
DecimalFormatSymbols
otherSymbols
=
new
DecimalFormatSymbols
();
char
ds
=
i18n
.
getDecimalDelimiter
()
==
null
||
i18n
.
getDecimalDelimiter
().
isEmpty
()
?
'.'
:
i18n
.
getDecimalDelimiter
().
charAt
(
0
);
char
gs
=
i18n
.
getThousandDelimiter
()
==
null
||
i18n
.
getThousandDelimiter
().
isEmpty
()
?
'.'
:
i18n
.
getThousandDelimiter
().
charAt
(
0
);
otherSymbols
.
setDecimalSeparator
(
ds
);
otherSymbols
.
setGroupingSeparator
(
gs
);
DecimalFormat
df
=
new
DecimalFormat
(
"#"
,
otherSymbols
);
df
.
setGroupingUsed
(
true
);
df
.
setGroupingSize
(
3
);
df
.
setMinimumIntegerDigits
(
1
);
df
.
setMinimumFractionDigits
(
fixed
);
df
.
setMaximumFractionDigits
(
fixed
);
nf
=
df
;
numberFormats
.
put
(
nfk
,
df
);
}
return
nf
.
format
(
number
);
}
/**
* Format money.
*
* @param number the number
* @param currency the currency
* @param i18n the i 18 n
* @param fixed the fixed
* @return the string
*/
public
String
formatMoney
(
Number
number
,
String
currency
,
I18nContext
i18n
,
int
fixed
)
{
if
(
number
==
null
)
{
return
""
;
}
if
(
i18n
==
null
)
{
i18n
=
defaultI18n
;
}
if
(
currency
==
null
)
{
currency
=
""
;
}
if
(!
"right"
.
equals
(
i18n
.
getCurrencyFormat
()))
{
StringBuilder
sb
=
new
StringBuilder
(
currency
);
sb
.
append
(
" "
).
append
(
formatNumber
(
number
,
fixed
,
i18n
));
return
sb
.
toString
();
}
StringBuilder
sb
=
new
StringBuilder
(
formatNumber
(
number
,
fixed
,
i18n
));
sb
.
append
(
" "
).
append
(
currency
);
return
sb
.
toString
();
}
/**
* Format money.
*
* @param number the number
* @param currency the currency
* @param i18n the i 18 n
* @return the string
*/
public
String
formatMoney
(
Number
number
,
String
currency
,
I18nContext
i18n
)
{
return
formatMoney
(
number
,
currency
,
i18n
,
2
);
}
/**
* Format percent.
*
* @param number the number
* @param i18n the i 18 n
* @return the string
*/
public
String
formatPercent
(
Number
number
,
I18nContext
i18n
)
{
if
(
number
==
null
)
{
return
""
;
}
StringBuilder
sb
=
new
StringBuilder
(
formatNumber
(
number
,
i18n
));
sb
.
append
(
" %"
);
return
sb
.
toString
();
}
/**
* Format date.
*
* @param date the date
* @param i18n the i 18 n
* @return the string
*/
public
String
formatDate
(
Date
date
,
I18nContext
i18n
)
{
if
(
date
==
null
)
{
return
""
;
}
if
(
i18n
==
null
)
{
i18n
=
defaultI18n
;
}
String
format
=
Objects
.
toString
(
i18n
.
getDateFormat
(),
"MM/dd/yyyy"
);
SimpleDateFormat
sdf
=
dateFormats
.
get
(
format
);
if
(
sdf
==
null
)
{
dateFormats
.
put
(
format
,
sdf
=
new
SimpleDateFormat
(
format
));
}
return
sdf
.
format
(
date
);
}
/**
* Format date.
*
* @param date the date
* @param i18n the i 18 n
* @return the string
*/
public
String
formatDate
(
LocalDate
date
,
I18nContext
i18n
)
{
if
(
date
==
null
)
{
return
""
;
}
if
(
i18n
==
null
)
{
i18n
=
defaultI18n
;
}
String
format
=
Objects
.
toString
(
i18n
.
getDateFormat
(),
"MM/dd/yyyy"
);
DateTimeFormatter
dtf
=
dateFormatters
.
get
(
format
);
if
(
dtf
==
null
)
{
dateFormatters
.
put
(
format
,
dtf
=
DateTimeFormatter
.
ofPattern
(
convertJSFormat
(
format
)));
}
return
date
.
format
(
dtf
);
}
/**
* Convert JS format.
*
* @param format the format
* @return the string
*/
private
String
convertJSFormat
(
String
format
)
{
return
format
.
replace
(
"D"
,
"d"
).
replace
(
"m"
,
"M"
).
replace
(
"Y"
,
"y"
);
}
/**
* Gets the single instance of I18nUtils.
*
* @return single instance of I18nUtils
*/
public
static
I18nUtils
getInstance
()
{
return
instance
;
}
}
src/main/java/com/jh/common/template/JhTemplateConfig.java
0 → 100644
View file @
13ec164f
package
com
.
jh
.
common
.
template
;
import
org.springframework.context.annotation.Bean
;
public
class
JhTemplateConfig
{
@Bean
public
TemplateEngine
templateEngine
()
{
return
null
;
}
@Bean
public
TemplateService
templateService
()
{
return
null
;
}
}
src/main/java/com/jh/common/template/Template.java
0 → 100644
View file @
13ec164f
package
com
.
jh
.
common
.
template
;
import
javax.persistence.Column
;
import
javax.persistence.Entity
;
import
javax.persistence.Table
;
import
com.jh.common.jpa.AbstractIdEntity
;
@Entity
@Table
(
name
=
"CUSTOMIZABLE_TEMPLATE"
)
public
class
Template
extends
AbstractIdEntity
{
@Column
(
name
=
"CODE"
)
private
String
code
;
@Column
(
name
=
"NAME"
)
private
String
name
;
@Column
(
name
=
"TEMPLATE"
)
private
String
template
;
@Column
(
name
=
"TRANSLATE_NAME"
)
private
Boolean
translateName
;
public
Template
()
{
super
();
}
public
Template
(
Long
templateId
)
{
super
();
setId
(
templateId
);
}
public
String
getCode
()
{
return
code
;
}
public
void
setCode
(
String
code
)
{
this
.
code
=
code
;
}
public
String
getName
()
{
return
name
;
}
public
void
setName
(
String
name
)
{
this
.
name
=
name
;
}
public
String
getTemplate
()
{
return
template
;
}
public
void
setTemplate
(
String
template
)
{
this
.
template
=
template
;
}
public
Boolean
getTranslateName
()
{
return
translateName
;
}
public
void
setTranslateName
(
Boolean
translateName
)
{
this
.
translateName
=
translateName
;
}
}
src/main/java/com/jh/common/template/TemplateEngine.java
0 → 100644
View file @
13ec164f
package
com
.
jh
.
common
.
template
;
import
java.io.Writer
;
import
java.util.Locale
;
import
java.util.Map
;
public
interface
TemplateEngine
{
/**
* TODO.
*
* @param templateName the template name
* @param clazz the clazz
* @param data the data
* @param locale the locale
* @param writer the writer
*/
void
evaluateTemplate
(
String
templateName
,
Class
<?>
clazz
,
Map
<
String
,
Object
>
data
,
Locale
locale
,
Writer
writer
);
/**
* TODO.
*
* @param template the template
* @param data the data
* @param locale the locale
* @param writer the writer
*/
void
evaluateTemplate
(
String
template
,
Map
<
String
,
Object
>
data
,
Locale
locale
,
Writer
writer
);
}
\ No newline at end of file
src/main/java/com/jh/common/template/TemplateLoader.java
0 → 100644
View file @
13ec164f
package
com
.
jh
.
common
.
template
;
public
interface
TemplateLoader
{
}
src/main/java/com/jh/common/template/TemplateService.java
View file @
13ec164f
...
...
@@ -6,25 +6,8 @@ import java.util.Map;
public
interface
TemplateService
{
/**
* TODO.
*
* @param templateName the template name
* @param clazz the clazz
* @param data the data
* @param locale the locale
* @param writer the writer
*/
void
evaluateTemplate
(
String
templateName
,
Class
<?>
clazz
,
Map
<
String
,
Object
>
data
,
Locale
locale
,
Writer
writer
);
void
evaluate
(
Writer
writer
,
String
templateCode
,
Map
<
String
,
Object
>
data
,
Locale
locale
);
/**
* TODO.
*
* @param template the template
* @param data the data
* @param locale the locale
* @param writer the writer
*/
void
evaluateTemplate
(
String
template
,
Map
<
String
,
Object
>
data
,
Locale
locale
,
Writer
writer
);
void
evaluateInline
(
Writer
writer
,
String
template
,
Map
<
String
,
Object
>
data
,
Locale
locale
);
}
src/main/java/com/jh/common/template/customizable/CustomizableLabelsRepository.java
0 → 100644
View file @
13ec164f
package
com
.
jh
.
common
.
template
.
customizable
;
import
java.util.Collection
;
import
java.util.List
;
import
javax.persistence.Query
;
import
org.springframework.stereotype.Repository
;
import
com.jh.common.jpa.AbstractHibernateRepository
;
import
com.jh.common.template.Template
;
@Repository
public
class
CustomizableLabelsRepository
extends
AbstractHibernateRepository
{
@SuppressWarnings
(
"unchecked"
)
public
Template
fetchTemplate
(
String
code
)
{
Query
q
=
entityManager
.
createQuery
(
"select t from Template t where code = :code"
);
q
.
setParameter
(
"code"
,
code
);
List
<
Template
>
list
=
q
.
getResultList
();
return
list
.
isEmpty
()
?
null
:
list
.
get
(
0
);
}
@SuppressWarnings
(
"unchecked"
)
public
List
<
CustomizableTemplateLabel
>
findCustomizedTemplateLabels
(
Long
templateId
,
Long
unitId
)
{
Query
q
=
entityManager
.
createQuery
(
"select tl from TemplateLabel tl left join tl.template t where t.id = :templateId and tl.unitId = :unitId order by tl.position asc"
);
q
.
setParameter
(
"template.id"
,
templateId
);
q
.
setParameter
(
"unitId"
,
unitId
);
return
q
.
getResultList
();
}
@SuppressWarnings
(
"unchecked"
)
public
List
<
CustomizableTemplateLabel
>
findDefaultTemplateLabels
(
Long
templateId
)
{
Query
q
=
entityManager
.
createQuery
(
"select tl from TemplateLabel tl left join tl.template t where t.id = :templateId and tl.unitId is null"
);
q
.
setParameter
(
"template.id"
,
templateId
);
return
q
.
getResultList
();
}
public
void
saveCustomizedLabels
(
Collection
<
CustomizableTemplateLabel
>
labels
)
{
if
(
labels
==
null
)
{
return
;
}
labels
.
stream
().
forEach
(
this
::
save
);
}
}
src/main/java/com/jh/common/template/customizable/CustomizableLabelsService.java
0 → 100644
View file @
13ec164f
package
com
.
jh
.
common
.
template
.
customizable
;
import
java.util.Collection
;
import
java.util.HashMap
;
import
java.util.LinkedHashSet
;
import
java.util.List
;
import
java.util.Map
;
import
java.util.Map.Entry
;
import
java.util.Set
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.beans.factory.annotation.Value
;
import
org.springframework.stereotype.Service
;
import
org.springframework.transaction.annotation.Transactional
;
import
com.jh.common.template.Template
;
@Service
public
class
CustomizableLabelsService
{
private
CustomizableLabelsRepository
repo
;
private
Map
<
Long
,
CustomizableTemplateLabels
>
templateLabelsCache
=
new
HashMap
<>();
private
boolean
useCache
;
@Transactional
public
Template
getTemplateContent
(
String
code
)
{
return
repo
.
fetchTemplate
(
code
);
}
@Transactional
public
Map
<
String
,
CustomizableTemplateLabel
>
getCustomizationTemplateLabels
(
Long
templateId
,
Long
unitId
,
String
defaultLanguage
)
{
TemplateLabels
templateLabels
=
getTemplateDefaultLabels
(
templateId
);
List
<
CustomizableTemplateLabel
>
labels
=
repo
.
findCustomizedTemplateLabels
(
templateId
,
unitId
);
Map
<
String
,
CustomizableTemplateLabel
>
defaultMap
=
templateLabels
.
getLanguages
().
get
(
defaultLanguage
);
if
(
defaultMap
==
null
)
{
defaultMap
=
templateLabels
.
getFallbackLabels
();
}
if
(
defaultMap
==
null
)
{
return
null
;
}
Map
<
String
,
CustomizableTemplateLabel
>
result
=
new
HashMap
<>();
for
(
String
code
:
templateLabels
.
getCodes
())
{
CustomizableTemplateLabel
label
=
defaultMap
.
get
(
code
);
CustomizableTemplateLabel
newLabel
=
new
CustomizableTemplateLabel
();
newLabel
.
setCode
(
code
);
newLabel
.
setLabel
(
label
.
getLabel
());
newLabel
.
setDefaultLabel
(
label
.
getLabel
());
newLabel
.
setPosition
(
label
.
getPosition
());
result
.
put
(
code
,
newLabel
);
}
for
(
CustomizableTemplateLabel
label
:
labels
)
{
CustomizableTemplateLabel
defaultLabel
=
result
.
get
(
label
.
getCode
());
if
(
defaultLabel
!=
null
)
{
label
.
setDefaultLabel
(
defaultLabel
.
getLabel
());
}
result
.
put
(
defaultLanguage
,
label
);
}
return
result
;
}
@Transactional
public
Map
<
String
,
String
>
getTranslatedTemplateLabels
(
Long
templateId
,
Long
unitId
,
String
defaultLanguage
)
{
TemplateLabels
templateLabels
=
getTemplateDefaultLabels
(
templateId
);
List
<
CustomizableTemplateLabel
>
labels
=
repo
.
findCustomizedTemplateLabels
(
templateId
,
unitId
);
Map
<
String
,
CustomizableTemplateLabel
>
defaultMap
=
templateLabels
.
getLanguages
().
get
(
defaultLanguage
);
if
(
defaultMap
==
null
)
{
defaultMap
=
templateLabels
.
getFallbackLabels
();
}
if
(
defaultMap
==
null
)
{
return
null
;
}
Map
<
String
,
String
>
result
=
new
HashMap
<>();
for
(
String
code
:
templateLabels
.
getCodes
())
{
CustomizableTemplateLabel
label
=
defaultMap
.
get
(
code
);
if
(
label
!=
null
)
{
result
.
put
(
code
,
label
.
getLabel
());
}
}
for
(
CustomizableTemplateLabel
label
:
labels
)
{
result
.
put
(
label
.
getCode
(),
label
.
getLabel
());
}
return
result
;
}
@Transactional
public
List
<
CustomizableTemplateLabel
>
fetchLabels
(
Long
templateId
,
Long
unitId
)
{
return
repo
.
findCustomizedTemplateLabels
(
templateId
,
unitId
);
}
@Transactional
public
TemplateLabels
getTemplateDefaultLabels
(
Long
templateId
)
{
CustomizableTemplateLabels
labels
=
useCache
?
templateLabelsCache
.
get
(
templateId
)
:
null
;
if
(
labels
!=
null
)
{
return
labels
;
}
Set
<
String
>
codes
=
new
LinkedHashSet
<>();
Map
<
String
,
Map
<
String
,
CustomizableTemplateLabel
>>
maps
=
new
HashMap
<>();
Map
<
String
,
CustomizableTemplateLabel
>
fallbackMap
=
new
HashMap
<>();
List
<
CustomizableTemplateLabel
>
defaultLabels
=
repo
.
findDefaultTemplateLabels
(
templateId
);
//keep order
for
(
CustomizableTemplateLabel
ctl
:
defaultLabels
)
{
codes
.
add
(
ctl
.
getCode
());
}
//map labels without order
for
(
CustomizableTemplateLabel
ctl
:
defaultLabels
)
{
Map
<
String
,
CustomizableTemplateLabel
>
map
=
maps
.
get
(
ctl
.
getLanguageCode
());
if
(
map
==
null
)
{
maps
.
put
(
ctl
.
getLanguageCode
(),
map
=
new
HashMap
<>());
}
map
.
put
(
ctl
.
getCode
(),
ctl
);
if
(
"en"
.
equalsIgnoreCase
(
ctl
.
getLanguageCode
())
||
!
fallbackMap
.
containsKey
(
ctl
.
getCode
()))
{
fallbackMap
.
put
(
ctl
.
getCode
(),
ctl
);
}
}
labels
=
new
CustomizableTemplateLabels
();
labels
.
codes
=
codes
;
labels
.
languages
=
new
HashMap
<>();
for
(
String
lang
:
maps
.
keySet
())
{
labels
.
languages
.
put
(
lang
,
new
HashMap
<>());
}
// align maps
for
(
Entry
<
String
,
Map
<
String
,
CustomizableTemplateLabel
>>
entry
:
maps
.
entrySet
())
{
Map
<
String
,
CustomizableTemplateLabel
>
langMap
=
labels
.
languages
.
get
(
entry
.
getKey
());
for
(
String
code
:
codes
)
{
CustomizableTemplateLabel
ctl
=
entry
.
getValue
().
get
(
code
);
if
(
ctl
==
null
)
{
ctl
=
fallbackMap
.
get
(
code
);
}
if
(
ctl
==
null
)
{
continue
;
}
langMap
.
put
(
code
,
ctl
);
}
}
if
(
useCache
)
{
templateLabelsCache
.
put
(
templateId
,
labels
);
}
return
labels
;
}
@Transactional
public
void
saveCustomizedLabels
(
Collection
<
CustomizableTemplateLabel
>
labels
)
{
repo
.
saveCustomizedLabels
(
labels
);
}
@Transactional
public
void
saveCustomizedLabels
(
Long
unitId
,
Long
templateId
,
Map
<
String
,
String
>
labels
)
{
Map
<
String
,
String
>
map
=
new
HashMap
<>(
labels
);
List
<
CustomizableTemplateLabel
>
list
=
repo
.
findCustomizedTemplateLabels
(
templateId
,
unitId
);
for
(
CustomizableTemplateLabel
label
:
list
)
{
String
s
=
map
.
get
(
label
.
getCode
());
if
(
s
==
null
)
{
repo
.
delete
(
label
);
}
else
{
label
.
setLabel
(
s
);
repo
.
save
(
label
);
map
.
remove
(
label
.
getCode
());
}
}
for
(
Entry
<
String
,
String
>
e
:
map
.
entrySet
())
{
CustomizableTemplateLabel
label
=
new
CustomizableTemplateLabel
();
label
.
setUnitId
(
unitId
);
label
.
setTemplate
(
new
Template
(
templateId
));
label
.
setCode
(
e
.
getKey
());
label
.
setLabel
(
e
.
getValue
());
repo
.
save
(
label
);
}
}
@Autowired
(
required
=
false
)
public
void
setRepo
(
CustomizableLabelsRepository
repo
)
{
this
.
repo
=
repo
;
}
@Value
(
"${global.caching:true}"
)
public
void
setUseCache
(
boolean
useCache
)
{
this
.
useCache
=
useCache
;
}
protected
class
CustomizableTemplateLabels
implements
TemplateLabels
{
Set
<
String
>
codes
=
new
LinkedHashSet
<>();
Map
<
String
,
Map
<
String
,
CustomizableTemplateLabel
>>
languages
=
new
HashMap
<>();
Map
<
String
,
CustomizableTemplateLabel
>
fallbackLabels
=
new
HashMap
<>();
@Override
public
Set
<
String
>
getCodes
()
{
return
codes
;
}
@Override
public
Map
<
String
,
Map
<
String
,
CustomizableTemplateLabel
>>
getLanguages
()
{
return
languages
;
}
@Override
public
Map
<
String
,
CustomizableTemplateLabel
>
getFallbackLabels
()
{
return
fallbackLabels
;
}
}
}
src/main/java/com/jh/common/template/customizable/CustomizableTemplateLabel.java
0 → 100644
View file @
13ec164f
package
com
.
jh
.
common
.
template
.
customizable
;
import
javax.persistence.Column
;
import
javax.persistence.Entity
;
import
javax.persistence.JoinColumn
;
import
javax.persistence.ManyToOne
;
import
javax.persistence.Table
;
import
javax.persistence.Transient
;
import
com.fasterxml.jackson.annotation.JsonIgnore
;
import
com.jh.common.jpa.AbstractIdEntity
;
import
com.jh.common.template.Template
;
@Entity
@Table
(
name
=
"CUSTOMIZABLE_TEMPLATE_LABEL"
)
public
class
CustomizableTemplateLabel
extends
AbstractIdEntity
{
@ManyToOne
@JoinColumn
(
name
=
"TEMPLATE_ID"
,
nullable
=
false
,
updatable
=
false
)
@JsonIgnore
private
Template
template
;
@Column
(
name
=
"UNIT_ID"
)
@JsonIgnore
private
Long
unitId
;
@Column
(
name
=
"CODE"
)
private
String
code
;
@JsonIgnore
@Column
(
name
=
"POSITION"
)
private
Long
position
;
@Column
(
name
=
"LANG"
)
@JsonIgnore
private
String
languageCode
;
@Column
(
name
=
"LABEL"
)
private
String
label
;
@Transient
private
String
defaultLabel
;
@Transient
private
String
defaultLanguageCode
;
public
Template
getTemplate
()
{
return
template
;
}
public
void
setTemplate
(
Template
template
)
{
this
.
template
=
template
;
}
public
Long
getUnitId
()
{
return
unitId
;
}
public
void
setUnitId
(
Long
unitId
)
{
this
.
unitId
=
unitId
;
}
public
String
getCode
()
{
return
code
;
}
public
void
setCode
(
String
code
)
{
this
.
code
=
code
;
}
public
Long
getPosition
()
{
return
position
;
}
public
void
setPosition
(
Long
position
)
{
this
.
position
=
position
;
}
public
String
getLanguageCode
()
{
return
languageCode
;
}
public
void
setLanguageCode
(
String
languageCode
)
{
this
.
languageCode
=
languageCode
;
}
public
String
getLabel
()
{
return
label
;
}
public
void
setLabel
(
String
label
)
{
this
.
label
=
label
;
}
public
String
getDefaultLabel
()
{
return
defaultLabel
;
}
public
void
setDefaultLabel
(
String
defaultLabel
)
{
this
.
defaultLabel
=
defaultLabel
;
}
public
String
getDefaultLanguageCode
()
{
return
defaultLanguageCode
;
}
public
void
setDefaultLanguageCode
(
String
defaultLanguageCode
)
{
this
.
defaultLanguageCode
=
defaultLanguageCode
;
}
@Override
public
String
toString
()
{
return
"unitId="
+
unitId
+
", code="
+
code
+
", languageCode="
+
languageCode
+
", label="
+
label
;
}
}
src/main/java/com/jh/common/template/customizable/TemplateLabels.java
0 → 100644
View file @
13ec164f
package
com
.
jh
.
common
.
template
.
customizable
;
import
java.util.Map
;
import
java.util.Set
;
public
interface
TemplateLabels
{
Set
<
String
>
getCodes
();
Map
<
String
,
Map
<
String
,
CustomizableTemplateLabel
>>
getLanguages
();
Map
<
String
,
CustomizableTemplateLabel
>
getFallbackLabels
();
}
\ No newline at end of file
src/main/java/com/jh/common/template/customizable/TemplateParam.java
0 → 100644
View file @
13ec164f
package
com
.
jh
.
common
.
template
.
customizable
;
import
javax.persistence.Column
;
import
javax.persistence.JoinColumn
;
import
javax.persistence.ManyToOne
;
import
com.jh.common.jpa.AbstractIdEntity
;
import
com.jh.common.template.Template
;
//@Entity
//@Table(name = "CUSTOMIZABLE_TEMPLATE_PARAM")
public
class
TemplateParam
extends
AbstractIdEntity
{
@Column
(
name
=
"CODE"
)
private
String
code
;
@Column
(
name
=
"NAME"
)
private
String
name
;
@Column
(
name
=
"LABEL"
)
private
String
label
;
@ManyToOne
@JoinColumn
(
name
=
"TEMPLATE_ID"
)
private
Template
template
;
@Column
(
name
=
"DEFAULT_VALUE"
)
private
String
defaultValue
;
public
String
getCode
()
{
return
code
;
}
public
void
setCode
(
String
code
)
{
this
.
code
=
code
;
}
public
String
getName
()
{
return
name
;
}
public
void
setName
(
String
name
)
{
this
.
name
=
name
;
}
public
String
getLabel
()
{
return
label
;
}
public
void
setLabel
(
String
label
)
{
this
.
label
=
label
;
}
public
Template
getTemplate
()
{
return
template
;
}
public
void
setTemplate
(
Template
template
)
{
this
.
template
=
template
;
}
public
String
getDefaultValue
()
{
return
defaultValue
;
}
public
void
setDefaultValue
(
String
defaultValue
)
{
this
.
defaultValue
=
defaultValue
;
}
}
src/main/java/com/jh/common/template/customizable/TemplateParamValue.java
0 → 100644
View file @
13ec164f
package
com
.
jh
.
common
.
template
.
customizable
;
import
javax.persistence.Column
;
import
javax.persistence.JoinColumn
;
import
javax.persistence.ManyToOne
;
import
com.jh.common.jpa.AbstractIdEntity
;
import
com.jh.common.template.Template
;
//@Entity
//@Table(name = "CUSTOMIZABLE_TEMPLATE_PARAM")
public
class
TemplateParamValue
extends
AbstractIdEntity
{
private
Long
unitId
;
@ManyToOne
@JoinColumn
(
name
=
"TEMPLATE_PARAM_ID"
)
private
Template
template
;
@Column
(
name
=
"VALUE"
)
private
String
value
;
}
src/main/java/com/jh/common/template/customizable/TemplateSettings.java
0 → 100644
View file @
13ec164f
package
com
.
jh
.
common
.
template
.
customizable
;
import
javax.persistence.Column
;
import
com.jh.common.jpa.AbstractIdEntity
;
//@Entity
//@Table(name = "CUSTOMIZABLE_TEMPLATE_SETTINGS")
public
class
TemplateSettings
extends
AbstractIdEntity
{
@Column
(
name
=
"UNIT_ID"
)
private
Long
unitId
;
@Column
(
name
=
"TEMPLATE_ID"
)
private
Long
templateId
;
@Column
(
name
=
"DEFAULT_LANG"
)
private
String
defaultLanguage
;
public
TemplateSettings
()
{
super
();
}
public
TemplateSettings
(
Long
templateId
)
{
super
();
setId
(
templateId
);
}
}
src/main/java/com/jh/common/template/handlebars/HandlebarsTemplateService.java
0 → 100644
View file @
13ec164f
package
com
.
jh
.
common
.
template
.
handlebars
;
import
java.io.ByteArrayOutputStream
;
import
java.io.IOException
;
import
java.io.InputStream
;
import
java.io.Writer
;
import
java.text.MessageFormat
;
import
java.time.LocalDate
;
import
java.util.Arrays
;
import
java.util.HashMap
;
import
java.util.Locale
;
import
java.util.Map
;
import
java.util.Objects
;
import
javax.annotation.PostConstruct
;
import
org.springframework.beans.factory.annotation.Value
;
import
com.github.jknack.handlebars.Context
;
import
com.github.jknack.handlebars.Handlebars
;
import
com.github.jknack.handlebars.Helper
;
import
com.github.jknack.handlebars.Options
;
import
com.github.jknack.handlebars.Template
;
import
com.github.jknack.handlebars.context.JavaBeanValueResolver
;
import
com.github.jknack.handlebars.context.MapValueResolver
;
import
com.jh.common.i18n.I18nContext
;
import
com.jh.common.i18n.I18nUtils
;
import
com.jh.common.template.TemplateService
;
/**
*
*
* {{#if author}}
* <h1>{{firstName}} {{lastName}}</h1>
* {{else}}
* <h1>Unknown Author</h1>
* {{/if}}
*
*
* {{#each array}}
{{@index}}: {{this}}
{{/each}}
*
*
*{{#each array as |value key|}}
{{#each child as |childValue childKey|}}
{{key}} - {{childKey}}. {{childValue}}
{{/each}}
{{/each}}
*
* {{#with author}}
<p>{{name}}</p>
{{else}}
<p class="empty">No content</p>
{{/with}}
{{#with author as |myAuthor|}}
<h2>By {{myAuthor.firstName}} {{myAuthor.lastName}}</h2>
{{/with}}
*
* Nested handlebars paths can also include ../ segments, which evaluate their paths against a parent context.
*
*
* @author Jan Hrabal
*/
public
class
HandlebarsTemplateService
implements
TemplateService
{
/** The use cache. */
private
boolean
useCache
=
false
;
/** The template cache. */
private
Map
<
String
,
Template
>
templateCache
;
private
Handlebars
handlebars
;
/**
* Initializes instance.
*/
@PostConstruct
public
void
init
()
{
templateCache
=
new
HashMap
<>();
handlebars
=
new
Handlebars
();
handlebars
.
setParentScopeResolution
(
true
);
handlebars
.
setPreEvaluatePartialBlocks
(
false
);
//conditional helpers
handlebars
.
registerHelper
(
"eq"
,
new
Helper
<
Object
>()
{
public
CharSequence
apply
(
Object
a
,
Options
options
)
throws
IOException
{
Object
b
=
options
.
param
(
0
,
null
);
boolean
result
=
Objects
.
equals
(
a
,
b
);
if
(!
result
)
{
result
=
Objects
.
equals
(
Objects
.
toString
(
a
,
null
),
Objects
.
toString
(
b
,
null
));
}
return
result
?
options
.
fn
()
:
options
.
inverse
();
}
});
I18nUtils
i18nUtils
=
I18nUtils
.
getInstance
();
handlebars
.
registerHelper
(
"formatNumber"
,
new
Helper
<
Number
>()
{
public
CharSequence
apply
(
Number
num
,
Options
options
)
throws
IOException
{
I18nContext
i18nCtx
=
(
I18nContext
)
options
.
param
(
0
);
return
i18nUtils
.
formatNumber
(
num
,
i18nCtx
);
}
});
handlebars
.
registerHelper
(
"formatPercent"
,
new
Helper
<
Number
>()
{
public
CharSequence
apply
(
Number
num
,
Options
options
)
throws
IOException
{
I18nContext
i18nCtx
=
(
I18nContext
)
options
.
param
(
0
);
return
i18nUtils
.
formatPercent
(
num
,
i18nCtx
);
}
});
handlebars
.
registerHelper
(
"formatMoney"
,
new
Helper
<
Number
>()
{
public
CharSequence
apply
(
Number
num
,
Options
options
)
throws
IOException
{
String
currency
=
(
String
)
options
.
param
(
0
);
I18nContext
i18nCtx
=
(
I18nContext
)
options
.
param
(
1
);
return
i18nUtils
.
formatMoney
(
num
,
currency
,
i18nCtx
);
}
});
handlebars
.
registerHelper
(
"formatDate"
,
new
Helper
<
LocalDate
>()
{
public
CharSequence
apply
(
LocalDate
date
,
Options
options
)
throws
IOException
{
I18nContext
i18nCtx
=
(
I18nContext
)
options
.
param
(
0
);
return
i18nUtils
.
formatDate
(
date
,
i18nCtx
);
}
});
handlebars
.
registerHelper
(
"formatLabel"
,
new
Helper
<
String
>()
{
public
CharSequence
apply
(
String
key
,
Options
options
)
throws
IOException
{
if
(
options
.
params
==
null
||
options
.
params
.
length
<
1
)
{
return
"Wrong formatLabel syntax for key "
+
key
+
". It should be formatLabel key labels ...params"
;
}
Map
<
String
,
Object
>
labels
=
(
Map
<
String
,
Object
>)
options
.
params
[
0
];
if
(
labels
==
null
)
{
return
"!!"
+
key
;
}
String
label
=
(
String
)
labels
.
get
(
key
);
if
(
label
==
null
)
{
return
"!!"
+
key
;
}
Object
[]
messageParams
=
options
.
params
.
length
>
1
?
Arrays
.
copyOfRange
(
options
.
params
,
1
,
options
.
params
.
length
)
:
new
Object
[
0
];
return
MessageFormat
.
format
(
label
,
messageParams
);
}
});
}
@Override
public
void
evaluate
(
Writer
writer
,
String
templateCode
,
Map
<
String
,
Object
>
data
,
Locale
locale
)
{
String
name
=
"template://"
+
templateCode
;
Template
template
=
useCache
?
templateCache
.
get
(
name
)
:
null
;
//TODO read template
if
(
template
==
null
)
{
template
=
handlebars
.
compileInline
(
s
);
if
(
useCache
)
{
templateCache
.
put
(
name
,
template
);
}
}
evaluateTemplate
(
template
,
data
,
locale
,
writer
);
}
@Override
public
void
evaluateInline
(
Writer
writer
,
String
template
,
Map
<
String
,
Object
>
data
,
Locale
locale
)
{
if
(
locale
==
null
)
{
locale
=
Locale
.
ENGLISH
;
}
String
name
=
"inline://"
+
template
;
Template
t
=
useCache
?
templateCache
.
get
(
name
)
:
null
;
if
(
t
==
null
)
{
try
{
t
=
handlebars
.
compileInline
(
template
);
}
catch
(
Exception
e
)
{
throw
new
RuntimeException
(
String
.
format
(
"Inline template '%s' cannot be read"
,
template
),
e
);
}
if
(
useCache
)
{
templateCache
.
put
(
name
,
t
);
}
}
evaluateTemplate
(
t
,
data
,
locale
,
writer
);
}
protected
void
evaluateTemplate
(
Template
t
,
Map
<
String
,
Object
>
data
,
Locale
locale
,
Writer
writer
)
{
Context
context
=
Context
.
newBuilder
(
data
)
.
combine
(
data
)
.
resolver
(
JavaBeanValueResolver
.
INSTANCE
,
MapValueResolver
.
INSTANCE
)
.
build
();
try
{
t
.
apply
(
context
,
writer
);
}
catch
(
IOException
e
)
{
throw
new
RuntimeException
(
"Cannot evaluate template"
,
e
);
}
}
/**
* Sets the use cache.
*
* @param useCache the new use cache
*/
@Value
(
"${global.caching:true}"
)
public
void
setUseCache
(
boolean
useCache
)
{
this
.
useCache
=
useCache
;
}
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment