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.contract.writer.search;
017
018import org.kuali.student.contract.model.SearchCriteria;
019import org.kuali.student.contract.model.SearchCriteriaParameter;
020import org.kuali.student.contract.model.SearchImplementation;
021import org.kuali.student.contract.model.SearchModel;
022import org.kuali.student.contract.model.SearchResult;
023import org.kuali.student.contract.model.SearchResultColumn;
024import org.kuali.student.contract.model.SearchType;
025import org.kuali.student.contract.model.validation.DictionaryValidationException;
026import org.kuali.student.contract.model.validation.SearchModelValidator;
027import org.kuali.student.contract.writer.XmlWriter;
028import java.io.PrintStream;
029import java.util.ArrayList;
030import java.util.Collection;
031import java.util.Date;
032import java.util.HashSet;
033import java.util.List;
034import java.util.Set;
035
036/**
037 * This writes out the entire search xml file
038 * @author nwright
039 */
040public class SearchModelWriter {
041
042    private SearchModel model;
043    private XmlWriter writer;
044
045    public SearchModelWriter(PrintStream out, SearchModel model) {
046        this.writer = new XmlWriter(out, 0);
047        this.model = model;
048    }
049
050    /**
051     * Write out the entire file
052     * @param out
053     */
054    public void write() {
055        Collection<String> errors = new SearchModelValidator(model).validate();
056        if (errors.size() > 0) {
057            StringBuffer buf = new StringBuffer();
058            buf.append(errors.size()
059                    + " errors found while validating the spreadsheet.");
060            int cnt = 0;
061            for (String msg : errors) {
062                cnt++;
063                buf.append("\n");
064                buf.append("*error*" + cnt + ":" + msg);
065            }
066            throw new DictionaryValidationException(buf.toString());
067        }
068        writeHeader();
069        writeSearchTypes();
070        writeSearchCriteria();
071        writeSearchCriteriaParameters();
072        writeSearchResultTypes();
073        writeSearchResultColumns();
074        writeSqlQueryMap();
075        writeFooter();
076    }
077
078    private void indentPrint(String str) {
079        writer.indentPrintln(str);
080    }
081
082    private void indentPrintln(String str) {
083        writer.indentPrintln(str);
084    }
085
086    private void println(String str) {
087        writer.indentPrintln(str);
088    }
089
090    private void writeComment(String str) {
091        writer.writeComment(str);
092    }
093
094    private void incrementIndent() {
095        writer.incrementIndent();
096    }
097
098    private void decrementIndent() {
099        writer.decrementIndent();
100    }
101
102    private void writeTag(String tag, String value) {
103        writer.writeTag(tag, value);
104    }
105
106    private void writeAttribute(String attribute, String value) {
107        writer.writeAttribute(attribute, value);
108    }
109
110    /**
111     * write out the header
112     * @param out
113     */
114    protected void writeHeader() {
115        indentPrintln("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
116        indentPrintln("<beans xmlns=\"http://www.springframework.org/schema/beans\"");
117        indentPrintln("xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"");
118        indentPrintln("xmlns:search=\"http://student.kuali.org/xsd/search-extension\"");
119        indentPrintln("xmlns:dict=\"http://student.kuali.org/xsd/dictionary-extension\"");
120        indentPrintln("xsi:schemaLocation=\"");
121        indentPrintln("http://student.kuali.org/xsd/search-extension http://student.kuali.org/xsd/search-extension/search-extension.xsd");
122        indentPrintln("http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd");
123        indentPrintln("\">");
124        StringBuffer buf = new StringBuffer();
125        buf.append("*** Automatically Generated ***");
126        buf.append("\n");
127        buf.append("on: " + (new Date()));
128        buf.append("\n");
129        buf.append("by: " + this.getClass().getName());
130        buf.append("\n");
131        buf.append("using: ");
132        String comma = "";
133        for (String soureName : model.getSourceNames()) {
134            buf.append(soureName);
135            buf.append(comma);
136            comma = ", ";
137        }
138        buf.append("\n");
139        writeComment(buf.toString());
140    }
141
142    protected void writeFooter() {
143        indentPrintln("</beans>");
144    }
145
146    /**
147     * write out the the base fields
148     * @param out
149     */
150    protected void writeSearchTypes() {
151        println("");
152        writeComment("Search Types");
153        for (SearchType st : model.getSearchTypes()) {
154            new SearchTypeWriter(writer.getOut(), writer.getIndent() + 1, st).write();
155        }
156    }
157
158    /**
159     * write out the the object structure
160     * @param out
161     */
162    protected void writeSearchResultTypes() {
163        println("");
164        writeComment("Search Results");
165        for (SearchResult sr : getSearchResults()) {
166            new SearchResultWriter(writer.getOut(), writer.getIndent() + 1, sr).write();
167        }
168
169    }
170
171    private List<SearchResult> getSearchResults() {
172        List<SearchResult> list = new ArrayList();
173        Set<String> keys = new HashSet();
174        for (SearchType st : model.getSearchTypes()) {
175            if (keys.add(st.getSearchResult().getKey())) {
176                list.add(st.getSearchResult());
177            }
178        }
179        return list;
180    }
181
182    /**
183     * write out the the object structure
184     * @param out
185     */
186    protected void writeSearchResultColumns() {
187        println("");
188        writeComment("Search Result Columns");
189        for (SearchResultColumn col : getSearchResultColumns()) {
190            new SearchResultColumnWriter(writer.getOut(), writer.getIndent() + 1, col).write();
191        }
192    }
193
194    private List<SearchResultColumn> getSearchResultColumns() {
195        List<SearchResultColumn> list = new ArrayList();
196        Set<String> keys = new HashSet();
197        for (SearchResult searchResult : getSearchResults()) {
198            for (SearchResultColumn col : searchResult.getResultColumns()) {
199                if (keys.add(col.getKey())) {
200                    list.add(col);
201                }
202
203            }
204        }
205        return list;
206    }
207
208    /**
209     * write out the the object structure
210     * @param out
211     */
212    protected void writeSearchCriteria() {
213        println("");
214        writeComment("Search Criteria");
215        for (SearchCriteria sr : getSearchCriteria()) {
216            new SearchCriteriaWriter(writer.getOut(), writer.getIndent() + 1, sr).write();
217        }
218    }
219
220    private List<SearchCriteria> getSearchCriteria() {
221        List<SearchCriteria> list = new ArrayList();
222        Set<String> keys = new HashSet();
223        for (SearchType st : model.getSearchTypes()) {
224            if (keys.add(st.getSearchCriteria().getKey())) {
225                list.add(st.getSearchCriteria());
226            }
227        }
228        return list;
229    }
230
231    /**
232     * write out the the object structure
233     * @param out
234     */
235    protected void writeSearchCriteriaParameters() {
236        println("");
237        writeComment("Search Criteria Parameters");
238        for (SearchCriteriaParameter col : getSearchCriteriaParameters()) {
239            new SearchCriteriaParameterWriter(writer.getOut(), writer.getIndent() + 1, col).write();
240        }
241    }
242
243    private List<SearchCriteriaParameter> getSearchCriteriaParameters() {
244        List<SearchCriteriaParameter> list = new ArrayList();
245        Set<String> keys = new HashSet();
246        for (SearchCriteria criteria : getSearchCriteria()) {
247            for (SearchCriteriaParameter parm : criteria.getParameters()) {
248                if (keys.add(parm.getKey())) {
249                    list.add(parm);
250                }
251
252            }
253        }
254        return list;
255    }
256
257    /**
258     * write out the the object structure
259     * @param out
260     */
261    protected void writeSqlQueryMap() {
262        println("");
263        incrementIndent();
264        writeComment("Query Map");
265        indentPrintln("<bean id=\"queryMap\" class=\"org.springframework.beans.factory.config.MapFactoryBean\">");
266        indentPrintln("<property name=\"sourceMap\">");
267        indentPrintln("<map>");
268        incrementIndent();
269        for (SearchImplementation impl : getJPQLImplementations()) {
270            println("");
271            indentPrint("<entry");
272            writeAttribute("key", impl.getKey());
273            indentPrintln(">");
274            writeComment(impl.getComments());
275            incrementIndent();
276            writeTag("value", "\n" + impl.getDescription() + "\n");
277            decrementIndent();
278            indentPrintln("</entry>");
279        }
280        decrementIndent();
281        indentPrintln("</map>");
282        indentPrintln("</property>");
283        indentPrintln("</bean>");
284        decrementIndent();
285    }
286
287    private List<SearchImplementation> getImplementations() {
288        List<SearchImplementation> list = new ArrayList();
289        Set<String> keys = new HashSet();
290        for (SearchType st : model.getSearchTypes()) {
291            if (keys.add(st.getImplementation().getKey())) {
292                list.add(st.getImplementation());
293            }
294        }
295        return list;
296    }
297
298    private List<SearchImplementation> getJPQLImplementations() {
299        List<SearchImplementation> list = new ArrayList();
300        Set<String> keys = new HashSet();
301        for (SearchImplementation impl : getImplementations()) {
302            if (impl.getType().equals("JPQL")) {
303                list.add(impl);
304            }
305        }
306        return list;
307    }
308}