miercuri, 20 mai 2015

[OmniFaces utilities 2.0] Working with OmniFaces MapWrapper


MapWrapper is an implementation of Map that wraps another map. This allows interception of one or more method on this wrapped map.


The OmniFaces MapWrapper is a simple implementation of Map that wraps another map. Basically, if you have a Map instance and you need to intercept its methods (e.g. get(), put(), containsKey()), then you can wrap it via MapWrapper. Is a well-known fact that JSF uses several maps, like request/session/application/view map, faces context attributes map, components attributes map etc. When you are writing custom JSF artifacts (e.g. see OmniFaces, ViewParam), you may find useful a MapWrapper, since you can override (alter) only the needed Map methods for an existing instance.
As a "didactic" example, let's suppose that you want to intercept the methods of the faces context attributes map, and modify their behavior to accept to put in map only entries whose keys are starting with the text B797, and to accept to get from map only the entries whose keys are not starting with this text. Moreover, we don't want to reveal the existence of such entries via Map#containsKey(), or any other Map methods. So, we can write a custom FacesContext and override the getAttributes() method to return a MapWrapper instance instead of the original (wrapped) map:

public class MyFacesContext extends FacesContextWrapper {

 private FacesContext wrapped;

 public MyFacesContext() {
 }

 public MyFacesContext(FacesContext wrapped) {
  this.wrapped = wrapped;
 }

 @Override
 public Map<Object, Object> getAttributes() {

  return new MapWrapper<Object, Object>(super.getAttributes()) {

   private static final long serialVersionUID = -7674000948288609007L;

   @Override
   public Object put(Object key, Object value) {
    if (((String) key).startsWith("B797")) {
        return super.put(key, value);
    }
    return null;
   }

   @Override
   public Object get(Object key) {
   if (!((String) key).startsWith("B797")) {
       return super.get(key);
   }
   return null;
  }

  @Override
  public boolean containsKey(Object key) {
   if (!((String) key).startsWith("B797")) {
       return super.containsKey(key);
   }
   return false;
  }

  // more overridden methods to fortify the "secret" attributes
  };
 }

 @Override
 public FacesContext getWrapped() {
  return wrapped;
 }
}

Now, supposing that you have set this as the current FacesContext of the application (e.g. via FacesContextFactory, or OmniFaces, Faces#setContext()), you can test it and notice that a call as:

String added = (String)FacesContext.getCurrentInstance().getAttributes().put("dummy", "foo");

will not be added in the faces context attribute map.

By the other hand, a call as:

String added = (String)FacesContext.getCurrentInstance().getAttributes().put("B797dummy", "foo");

will add the corresponding entry (B797dummy = foo) in the faces context attributes map, but the below calls will return null, respectively, false:

String foo = (String)FacesContext.getCurrentInstance().getAttributes().get("B797dummy");
boolean isFoo = FacesContext.getCurrentInstance().getAttributes().containsKey("B797dummy");

Niciun comentariu:

Trimiteți un comentariu