View Javadoc
1   package de.fhdw.wtf.common.ast;
2   
3   import java.util.Collection;
4   import java.util.HashSet;
5   import java.util.Iterator;
6   
7   import de.fhdw.wtf.common.ast.type.ClassType;
8   import de.fhdw.wtf.common.ast.type.ProductType;
9   import de.fhdw.wtf.common.ast.type.Type;
10  import de.fhdw.wtf.common.ast.visitor.ConstructorOrOperationExceptionVisitor;
11  import de.fhdw.wtf.common.ast.visitor.OperationModifierVisitorReturn;
12  import de.fhdw.wtf.common.constants.parser.AstDescriptionConstants;
13  import de.fhdw.wtf.common.exception.walker.TaskException;
14  import de.fhdw.wtf.common.token.Token;
15  
16  /**
17   * This class represents a operation of a class. It is held by a <ClassType>, can contain multiple
18   * {@link OperationModifier}, has a name, returnType and parameters.
19   */
20  public final class Operation extends ConstructorOrOperation {
21  	
22  	/**
23  	 * generated.
24  	 */
25  	private static final long serialVersionUID = 8835914994800497991L;
26  	
27  	/**
28  	 * The modifiers of the operation.
29  	 * 
30  	 */
31  	private final Collection<OperationModifier> modifiers;
32  	
33  	/**
34  	 * Overriding Operations in the Model
35  	 * 
36  	 */
37  	private final Collection<Operation> overridingOperations;
38  	
39  	/**
40  	 * Private-Constructor of {@link Operation}.
41  	 * 
42  	 * @param name
43  	 *            name
44  	 * @param modifiers
45  	 *            The modifiers of the operation.
46  	 * @param parameters
47  	 *            The parameters of the operation.
48  	 * @param containingType
49  	 *            The classType of the class, that contains the operation.
50  	 * @param returnType
51  	 *            The return-type of the Operation.
52  	 * @param firstToken
53  	 *            firstToken
54  	 * @param lastToken
55  	 *            lastToken
56  	 */
57  	private Operation(final String name,
58  			final Collection<OperationModifier> modifiers,
59  			final ProductType parameters,
60  			final ClassType containingType,
61  			final Type returnType,
62  			final Token firstToken,
63  			final Token lastToken) {
64  		super(name, parameters, containingType, returnType, firstToken, lastToken);
65  		this.modifiers = modifiers;
66  		this.overridingOperations = new HashSet<Operation>();
67  	}
68  	
69  	/**
70  	 * Creates a {@link Operation}-Object.
71  	 * 
72  	 * @param name
73  	 *            name
74  	 * @param modifiers
75  	 *            The modifiers of the operation.
76  	 * @param parameters
77  	 *            The params of the operation.
78  	 * @param containingType
79  	 *            The classType of the class, that contains the constructor or operation.
80  	 * @param returnType
81  	 *            The Returntype of the Operation.
82  	 * @param firstToken
83  	 *            firstToken
84  	 * @param lastToken
85  	 *            lastToken
86  	 * @return The Operation-Object
87  	 */
88  	public static Operation create(final String name,
89  			final Collection<OperationModifier> modifiers,
90  			final ProductType parameters,
91  			final ClassType containingType,
92  			final Type returnType,
93  			final Token firstToken,
94  			final Token lastToken) {
95  		return new Operation(name, modifiers, parameters, containingType, returnType, firstToken, lastToken);
96  	}
97  	
98  	/**
99  	 * Creates a {@link Operation}-Object.
100 	 * 
101 	 * @param name
102 	 *            name
103 	 * @param modifiers
104 	 *            The modifiers of the operation.
105 	 * @param parameters
106 	 *            The params of the operation.
107 	 * @param containingType
108 	 *            The classType of the class, that contains the constructor or operation.
109 	 * @param returnType
110 	 *            The Returntype of the Operation.
111 	 * @param firstToken
112 	 *            firstToken
113 	 * @return The Operation-Object
114 	 */
115 	public static Operation create(final String name,
116 			final Collection<OperationModifier> modifiers,
117 			final ProductType parameters,
118 			final ClassType containingType,
119 			final Type returnType,
120 			final Token firstToken) {
121 		return new Operation(name, modifiers, parameters, containingType, returnType, firstToken, null);
122 	}
123 	
124 	/**
125 	 * Returns true if <code>this</code> is an abstract operation. False otherwise.
126 	 * 
127 	 * @return boolean.
128 	 */
129 	public boolean isAbstract() {
130 		final OperationModifierVisitorReturn<Boolean> visitor = new OperationModifierVisitorReturn<Boolean>() {
131 			@Override
132 			public Boolean handle(final OperationModifierAbstract v) {
133 				return true;
134 			}
135 		};
136 		return this.processModifierVisitor(visitor);
137 	}
138 	
139 	/**
140 	 * Processes a Returnvisitor with Return-Type Boolean and returns the result.
141 	 * 
142 	 * @param visitor
143 	 *            visitor.
144 	 * @return boolean.
145 	 */
146 	private boolean processModifierVisitor(final OperationModifierVisitorReturn<Boolean> visitor) {
147 		for (final OperationModifier current : this.getModifiers()) {
148 			if (current.accept(visitor)) {
149 				return true;
150 			}
151 		}
152 		return false;
153 	}
154 	
155 	@Override
156 	public boolean equals(final Object o) {
157 		if (o instanceof Operation) {
158 			final Operation other = (Operation) o;
159 			boolean result = true;
160 			result = result && this.getName().equals(other.getName());
161 			result = result && this.getReturnType().equals(other.getReturnType());
162 			final Iterator<OperationModifier> i = this.getModifiers().iterator();
163 			while (i.hasNext()) {
164 				final OperationModifier current = i.next();
165 				result = result && other.getModifiers().contains(current);
166 			}
167 			// there is no use hitting a dead body
168 			if (!result) {
169 				return result;
170 			}
171 			return this.getParameters().equals(other.getParameters());
172 		}
173 		return false;
174 	}
175 	
176 	@Override
177 	public int hashCode() {
178 		int result = this.getName().hashCode() ^ this.getReturnType().hashCode() ^ this.getParameters().hashCode();
179 		for (final OperationModifier modifier : this.getModifiers()) {
180 			result ^= modifier.hashCode();
181 		}
182 		return result;
183 	}
184 	
185 	@Override
186 	public String toString() {
187 		final StringBuilder result = new StringBuilder();
188 		result.append(this.getName()).append(AstDescriptionConstants.COLON_TOKEN)
189 				.append(AstDescriptionConstants.DOUBLE_SQUARE_BRACKET_OPEN_TOKEN).append(this.getParameters())
190 				.append(AstDescriptionConstants.ARROW_TOKEN).append(this.getReturnType())
191 				.append(AstDescriptionConstants.DOUBLE_SQUARE_BRACKET_CLOSE_TOKEN);
192 		if (!this.getModifiers().isEmpty()) {
193 			final Iterator<OperationModifier> i = this.getModifiers().iterator();
194 			while (i.hasNext()) {
195 				result.append(' ').append(i.next());
196 			}
197 		}
198 		result.append(AstDescriptionConstants.SEMICOLON_TOKEN);
199 		return result.toString();
200 	}
201 	
202 	/**
203 	 * The modifiers of the operation.
204 	 * 
205 	 * @return modifiers
206 	 */
207 	public Collection<OperationModifier> getModifiers() {
208 		return this.modifiers;
209 	}
210 	
211 	/**
212 	 * The name of the operation.
213 	 * 
214 	 * @return name
215 	 */
216 	@Override
217 	public String getName() {
218 		return this.getSignature().getName();
219 	}
220 	
221 	@Override
222 	public void accept(final ConstructorOrOperationExceptionVisitor<TaskException> constructorAndOperationVisitor)
223 			throws TaskException {
224 		constructorAndOperationVisitor.handleOperation(this);
225 		
226 	}
227 	
228 	/**
229 	 * @returns the Operations, which override this operation!
230 	 */
231 	public Collection<Operation> getOverridingOperations() {
232 		return this.overridingOperations;
233 	}
234 }