/********************************************************************************** * $URL: https://source.sakaiproject.org/svn/rwiki/trunk/rwiki-util/util/src/java/uk/ac/cam/caret/sakai/rwiki/utils/NameHelper.java $ * $Id: NameHelper.java 96735 2011-08-10 15:57:33Z aaronz@vt.edu $ *********************************************************************************** * * Copyright (c) 2003, 2004, 2005, 2006 The Sakai Foundation. * * Licensed under the Educational Community License, Version 1.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.opensource.org/licenses/ecl1.php * * 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. * **********************************************************************************/ package uk.ac.cam.caret.sakai.rwiki.utils; import java.nio.CharBuffer; import java.util.List; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.sakaiproject.alias.api.AliasEdit; import org.sakaiproject.alias.cover.AliasService; import org.sakaiproject.entity.api.Entity; import org.sakaiproject.site.cover.SiteService; import org.apache.commons.lang.StringUtils; public class NameHelper { public static final char SPACE_SEPARATOR = '/'; private static final Log log = LogFactory.getLog(NameHelper.class); public static final String DEFAULT_PAGE = "home"; public static boolean isGlobalised(final String name) { // This should be a RE but RE is too slow if (name == null) { return false; } char[] chars = name.toCharArray(); boolean allowedSpaceOrSeparator = false; int numberOfSeparators = 1; if (chars[0] != SPACE_SEPARATOR) { return false; } for (int i = 1; i < chars.length; i++) { if (chars[i] == ' ' || chars[i] == SPACE_SEPARATOR) { if (chars[i] == SPACE_SEPARATOR) { numberOfSeparators++; } if (!allowedSpaceOrSeparator) { return false; } else { allowedSpaceOrSeparator = false; } } else if (Character.isWhitespace(chars[i])) { return false; } else if (Character.isUpperCase(chars[i]) && numberOfSeparators < 3) { return false; } else { allowedSpaceOrSeparator = true; } } return allowedSpaceOrSeparator; } public static String globaliseName(final String name, final String defaultSpace) { if (name == null || name.length() == 0) { return normalize(defaultSpace + SPACE_SEPARATOR + DEFAULT_PAGE, false); } if (name.charAt(0) != SPACE_SEPARATOR) { return normalize(defaultSpace + SPACE_SEPARATOR + name, true); } else { return normalize(name, true); } } /** * Takes a globalised page name and a space name and localises that page * name within that space. * * @param pageName * Globalised page name * @param space * Globalised space name to localise within * @return localised page name */ public static String localizeName(final String pageName, final String space) { // Space may not be normalized SAK-2697, and may aswell globalise the // pageName whilst we are at it. String normalSpace = normalize(space, false); String name = globaliseName(pageName, normalSpace); int nameLength = name.length(); int spaceLength = normalSpace.length(); char[] chars = name.toCharArray(); int lastSeparator = findLastSeparator(chars, nameLength); if (lastSeparator >= findThirdSeparator(chars, nameLength)) { boolean capitalise = true; for (int i = lastSeparator; i < nameLength; i++) { if (chars[i] == SPACE_SEPARATOR || chars[i] == ' ') { capitalise = true; } else if (capitalise) { chars[i] = Character.toUpperCase(chars[i]); capitalise = false; } } } if (nameLength <= spaceLength + 1) { return new String(chars); } char[] spaceChars = normalSpace.toCharArray(); for (int i = 0; i < spaceLength; i++) { if (chars[i] != spaceChars[i]) { return new String(chars); } } if (chars[spaceLength] != SPACE_SEPARATOR) { return new String(chars); } else { return new String(chars, spaceLength + 1, nameLength - spaceLength - 1); } } private static int findLastSeparator(char[] chars, int nameLength) { for (int i = nameLength - 1; i >= 0; i--) { if (chars[i] == SPACE_SEPARATOR) { return i; } } return 0; } private static int findThirdSeparator(char[] chars, int nameLength) { int numberOfSeparators = 0; for (int i = 0; i < nameLength; i++) { if (chars[i] == SPACE_SEPARATOR) { numberOfSeparators++; if (numberOfSeparators == 3) { return i; } } } return nameLength; } private static String normalize(final String nameToNormalize, final boolean isPageName) { char[] chars = nameToNormalize.toCharArray(); int charBufferLength = chars.length + 1 + (isPageName ? DEFAULT_PAGE.length() : 0); CharBuffer name = CharBuffer.allocate(charBufferLength); int wordStart = 0; boolean addSeparator = true; boolean addWhiteSpaceOrSeparator = true; int numberOfSeparators = 0; for (int i = 0; i < chars.length; i++) { char c = chars[i]; if (c == SPACE_SEPARATOR) { if (!addWhiteSpaceOrSeparator) { name.put(chars, wordStart, i - wordStart); } addSeparator = true; addWhiteSpaceOrSeparator = true; } else if (Character.isWhitespace(c)) { if (!addWhiteSpaceOrSeparator) { name.put(chars, wordStart, i - wordStart); } addWhiteSpaceOrSeparator = true; } else if (addSeparator) { name.put(SPACE_SEPARATOR); if (++numberOfSeparators > 2) { chars[i] = Character.toLowerCase(c); } wordStart = i; addSeparator = false; addWhiteSpaceOrSeparator = false; } else if (addWhiteSpaceOrSeparator) { addWhiteSpaceOrSeparator = false; wordStart = i; name.put(' '); if (numberOfSeparators > 2) { chars[i] = Character.toLowerCase(c); } } else { if (numberOfSeparators > 2) { chars[i] = Character.toLowerCase(c); } } } if (addSeparator && isPageName) { name.put(SPACE_SEPARATOR); name.put(DEFAULT_PAGE); } else if (!addWhiteSpaceOrSeparator) { name.put(chars, wordStart, chars.length - wordStart); } int position = name.position(); name.position(0); name.limit(position); return name.toString(); } /** * @param pageName * @param defaultSpace * @return */ public static String localizeSpace(final String pageName, final String defaultSpace) { String globalName = globaliseName(pageName, defaultSpace); int index = globalName.lastIndexOf(SPACE_SEPARATOR); return globalName.substring(0, index); } public static String localizeSpace(final String globalPageName) { int index = globalPageName.lastIndexOf(SPACE_SEPARATOR); return globalPageName.substring(0, index); } /** * @param localSpace with format "/site/siteId" * @return aliasSpace if available with format "/siteAliasName". Otherwise, return "/site/siteId" */ public static String aliasSpace (final String localSpace) { String localAliasSpace = localSpace; String parts[] = StringUtils.split (localSpace, Entity.SEPARATOR); String siteId = null; if (parts.length > 1) { siteId = parts[1]; } // recognize alias for site id - but if a site id exists that matches the requested site id, that's what we will use if ((siteId != null) && (siteId.length() > 0)) { // get site alias first List target = AliasService.getAliases( "/site/" + siteId); // get mail archive alias, if site alias is not available if (target.isEmpty()) { target = AliasService.getAliases( "/mailarchive/channel/" + siteId + "/main"); } if (!target.isEmpty()) { // take the first alias only AliasEdit alias = (AliasEdit) target.get(0); siteId = alias.getId(); // if there is no a site id exists that matches the alias name if (!SiteService.siteExists(siteId)) { localAliasSpace = "/" + siteId; } } } return localAliasSpace; } }