View Javadoc
1   package de.fhdw.wtf.walker.tasks;
2   
3   import de.fhdw.wtf.common.ast.Attribute;
4   import de.fhdw.wtf.common.ast.AttributeModifier;
5   import de.fhdw.wtf.common.ast.AttributeModifierFindable;
6   import de.fhdw.wtf.common.ast.AttributeModifierMutable;
7   import de.fhdw.wtf.common.ast.AttributeModifierPrior;
8   import de.fhdw.wtf.common.ast.AttributeModifierSymmetric;
9   import de.fhdw.wtf.common.ast.AttributeModifierTransient;
10  import de.fhdw.wtf.common.ast.ConstructorOrOperation;
11  import de.fhdw.wtf.common.ast.Group;
12  import de.fhdw.wtf.common.ast.Model;
13  import de.fhdw.wtf.common.ast.type.AtomicType;
14  import de.fhdw.wtf.common.ast.type.BaseType;
15  import de.fhdw.wtf.common.ast.type.ClassType;
16  import de.fhdw.wtf.common.ast.type.CompositeType;
17  import de.fhdw.wtf.common.ast.type.ListType;
18  import de.fhdw.wtf.common.ast.type.MapType;
19  import de.fhdw.wtf.common.ast.type.ProductElementType;
20  import de.fhdw.wtf.common.ast.type.ProductType;
21  import de.fhdw.wtf.common.ast.type.SumType;
22  import de.fhdw.wtf.common.ast.type.ThrownType;
23  import de.fhdw.wtf.common.ast.type.Type;
24  import de.fhdw.wtf.common.ast.type.TypeProxy;
25  import de.fhdw.wtf.common.ast.visitor.AtomicTypeVisitorException;
26  import de.fhdw.wtf.common.ast.visitor.AttributeModifierVisitorReturnException;
27  import de.fhdw.wtf.common.ast.visitor.CompositeTypeVisitorException;
28  import de.fhdw.wtf.common.ast.visitor.TypeVisitorException;
29  import de.fhdw.wtf.common.constants.walker.ExceptionConstants;
30  import de.fhdw.wtf.common.exception.walker.InvalidAttributeModifierException;
31  import de.fhdw.wtf.common.exception.walker.TaskException;
32  import de.fhdw.wtf.common.task.TaskExecutor;
33  import de.fhdw.wtf.walker.walker.HelperUtils;
34  import de.fhdw.wtf.walker.walker.SimpleWalkerTask;
35  
36  /**
37   * This task checked the {@link AttributeModifier}s in the model. For example: symmetric is not allowed with BaseTypes,
38   * because BaseTypes canĀ“t have reverse getters.
39   * 
40   * This Checker must run after the {@link TypeReferencer}.
41   */
42  public final class InvalidAttributeModifierCheck extends SimpleWalkerTask {
43  	
44  	/**
45  	 * Constructor of {@link InvalidAttributeModifierCheck}.
46  	 * 
47  	 * @param m
48  	 *            model
49  	 * @param taskmanager
50  	 *            taskmanager
51  	 */
52  	private InvalidAttributeModifierCheck(final Model m, final TaskExecutor taskmanager) {
53  		super(m, taskmanager);
54  	}
55  	
56  	/**
57  	 * Creates a {@link InvalidAttributeModifierCheck}-Object.
58  	 * 
59  	 * @param model
60  	 *            model
61  	 * @param taskmanager
62  	 *            taskmanager
63  	 * @return The {@link InvalidAttributeModifierCheck}-Object.
64  	 */
65  	public static InvalidAttributeModifierCheck create(final Model model, final TaskExecutor taskmanager) {
66  		return new InvalidAttributeModifierCheck(model, taskmanager);
67  	}
68  	
69  	@Override
70  	public void handleClass(final ClassType c) throws TaskException {
71  		// Nothing
72  	}
73  	
74  	@Override
75  	public void handleGroup(final Group g) throws TaskException {
76  		// Nothing
77  	}
78  	
79  	@Override
80  	public void handleAttribute(final Attribute a, final ClassType owner) throws TaskException {
81  		// TODO: Check attribute modifiers besides symmetric. (Bug #770)
82  		for (final AttributeModifier modifier : a.getModifiers()) {
83  			modifier.accept(new AttributeModifierVisitorReturnException<Boolean, TaskException>() {
84  				
85  				@Override
86  				public Boolean handle(final AttributeModifierFindable modFindable) throws TaskException {
87  					return false;
88  				}
89  				
90  				@Override
91  				public Boolean handle(final AttributeModifierPrior modPrior) throws TaskException {
92  					return false;
93  				}
94  				
95  				@Override
96  				public Boolean handle(final AttributeModifierTransient modTransient) throws TaskException {
97  					return false;
98  				}
99  				
100 				@Override
101 				public Boolean handle(final AttributeModifierMutable modMutable) throws TaskException {
102 					return false;
103 				}
104 				
105 				@Override
106 				public Boolean handle(final AttributeModifierSymmetric modSymmetric) throws TaskException {
107 					final Type attrType = a.getAttrType();
108 					InvalidAttributeModifierCheck.this.checkSymmetricType(a, modSymmetric, attrType);
109 					return false;
110 				}
111 			});
112 		}
113 	}
114 	
115 	/**
116 	 * Check the symmetric modifier.
117 	 * 
118 	 * @param attribute
119 	 *            attribute
120 	 * @param symmetricModifier
121 	 *            symmetricModifier
122 	 * @param attrType
123 	 *            attrType
124 	 * @throws TaskException
125 	 *             possible Exception
126 	 */
127 	void checkSymmetricType(final Attribute attribute,
128 			final AttributeModifierSymmetric symmetricModifier,
129 			final Type attrType) throws TaskException {
130 		attrType.accept(new TypeVisitorException<TaskException>() {
131 			
132 			@Override
133 			public void handle(final AtomicType s) throws TaskException {
134 				s.accept(new AtomicTypeVisitorException<TaskException>() {
135 					
136 					@Override
137 					public void handle(final BaseType baseType) throws TaskException {
138 						throw InvalidAttributeModifierException.create(
139 								symmetricModifier,
140 								ExceptionConstants.INVALID_SYMMETRIC_ATTRIBUTE_REASON);
141 					}
142 					
143 					@Override
144 					public void handle(final ClassType clazz) throws TaskException {
145 						// Nothing: everything right
146 					}
147 				});
148 			}
149 			
150 			@Override
151 			public void handle(final CompositeType c) throws TaskException {
152 				c.accept(new CompositeTypeVisitorException<TaskException>() {
153 					
154 					@Override
155 					public void handle(final MapType map) throws TaskException {
156 						InvalidAttributeModifierCheck.this.checkSymmetricType(attribute, symmetricModifier, map.getOf());
157 					}
158 					
159 					@Override
160 					public void handle(final ListType list) throws TaskException {
161 						InvalidAttributeModifierCheck.this.checkSymmetricType(
162 								attribute,
163 								symmetricModifier,
164 								list.getOf());
165 					}
166 					
167 					@Override
168 					public void handle(final ProductType product) throws TaskException {
169 						for (final ProductElementType element : product.getElements()) {
170 							InvalidAttributeModifierCheck.this.checkSymmetricType(
171 									attribute,
172 									symmetricModifier,
173 									element.getType());
174 						}
175 					}
176 					
177 					@Override
178 					public void handle(final SumType sum) throws TaskException {
179 						for (final Type element : sum.getElements()) {
180 							InvalidAttributeModifierCheck.this
181 									.checkSymmetricType(attribute, symmetricModifier, element);
182 						}
183 					}
184 					
185 					@Override
186 					public void handle(final ThrownType thrownType) throws TaskException {
187 						// Nothing
188 					}
189 				});
190 			}
191 			
192 			@Override
193 			public void handle(final TypeProxy s) throws TaskException {
194 				final AtomicType targetType = HelperUtils.getTargetAtomicType(s);
195 				InvalidAttributeModifierCheck.this.checkSymmetricType(attribute, symmetricModifier, targetType);
196 			}
197 		});
198 	}
199 	
200 	@Override
201 	public void finalizeTask() throws TaskException {
202 		// Nothing
203 	}
204 	
205 	@Override
206 	public void beginTask() throws TaskException {
207 		// Nothing to do here
208 	}
209 	
210 	@Override
211 	public void handleConstructorOrOperation(final ConstructorOrOperation coo, final ClassType owner)
212 			throws TaskException {
213 		// Nothing to do here
214 	}
215 }