How to build a locale aware VirtualURIMapping in Magnolia. With RegExp.

In a standard Magnolia installation, VirtualURIMapping are locale agnostic: they simply don’t care about locale. This is quite nice, if you have single locale website, but normally, this is not the case.
So.. I’0ve googled and found this and this. But not enough, I need to have Regexp in fromUri field.. so, let’s write that!

First, focus on configuration (Node2Bean in-primis):

localized-virtual-uri-mapping

And now the code. Unfortunately, standard RegexpVirtualURIMapping direct access the “toURI” class member and that is in memory (pooled in a Magnolia registry). So, we need to completely (?!?!) rewrite the class.


package com.matteopelucco.virtualurimapping;

import info.magnolia.cms.beans.config.DefaultVirtualURIMapping;
import info.magnolia.cms.beans.config.QueryAwareVirtualURIMapping;
import info.magnolia.context.MgnlContext;

import java.util.LinkedHashMap;
import java.util.Locale;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.commons.lang.StringUtils;

public class LocaleRegexpVirtualURIMapping extends DefaultVirtualURIMapping implements QueryAwareVirtualURIMapping {
  private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(LocaleRegexpVirtualURIMapping .class);
  private Pattern regexp;
  
  // local mapping 
  private Map<string , String> localizedToURI = new LinkedHashMap</string><string , String>();

@Override
public MappingResult mapURI(final String uri) {
  return mapURI(uri, null);
}

@Override
public MappingResult mapURI(final String uri, String queryString) {
  if (regexp != null) {
    final Matcher matcher;
    if (queryString != null) {
      matcher = regexp.matcher(uri + "?" + queryString);
    } else {
      matcher = regexp.matcher(uri);
    }

    if (matcher.find()) {
      final MappingResult r = new MappingResult();
      final int matcherCount = matcher.groupCount();
      try {
        final String replaced = matcher.replaceAll(getToURI()); // this is the only piece rewritten, since it direct accesses to class member
        r.setLevel(matcherCount + 1);
        r.setToURI(replaced);
        return r;
      } catch (IndexOutOfBoundsException e) {
        log.warn("{} misconfigured: {}", toString(), e.getMessage());
      }
    }
  }

  return null;
}

@Override
public void setFromURI(String fromURI) {
  this.fromURI = fromURI;
  this.regexp = Pattern.compile(fromURI);
}

/**
 * Dynamic part
 */
public String getToURI() {

  String language = "";
  Locale locale = MgnlContext.getAggregationState().getLocale();
  if (locale != null) {
    language = locale.getLanguage();
  }

  return StringUtils.defaultIfEmpty(localizedToURI.get(language), super.getToURI());
}

/** node2bean **/
public Map</string><string , String> getLocalizedToURI() {
  return localizedToURI;
}

public void setLocalizedToURI(Map</string><string , String> localizedToURI) {
  this.localizedToURI = localizedToURI;
}

public void addLocalizedToURI(String key, String value) {
  this.localizedToURI.put(key, value);
}

	

}

</string>

And.. that’s it! Just configure the right mapping (yes, they are aware of RegeExp replacements!) and the game is done.
Hope it helps!

Latest articles

Matteo Pelucco Written by:

4 Comments

  1. Jozef Chocholáček
    July 31

    Yes, it definitely helps! You’ve saved me few hours of investigating and coding, man. I owe you a beer, even two! 😉

  2. Pierre Sandrin
    November 12

    I modified it for Magnolia 5.7 And here is what i came up with. It gets easier, you can extend the class RegexpVirtualUriMapping and only have to override the method getToUri() and add the node to bean methods. The config remains the same.

    public class LocaleRegexpVirtualUriMapping extends RegexpVirtualUriMapping {
    private Map localizedToURI = new LinkedHashMap();

    @Override
    public String getToUri() {
    String language = “”;
    Locale locale = MgnlContext.getAggregationState().getLocale();
    if (locale != null) {
    language = locale.getLanguage();
    }

    return StringUtils.defaultIfEmpty(localizedToURI.get(language), super.getToUri());
    }

    /** node2bean **/
    public Map getLocalizedToURI() {
    return localizedToURI;
    }

    public void setLocalizedToURI(Map localizedToURI) {
    this.localizedToURI = localizedToURI;
    }

    public void addLocalizedToURI(String key, String value) {
    this.localizedToURI.put(key, value);
    }

    }

  3. Pierre Sandrin
    November 12

    The configuration can be done by yaml of course. In my case like this
    class: ch.openinteractive.virtualUriMapping.LocaleRegexpVirtualUriMapping
    fromUri: /reference/(.*)(\.html|\.xhtml)
    toUri: redirect:/reference$2?referencePath=/$1
    localizedToURI:
    de: forward:/reference$2?referencePath=/$1
    fr: forward:/fr/reference$2?referencePath=/$1
    en: forward:/en/reference$2?referencePath=/$1

  4. June 8

    What draws people-so much in regards to it is the fact that they’re able
    to make plenty of money when they possess a large amount of strategy not to mention, several little bit of luck.

Leave a Reply to Pierre Sandrin

Your email address will not be published. Required fields are marked *


seven × = 35