001/**
002 * Copyright 2004-2014 The Kuali Foundation
003 *
004 * Licensed under the Educational Community License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 * http://www.opensource.org/licenses/ecl2.php
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016package org.kuali.student.mock.mojo;
017
018import org.kuali.student.contract.model.MessageStructure;
019import org.kuali.student.contract.model.Service;
020import org.kuali.student.contract.model.ServiceContractModel;
021import org.kuali.student.contract.model.ServiceMethod;
022import org.kuali.student.contract.model.ServiceMethodError;
023import org.kuali.student.contract.writer.service.GetterSetterNameCalculator;
024
025import java.util.List;
026
027/**
028 * This class will generate the extended class that does CRUD tests as
029 * part of the Conformance Tests for services. The generated class will
030 * complete the base class and is meant to be generated once and then
031 * edited (and mantained) by developers.
032 *
033 * @author Mezba Mahtab (mezba.mahtab@utoronto.ca)
034 */
035public class ConformanceTestExtendedCrudClassServiceWriter extends ConformanceTestBaseCrudClassServiceWriter {
036
037    ////////////////////////////
038    // CONSTRUCTOR
039    ////////////////////////////
040
041    public ConformanceTestExtendedCrudClassServiceWriter (ServiceContractModel model,
042                                                          String directory,
043                                                          String rootPackage,
044                                                          String servKey,
045                                                          List<ServiceMethod> methods,
046                                                          boolean isR1) {
047        super(model, directory, rootPackage, servKey, methods, isR1, calcPackage(servKey, rootPackage), calcClassName(servKey));
048    }
049
050    //////////////////////////
051    // FUNCTIONALS
052    //////////////////////////
053
054    /**
055     * Given the service key (name), returns a calculated class name for the conformance tester.
056     */
057    public static String calcClassName(String servKey) {
058        return "Test" + GetterSetterNameCalculator.calcInitUpper(fixServKey(servKey) + "ServiceImplConformanceExtendedCrud");
059    }
060
061    /**
062     * Write out the entire file
063     */
064    public void write() {
065        // begin file
066        indentPrintln("@RunWith(SpringJUnit4ClassRunner.class)");
067        indentPrintln("@ContextConfiguration(locations = {\"classpath:" + servKey + "-test-with-mock-context.xml\"})");
068        indentPrint("public class " + calcClassName(servKey));
069        println(" extends " + super.calcClassName(servKey) + " ");
070        Service serv = finder.findService(servKey);
071        setPackageName(serv.getImplProject() + ".impl"); // change the package name
072        importsAdd(serv.getImplProject() + "." + serv.getName()); // import for the service
073        doTestImportsAdd();
074        openBrace();
075
076        indentPrintln("");
077
078        // print out list of methods for DTO fields per DTO that need to be completed
079        indentPrintDecoratedComment("DTO FIELD SPECIFIC METHODS", H1_COMMENT_CHAR, H1_COMMENT_MARK_LENGTH*2);
080        indentPrintln("");
081
082        // for each DTO, write the DOT field management methods that were left abstract in base class
083        for (String dtoObjectName : calcNamesOfDTOsWithCrudManagedByService()) {
084            indentPrintln("// ****************************************************");
085            indentPrintln("//           " + dtoObjectName + "Info");
086            indentPrintln("// ****************************************************");
087            indentPrintln("");
088
089            // get the message structures of the dto
090            List<MessageStructure> messageStructures = finder.findMessageStructures(dtoObjectName + "Info");
091
092            writetestCrudXXX_setDTOFieldsForTestCreate(dtoObjectName, messageStructures);
093            writetestCrudXXX_testDTOFieldsForTestCreateUpdate(dtoObjectName, messageStructures);
094            writetestCrudXXX_setDTOFieldsForTestUpdate(dtoObjectName, messageStructures);
095            writetestCrudXXX_testDTOFieldsForTestReadAfterUpdate(dtoObjectName, messageStructures);
096            writetestCrudXXX_setDTOFieldsForTestReadAfterUpdate(dtoObjectName, messageStructures);
097            indentPrintln("");
098        }
099
100        // print out list of service operations that are not tested as abstract test methods
101        indentPrintDecoratedComment("SERVICE OPS NOT TESTED IN BASE TEST CLASS", H1_COMMENT_CHAR, H1_COMMENT_MARK_LENGTH*2);
102        indentPrintln("");
103
104        // for each method, create an abstract method to test that and print it out
105        for (ServiceMethod method: methods) {
106            if (!isServiceMethodTestedAsPartofCrudInBaseConformanceTest (method)) {
107                indentPrintln("/* Method Name: " + method.getName() + " */");
108                indentPrintln("@Test");
109                indentPrintln("public void test_" + method.getName() + "() ");
110                if (method.getErrors().size()>0) {
111                    indentPrint("throws ");
112                    String comma = "";
113                    for (ServiceMethodError error: method.getErrors()) {
114                        indentPrint(comma + error.getClassName().trim());
115                        comma = ",";
116                    }
117                }
118                openBrace();
119                closeBrace();
120                indentPrintln("");
121            }
122        }
123
124
125
126        // end file print out
127        closeBrace ();
128        println ("");
129
130        // close and print file
131        this.writeJavaClassAndImportsOutToFile();
132        this.getOut().close();
133    }
134
135    /**
136     * Writes the section to set fields specific to this dto for testCreate section.
137     */
138    public void writetestCrudXXX_setDTOFieldsForTestCreate(String dtoObjectName, List<MessageStructure> messageStructures) {
139        indentPrintln("/*");
140        incrementIndent();
141        indentPrintln("A method to set the fields for a " + dtoObjectName  + " in a 'test create' section prior to calling the 'create' operation.");
142        decrementIndent();
143        indentPrintln("*/");
144        indentPrintln("public void testCrud" + dtoObjectName + "_setDTOFieldsForTestCreate(" + dtoObjectName + "Info expected) ");
145        openBrace();
146        for (MessageStructure ms: messageStructures) {
147            if (ms.getShortName().equals("id")) continue;
148            if (ms.getShortName().equals("meta")) continue;
149            if (ms.getShortName().equals("attributes")) continue;
150            if (ms.getType().equals("String")) {
151                indentPrintln("expected." + new GetterSetterNameCalculator (ms, this, model).calcSetter() + "(\"" + ms.getShortName()+ "01\");");
152            }
153            else if (ms.getShortName().equals("descr")) {
154                indentPrintln("expected.setDescr(RichTextHelper.buildRichTextInfo(\"descr01\", \"descr01\"));");
155            }
156            else {
157                indentPrintln("//TODO *TYPE = " + ms.getType() + "* expected." + new GetterSetterNameCalculator (ms, this, model).calcSetter() + "(\"" + ms.getShortName()+ "01\");");
158            }
159        }
160        closeBrace();
161        indentPrintln("");
162    }
163
164    /**
165     * Writes the section to test fields specific to this dto for testCreate and testUpdate sections.
166     */
167    public void writetestCrudXXX_testDTOFieldsForTestCreateUpdate(String dtoObjectName, List<MessageStructure> messageStructures) {
168        indentPrintln("/*");
169        incrementIndent();
170        indentPrintln("A method to test the fields for a " + dtoObjectName  + ". This is called after:");
171        indentPrintln("- creating a DTO, where actual is the DTO returned by the create operation, and expected is the dto passed in to the create operation");
172        indentPrintln("- reading a DTO after creating it, and actual is the read DTO, and expected is the dto that was created");
173        indentPrintln("- updating a DTO, where actual is DTO returned by the update operation, and expected is the dto that was passed in to the update operation");
174        decrementIndent();
175        indentPrintln("*/");
176        indentPrintln("public void testCrud" + dtoObjectName + "_testDTOFieldsForTestCreateUpdate(" + dtoObjectName + "Info expected, " + dtoObjectName + "Info actual) ");
177        openBrace();
178        for (MessageStructure ms: messageStructures) {
179            if (ms.getShortName().equals("id")) continue;
180            if (ms.getShortName().equals("meta")) continue;
181            if (ms.getShortName().equals("attributes")) continue;
182            if (ms.getType().equals("String")) {
183                indentPrintln("assertEquals (expected." + new GetterSetterNameCalculator (ms, this, model).calcGetter() + "(), actual." + new GetterSetterNameCalculator (ms, this, model).calcGetter() + "());");
184            }
185            else if (ms.getShortName().equals("descr")) {
186                indentPrintln("new RichTextTester().check(expected.getDescr(), actual.getDescr());");
187            }
188            else {
189                indentPrintln("//TODO *TYPE = " + ms.getType() + "* assertEquals (expected." + new GetterSetterNameCalculator (ms, this, model).calcGetter() + "(), actual." + new GetterSetterNameCalculator (ms, this, model).calcGetter() + "());");
190            }
191        }
192        closeBrace();
193        indentPrintln("");
194    }
195
196
197    /**
198     * Writes the section to set fields specific to this dto for testUpdate sections.
199     */
200    public void writetestCrudXXX_setDTOFieldsForTestUpdate(String dtoObjectName, List<MessageStructure> messageStructures) {
201        indentPrintln("/*");
202        incrementIndent();
203        indentPrintln("A method to set the fields for a " + dtoObjectName + " in a 'test update' section prior to calling the 'update' operation.");
204        decrementIndent();
205        indentPrintln("*/");
206        indentPrintln("public void testCrud" + dtoObjectName + "_setDTOFieldsForTestUpdate(" + dtoObjectName + "Info expected) ");
207        openBrace();
208        for (MessageStructure ms: messageStructures) {
209            if (ms.getShortName().equals("id")) continue;
210            if (ms.getShortName().equals("meta")) continue;
211            if (ms.getShortName().equals("attributes")) continue;
212            if (ms.getType().equals("String")) {
213                indentPrintln("expected." + new GetterSetterNameCalculator (ms, this, model).calcSetter() + "(\"" + ms.getShortName()+ "_Updated\");");
214            }
215            else if (ms.getShortName().equals("descr")) {
216                indentPrintln("expected.setDescr(RichTextHelper.buildRichTextInfo(\"descr_Updated\", \"descr_Updated\"));");
217            }
218            else {
219                indentPrintln("//TODO *TYPE = " + ms.getType() + "* expected." + new GetterSetterNameCalculator (ms, this, model).calcSetter() + "(\"" + ms.getShortName()+ "_Updated\");");
220            }
221        }
222        closeBrace();
223        indentPrintln("");
224    }
225
226    /**
227     * Writes the section to test fields specific to this dto for testReadAfterUpdate sections.
228     */
229    public void writetestCrudXXX_testDTOFieldsForTestReadAfterUpdate(String dtoObjectName, List<MessageStructure> messageStructures) {
230        indentPrintln("/*");
231        incrementIndent();
232        indentPrintln("A method to test the fields for a " + dtoObjectName  + " after an update operation, followed by a read operation,");
233        indentPrintln("where actual is the DTO returned by the read operation, and expected is the dto returned by the update operation.");
234        decrementIndent();
235        indentPrintln("*/");
236        indentPrintln("public void testCrud" + dtoObjectName + "_testDTOFieldsForTestReadAfterUpdate(" + dtoObjectName + "Info expected, " + dtoObjectName + "Info actual) ");
237        openBrace();
238        for (MessageStructure ms: messageStructures) {
239            if (ms.getShortName().equals("meta")) continue;
240            if (ms.getShortName().equals("attributes")) continue;
241            if (ms.getType().equals("String")) {
242                indentPrintln("assertEquals (expected." + new GetterSetterNameCalculator (ms, this, model).calcGetter() + "(), actual." + new GetterSetterNameCalculator (ms, this, model).calcGetter() + "());");
243            }
244            else if (ms.getShortName().equals("descr")) {
245                indentPrintln("new RichTextTester().check(expected.getDescr(), actual.getDescr());");
246            }
247            else {
248                indentPrintln("//TODO *TYPE = " + ms.getType() + "* assertEquals (expected." + new GetterSetterNameCalculator (ms, this, model).calcGetter() + "(), actual." + new GetterSetterNameCalculator (ms, this, model).calcGetter() + "());");
249            }
250        }
251        closeBrace();
252        indentPrintln("");
253    }
254
255    /**
256     * Writes the section to set fields specific to this dto for testReadAfterUpdate sections.
257     */
258    public void writetestCrudXXX_setDTOFieldsForTestReadAfterUpdate(String dtoObjectName, List<MessageStructure> messageStructures) {
259        indentPrintln("/*");
260        incrementIndent();
261        indentPrintln("A method to set the fields for a " + dtoObjectName  + " in the 'test read after update' section.");
262        indentPrintln("This dto is another (second) dto object being created for other tests.");
263        decrementIndent();
264        indentPrintln("*/");
265        indentPrintln("public void testCrud" + dtoObjectName + "_setDTOFieldsForTestReadAfterUpdate(" + dtoObjectName + "Info expected) ");
266        openBrace();
267        for (MessageStructure ms: messageStructures) {
268            if (ms.getShortName().equals("id")) continue;
269            if (ms.getShortName().equals("typeKey")) continue;
270            if (ms.getShortName().equals("stateKey")) continue;
271            if (ms.getShortName().equals("meta")) continue;
272            if (ms.getShortName().equals("descr")) continue;
273            if (ms.getShortName().equals("attributes")) continue;
274            if (ms.getType().equals("String")) {
275                indentPrintln("expected." + new GetterSetterNameCalculator (ms, this, model).calcSetter() + "(\"" + ms.getShortName()+ "_Updated\");");
276            } else {
277                indentPrintln("//TODO *TYPE = " + ms.getType() + "* expected." + new GetterSetterNameCalculator (ms, this, model).calcSetter() + "(\"" + ms.getShortName()+ "_Updated\");");
278            }
279        }
280        closeBrace();
281        indentPrintln("");
282    }
283
284}