1   package com.trendmicro.grid.acl.metadata;
2   
3   import javax.xml.bind.annotation.*;
4   import java.util.*;
5   
6   /**
7    * Declares a single profile to describe a metadata package's content.
8    *
9    * @author Juergen_Kellerer, 2010-04-21
10   * @version 1.0
11   */
12  @XmlAccessorType(XmlAccessType.FIELD)
13  @XmlAccessorOrder(value = XmlAccessOrder.UNDEFINED)
14  @XmlType(name = "profile", namespace = ProfilesDocument.NS)
15  public class Profile {
16  
17  	static <E> boolean isNull(E... values) {
18  		return values != null && (values.length == 0 || (values.length == 1 && values[0] == null));
19  	}
20  
21  	@XmlID
22  	@XmlAttribute(required = true)
23  	private String name;
24  
25  	@XmlAttribute
26  	private AccessLevel defaultAccess;
27  
28  	@XmlAttribute
29  	private Boolean disableTypeValidation;
30  
31  	@XmlElement(name = "description", nillable = true)
32  	private String description;
33  
34  	@XmlIDREF
35  	@XmlElement(name = "parentProfile", nillable = true)
36  	private Profile[] parentProfiles;
37  
38  	@XmlElement(name = "entry", required = true)
39  	private List<ProfileEntry> profileEntries;
40  
41  	public Profile() {
42  	}
43  
44  	public Profile(String name) {
45  		this.name = name;
46  	}
47  
48  	public String getName() {
49  		return name;
50  	}
51  
52  	public String getDescription() {
53  		return description;
54  	}
55  
56  	public Profile[] getParentProfiles() {
57  		return parentProfiles;
58  	}
59  
60  	public void setParentProfiles(Profile... parentProfiles) {
61  		this.parentProfiles = isNull(parentProfiles) ? null : parentProfiles;
62  	}
63  
64  	public List<ProfileEntry> getProfileEntries() {
65  		if (profileEntries == null)
66  			profileEntries = new ArrayList<ProfileEntry>();
67  		return profileEntries;
68  	}
69  
70  	public void setProfileEntries(List<ProfileEntry> profileEntries) {
71  		this.profileEntries = profileEntries;
72  	}
73  
74  	public ProfileEntry add(String name, DataType... validType) {
75  		ProfileEntry e = new ProfileEntry(name, validType);
76  		getProfileEntries().add(e);
77  		return e;
78  	}
79  
80  	/**
81  	 * Returns the default protection level to apply to un-defined meta data entries.
82  	 * <p/>
83  	 * When a profile returns 'null' on the default protection (= default) then the validation
84  	 * method allows only entries that were defined inside the profile.
85  	 *
86  	 * @return the default protection level to apply to un-defined meta data entries or
87  	 *         'null' if no un-defined meta data entries should be allowed.
88  	 */
89  	public AccessLevel getDefaultAccess() {
90  		AccessLevel level = null;
91  
92  		if (parentProfiles != null) {
93  			for (Profile profile : parentProfiles) {
94  				AccessLevel parentLevel = profile.getDefaultAccess();
95  				if (parentLevel != null)
96  					level = parentLevel;
97  			}
98  		}
99  
100 		if (defaultAccess != null)
101 			level = defaultAccess;
102 
103 		return level;
104 	}
105 
106 	/**
107 	 * Returns true if no type validation should be applied with the current profile.
108 	 *
109 	 * @return true if no type validation should be applied with the current profile.
110 	 */
111 	public boolean isDisableTypeValidation() {
112 		if (parentProfiles != null) {
113 			for (Profile parent : parentProfiles)
114 				if (parent.isDisableTypeValidation())
115 					return true;
116 		}
117 
118 		return Boolean.TRUE.equals(disableTypeValidation);
119 	}
120 
121 	/**
122 	 * Returns a map of profile entries reflecting the inheritance declared inside the parent profile names.
123 	 *
124 	 * @return a map of profile entries reflecting the inheritance declared inside the parent profile names.
125 	 */
126 	public Map<String, ProfileEntry> getEffectiveProfileEntries() {
127 		Map<String, ProfileEntry> entries = new LinkedHashMap<String, ProfileEntry>(64);
128 
129 		if (parentProfiles != null) {
130 			for (Profile profile : parentProfiles)
131 				entries.putAll(profile.getEffectiveProfileEntries());
132 		}
133 
134 		for (ProfileEntry entry : getProfileEntries())
135 			entries.put(entry.getMetaName(), entry);
136 
137 		return entries;
138 	}
139 
140 	@Override
141 	public boolean equals(Object o) {
142 		if (this == o) return true;
143 		if (!(o instanceof Profile)) return false;
144 
145 		Profile profile = (Profile) o;
146 
147 		if (!name.equals(profile.name)) return false;
148 		if (defaultAccess != null ? !defaultAccess.equals(profile.defaultAccess) : profile.defaultAccess != null)
149 			return false;
150 		if (!Arrays.equals(parentProfiles, profile.parentProfiles)) return false;
151 		if (profileEntries != null ? !profileEntries.equals(profile.profileEntries) : profile.profileEntries != null)
152 			return false;
153 
154 		return true;
155 	}
156 
157 	@Override
158 	public int hashCode() {
159 		int result = name.hashCode();
160 		result = 31 * result + (defaultAccess != null ? defaultAccess.hashCode() : 0);
161 		result = 31 * result + (parentProfiles != null ? Arrays.hashCode(parentProfiles) : 0);
162 		result = 31 * result + (profileEntries != null ? profileEntries.hashCode() : 0);
163 		return result;
164 	}
165 
166 	@Override
167 	public String toString() {
168 		return "Profile{" +
169 			"name='" + name + '\'' +
170 			"defaultAccess='" + defaultAccess + '\'' +
171 			", parentProfileNames=" + (parentProfiles == null ? null : Arrays.asList(parentProfiles)) +
172 			", profileEntries=" + profileEntries +
173 			'}';
174 	}
175 }