source: contrib/MailArchiver/sources/src/serpro/mailarchiver/service/web/DefaultListMessagesOperation.java @ 6785

Revision 6785, 32.2 KB checked in by rafaelraymundo, 12 years ago (diff)

Ticket #2946 - Liberado codigo do MailArchiver?. Documentação na subpasta DOCS.

Line 
1/**
2 * MailArchiver is an application that provides services for storing and managing e-mail messages through a Web Services SOAP interface.
3 * Copyright (C) 2012  Marcio Andre Scholl Levien and Fernando Alberto Reuter Wendt and Jose Ronaldo Nogueira Fonseca Junior
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU Affero General Public License as
7 * published by the Free Software Foundation, either version 3 of the
8 * License, or (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 * GNU Affero General Public License for more details.
14 *
15 * You should have received a copy of the GNU Affero General Public License
16 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
17 */
18
19/******************************************************************************\
20*
21*  This product was developed by
22*
23*        SERVIÇO FEDERAL DE PROCESSAMENTO DE DADOS (SERPRO),
24*
25*  a government company established under Brazilian law (5.615/70),
26*  at Department of Development of Porto Alegre.
27*
28\******************************************************************************/
29
30package serpro.mailarchiver.service.web;
31
32import java.io.IOException;
33import java.io.StringReader;
34import java.util.ArrayList;
35import java.util.Calendar;
36import java.util.Date;
37import java.util.GregorianCalendar;
38import java.util.HashSet;
39import java.util.List;
40import java.util.Map;
41import java.util.Map.Entry;
42import java.util.Set;
43import java.util.TreeMap;
44
45import javax.jdo.JDOObjectNotFoundException;
46import javax.jdo.Query;
47import javax.jdo.annotations.PersistenceAware;
48
49import javax.xml.stream.XMLInputFactory;
50import javax.xml.stream.XMLStreamException;
51
52import com.ctc.wstx.stax.WstxInputFactory;
53
54import org.codehaus.jettison.mapped.Configuration;
55import org.codehaus.jettison.mapped.MappedXMLInputFactory;
56
57import org.codehaus.staxmate.SMInputFactory;
58import org.codehaus.staxmate.in.SMEvent;
59import org.codehaus.staxmate.in.SMHierarchicCursor;
60import org.codehaus.staxmate.in.SMInputCursor;
61
62import org.datanucleus.query.typesafe.BooleanExpression;
63import org.datanucleus.query.typesafe.DateTimeExpression;
64import org.datanucleus.query.typesafe.NumericExpression;
65import org.datanucleus.query.typesafe.OrderExpression;
66import org.datanucleus.query.typesafe.StringExpression;
67import org.datanucleus.query.typesafe.TypesafeQuery;
68
69import org.springframework.beans.factory.annotation.Autowired;
70
71import serpro.mailarchiver.domain.metaarchive.Folder;
72import serpro.mailarchiver.domain.metaarchive.Message;
73import serpro.mailarchiver.domain.metaarchive.QDateTimeField;
74import serpro.mailarchiver.domain.metaarchive.QFolder;
75import serpro.mailarchiver.domain.metaarchive.QMailboxListField;
76import serpro.mailarchiver.domain.metaarchive.QMailboxListField_Mailbox;
77import serpro.mailarchiver.domain.metaarchive.QMessage;
78import serpro.mailarchiver.domain.metaarchive.QUnstructuredField;
79import serpro.mailarchiver.service.BaseService;
80import serpro.mailarchiver.service.dto.TMessage;
81import serpro.mailarchiver.service.find.FFolder;
82import serpro.mailarchiver.session.Session;
83import serpro.mailarchiver.util.Logger;
84import serpro.mailarchiver.util.jdo.PersistenceManager;
85import serpro.mailarchiver.util.transaction.WithReadOnlyTx;
86
87@PersistenceAware
88public class DefaultListMessagesOperation
89    extends BaseService
90    implements ListMessagesOperation
91{
92    private enum Order {
93        FromAsc, FromDesc,
94        SubjectAsc, SubjectDesc,
95        DateAsc, DateDesc,
96        SizeAsc, SizeDesc
97    }
98
99    private static final Logger log = Logger.getLocalLogger();
100    private static final boolean _DEBUG_ = true;
101
102    @Autowired
103    private FFolder findFolder;
104
105    @WithReadOnlyTx
106    @Override
107    public TMessage[] apply(String queryConfig) throws ServiceFault {
108
109        /*
110         * queryConfig:
111         *
112         *  <query
113         *      body="term"
114         *      subject="term"
115         *      from="term"
116         *      to="term" toOrCc="term" toOrCcOrBcc="term"
117         *      cc="term" ccOrBcc="term"
118         *      bcc="term"
119         *      lowerDate="time" upperDate="time"
120         *      date="time"
121         *      lowerIndex="idx" upperIndex="idx">
122         *
123         *      <folder id="id"/>
124         *      <folder id="id" recursive="true|false"/>
125         *
126         *      <tags contains="tag"/>
127         *      <tags notContains="tag"/>
128         *
129         *      <order date="asc|desc"/>
130         *      <order from="asc|desc"/>
131         *      <order subject="asc|desc"/>
132         *      <order size="asc|desc"/>
133         *  </query>
134         */
135
136        PersistenceManager pm = getPersistenceManager();
137
138        if(queryConfig.isEmpty()) {
139            ServiceFault.invalidQueryConfig()
140                    .setActor("listMessages")
141                    .setMessage("Query config is null or empty.")
142                    .raise();
143        }
144
145        XMLInputFactory inf = null;
146        switch(queryConfig.charAt(0)) {
147            case '<':
148                inf = new WstxInputFactory();
149                break;
150
151            case '{':
152                Configuration config = new Configuration();
153                config.setIgnoreNamespaces(true);
154                inf = new MappedXMLInputFactory(config);
155                break;
156
157            default:
158                ServiceFault.invalidQueryConfig()
159                        .setActor("listMessages")
160                        .setMessage("Invalid query config.")
161                        .raise();
162        }
163
164        String bodyCriteria = null;
165        String subjectCriteria = null;
166        String fromCriteria = null;
167        String toCriteria = null;
168        String toOrCcCriteria = null;
169        String toOrCcOrBccCriteria = null;
170        String ccCriteria = null;
171        String ccOrBccCriteria = null;
172        String bccCriteria = null;
173
174        String queryExpression = null;
175
176        TypesafeQuery<Message> tq = pm.newTypesafeQuery(Message.class);
177        QMessage cand = QMessage.candidate();
178
179        class NameGenerator {
180            private int variableCount = 0;
181            String var() {
182                return "v" + (++variableCount);
183            }
184            private int parameterCount = 0;
185            String par() {
186                return "p" + (++parameterCount);
187            }
188        }
189        NameGenerator next = new NameGenerator();
190
191        BooleanExpression folderCriteria = null;
192        BooleanExpression dateCriteria = null;
193        BooleanExpression tagCriteria = null;
194
195        BooleanExpression criteria = null;
196
197        Set<Folder> targetFolders = new HashSet<Folder>();
198
199        List<Order> ordering = new ArrayList<Order>();
200
201        long rangeStart = -1;
202        long rangeEnd = -1;
203
204        Map<String, String> params = new TreeMap<String, String>();
205
206        SMInputFactory sminf = new SMInputFactory(inf);
207        StringReader strReader = new StringReader(queryConfig);
208
209        try {
210            SMHierarchicCursor rootCursor = sminf.rootElementCursor(strReader);
211            rootCursor.advance();
212
213            String rootLocalName = rootCursor.getLocalName();
214
215            //------------------------------------------------------------------
216            if(rootLocalName.equalsIgnoreCase("query")) {
217
218                for(int i = 0; i < rootCursor.getAttrCount(); i++) {
219                    String attrLocalName = rootCursor.getAttrLocalName(i);
220
221                    if(attrLocalName.equalsIgnoreCase("body")) {
222                        String arg = rootCursor.getAttrValue(i);
223                        bodyCriteria = String.format("(body:(%s))", arg);
224                    }
225                    else if(attrLocalName.equalsIgnoreCase("subject")) {
226                        String arg = rootCursor.getAttrValue(i);
227                        subjectCriteria = String.format("(subject:(%s))", arg);
228                    }
229                    else if(attrLocalName.equalsIgnoreCase("from")) {
230                        String arg = rootCursor.getAttrValue(i);
231                        fromCriteria = String.format("(from:(%s) OR from_mbox:(%<s))", arg);
232                    }
233                    else if(attrLocalName.equalsIgnoreCase("to")) {
234                        String arg = rootCursor.getAttrValue(i);
235                        toCriteria = String.format("(to:(%s) OR to_mbox:(%<s))", arg);
236                    }
237                    else if(attrLocalName.equalsIgnoreCase("toOrCc")) {
238                        String arg = rootCursor.getAttrValue(i);
239                        toOrCcCriteria = String.format("(to:(%s) OR to_mbox:(%<s) OR cc:(%<s) OR cc_mbox:(%<s))", arg);
240                    }
241                    else if(attrLocalName.equalsIgnoreCase("toOrCcOrBcc")) {
242                        String arg = rootCursor.getAttrValue(i);
243                        toOrCcOrBccCriteria = String.format("(to:(%s) OR to_mbox:(%<s) OR cc:(%<s) OR cc_mbox:(%<s) OR bcc:(%<s) OR bcc_mbox:(%<s))", arg);
244                    }
245                    else if(attrLocalName.equalsIgnoreCase("cc")) {
246                        String arg = rootCursor.getAttrValue(i);
247                        ccCriteria = String.format("(cc:(%s) OR cc_mbox:(%<s))", arg);
248                    }
249                    else if(attrLocalName.equalsIgnoreCase("ccOrBcc")) {
250                        String arg = rootCursor.getAttrValue(i);
251                        ccOrBccCriteria = String.format("(cc:(%s) OR cc_mbox:(%<s) OR bcc:(%<s) OR bcc_mbox:(%<s))", arg);
252                    }
253                    else if(attrLocalName.equalsIgnoreCase("bcc")) {
254                        String arg = rootCursor.getAttrValue(i);
255                        bccCriteria = String.format("(bcc:(%s) OR bcc_mbox:(%<s))", arg);
256                    }
257                    else if(attrLocalName.equalsIgnoreCase("lowerDate")) {
258                        String arg = rootCursor.getAttrValue(i);
259
260                        String pName = next.par();
261                        DateTimeExpression<Date> p = tq.datetimeParameter(pName);
262
263                        String vName = next.var();
264                        QDateTimeField v = QDateTimeField.variable(vName);
265                        tq.addExtension("datanucleus.query.jdoql." + vName + ".join", "INNERJOIN");
266
267                        BooleanExpression expr = cand.fields.contains(v)
268                            .and(v.name.equalsIgnoreCase("date"))
269                            .and(v.date.gteq(p));
270
271                        tq.setParameter(pName, new Date(Long.parseLong(arg)));
272                        params.put(pName, arg);
273
274                        dateCriteria = (dateCriteria == null) ? (expr) : dateCriteria.and(expr);
275                    }
276                    else if(attrLocalName.equalsIgnoreCase("upperDate")) {
277                        String arg = rootCursor.getAttrValue(i);
278
279                        String pName = next.par();
280                        DateTimeExpression<Date> p = tq.datetimeParameter(pName);
281
282                        String vName = next.var();
283                        QDateTimeField v = QDateTimeField.variable(vName);
284                        tq.addExtension("datanucleus.query.jdoql." + vName + ".join", "INNERJOIN");
285
286                        BooleanExpression expr = cand.fields.contains(v)
287                            .and(v.name.equalsIgnoreCase("date"))
288                            .and(v.date.lteq(p));
289
290                        tq.setParameter(pName, new Date(Long.parseLong(arg)));
291                        params.put(pName, arg);
292
293                        dateCriteria = (dateCriteria == null) ? (expr) : dateCriteria.and(expr);
294                    }
295                    else if(attrLocalName.equalsIgnoreCase("date")) {
296                        String arg = rootCursor.getAttrValue(i);
297
298                        String pName = next.par();
299                        DateTimeExpression<Date> p = tq.datetimeParameter(pName);
300
301                        String qName = next.par();
302                        DateTimeExpression<Date> q = tq.datetimeParameter(qName);
303
304                        String vName = next.var();
305                        QDateTimeField v = QDateTimeField.variable(vName);
306                        tq.addExtension("datanucleus.query.jdoql." + vName + ".join", "INNERJOIN");
307
308                        BooleanExpression expr = cand.fields.contains(v)
309                            .and(v.name.equalsIgnoreCase("date"))
310                            .and(v.date.gteq(p))
311                            .and(v.date.lteq(q));
312
313                        Calendar calendar = new GregorianCalendar();
314                        calendar.setTimeInMillis(Long.parseLong(arg));
315                        calendar.set(Calendar.HOUR_OF_DAY, 0);
316                        calendar.set(Calendar.MINUTE, 0);
317                        calendar.set(Calendar.SECOND, 0);
318                        calendar.set(Calendar.MILLISECOND, 0);
319
320                        long lower = calendar.getTimeInMillis();
321                        tq.setParameter(pName, new Date(lower));
322                        params.put(pName, String.valueOf(lower));
323
324                        calendar.add(Calendar.DAY_OF_MONTH, 1);
325
326                        long upper = calendar.getTimeInMillis();
327                        tq.setParameter(qName, new Date(upper));
328                        params.put(qName, String.valueOf(upper));
329
330                        dateCriteria = (dateCriteria == null) ? (expr) : dateCriteria.and(expr);
331                    }
332                    else if(attrLocalName.equalsIgnoreCase("lowerIndex")) {
333                        String arg = rootCursor.getAttrValue(i);
334                        rangeStart = Long.parseLong(arg);
335                    }
336                    else if(attrLocalName.equalsIgnoreCase("upperIndex")) {
337                        String arg = rootCursor.getAttrValue(i);
338                        rangeEnd = Long.parseLong(arg);
339                    }
340                    else {
341                        //ignore ?
342                    }
343                }
344
345                SMInputCursor childCursor = rootCursor.childElementCursor();
346                SMEvent nextChild;
347
348                while((nextChild = childCursor.getNext()) != null) {
349
350                    String childLocalName = childCursor.getLocalName();
351
352                    //----------------------------------------------------------
353                    if(childLocalName.equalsIgnoreCase("folder")) {
354                        String folderId = "";
355                        boolean recursive = false;
356
357                        for(int i = 0; i < childCursor.getAttrCount(); i++) {
358                            String attrLocalName = childCursor.getAttrLocalName(i);
359
360                            if(attrLocalName.equalsIgnoreCase("id")) {
361                                folderId = childCursor.getAttrValue(i);
362                            }
363                            else if(attrLocalName.equalsIgnoreCase("recursive")) {
364                                recursive = childCursor.getAttrBooleanValue(i);
365                            }
366                            else {
367                                //ignore ?
368                            }
369                        }
370
371                        if(folderId.isEmpty()) {
372                            ServiceFault.invalidFolderId()
373                                    .setActor("listMessages")
374                                    .setMessage("Folder id is empty.")
375                                    .raise();
376                        }
377
378                        Folder folder = findFolder.byId(folderId);
379
380                        if(folder == null) {
381                            ServiceFault.folderNotFound()
382                                    .setActor("listMessages")
383                                    .setMessage("Folder not found.")
384                                    .addValue("folderId", folderId)
385                                    .raise();
386                        }
387
388                        if(recursive) {
389                            targetFolders.addAll(listFolders(folder));
390                        }
391                        else {
392                            targetFolders.add(folder);
393                        }
394                    }
395
396                    //----------------------------------------------------------
397                    else if(childLocalName.equalsIgnoreCase("tags")) {
398
399                        for(int i = 0; i < childCursor.getAttrCount(); i++) {
400                            String attrLocalName = childCursor.getAttrLocalName(i);
401
402                            if(attrLocalName.equalsIgnoreCase("contains")) {
403                                String arg = childCursor.getAttrValue(i);
404
405                                String pName = next.par();
406                                StringExpression p = tq.stringParameter(pName);
407
408                                BooleanExpression expr = cand.tags.contains(p);
409
410                                tq.setParameter(pName, arg.toLowerCase());
411                                params.put(pName, arg);
412
413                                tagCriteria = (tagCriteria == null) ? (expr) : tagCriteria.and(expr);
414                            }
415                            else if(attrLocalName.equalsIgnoreCase("notContains")) {
416                                String arg = childCursor.getAttrValue(i);
417
418                                String pName = next.par();
419                                StringExpression p = tq.stringParameter(pName);
420
421                                BooleanExpression expr = cand.tags.contains(p).not();
422
423                                tq.setParameter(pName, arg.toLowerCase());
424                                params.put(pName, arg);
425
426                                tagCriteria = (tagCriteria == null) ? (expr) : tagCriteria.and(expr);
427                            }
428                            else {
429                                //ignore ?
430                            }
431                        }
432                    }
433
434                    //----------------------------------------------------------
435                    else if(childLocalName.equalsIgnoreCase("order")) {
436
437                        for(int i = 0; i < childCursor.getAttrCount(); i++) {
438                            String attrLocalName = childCursor.getAttrLocalName(i);
439
440                            if(attrLocalName.equalsIgnoreCase("from")) {
441                                String arg = childCursor.getAttrValue(i);
442
443                                if(arg.equalsIgnoreCase("asc")) {
444                                    ordering.add(Order.FromAsc);
445                                }
446                                else if(arg.equalsIgnoreCase("desc")) {
447                                    ordering.add(Order.FromDesc);
448                                }
449                                else {
450                                    //ignore ?
451                                }
452                            }
453                            else if(attrLocalName.equalsIgnoreCase("subject")) {
454                                String arg = childCursor.getAttrValue(i);
455
456                                if(arg.equalsIgnoreCase("asc")) {
457                                    ordering.add(Order.SubjectAsc);
458                                }
459                                else if(arg.equalsIgnoreCase("desc")) {
460                                    ordering.add(Order.SubjectDesc);
461                                }
462                                else {
463                                    //ignore ?
464                                }
465                            }
466                            else if(attrLocalName.equalsIgnoreCase("date")) {
467                                String arg = childCursor.getAttrValue(i);
468
469                                if(arg.equalsIgnoreCase("asc")) {
470                                    ordering.add(Order.DateAsc);
471                                }
472                                else if(arg.equalsIgnoreCase("desc")) {
473                                    ordering.add(Order.DateDesc);
474                                }
475                                else {
476                                    //ignore ?
477                                }
478                            }
479                            else if(attrLocalName.equalsIgnoreCase("size")) {
480                                String arg = childCursor.getAttrValue(i);
481
482                                if(arg.equalsIgnoreCase("asc")) {
483                                    ordering.add(Order.SizeAsc);
484                                }
485                                else if(arg.equalsIgnoreCase("desc")) {
486                                    ordering.add(Order.SizeDesc);
487                                }
488                                else {
489                                    //ignore ?
490                                }
491                            }
492                            else {
493                                //ignore ?
494                            }
495                        }
496                    }
497                    //----------------------------------------------------------
498                    else {
499                        //ignore ?
500                    }
501                }
502            }
503            else {
504                //ignore ?
505            }
506        }
507        catch(XMLStreamException ex) {
508            ServiceFault.runtimeException()
509                    .setActor("listMessages")
510                    .setMessage("Query config parse exception.")
511                    .setCause(ex)
512                    .raise();
513        }
514
515
516        if(bodyCriteria != null) {
517            queryExpression = (queryExpression == null) ? bodyCriteria : queryExpression.concat(" AND ").concat(bodyCriteria);
518        }
519
520        if(subjectCriteria != null) {
521            queryExpression = (queryExpression == null) ? subjectCriteria : queryExpression.concat(" AND ").concat(subjectCriteria);
522        }
523
524        if(fromCriteria != null) {
525            queryExpression = (queryExpression == null) ? fromCriteria : queryExpression.concat(" AND ").concat(fromCriteria);
526        }
527
528        if(toCriteria != null) {
529            queryExpression = (queryExpression == null) ? toCriteria : queryExpression.concat(" AND ").concat(toCriteria);
530        }
531
532        if(toOrCcCriteria != null) {
533            queryExpression = (queryExpression == null) ? toOrCcCriteria : queryExpression.concat(" AND ").concat(toOrCcCriteria);
534        }
535
536        if(toOrCcOrBccCriteria != null) {
537            queryExpression = (queryExpression == null) ? toOrCcOrBccCriteria : queryExpression.concat(" AND ").concat(toOrCcOrBccCriteria);
538        }
539
540        if(ccCriteria != null) {
541            queryExpression = (queryExpression == null) ? ccCriteria : queryExpression.concat(" AND ").concat(ccCriteria);
542        }
543
544        if(ccOrBccCriteria != null) {
545            queryExpression = (queryExpression == null) ? ccOrBccCriteria : queryExpression.concat(" AND ").concat(ccOrBccCriteria);
546        }
547
548        if(bccCriteria != null) {
549            queryExpression = (queryExpression == null) ? bccCriteria : queryExpression.concat(" AND ").concat(bccCriteria);
550        }
551
552        Long queryCandidatesSet = null;
553
554        if(queryExpression != null) {
555
556            try {
557                for(String id : Session.getLuceneIndex().search(queryExpression)) {
558
559                    if(queryCandidatesSet == null) {
560                        Query q = pm.newQuery(javax.jdo.Query.SQL, "SELECT NEXTVAL('METAARCHIVE', 'QUERY_CANDIDATES_SET')");
561                        q.setUnique(true);
562                        q.setResultClass(Long.class);
563                        queryCandidatesSet = (Long) q.execute();
564                    }
565
566                    try {
567                        Message candidate = pm.getObjectById(Message.class, id);
568                        candidate.setQueryCandidatesSet(queryCandidatesSet);
569                    }
570                    catch(JDOObjectNotFoundException e) {
571                        log.warn(e, "message not found: %s", id);
572                    }
573                }
574            }
575            catch(IOException ex) {
576                ServiceFault.fileSystemFailure()
577                        .setActor("listMessages")
578                        .setMessage("Lucene search failure.")
579                        .setCause(ex)
580                        .raise();
581            }
582
583            if(queryCandidatesSet == null) {
584                return new TMessage[]{};
585            }
586        }
587
588        if(queryCandidatesSet != null) {
589
590            String pName = next.par();
591            NumericExpression<Long> p = tq.longParameter(pName);
592
593            criteria = cand.queryCandidatesSet.eq(p);
594
595            tq.setParameter(pName, queryCandidatesSet);
596            params.put(pName, queryCandidatesSet.toString());
597        }
598
599        if(targetFolders.isEmpty()) {
600
601            Folder homeFolder = findFolder.byId("home");
602
603            if(homeFolder == null) {
604                ServiceFault.folderNotFound()
605                        .setActor("listMessages")
606                        .setMessage("Home folder not found.")
607                        .raise();
608            }
609            targetFolders.addAll(listFolders(homeFolder));
610        }
611
612        {
613            String vName = next.var();
614            QFolder v = QFolder.variable(vName);
615            tq.addExtension("datanucleus.query.jdoql." + vName + ".join", "INNERJOIN");
616
617            BooleanExpression expr = null;
618
619            for(Folder folder : targetFolders) {
620
621                String pName = next.par();
622                StringExpression p = tq.stringParameter(pName);
623
624                expr = (expr == null) ? v.oid.eq(p) : expr.or(v.oid.eq(p));
625
626                tq.setParameter(pName, folder.getOid());
627                params.put(pName, folder.getOid());
628            }
629
630            folderCriteria = cand.folder.eq(v).and(expr);
631
632            criteria = (criteria == null) ? (folderCriteria) : criteria.and(folderCriteria);
633        }
634
635        if(dateCriteria != null) {
636            criteria = criteria.and(dateCriteria);
637        }
638
639        if(tagCriteria != null) {
640            criteria = criteria.and(tagCriteria);
641        }
642
643        List<OrderExpression> orderExpressions = new ArrayList<OrderExpression>();
644
645        for(Order order : ordering) {
646            switch(order) {
647                case FromAsc:
648                {
649                    String vName = next.var();
650                    QMailboxListField v = QMailboxListField.variable(vName);
651                    tq.addExtension("datanucleus.query.jdoql." + vName + ".join", "INNERJOIN");
652
653                    String wName = next.var();
654                    QMailboxListField_Mailbox w = QMailboxListField_Mailbox.variable(wName);
655                    tq.addExtension("datanucleus.query.jdoql." + wName + ".join", "INNERJOIN");
656
657                    BooleanExpression expr = cand.fields.contains(v)
658                        .and(v.name.equalsIgnoreCase("from"))
659                        .and(v.mailboxList.contains(w));
660
661                    criteria = criteria.and(expr);
662
663                    //orderExpressions.add(w.name.asc());
664                    orderExpressions.add(w.localPart.toUpperCase().asc());
665                    orderExpressions.add(w.domain.toUpperCase().asc());
666                }
667                    break;
668
669                case FromDesc:
670                {
671                    String vName = next.var();
672                    QMailboxListField v = QMailboxListField.variable(vName);
673                    tq.addExtension("datanucleus.query.jdoql." + vName + ".join", "INNERJOIN");
674
675                    String wName = next.var();
676                    QMailboxListField_Mailbox w = QMailboxListField_Mailbox.variable(wName);
677                    tq.addExtension("datanucleus.query.jdoql." + wName + ".join", "INNERJOIN");
678
679                    BooleanExpression expr = cand.fields.contains(v)
680                        .and(v.name.equalsIgnoreCase("from"))
681                        .and(v.mailboxList.contains(w));
682
683                    criteria = criteria.and(expr);
684
685                    //orderExpressions.add(w.name.desc());
686                    orderExpressions.add(w.localPart.toUpperCase().desc());
687                    orderExpressions.add(w.domain.toUpperCase().desc());
688                }
689                    break;
690
691                case SubjectAsc:
692                {
693                    String vName = next.var();
694                    QUnstructuredField v = QUnstructuredField.variable(vName);
695                    tq.addExtension("datanucleus.query.jdoql." + vName + ".join", "INNERJOIN");
696
697                    BooleanExpression expr = cand.fields.contains(v)
698                        .and(v.name.equalsIgnoreCase("subject"));
699
700                    criteria = criteria.and(expr);
701
702                    orderExpressions.add(v.text.toUpperCase().asc());
703                }
704                    break;
705
706                case SubjectDesc:
707                {
708                    String vName = next.var();
709                    QUnstructuredField v = QUnstructuredField.variable(vName);
710                    tq.addExtension("datanucleus.query.jdoql." + vName + ".join", "INNERJOIN");
711
712                    BooleanExpression expr = cand.fields.contains(v)
713                        .and(v.name.equalsIgnoreCase("subject"));
714
715                    criteria = criteria.and(expr);
716
717                    orderExpressions.add(v.text.toUpperCase().desc());
718                }
719                    break;
720
721                case DateAsc:
722                {
723                    String vName = next.var();
724                    QDateTimeField v = QDateTimeField.variable(vName);
725                    tq.addExtension("datanucleus.query.jdoql." + vName + ".join", "INNERJOIN");
726
727                    BooleanExpression expr = cand.fields.contains(v)
728                        .and(v.name.equalsIgnoreCase("date"));
729
730                    criteria = criteria.and(expr);
731
732                    orderExpressions.add(v.date.asc());
733                }
734                    break;
735
736                case DateDesc:
737                {
738                    String vName = next.var();
739                    QDateTimeField v = QDateTimeField.variable(vName);
740                    tq.addExtension("datanucleus.query.jdoql." + vName + ".join", "INNERJOIN");
741
742                    BooleanExpression expr = cand.fields.contains(v)
743                        .and(v.name.equalsIgnoreCase("date"));
744
745                    criteria = criteria.and(expr);
746
747                    orderExpressions.add(v.date.desc());
748                }
749                    break;
750
751                case SizeAsc:
752                {
753                    orderExpressions.add(cand.size.asc());
754                }
755                    break;
756
757                case SizeDesc:
758                {
759                    orderExpressions.add(cand.size.desc());
760                }
761                    break;
762
763                default:
764                {
765                }
766            }
767        }
768
769        tq.filter(criteria);
770
771        if(orderExpressions.size() > 0) {
772            tq.orderBy(orderExpressions.toArray(new OrderExpression[orderExpressions.size()]));
773        }
774
775        if((rangeStart >= 0) && (rangeEnd >= 0) && (rangeStart <= rangeEnd)) {
776            tq.range(rangeStart, rangeEnd);
777        }
778
779        tq.addExtension("datanucleus.sqlTableNamingStrategy", "t-scheme");
780
781        if(_DEBUG_) {
782            try {
783                System.out.println("Lucene Query Expression:\n" + queryExpression);
784
785                String ssq = tq.toString();
786                System.out.println("JDOQL Single-String Query:\n" + ssq);
787
788                StringBuilder sb = new StringBuilder();
789                sb.append("JDOQL Query Parameters:\n");
790                for(Entry<String, String> param : params.entrySet()) {
791                    sb.append("\t").append(param.getKey()).append("=").append(param.getValue()).append("\n");
792                }
793                System.out.println(sb.toString());
794            }
795            catch(UnsupportedOperationException ex) {
796                //Dont currently support operator NOT in JDOQL conversion
797            }
798        }
799
800        List<Message> results = tq.executeList();
801
802        int size = results.size();
803
804        TMessage[] messageDtoArray = new TMessage[size];
805
806        for(int i = 0; i < size; i++) {
807            messageDtoArray[i] = new TMessage(results.get(i));
808        }
809
810        return messageDtoArray;
811    }
812
813    private List<Folder> listFolders(Folder folder) {
814        List<Folder> list = new ArrayList<Folder>();
815        listFolders(folder, list);
816        return list;
817    }
818
819    private void listFolders(Folder folder, List<Folder> list) {
820        list.add(folder);
821        for(Folder child : folder.getChildren()) {
822            listFolders(child, list);
823        }
824    }
825}
Note: See TracBrowser for help on using the repository browser.