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