1   package com.trendmicro.grid.acl.metadata;
2   
3   import net.sf.tinyjee.util.Assert;
4   
5   import java.util.Map;
6   import java.util.Set;
7   import java.util.concurrent.ConcurrentHashMap;
8   
9   /**
10   * Implements profile based Validator factory.
11   *
12   * @author juergen_kellerer, 2010-12-02
13   * @version 1.0
14   */
15  public class ProfilesDocumentValidatorFactory implements ValidatorFactory {
16  
17  	final ProfilesDocument profiles;
18  	final Map<String, ProfileValidatorFactory> profileFactories =
19  			new ConcurrentHashMap<String, ProfileValidatorFactory>();
20  
21  	/**
22  	 * Creates a new validator factory for the given profiles document.
23  	 *
24  	 * @param profiles the document containing all defined validation profiles.
25  	 */
26  	public ProfilesDocumentValidatorFactory(ProfilesDocument profiles) {
27  		this.profiles = profiles;
28  	}
29  
30  	/**
31  	 * {@inheritDoc}
32  	 */
33  	@Override
34  	public Validator newValidator(ValidationInstructions instructions) {
35  		Assert.assertNotNull("instructions", instructions);
36  		Profile profile = profiles.get(instructions.getActiveProfileName());
37  
38  		if (profile == null) {
39  			throw new IllegalArgumentException("No profile was registered under the FQN: " +
40  					instructions.getActiveProfileName());
41  		}
42  
43  		ProfileValidatorFactory factory = profileFactories.get(profile.getName());
44  		if (factory == null)
45  			profileFactories.put(profile.getName(), factory = new ProfileValidatorFactory(profile));
46  
47  		return factory.newValidator(instructions);
48  	}
49  
50  	/**
51  	 * Implements a factory that binds on a single profile instance.
52  	 */
53  	static class ProfileValidatorFactory implements ValidatorFactory {
54  
55  		final boolean isTypeValidationEnabled;
56  		final AccessLevel defaultAccessLevel;
57  		final Map<String, ProfileEntry> entries;
58  
59  		private ProfileValidatorFactory(Profile profile) {
60  			isTypeValidationEnabled = !profile.isDisableTypeValidation();
61  			defaultAccessLevel = profile.getDefaultAccess();
62  			entries = profile.getEffectiveProfileEntries();
63  		}
64  
65  		/**
66  		 * {@inheritDoc}
67  		 */
68  		@Override
69  		public Validator newValidator(final ValidationInstructions instructions) {
70  			return new Validator() {
71  				@Override
72  				public boolean isValid(Meta meta) {
73  					if (isTypeValidationEnabled) {
74  						ProfileEntry entry = entries.get(meta.getName());
75  						if (entry != null)
76  							return entry.getValidTypes().contains(meta.getDataType());
77  					}
78  					return true;
79  				}
80  
81  				private boolean checkCanAccess(String metaName, boolean readAndWrite) {
82  					ProfileEntry entry = entries.get(metaName);
83  					if (entry == null) {
84  						return defaultAccessLevel != null &&
85  								instructions.isElementVisible(defaultAccessLevel);
86  					} else {
87  						if (instructions.isElementVisible(entry.getAccessLevel()) &&
88  								!(readAndWrite && entry.isReadonly())) {
89  
90  							Set<String> roles = entry.getRequiredRoles();
91  							return roles == null || roles.isEmpty() || instructions.getRoles().containsAll(roles);
92  						}
93  						return false;
94  					}
95  				}
96  
97  				/**
98  				 * {@inheritDoc}
99  				 */
100 				@Override
101 				public boolean isReadable(String metaName) {
102 					return checkCanAccess(metaName, false);
103 				}
104 
105 				/**
106 				 * {@inheritDoc}
107 				 */
108 				@Override
109 				public boolean isWritable(String metaName) {
110 					return checkCanAccess(metaName, true);
111 				}
112 			};
113 		}
114 	}
115 }