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.admin.ui.mojo;
017
018import java.io.File;
019import java.io.FileNotFoundException;
020import java.io.FileOutputStream;
021import java.io.PrintStream;
022import java.util.List;
023import java.util.Stack;
024import org.kuali.student.contract.model.Lookup;
025import org.kuali.student.contract.model.MessageStructure;
026import org.kuali.student.contract.model.Service;
027
028import org.kuali.student.contract.model.ServiceContractModel;
029import org.kuali.student.contract.model.ServiceMethod;
030import org.kuali.student.contract.model.XmlType;
031import org.kuali.student.contract.model.util.ModelFinder;
032import org.kuali.student.contract.writer.XmlWriter;
033import org.kuali.student.contract.writer.service.GetterSetterNameCalculator;
034
035/**
036 *
037 * @author nwright
038 */
039public class AdminUiInquiryViewBeanWriter {
040
041    private ServiceContractModel model;
042    private ModelFinder finder;
043    private String directory;
044    private String rootPackage;
045    private String servKey;
046    private Service service;
047    private XmlType xmlType;
048    private List<ServiceMethod> methods;
049    private XmlWriter out;
050    String fileName;
051    String fullDirectoryPath;
052
053    public AdminUiInquiryViewBeanWriter(ServiceContractModel model,
054            String directory,
055            String rootPackage,
056            String servKey,
057            XmlType xmlType,
058            List<ServiceMethod> methods) {
059        this.model = model;
060        this.finder = new ModelFinder(model);
061        this.directory = directory;
062        this.rootPackage = rootPackage;
063        this.servKey = servKey;
064        service = finder.findService(servKey);
065        this.xmlType = xmlType;
066        this.methods = methods;
067    }
068
069    /**
070     * Write out the entire file
071     *
072     * @param out
073     */
074    public void write() {
075        initXmlWriter();
076        writeBoilerPlate();
077        writeBean();
078    }
079
080    private void writeBean() {
081        String infoClass = GetterSetterNameCalculator.calcInitUpper(xmlType.getName());
082        String serviceClass = GetterSetterNameCalculator.calcInitUpper(service.getName());
083        String serviceVar = GetterSetterNameCalculator.calcInitLower(service.getName());
084        String serviceContract = service.getImplProject() + "." + service.getName();
085        String inquirable = AdminUiInquirableWriter.calcPackage(servKey, rootPackage, xmlType) + "."
086                + AdminUiInquirableWriter.calcClassName(servKey, xmlType);
087        out.println("");
088        out.incrementIndent();
089        out.indentPrintln("<import resource=\"classpath:ks-" + infoClass + "-dictionary.xml\"/>");
090        out.indentPrintln("<import resource=\"classpath:UifKSDefinitions.xml\"/>");
091        out.indentPrintln("<!-- **********************************************");
092        out.indentPrintln("Paste bean definition below into the list of dataDictionaryPackages in StudentSpringBeans.xml ");
093        out.indentPrintln ("<value>classpath:" + fullDirectoryPath + "/" + fileName + "</value>");
094        out.indentPrintln("********************************************** -->");
095        out.indentPrintln("<!-- InquiryView -->");
096        out.indentPrintln("<bean id=\"KS-" + infoClass + "-AdminInquiryView\" parent=\"KS-Uif-InquiryView\"");
097        out.incrementIndent();
098        out.indentPrintln("p:title=\"" + xmlType.getName() + " Inquiry\"");
099        out.indentPrintln("p:dataObjectClassName=\"" + xmlType.getJavaPackage() + "." + infoClass + "\"");
100        out.indentPrintln("p:viewHelperServiceClass=\"" + inquirable + "\">");
101        out.indentPrintln("");
102        out.indentPrintln("<property name=\"Items\">");
103        out.indentPrintln("    <list>");
104        out.indentPrintln("        <bean parent=\"Uif-Disclosure-GridSection\">");
105        out.indentPrintln("            <property name=\"layoutManager.numberOfColumns\" value=\"2\"/>");
106        out.indentPrintln("            <property name=\"headerText\" value=\"" + xmlType.getName() + " Inquiry\"/>");
107        out.indentPrintln("            <property name=\"items\">");
108        out.indentPrintln("                <list>");
109        this.writeFields(xmlType, new Stack<XmlType>(), "");
110        out.indentPrintln("                </list>");
111        out.indentPrintln("            </property>");
112        out.indentPrintln("        </bean>");
113        out.indentPrintln("    </list>");
114        out.indentPrintln("</property>");
115        out.decrementIndent();
116        out.indentPrintln("</bean>");
117        out.indentPrintln("");
118        out.decrementIndent();
119        out.indentPrintln("</beans>");
120
121    }
122
123    private void writeFields(XmlType type, Stack<XmlType> parents, String prefix) {
124        // avoid recursion
125        if (parents.contains(type)) {
126            return;
127        }
128        parents.push(type);
129        for (MessageStructure ms : finder.findMessageStructures(type.getName())) {
130            String fieldName = GetterSetterNameCalculator.calcInitLower(ms.getShortName());
131            if (!prefix.isEmpty()) {
132                fieldName = prefix + "." + fieldName;
133            }
134            if (ms.getType().equalsIgnoreCase("AttributeInfoList")) {
135                out.indentPrintln("                    <!-- TODO: deal with dynamic attributes -->");
136                continue;
137            }
138            if (ms.getType().endsWith("List")) {
139                out.indentPrintln("                    <!-- TODO: deal with " + fieldName + " which is a list -->");
140                continue;
141            }
142            XmlType fieldType = finder.findXmlType(ms.getType());
143            if (fieldType.getPrimitive().equalsIgnoreCase(XmlType.COMPLEX)) {
144                // complex sub-types such as rich text 
145                this.writeFields(fieldType, parents, fieldName);
146                continue;
147            }
148            out.indentPrint("                    <bean parent=\"Uif-DataField\" p:propertyName=\"" + fieldName + "\"");
149            if (!shouldDoLookup (ms.getLookup())) {
150                out.println(" />");
151                continue;
152            }
153            // process lookup
154            out.println(">");
155            Lookup lookup = ms.getLookup();
156            XmlType msType = finder.findXmlType(lookup.getXmlTypeName());
157            MessageStructure pk = this.getPrimaryKey(ms.getLookup().getXmlTypeName());
158            out.indentPrintln("                        <property name=\"inquiry\">");
159            out.indentPrintln("                            <bean parent=\"Uif-Inquiry\" p:dataObjectClassName=\"" 
160                    + msType.getJavaPackage() + "." + msType.getName() 
161                    + "\" p:inquiryParameters=\"" + fieldName + ":" + pk.getShortName() + "\" />");
162            out.indentPrintln("                        </property>");
163            out.indentPrintln("                    </bean>");
164        }
165        parents.pop();
166    }
167
168        
169    public static boolean shouldDoLookup (Lookup lookup) {
170        if (lookup == null) {
171            return false;
172        }
173        
174        // can't do lookups on things we don't have inquirables on yet        
175//        if (lookup.getXmlTypeName().equals("OrgInfo")) {
176//            return true;
177//        }
178        if (lookup.getXmlTypeName().equals("Principal")) {
179            return false;
180        }
181        if (lookup.getXmlTypeName().equals("Agenda")) {
182            return false;
183        }
184        return true;
185    }
186    
187    private MessageStructure getPrimaryKey(String xmlTypeName) {
188        for (MessageStructure ms : finder.findMessageStructures(xmlTypeName)) {
189            if (ms.isPrimaryKey()) {
190                return ms;
191            }
192        }
193        throw new NullPointerException ("could not find primary key for " + xmlTypeName);
194    }
195    private void initXmlWriter() {
196        String infoClass = GetterSetterNameCalculator.calcInitUpper(xmlType.getName());
197        String serviceClass = GetterSetterNameCalculator.calcInitUpper(service.getName());
198        String serviceVar = GetterSetterNameCalculator.calcInitLower(service.getName());
199        String serviceContract = service.getImplProject() + "." + service.getName();
200
201        fullDirectoryPath = AdminUiInquirableWriter.calcPackage(servKey, rootPackage, xmlType).replace('.', '/');
202        fileName = infoClass + "AdminInquiryView.xml";
203
204        File dir = new File(this.directory);
205
206        if (!dir.exists()) {
207            if (!dir.mkdirs()) {
208                throw new IllegalStateException("Could not create directory "
209                        + this.directory);
210            }
211        }
212
213        String dirStr = this.directory + "/" + "resources" + "/" + fullDirectoryPath;
214        File dirFile = new File(dirStr);
215        if (!dirFile.exists()) {
216            if (!dirFile.mkdirs()) {
217                throw new IllegalStateException(
218                        "Could not create directory " + dirStr);
219            }
220        }
221        try {
222            PrintStream out = new PrintStream(new FileOutputStream(
223                    dirStr + "/" + fileName, false));
224            this.out = new XmlWriter(out, 0);
225        } catch (FileNotFoundException ex) {
226            throw new IllegalStateException(ex);
227        }
228    }
229
230    private void writeBoilerPlate() {
231        out.println("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
232        out.println("<beans xmlns=\"http://www.springframework.org/schema/beans\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"");
233        out.println("       xmlns:p=\"http://www.springframework.org/schema/p\"");
234        out.println("       xsi:schemaLocation=\"http://www.springframework.org/schema/beans");
235        out.println("                    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd\">");
236        out.println("    <!--");
237        out.println("     Copyright 2007-2012 The Kuali Foundation");
238        out.println("");
239        out.println("     Licensed under the Educational Community License, Version 2.0 (the \"License\");");
240        out.println("     you may not use this file except in compliance with the License.");
241        out.println("     You may obtain a copy of the License at");
242        out.println("");
243        out.println("     http://www.opensource.org/licenses/ecl2.php");
244        out.println("");
245        out.println("     Unless required by applicable law or agreed to in writing, software");
246        out.println("     distributed under the License is distributed on an \"AS IS\" BASIS,");
247        out.println("     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.");
248        out.println("     See the License for the specific language governing permissions and");
249        out.println("     limitations under the License.");
250        out.println("    -->");
251
252    }
253}