View Javadoc
1   package de.fhdw.wtf.walker.tasks;
2   
3   import java.util.ArrayList;
4   import java.util.Iterator;
5   
6   import de.fhdw.wtf.common.ast.Attribute;
7   import de.fhdw.wtf.common.ast.AttributeModifier;
8   import de.fhdw.wtf.common.ast.AttributeModifierSymmetric;
9   import de.fhdw.wtf.common.ast.ConstructorOrOperation;
10  import de.fhdw.wtf.common.ast.Group;
11  import de.fhdw.wtf.common.ast.Model;
12  import de.fhdw.wtf.common.ast.type.ClassType;
13  import de.fhdw.wtf.common.ast.type.Type;
14  import de.fhdw.wtf.common.exception.walker.SymmetricCheckException;
15  import de.fhdw.wtf.common.exception.walker.TaskException;
16  import de.fhdw.wtf.common.task.TaskExecutor;
17  import de.fhdw.wtf.common.task.TaskExecutorFixed;
18  import de.fhdw.wtf.walker.walker.SimpleWalkerTask;
19  
20  /**
21   * @author hfw413hy
22   *
23   */
24  public class SymmetricCheck extends SimpleWalkerTask {
25  	
26  	private final ArrayList<SymmetricCheckPart> parts = new ArrayList<>();
27  	
28  	private final void addPart(final Attribute a, final ClassType owner) {
29  		this.parts.add(new SymmetricCheckPart(owner, a));
30  	}
31  	
32  	/**
33  	 * Erzeugt ein Check-Objekt zum Prüfen, ob symmetrische Beziehungen auf beiden Seiten der Klasse angegeben wurden.
34  	 * 
35  	 * @param model
36  	 *            Das zugrunde liegende Modell, welches geprüft werden soll.
37  	 * @param taskmanager
38  	 *            Der Manager.
39  	 * @return Das Check-Objekt.
40  	 */
41  	public static SymmetricCheck create(final Model model, final TaskExecutorFixed taskmanager) {
42  		return new SymmetricCheck(model, taskmanager);
43  	}
44  	
45  	private SymmetricCheck(final Model m, final TaskExecutor taskmanager) {
46  		super(m, taskmanager);
47  	}
48  	
49  	@Override
50  	public void handleClass(final ClassType c) throws TaskException {
51  		// Nichts
52  	}
53  	
54  	@Override
55  	public void handleGroup(final Group g) throws TaskException {
56  		// Nichts
57  	}
58  	
59  	@Override
60  	public void handleAttribute(final Attribute a, final ClassType owner) throws TaskException {
61  		if (a.isSymmetric()) {
62  			this.addPart(a, owner);
63  		}
64  	}
65  	
66  	@Override
67  	public void handleConstructorOrOperation(final ConstructorOrOperation coo, final ClassType owner)
68  			throws TaskException {
69  		// Nichts...
70  	}
71  	
72  	/**
73  	 * Prüft ob es in der Liste aller symmetrischen Attribute ein Gegenstück gibt.
74  	 * 
75  	 * @param g
76  	 *            Die Gruppe in der wir symmetrische Beziehungen testen.
77  	 * @param current
78  	 *            Das Ausgangs-Attribut.
79  	 * @throws SymmetricCheckException
80  	 */
81  	private void findCorrespondingAttribute(final SymmetricCheckPart current) throws SymmetricCheckException {
82  		final boolean debug = true;
83  		final Iterator<SymmetricCheckPart> itemIt = this.parts.iterator();
84  		while (itemIt.hasNext()) {
85  			final SymmetricCheckPart cur = itemIt.next();
86  			
87  			// Überspringe Vergleich mit sich selbst
88  			if (current.equals(cur)) {
89  				continue;
90  			}
91  			
92  			// Klasse A: idA : B symmetric(idB);
93  			// Klasse B: idB : A symmetric(idA);
94  			
95  			// Überprüfen der Attributnamen-Referenzierung
96  			// Prüft ob "idA" (in A) so als Identifier in B (in symmetric(idA)) hinterlegt ist...
97  			if (!cur.getAttributeName().equals(current.getSymmetricIdentifier())) {
98  				if (debug) {
99  					System.out.println("1 : " + cur.getAttributeName() + " vs " + current.getSymmetricIdentifier());
100 				}
101 				continue;
102 			}
103 			// ...und umgekehrt
104 			if (!current.getAttributeName().equals(cur.getSymmetricIdentifier())) {
105 				if (debug) {
106 					System.out.println("2 : " + current.getAttributeName() + " vs " + cur.getSymmetricIdentifier());
107 				}
108 				continue;
109 			}
110 			
111 			// Prüft ob die Typen übereinstimmen
112 			if (!cur.getAttributeTypeString().equals(current.getClassTypeString())) {
113 				if (debug) {
114 					System.out.println("3 : " + cur.getAttributeTypeString() + " vs " + current.getClassTypeString());
115 				}
116 				continue;
117 			}
118 			if (!current.getAttributeTypeString().equals(cur.getClassTypeString())) {
119 				if (debug) {
120 					System.out.println("4 : " + current.getAttributeTypeString() + " vs " + cur.getClassTypeString());
121 				}
122 				continue;
123 			}
124 			
125 			// Wir haben den passenden Typ gefunden der zu "current" passt
126 			return;
127 		}
128 		
129 		throw SymmetricCheckException.create("Kein passendes Attribut in der Klasse "
130 				+ current.getAttributeType().getTypeString() + " gefunden!", current.getAttribute());
131 	}
132 	
133 	@Override
134 	public void finalizeTask() throws TaskException {
135 		final Iterator<SymmetricCheckPart> groupIt = this.parts.iterator();
136 		while (groupIt.hasNext()) {
137 			this.findCorrespondingAttribute(groupIt.next());
138 		}
139 	}
140 	
141 	@Override
142 	public void beginTask() throws TaskException {
143 		// Nichts...
144 	}
145 	
146 }
147 
148 /**
149  * 
150  * @author hfw413hy
151  *
152  */
153 class SymmetricCheckPart {
154 	private final ClassType Owner;
155 	private final Attribute OwnerAttribute;
156 	
157 	public SymmetricCheckPart(final ClassType owner, final Attribute a) {
158 		this.Owner = owner;
159 		this.OwnerAttribute = a;
160 	}
161 	
162 	public Type getClassType() {
163 		return this.Owner;
164 	}
165 	
166 	public Type getAttributeType() {
167 		return this.OwnerAttribute.getAttrType();
168 	}
169 	
170 	public String getAttributeTypeString() {
171 		String tmp = this.OwnerAttribute.getAttrType().getTypeString();
172 		final int idx = tmp.indexOf("*");
173 		if (idx > -1) {
174 			tmp = tmp.substring(0, idx) + tmp.substring(idx + 1);
175 		}
176 		return tmp;
177 	}
178 	
179 	public Attribute getAttribute() {
180 		return this.OwnerAttribute;
181 	}
182 	
183 	/**
184 	 * Liefert den Identifier eines Symmetrischen Attributes zurück, Bsp.: "a : A symmetric(myA)" -> "myA".
185 	 * 
186 	 * @return Der Identifier eines Symmetrischen Attributes, Bsp.: "a : A symmetric(myA)" -> "myA".
187 	 */
188 	public String getSymmetricIdentifier() {
189 		final Iterator<AttributeModifier> i = this.OwnerAttribute.getModifiers().iterator();
190 		while (i.hasNext()) {
191 			final AttributeModifier m = i.next();
192 			if (m instanceof AttributeModifierSymmetric) {
193 				final AttributeModifierSymmetric cur = (AttributeModifierSymmetric) m;
194 				return cur.getIdentifierToken().getIdentifier();
195 			}
196 		}
197 		return "";
198 	}
199 	
200 	public String getAttributeName() {
201 		return this.OwnerAttribute.getName();
202 	}
203 	
204 	/**
205 	 * Liefert bei einem qualifizierten Namen (Bsp.: "de>fhdw>test>a") den Klassennamen "a".
206 	 * 
207 	 * @return Liefert bei einem qualifizierten Namen (Bsp.: "de>fhdw>test>a") den Klassennamen "a".
208 	 */
209 	public String getClassTypeString() {
210 		final String[] arr = this.getClassType().getTypeString().split(">");
211 		return arr[arr.length - 1];
212 	}
213 }