mirror of
https://github.com/mainflux/mainflux.git
synced 2025-05-02 22:17:10 +08:00

* Use normalizer as stream source Renamed 'writer' service to 'normalizer' and dropped Cassandra facilities from it. Extracted the common dependencies to 'mainflux' package for easier sharing. Fixed the API docs and unified environment variables. Signed-off-by: Dejan Mijic <dejan@mainflux.com> * Use docker build arguments to specify build Signed-off-by: Dejan Mijic <dejan@mainflux.com> * Remove cassandra libraries Signed-off-by: Dejan Mijic <dejan@mainflux.com> * Update go-kit version to 0.6.0 Signed-off-by: Dejan Mijic <dejan@mainflux.com> * Fix manager configuration Signed-off-by: Dejan Mijic <dejan@mainflux.com> * Refactor docker-compose Merged individual compose files and dropped external links. Remove CoAP container since it is not referenced from NginX config at the moment. Update port mapping in compose and nginx.conf. Dropped bin scripts. Updated service documentation. Signed-off-by: Dejan Mijic <dejan@mainflux.com> * Drop content-type check Signed-off-by: Dejan Mijic <dejan@mainflux.com> * Implement users data access layer in PostgreSQL Signed-off-by: Dejan Mijic <dejan@mainflux.com> * Bump version to 0.1.0 Signed-off-by: Dejan Mijic <dejan@mainflux.com> * Use go-kit logger everywhere (except CoAP) Signed-off-by: Dejan Mijic <dejan@mainflux.com> * Improve factory methods naming Signed-off-by: Dejan Mijic <dejan@mainflux.com> * Implement clients data access layer on PostgreSQL Signed-off-by: Dejan Mijic <dejan@mainflux.com> * Make tests stateless All tests are refactored to use map-based table-driven tests. No cross-tests dependencies is present anymore. Signed-off-by: Dejan Mijic <dejan@mainflux.com> * Remove gitignore Signed-off-by: Dejan Mijic <dejan@mainflux.com> * Fix nginx proxying Signed-off-by: Dejan Mijic <dejan@mainflux.com> * Mark client-user FK explicit Signed-off-by: Dejan Mijic <dejan@mainflux.com> * Update API documentation Signed-off-by: Dejan Mijic <dejan@mainflux.com> * Update channel model Signed-off-by: Dejan Mijic <dejan@mainflux.com> * Add channel PostgreSQL repository tests Signed-off-by: Dejan Mijic <dejan@mainflux.com> * Implement PostgreSQL channels DAO Replaced update queries with raw SQL. Explicitly defined M2M table due to difficulties of ensuring the referential integrity through GORM. Signed-off-by: Dejan Mijic <dejan@mainflux.com> * Expose connection endpoints Signed-off-by: Dejan Mijic <dejan@mainflux.com> * Fix swagger docs and remove DB logging Signed-off-by: Dejan Mijic <dejan@mainflux.com> * Fix nested query remarks Signed-off-by: Dejan Mijic <dejan@mainflux.com> * Add unique indices Signed-off-by: Dejan Mijic <dejan@mainflux.com>
274 lines
8.0 KiB
Go
274 lines
8.0 KiB
Go
/*
|
|
Package inflection pluralizes and singularizes English nouns.
|
|
|
|
inflection.Plural("person") => "people"
|
|
inflection.Plural("Person") => "People"
|
|
inflection.Plural("PERSON") => "PEOPLE"
|
|
|
|
inflection.Singular("people") => "person"
|
|
inflection.Singular("People") => "Person"
|
|
inflection.Singular("PEOPLE") => "PERSON"
|
|
|
|
inflection.Plural("FancyPerson") => "FancydPeople"
|
|
inflection.Singular("FancyPeople") => "FancydPerson"
|
|
|
|
Standard rules are from Rails's ActiveSupport (https://github.com/rails/rails/blob/master/activesupport/lib/active_support/inflections.rb)
|
|
|
|
If you want to register more rules, follow:
|
|
|
|
inflection.AddUncountable("fish")
|
|
inflection.AddIrregular("person", "people")
|
|
inflection.AddPlural("(bu)s$", "${1}ses") # "bus" => "buses" / "BUS" => "BUSES" / "Bus" => "Buses"
|
|
inflection.AddSingular("(bus)(es)?$", "${1}") # "buses" => "bus" / "Buses" => "Bus" / "BUSES" => "BUS"
|
|
*/
|
|
package inflection
|
|
|
|
import (
|
|
"regexp"
|
|
"strings"
|
|
)
|
|
|
|
type inflection struct {
|
|
regexp *regexp.Regexp
|
|
replace string
|
|
}
|
|
|
|
// Regular is a regexp find replace inflection
|
|
type Regular struct {
|
|
find string
|
|
replace string
|
|
}
|
|
|
|
// Irregular is a hard replace inflection,
|
|
// containing both singular and plural forms
|
|
type Irregular struct {
|
|
singular string
|
|
plural string
|
|
}
|
|
|
|
// RegularSlice is a slice of Regular inflections
|
|
type RegularSlice []Regular
|
|
|
|
// IrregularSlice is a slice of Irregular inflections
|
|
type IrregularSlice []Irregular
|
|
|
|
var pluralInflections = RegularSlice{
|
|
{"([a-z])$", "${1}s"},
|
|
{"s$", "s"},
|
|
{"^(ax|test)is$", "${1}es"},
|
|
{"(octop|vir)us$", "${1}i"},
|
|
{"(octop|vir)i$", "${1}i"},
|
|
{"(alias|status)$", "${1}es"},
|
|
{"(bu)s$", "${1}ses"},
|
|
{"(buffal|tomat)o$", "${1}oes"},
|
|
{"([ti])um$", "${1}a"},
|
|
{"([ti])a$", "${1}a"},
|
|
{"sis$", "ses"},
|
|
{"(?:([^f])fe|([lr])f)$", "${1}${2}ves"},
|
|
{"(hive)$", "${1}s"},
|
|
{"([^aeiouy]|qu)y$", "${1}ies"},
|
|
{"(x|ch|ss|sh)$", "${1}es"},
|
|
{"(matr|vert|ind)(?:ix|ex)$", "${1}ices"},
|
|
{"^(m|l)ouse$", "${1}ice"},
|
|
{"^(m|l)ice$", "${1}ice"},
|
|
{"^(ox)$", "${1}en"},
|
|
{"^(oxen)$", "${1}"},
|
|
{"(quiz)$", "${1}zes"},
|
|
}
|
|
|
|
var singularInflections = RegularSlice{
|
|
{"s$", ""},
|
|
{"(ss)$", "${1}"},
|
|
{"(n)ews$", "${1}ews"},
|
|
{"([ti])a$", "${1}um"},
|
|
{"((a)naly|(b)a|(d)iagno|(p)arenthe|(p)rogno|(s)ynop|(t)he)(sis|ses)$", "${1}sis"},
|
|
{"(^analy)(sis|ses)$", "${1}sis"},
|
|
{"([^f])ves$", "${1}fe"},
|
|
{"(hive)s$", "${1}"},
|
|
{"(tive)s$", "${1}"},
|
|
{"([lr])ves$", "${1}f"},
|
|
{"([^aeiouy]|qu)ies$", "${1}y"},
|
|
{"(s)eries$", "${1}eries"},
|
|
{"(m)ovies$", "${1}ovie"},
|
|
{"(c)ookies$", "${1}ookie"},
|
|
{"(x|ch|ss|sh)es$", "${1}"},
|
|
{"^(m|l)ice$", "${1}ouse"},
|
|
{"(bus)(es)?$", "${1}"},
|
|
{"(o)es$", "${1}"},
|
|
{"(shoe)s$", "${1}"},
|
|
{"(cris|test)(is|es)$", "${1}is"},
|
|
{"^(a)x[ie]s$", "${1}xis"},
|
|
{"(octop|vir)(us|i)$", "${1}us"},
|
|
{"(alias|status)(es)?$", "${1}"},
|
|
{"^(ox)en", "${1}"},
|
|
{"(vert|ind)ices$", "${1}ex"},
|
|
{"(matr)ices$", "${1}ix"},
|
|
{"(quiz)zes$", "${1}"},
|
|
{"(database)s$", "${1}"},
|
|
}
|
|
|
|
var irregularInflections = IrregularSlice{
|
|
{"person", "people"},
|
|
{"man", "men"},
|
|
{"child", "children"},
|
|
{"sex", "sexes"},
|
|
{"move", "moves"},
|
|
{"mombie", "mombies"},
|
|
}
|
|
|
|
var uncountableInflections = []string{"equipment", "information", "rice", "money", "species", "series", "fish", "sheep", "jeans", "police"}
|
|
|
|
var compiledPluralMaps []inflection
|
|
var compiledSingularMaps []inflection
|
|
|
|
func compile() {
|
|
compiledPluralMaps = []inflection{}
|
|
compiledSingularMaps = []inflection{}
|
|
for _, uncountable := range uncountableInflections {
|
|
inf := inflection{
|
|
regexp: regexp.MustCompile("^(?i)(" + uncountable + ")$"),
|
|
replace: "${1}",
|
|
}
|
|
compiledPluralMaps = append(compiledPluralMaps, inf)
|
|
compiledSingularMaps = append(compiledSingularMaps, inf)
|
|
}
|
|
|
|
for _, value := range irregularInflections {
|
|
infs := []inflection{
|
|
inflection{regexp: regexp.MustCompile(strings.ToUpper(value.singular) + "$"), replace: strings.ToUpper(value.plural)},
|
|
inflection{regexp: regexp.MustCompile(strings.Title(value.singular) + "$"), replace: strings.Title(value.plural)},
|
|
inflection{regexp: regexp.MustCompile(value.singular + "$"), replace: value.plural},
|
|
}
|
|
compiledPluralMaps = append(compiledPluralMaps, infs...)
|
|
}
|
|
|
|
for _, value := range irregularInflections {
|
|
infs := []inflection{
|
|
inflection{regexp: regexp.MustCompile(strings.ToUpper(value.plural) + "$"), replace: strings.ToUpper(value.singular)},
|
|
inflection{regexp: regexp.MustCompile(strings.Title(value.plural) + "$"), replace: strings.Title(value.singular)},
|
|
inflection{regexp: regexp.MustCompile(value.plural + "$"), replace: value.singular},
|
|
}
|
|
compiledSingularMaps = append(compiledSingularMaps, infs...)
|
|
}
|
|
|
|
for i := len(pluralInflections) - 1; i >= 0; i-- {
|
|
value := pluralInflections[i]
|
|
infs := []inflection{
|
|
inflection{regexp: regexp.MustCompile(strings.ToUpper(value.find)), replace: strings.ToUpper(value.replace)},
|
|
inflection{regexp: regexp.MustCompile(value.find), replace: value.replace},
|
|
inflection{regexp: regexp.MustCompile("(?i)" + value.find), replace: value.replace},
|
|
}
|
|
compiledPluralMaps = append(compiledPluralMaps, infs...)
|
|
}
|
|
|
|
for i := len(singularInflections) - 1; i >= 0; i-- {
|
|
value := singularInflections[i]
|
|
infs := []inflection{
|
|
inflection{regexp: regexp.MustCompile(strings.ToUpper(value.find)), replace: strings.ToUpper(value.replace)},
|
|
inflection{regexp: regexp.MustCompile(value.find), replace: value.replace},
|
|
inflection{regexp: regexp.MustCompile("(?i)" + value.find), replace: value.replace},
|
|
}
|
|
compiledSingularMaps = append(compiledSingularMaps, infs...)
|
|
}
|
|
}
|
|
|
|
func init() {
|
|
compile()
|
|
}
|
|
|
|
// AddPlural adds a plural inflection
|
|
func AddPlural(find, replace string) {
|
|
pluralInflections = append(pluralInflections, Regular{find, replace})
|
|
compile()
|
|
}
|
|
|
|
// AddSingular adds a singular inflection
|
|
func AddSingular(find, replace string) {
|
|
singularInflections = append(singularInflections, Regular{find, replace})
|
|
compile()
|
|
}
|
|
|
|
// AddIrregular adds an irregular inflection
|
|
func AddIrregular(singular, plural string) {
|
|
irregularInflections = append(irregularInflections, Irregular{singular, plural})
|
|
compile()
|
|
}
|
|
|
|
// AddUncountable adds an uncountable inflection
|
|
func AddUncountable(values ...string) {
|
|
uncountableInflections = append(uncountableInflections, values...)
|
|
compile()
|
|
}
|
|
|
|
// GetPlural retrieves the plural inflection values
|
|
func GetPlural() RegularSlice {
|
|
plurals := make(RegularSlice, len(pluralInflections))
|
|
copy(plurals, pluralInflections)
|
|
return plurals
|
|
}
|
|
|
|
// GetSingular retrieves the singular inflection values
|
|
func GetSingular() RegularSlice {
|
|
singulars := make(RegularSlice, len(singularInflections))
|
|
copy(singulars, singularInflections)
|
|
return singulars
|
|
}
|
|
|
|
// GetIrregular retrieves the irregular inflection values
|
|
func GetIrregular() IrregularSlice {
|
|
irregular := make(IrregularSlice, len(irregularInflections))
|
|
copy(irregular, irregularInflections)
|
|
return irregular
|
|
}
|
|
|
|
// GetUncountable retrieves the uncountable inflection values
|
|
func GetUncountable() []string {
|
|
uncountables := make([]string, len(uncountableInflections))
|
|
copy(uncountables, uncountableInflections)
|
|
return uncountables
|
|
}
|
|
|
|
// SetPlural sets the plural inflections slice
|
|
func SetPlural(inflections RegularSlice) {
|
|
pluralInflections = inflections
|
|
compile()
|
|
}
|
|
|
|
// SetSingular sets the singular inflections slice
|
|
func SetSingular(inflections RegularSlice) {
|
|
singularInflections = inflections
|
|
compile()
|
|
}
|
|
|
|
// SetIrregular sets the irregular inflections slice
|
|
func SetIrregular(inflections IrregularSlice) {
|
|
irregularInflections = inflections
|
|
compile()
|
|
}
|
|
|
|
// SetUncountable sets the uncountable inflections slice
|
|
func SetUncountable(inflections []string) {
|
|
uncountableInflections = inflections
|
|
compile()
|
|
}
|
|
|
|
// Plural converts a word to its plural form
|
|
func Plural(str string) string {
|
|
for _, inflection := range compiledPluralMaps {
|
|
if inflection.regexp.MatchString(str) {
|
|
return inflection.regexp.ReplaceAllString(str, inflection.replace)
|
|
}
|
|
}
|
|
return str
|
|
}
|
|
|
|
// Singular converts a word to its singular form
|
|
func Singular(str string) string {
|
|
for _, inflection := range compiledSingularMaps {
|
|
if inflection.regexp.MatchString(str) {
|
|
return inflection.regexp.ReplaceAllString(str, inflection.replace)
|
|
}
|
|
}
|
|
return str
|
|
}
|