001/*
002 *  Copyright 2024 Anyware Services
003 *
004 *  Licensed under the Apache License, Version 2.0 (the "License");
005 *  you may not use this file except in compliance with the License.
006 *  You may obtain a copy of the License at
007 *
008 *      http://www.apache.org/licenses/LICENSE-2.0
009 *
010 *  Unless required by applicable law or agreed to in writing, software
011 *  distributed under the License is distributed on an "AS IS" BASIS,
012 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 *  See the License for the specific language governing permissions and
014 *  limitations under the License.
015 */
016package org.ametys.cms.repository.mentions;
017
018import java.util.HashSet;
019import java.util.Set;
020import java.util.regex.Matcher;
021import java.util.regex.Pattern;
022
023import org.apache.avalon.framework.component.Component;
024import org.apache.avalon.framework.service.ServiceException;
025import org.apache.avalon.framework.service.ServiceManager;
026import org.apache.avalon.framework.service.Serviceable;
027
028import org.ametys.core.user.User;
029import org.ametys.core.user.UserIdentity;
030import org.ametys.core.user.UserManager;
031import org.ametys.core.util.I18nUtils;
032import org.ametys.runtime.i18n.I18nizableText;
033import org.ametys.runtime.plugin.component.AbstractLogEnabled;
034
035/**
036 * Utils for Mentions
037 */
038public class MentionUtils extends AbstractLogEnabled implements Component, Serviceable
039{
040    /** Avalon role */
041    public static final String ROLE = MentionUtils.class.getName();
042
043    /** Regex used to extract mentions from a text. A mention is inside a @() */
044    public static final String __EXTRACT_MENTIONS_REGEX_SIMPLE_TEXT = "@\\(([^()]+)\\)";
045    
046    /** Regex used to extract mentions from a text. A mention is inside a @() */
047    public static final String __EXTRACT_MENTIONS_REGEX_RICH_TEXT = "data-ametys-mention-user=\"([^\"]+)\"";
048
049    /** The user manager */
050    protected UserManager _userManager;
051
052    /** The i18n utils. */
053    protected I18nUtils _i18nUtils;
054    
055    public void service(ServiceManager manager) throws ServiceException
056    {
057        _userManager = (UserManager) manager.lookup(UserManager.ROLE);
058        _i18nUtils = (I18nUtils) manager.lookup(I18nUtils.ROLE);
059    }
060
061    /**
062     * Extract mentioned users from simple text content
063     * @param content the simple text content
064     * @return the set of mentioned users
065     */
066    public static Set<UserIdentity> extractMentionedUsersFromSimpleText(String content)
067    {
068        Set<UserIdentity> mentionendUsers = new HashSet<>();
069        if (content != null)
070        {
071            Pattern pattern = Pattern.compile(__EXTRACT_MENTIONS_REGEX_SIMPLE_TEXT);
072            Matcher matcher = pattern.matcher(content);
073            
074            while (matcher.find())
075            {
076                String userIdentityAsString = matcher.group(1);
077                UserIdentity userIdentity = UserIdentity.stringToUserIdentity(userIdentityAsString);
078                mentionendUsers.add(userIdentity);
079            }
080        }
081        return mentionendUsers;
082    }
083    
084    /**
085     * Extract mentioned users from rich text content
086     * @param content the rich text content
087     * @return the set of mentioned users
088     */
089    public Set<UserIdentity> extractMentionedUsersFromRichText(String content)
090    {
091        Set<UserIdentity> mentionedUsers = new HashSet<>();
092        Pattern pattern = Pattern.compile("data-ametys-mention-user=\"([^\"]+)\"");
093        Matcher matcher = pattern.matcher(content);
094
095        while (matcher.find())
096        {
097            String userIdentityAsString = matcher.group(1);
098            UserIdentity userIdentity = UserIdentity.stringToUserIdentity(userIdentityAsString);
099            mentionedUsers.add(userIdentity);
100        }
101        return mentionedUsers;
102    }
103
104    /**
105     * Transform syntax text of a rich text to display text using a regex to find the parts to transform and a function to transform them
106     * @param syntaxText the syntax text
107     * @param recipient the recipient of the mail, for mail purposes
108     * @return the transformed text with colors according to the recipient
109     */
110    public String transformRichTextToReadableText(String syntaxText, UserIdentity recipient)
111    {
112        String readableText = syntaxText;
113
114        if (syntaxText != null)
115        {
116            Pattern pattern = Pattern.compile(__EXTRACT_MENTIONS_REGEX_RICH_TEXT);
117            Matcher matcher = pattern.matcher(syntaxText);
118            StringBuffer sb = new StringBuffer();
119
120            while (matcher.find())
121            {
122                String mentionBackgroundColor = _getMentionColor(recipient, matcher);
123                
124                StringBuilder replaceBy = new StringBuilder("style=\"background: ").append(mentionBackgroundColor).append("; color: #1264a3\"");
125                
126                matcher.appendReplacement(sb, Matcher.quoteReplacement(replaceBy.toString()));
127            }
128            matcher.appendTail(sb);
129            readableText = sb.toString();
130        }
131        return readableText;
132    }
133    
134    /**
135     * Transform syntax text of a simple text to display text using a regex to find the parts to transform and a function to transform them
136     * @param syntaxText the syntax text
137     * @param recipient the recipient of the mail, for mail purposes, can be null for any other purposes
138     * @return the transformed text with colors according to the recipient if not null, with full name in plain text otherwise
139     */
140    public String transformTextToReadableText(String syntaxText, UserIdentity recipient)
141    {
142        String readableText = syntaxText;
143
144        if (syntaxText != null)
145        {
146            Pattern pattern = Pattern.compile(__EXTRACT_MENTIONS_REGEX_SIMPLE_TEXT);
147            Matcher matcher = pattern.matcher(syntaxText);
148            StringBuffer sb = new StringBuffer();
149
150            while (matcher.find())
151            {
152                String userIdentityAsString = matcher.group(1);
153                UserIdentity mentionedUserIdentity = UserIdentity.stringToUserIdentity(userIdentityAsString);
154                User mentionedUser = _userManager.getUser(mentionedUserIdentity);
155                String mentionedUserName = mentionedUser != null ? mentionedUser.getFullName() : _i18nUtils.translate(new I18nizableText("plugin.core", "PLUGINS_CORE_USERS_UNKNOWN_USER"));
156                
157                StringBuilder replaceBy = new StringBuilder(mentionedUserName);
158                if (recipient != null)
159                {
160                    String mentionBackgroundColor = _getMentionColor(recipient, matcher);
161                    
162                    replaceBy = new StringBuilder("<span style=\"background: ").append(mentionBackgroundColor).append("; color: #1264a3\">")
163                            .append(mentionedUserName)
164                            .append("</span>");
165                }
166                
167                matcher.appendReplacement(sb, Matcher.quoteReplacement(replaceBy.toString()));
168            }
169            matcher.appendTail(sb);
170            readableText = sb.toString();
171        }
172        return readableText;
173    }
174
175    private String _getMentionColor(UserIdentity recipient, Matcher matcher)
176    {
177        String userIdentityAsString = matcher.group(1);
178        UserIdentity mentionedUserIdentity = UserIdentity.stringToUserIdentity(userIdentityAsString);
179
180        String mentionBackgroundColor = "rgba(29, 155, 209, 0.1)";
181        if (mentionedUserIdentity.equals(recipient))
182        {
183            mentionBackgroundColor = "rgba(255, 198, 0, 0.18)";
184        }
185        return mentionBackgroundColor;
186    }
187
188}