001    /*
002     * Copyright 2009 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.osedu.org/licenses/ECL-2.0
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     */
016    package org.kuali.student.contract.writer.search;
017    
018    import org.kuali.student.contract.model.SearchCriteria;
019    import org.kuali.student.contract.model.SearchCriteriaParameter;
020    import org.kuali.student.contract.model.SearchImplementation;
021    import org.kuali.student.contract.model.SearchModel;
022    import org.kuali.student.contract.model.SearchResult;
023    import org.kuali.student.contract.model.SearchResultColumn;
024    import org.kuali.student.contract.model.SearchType;
025    import org.kuali.student.contract.model.validation.DictionaryValidationException;
026    import org.kuali.student.contract.model.validation.SearchModelValidator;
027    import org.kuali.student.contract.writer.XmlWriter;
028    import java.io.PrintStream;
029    import java.util.ArrayList;
030    import java.util.Collection;
031    import java.util.Date;
032    import java.util.HashSet;
033    import java.util.List;
034    import java.util.Set;
035    
036    /**
037     * This writes out the entire search xml file
038     * @author nwright
039     */
040    public 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    }