001/* 002 * The contents of this file are subject to the terms of the Common Development and 003 * Distribution License (the License). You may not use this file except in compliance with the 004 * License. 005 * 006 * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the 007 * specific language governing permission and limitations under the License. 008 * 009 * When distributing Covered Software, include this CDDL Header Notice in each file and include 010 * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL 011 * Header, with the fields enclosed by brackets [] replaced by your own identifying 012 * information: "Portions copyright [year] [name of copyright owner]". 013 * 014 * Copyright 2014 ForgeRock AS. 015 */ 016 017package org.forgerock.openig.decoration.global; 018 019import java.util.Map; 020 021import org.forgerock.json.fluent.JsonValue; 022import org.forgerock.openig.decoration.Context; 023import org.forgerock.openig.decoration.Decorator; 024import org.forgerock.openig.heap.HeapException; 025 026/** 027 * A GlobalDecorator stores decorators configuration in order to re-apply them when requested 028 * to decorate a given heap object instance. 029 */ 030public class GlobalDecorator implements Decorator { 031 032 /** 033 * Heap Key for the global decorator(s). They may be local to each Heap. 034 */ 035 public static final String GLOBAL_DECORATOR_HEAP_KEY = "global-decorator"; 036 037 private final Decorator parent; 038 private final JsonValue decorators; 039 040 /** 041 * Builds a new GlobalDecorator using given decorators JSON object element. 042 * 043 * @param parent 044 * the parent global decorator from which additional global 045 * decorators may be inherited. May be {@code null} 046 * @param config 047 * a JSON configuration 048 * @param reservedFieldNames 049 * the names of reserved top level fields in the config which 050 * should not be parsed as global decorators 051 */ 052 public GlobalDecorator(final Decorator parent, final JsonValue config, 053 final String... reservedFieldNames) { 054 this.parent = parent; 055 // create a copy of the config with the reserved names filtered out 056 this.decorators = config.expect(Map.class).clone(); 057 for (String reservedFieldName : reservedFieldNames) { 058 decorators.remove(reservedFieldName); 059 } 060 } 061 062 @Override 063 public boolean accepts(final Class<?> type) { 064 // Not used 065 return true; 066 } 067 068 /** 069 * Decorate the given object instance with the previously declared set of decorations instead of the provided one. 070 * 071 * @param delegate 072 * instance to decorate 073 * @param ignored 074 * ignored (may probably be {@code null}) 075 * @param context 076 * Context of the heap object to be decorated 077 * @return the decorated instance or the original delegate (if no decorator could apply) 078 * @throws HeapException 079 * if one of the decorator failed to decorate the instance 080 */ 081 @Override 082 public Object decorate(final Object delegate, final JsonValue ignored, final Context context) 083 throws HeapException { 084 Object decorated = parent != null ? parent.decorate(delegate, ignored, context) : delegate; 085 for (JsonValue decoration : decorators) { 086 String decoratorName = decoration.getPointer().leaf(); 087 // Process the decoration 088 Decorator decorator = context.getHeap().get(decoratorName, Decorator.class); 089 090 if ((decorator != null) && decorator.accepts(delegate.getClass())) { 091 decorated = decorator.decorate(decorated, decoration, context); 092 } 093 } 094 return decorated; 095 } 096}