001/**
002 *
003 * Copyright (c) 2014, the Railo Company Ltd. All rights reserved.
004 *
005 * This library is free software; you can redistribute it and/or
006 * modify it under the terms of the GNU Lesser General Public
007 * License as published by the Free Software Foundation; either 
008 * version 2.1 of the License, or (at your option) any later version.
009 * 
010 * This library is distributed in the hope that it will be useful,
011 * but WITHOUT ANY WARRANTY; without even the implied warranty of
012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
013 * Lesser General Public License for more details.
014 * 
015 * You should have received a copy of the GNU Lesser General Public 
016 * License along with this library.  If not, see <http://www.gnu.org/licenses/>.
017 * 
018 **/
019package lucee.runtime.text.feed;
020
021import java.util.Iterator;
022import java.util.Map.Entry;
023
024import lucee.commons.lang.StringUtil;
025import lucee.runtime.exp.DatabaseException;
026import lucee.runtime.op.Caster;
027import lucee.runtime.type.Array;
028import lucee.runtime.type.CastableArray;
029import lucee.runtime.type.Collection;
030import lucee.runtime.type.Collection.Key;
031import lucee.runtime.type.KeyImpl;
032import lucee.runtime.type.Query;
033import lucee.runtime.type.QueryImpl;
034import lucee.runtime.type.Struct;
035import lucee.runtime.type.StructImpl;
036import lucee.runtime.type.util.KeyConstants;
037
038public class FeedQuery {
039
040        public static final Collection.Key VERSION = KeyImpl.intern("VERSION");
041        public static final Collection.Key ITEM = KeyImpl.intern("ITEM");
042        public static final Collection.Key ENTRY = KeyImpl.intern("ENTRY");
043        
044        public static final Collection.Key AUTHOREMAIL = KeyImpl.intern("AUTHOREMAIL");
045        public static final Collection.Key AUTHORNAME = KeyImpl.intern("AUTHORNAME");
046        public static final Collection.Key AUTHORURI = KeyImpl.intern("AUTHORURI");
047        public static final Collection.Key AUTHOR = KeyImpl.intern("AUTHOR");
048        public static final Collection.Key CATEGORYLABEL = KeyImpl.intern("CATEGORYLABEL");
049        public static final Collection.Key CATEGORYSCHEME = KeyImpl.intern("CATEGORYSCHEME");
050        public static final Collection.Key CATEGORYTERM = KeyImpl.intern("CATEGORYTERM");
051        public static final Collection.Key CATEGORY = KeyImpl.intern("CATEGORY");
052        public static final Collection.Key COMMENTS = KeyImpl.intern("COMMENTS");
053        public static final Collection.Key CONTENT = KeyImpl.intern("CONTENT");
054        public static final Collection.Key CONTENTMODE = KeyImpl.intern("CONTENTMODE");
055        public static final Collection.Key CONTENTSRC = KeyImpl.intern("CONTENTSRC");
056        public static final Collection.Key CONTENTTYPE = KeyImpl.intern("CONTENTTYPE");
057        public static final Collection.Key CONTRIBUTOREMAIL = KeyImpl.intern("CONTRIBUTOREMAIL");
058        public static final Collection.Key CONTRIBUTORNAME = KeyImpl.intern("CONTRIBUTORNAME");
059        public static final Collection.Key CONTRIBUTORURI = KeyImpl.intern("CONTRIBUTORURI");
060        public static final Collection.Key CONTRIBUTOR = KeyImpl.intern("CONTRIBUTOR");
061        public static final Collection.Key CREATEDDATE = KeyImpl.intern("CREATEDDATE");
062        public static final Collection.Key CREATED = KeyImpl.intern("CREATED");
063        public static final Collection.Key EXPIRATIONDATE = KeyImpl.intern("EXPIRATIONDATE");
064        public static final Collection.Key ID = KeyImpl.intern("ID");
065        public static final Collection.Key IDPERMALINK = KeyImpl.intern("IDPERMALINK");
066        public static final Collection.Key LINKHREF = KeyImpl.intern("LINKHREF");
067        public static final Collection.Key LINKHREFLANG = KeyImpl.intern("LINKHREFLANG");
068        public static final Collection.Key LINKLENGTH = KeyImpl.intern("LINKLENGTH");
069        public static final Collection.Key LINKREL = KeyImpl.intern("LINKREL");
070        public static final Collection.Key LINKTITLE = KeyImpl.intern("LINKTITLE");
071        public static final Collection.Key LINKTYPE = KeyImpl.intern("LINKTYPE");
072        public static final Collection.Key PUBLISHEDDATE = KeyImpl.intern("PUBLISHEDDATE");
073        public static final Collection.Key PUBLISHED = KeyImpl.intern("PUBLISHED");
074        public static final Collection.Key PUBDATE = KeyImpl.intern("pubDate");
075        public static final Collection.Key RDF_ABOUT = KeyImpl.intern("rdf:about");
076        
077        public static final Collection.Key RIGHTS = KeyImpl.intern("RIGHTS");
078        public static final Collection.Key RSSLINK = KeyImpl.intern("RSSLINK");
079        public static final Collection.Key SOURCE = KeyImpl.intern("SOURCE");
080        public static final Collection.Key SOURCEURL = KeyImpl.intern("SOURCEURL");
081        public static final Collection.Key SUMMARY = KeyImpl.intern("SUMMARY");
082        public static final Collection.Key SUMMARYMODE = KeyImpl.intern("SUMMARYMODE");
083        public static final Collection.Key SUMMARYSRC = KeyImpl.intern("SUMMARYSRC");
084        public static final Collection.Key SUMMARYTYPE = KeyImpl.intern("SUMMARYTYPE");
085        public static final Collection.Key TITLE = KeyImpl.intern("TITLE");
086        public static final Collection.Key TITLETYPE = KeyImpl.intern("TITLETYPE");
087        public static final Collection.Key UPDATEDDATE = KeyImpl.intern("UPDATEDDATE");
088        public static final Collection.Key URI = KeyImpl.intern("URI");
089        public static final Collection.Key XMLBASE = KeyImpl.intern("XMLBASE");
090        public static final Collection.Key GUID = KeyImpl.intern("guid");
091        public static final Collection.Key ENCLOSURE = KeyImpl.intern("enclosure");
092        public static final Collection.Key LINK = KeyImpl.intern("link");
093        public static final Collection.Key MODE = KeyImpl.intern("mode");
094        public static final Collection.Key TEXT = KeyImpl.intern("text");
095        public static final Collection.Key DOMAIN = KeyImpl.intern("domain");
096        public static final Collection.Key ISSUED = KeyImpl.intern("issued");
097        public static final Collection.Key COPYRIGHT = KeyImpl.intern("copyright");
098        public static final Collection.Key SRC = KeyImpl.intern("src");
099        public static final Collection.Key UPDATED = KeyImpl.intern("updated");
100        public static final Collection.Key MODIFIED = KeyImpl.intern("modified");
101        public static final Collection.Key URL = KeyImpl.intern("url");
102        public static final Collection.Key LENGTH = KeyImpl.intern("length");
103        public static final Collection.Key ISPERMALINK = KeyImpl.intern("isPermaLink");
104
105        public static final Collection.Key DC_CONTRIBUTOR = KeyImpl.intern("DC_CONTRIBUTOR");
106        public static final Collection.Key DC_COVERAGE = KeyImpl.intern("DC_COVERAGE");
107        public static final Collection.Key DC_CREATOR = KeyImpl.intern("DC_CREATOR");
108        public static final Collection.Key DC_DATE = KeyImpl.intern("DC_DATE");
109        public static final Collection.Key DC_DESCRIPTION = KeyImpl.intern("DC_DESCRIPTION");
110        public static final Collection.Key DC_FORMAT = KeyImpl.intern("DC_FORMAT");
111        public static final Collection.Key DC_IDENTIFIER = KeyImpl.intern("DC_IDENTIFIER");
112        public static final Collection.Key DC_LANGUAGE = KeyImpl.intern("DC_LANGUAGE");
113        public static final Collection.Key DC_PUBLISHER = KeyImpl.intern("DC_PUBLISHER");
114        public static final Collection.Key DC_RELATION = KeyImpl.intern("DC_RELATION");
115        public static final Collection.Key DC_RIGHT = KeyImpl.intern("DC_RIGHTS");
116        public static final Collection.Key DC_SOURCE = KeyImpl.intern("DC_SOURCE");
117        public static final Collection.Key DC_TITLE = KeyImpl.intern("DC_TITLE");
118        public static final Collection.Key DC_TYPE = KeyImpl.intern("DC_TYPE");
119        
120        public static final Collection.Key DC_SUBJECT_TAXONOMYURI = KeyImpl.intern("DC_SUBJECT_TAXONOMYURI");
121        public static final Collection.Key DC_SUBJECT_VALUE = KeyImpl.intern("DC_SUBJECT_VALUE");
122        public static final Collection.Key DC_SUBJECT = KeyImpl.intern("DC_SUBJECT");
123        
124                                
125        
126        
127        
128        private static Collection.Key[] COLUMNS=new Collection.Key[]{
129                AUTHOREMAIL,
130                AUTHORNAME,
131                AUTHORURI,
132                CATEGORYLABEL,
133                CATEGORYSCHEME,
134                CATEGORYTERM,
135                COMMENTS,
136                CONTENT,
137                CONTENTMODE,
138                CONTENTSRC,
139                CONTENTTYPE,
140                CONTRIBUTOREMAIL,
141                CONTRIBUTORNAME,
142                CONTRIBUTORURI,
143                CREATEDDATE,
144                EXPIRATIONDATE,
145                ID,
146                IDPERMALINK,
147                LINKHREF,
148                LINKHREFLANG,
149                LINKLENGTH,
150                LINKREL,
151                LINKTITLE,
152                LINKTYPE,
153                PUBLISHEDDATE,
154                RIGHTS,
155                RSSLINK,
156                SOURCE,
157                SOURCEURL,
158                SUMMARY,
159                SUMMARYMODE,
160                SUMMARYSRC,
161                SUMMARYTYPE,
162                TITLE,
163                TITLETYPE,
164                UPDATEDDATE,
165                URI,
166                XMLBASE
167        };
168        
169
170        private static Collection.Key[] COLUMNS_WITH_DC=new Collection.Key[]{
171                AUTHOREMAIL,
172                AUTHORNAME,
173                AUTHORURI,
174                CATEGORYLABEL,
175                CATEGORYSCHEME,
176                CATEGORYTERM,
177                COMMENTS,
178                CONTENT,
179                CONTENTMODE,
180                CONTENTSRC,
181                CONTENTTYPE,
182                CONTRIBUTOREMAIL,
183                CONTRIBUTORNAME,
184                CONTRIBUTORURI,
185                CREATEDDATE,
186                
187                DC_CONTRIBUTOR,
188                DC_COVERAGE,
189                DC_CREATOR,
190                DC_DATE,
191                DC_DESCRIPTION,
192                DC_FORMAT,
193                DC_IDENTIFIER,
194                DC_LANGUAGE,
195                DC_PUBLISHER,
196                DC_RELATION,
197                DC_RIGHT,
198                DC_SOURCE,
199                DC_TITLE,
200                DC_TYPE,
201                DC_SUBJECT_TAXONOMYURI,
202                DC_SUBJECT_VALUE,
203                
204                EXPIRATIONDATE,
205                ID,
206                IDPERMALINK,
207                LINKHREF,
208                LINKHREFLANG,
209                LINKLENGTH,
210                LINKREL,
211                LINKTITLE,
212                LINKTYPE,
213                PUBLISHEDDATE,
214                RIGHTS,
215                RSSLINK,
216                SOURCE,
217                SOURCEURL,
218                SUMMARY,
219                SUMMARYMODE,
220                SUMMARYSRC,
221                SUMMARYTYPE,
222                TITLE,
223                TITLETYPE,
224                UPDATEDDATE,
225                URI,
226                XMLBASE
227        };
228        
229        
230        public static Query toQuery(Struct data,boolean hasDC) throws DatabaseException {
231                Query qry=new QueryImpl(hasDC?COLUMNS_WITH_DC:COLUMNS,0,"");
232                
233                String version=Caster.toString(data.get(VERSION,""),"");
234                Array items=null;
235                if(StringUtil.startsWithIgnoreCase(version,"rss") || StringUtil.startsWithIgnoreCase(version,"rdf"))    {
236                        items=Caster.toArray(data.get(ITEM, null),null);
237                        if(items==null) {
238                                Struct sct=Caster.toStruct(data.get(version,null),null,false);
239                                if(sct!=null){
240                                        items=Caster.toArray(sct.get(ITEM, null),null);
241                                }
242                        }
243                        return toQuery(true,qry,items);
244                }
245                else if(StringUtil.startsWithIgnoreCase(version,"atom"))        {
246                        items=Caster.toArray(data.get(ENTRY, null),null);
247                        return toQuery(false,qry,items);
248                }
249                return qry;
250        }
251
252        private static Query toQuery(boolean isRss,Query qry, Array items) {
253                if(items==null)return qry;
254                
255                int len=items.size();
256                Struct item;
257                int row=0;
258                Iterator<Entry<Key, Object>> it;
259                Entry<Key, Object> e;
260                for(int i=1;i<=len;i++) {
261                        item=Caster.toStruct(items.get(i, null),null,false);
262                        if(item==null) continue;
263                        qry.addRow();
264                        row++;
265                        it = item.entryIterator();
266                        while(it.hasNext()) {
267                                e = it.next();
268                                if(isRss)setQueryValueRSS(qry,e.getKey(),e.getValue(),row);
269                                else setQueryValueAtom(qry,e.getKey(),e.getValue(),row);
270                        }
271                        
272                }
273                
274                return qry;
275        }
276
277        private static void setQueryValueAtom(Query qry, Key key, Object value, int row) {
278                
279                if(key.equals(AUTHOR)) {
280                        Struct sct=toStruct(value);
281                        
282                        if(sct!=null){
283                                qry.setAtEL(AUTHOREMAIL, row, sct.get("email",null));
284                                qry.setAtEL(AUTHORNAME, row, sct.get("name",null));
285                                qry.setAtEL(AUTHORURI, row, sct.get("uri",null));
286                        }
287                }
288                if(key.equals(CATEGORY)) {
289                        Struct sct=toStruct(value);
290                        if(sct!=null){
291                                qry.setAtEL(CATEGORYLABEL, row, sct.get("label",null));
292                                qry.setAtEL(CATEGORYSCHEME, row, sct.get("scheme",null));
293                                qry.setAtEL(CATEGORYTERM, row, sct.get("term",null));
294                        }
295                        //else qry.setAtEL(CATEGORYLABEL, row, getValue(value));
296                }
297                else if(key.equals(COMMENTS)) {
298                        qry.setAtEL(COMMENTS, row, getValue(value));
299                }
300                else if(key.equals(CONTENT)) {
301                        Struct sct=toStruct(value);
302                        if(sct!=null){
303                                qry.setAtEL(CONTENT, row, getValue(sct));
304                                qry.setAtEL(CONTENTMODE, row, sct.get(MODE,null));
305                                qry.setAtEL(CONTENTSRC, row, sct.get(SRC,null));
306                                qry.setAtEL(CONTENTTYPE, row, sct.get(KeyConstants._type,null));
307                                qry.setAtEL(XMLBASE, row, sct.get("xml:base",null));
308                        }
309                        else qry.setAtEL(CONTENT, row, getValue(value));
310                }
311                else if(key.equals(CONTRIBUTOR)) {
312                        Struct sct=toStruct(value);
313                        if(sct!=null){
314                                qry.setAtEL(CONTRIBUTOREMAIL, row, sct.get("email",null));
315                                qry.setAtEL(CONTRIBUTORNAME, row, sct.get(KeyConstants._name,null));
316                                qry.setAtEL(CONTRIBUTORURI, row, sct.get("uri",null));
317                        }
318                }
319                else if(key.equals(CREATED)) {
320                        qry.setAtEL(CREATEDDATE, row, getValue(value));
321                }
322                else if(key.equals(ID)) {
323                        qry.setAtEL(ID, row, getValue(value));
324                }
325                else if(key.equals(LINK)) {
326                        Struct sct=toStruct(value);
327                        if(sct!=null){
328                                qry.setAtEL(LINKHREF, row, sct.get("href",null));
329                                qry.setAtEL(LINKHREFLANG, row, sct.get("hreflang",null));
330                                qry.setAtEL(LINKLENGTH, row, sct.get(LENGTH,null));
331                                qry.setAtEL(LINKREL, row, sct.get("rel",null));
332                                qry.setAtEL(LINKTITLE, row, sct.get(TITLE,null));
333                                qry.setAtEL(LINKTYPE, row, sct.get(KeyConstants._type,null));
334                        }
335                }
336                else if(key.equals(PUBLISHED)) {
337                        qry.setAtEL(PUBLISHEDDATE, row, getValue(value));
338                }
339                else if(key.equals(ISSUED)) {
340                        qry.setAtEL(PUBLISHEDDATE, row, getValue(value));
341                }
342                else if(key.equals(RIGHTS)) {
343                        qry.setAtEL(RIGHTS, row, getValue(value));
344                }
345                else if(key.equals(COPYRIGHT)) {
346                        qry.setAtEL(RIGHTS, row, getValue(value));
347                }
348                else if(key.equals(SUMMARY)) {
349                        Struct sct=toStruct(value);
350                        if(sct!=null){
351                                qry.setAtEL(SUMMARY, row, getValue(sct));
352                                qry.setAtEL(SUMMARYMODE, row, sct.get(MODE,null));
353                                qry.setAtEL(SUMMARYSRC, row, sct.get(SRC,null));
354                                qry.setAtEL(SUMMARYTYPE, row, sct.get(KeyConstants._type,null));
355                        }
356                        else qry.setAtEL(SUMMARY, row, getValue(value));
357                }
358                else if(key.equals(TITLE)) {
359                        Struct sct=toStruct(value);
360                        if(sct!=null){
361                                qry.setAtEL(TITLE, row, getValue(sct));
362                                qry.setAtEL(TITLETYPE, row, sct.get(KeyConstants._type,null));
363                        }
364                        else qry.setAtEL(TITLE, row, getValue(value));
365                }
366                else if(key.equals(UPDATED)) {
367                        qry.setAtEL(UPDATEDDATE, row, getValue(value));
368                }
369                else if(key.equals(MODIFIED)) {
370                        qry.setAtEL(UPDATEDDATE, row, getValue(value));
371                }
372        }
373        private static void setQueryValueRSS(Query qry, Key key, Object value, int row) {
374                
375                if(key.equals(AUTHOR)) {
376                        qry.setAtEL(AUTHOREMAIL, row, getValue(value));
377                }
378                else if(key.equals(CATEGORY)) {
379                        Struct sct=toStruct(value);
380                        
381                        if(sct!=null){
382                                qry.setAtEL(CATEGORYLABEL, row, getValue(sct));
383                                qry.setAtEL(CATEGORYSCHEME, row, sct.get(DOMAIN,null));
384                        }
385                        else qry.setAtEL(CATEGORYLABEL, row, getValue(value));
386                }
387                else if(key.equals(COMMENTS)) {
388                        qry.setAtEL(COMMENTS, row, getValue(value));
389                }
390                else if(key.equals(KeyConstants._description)) {
391                        qry.setAtEL(CONTENT, row, getValue(value));
392                }
393                else if(key.equals(EXPIRATIONDATE)) {
394                        qry.setAtEL(EXPIRATIONDATE, row, getValue(value));
395                }
396                else if(key.equals(GUID)) {
397                        Struct sct=toStruct(value);
398                        
399                        if(sct!=null){
400                                qry.setAtEL(ID, row, getValue(sct));
401                                qry.setAtEL(IDPERMALINK, row, sct.get(ISPERMALINK,null));
402                        }
403                        else qry.setAtEL(ID, row, getValue(value));
404                }
405                else if(key.equals(ENCLOSURE)) {
406                        Struct sct=toStruct(value);
407                        if(sct!=null){
408                                qry.setAtEL(LINKHREF, row, sct.get(URL,null));
409                                qry.setAtEL(LINKLENGTH, row, sct.get(LENGTH,null));
410                                qry.setAtEL(LINKTYPE, row, sct.get(KeyConstants._type,null));
411                        }
412                }
413                else if(key.equals(PUBDATE)) {
414                        qry.setAtEL(PUBLISHEDDATE, row, getValue(value));
415                }
416                else if(key.equals(RDF_ABOUT)) {
417                        qry.setAtEL(URI, row, getValue(value));
418                }
419                else if(key.equals(LINK)) {
420                        
421                        Struct sct=toStruct(value);
422                        
423                        if(sct!=null){
424                                qry.setAtEL(RSSLINK, row, getValue(sct));
425                                Object v = sct.get(RDF_ABOUT,null);
426                                if(v!=null) qry.setAtEL(URI, row, v);
427                        }
428                        else qry.setAtEL(RSSLINK, row, getValue(value));
429                }
430                else if(key.equals(SOURCE)) {
431                        Struct sct=toStruct(value);
432                        
433                        if(sct!=null){
434                                qry.setAtEL(SOURCE, row, getValue(sct));
435                                qry.setAtEL(SOURCEURL, row, sct.get(URL,null));
436                        }
437                        else qry.setAtEL(SOURCE, row, getValue(value));
438                }
439                else if(key.equals(SUMMARY)) {
440                        Struct sct=toStruct(value);
441                        
442                        if(sct!=null){
443                                qry.setAtEL(SUMMARY, row, getValue(sct));
444                                qry.setAtEL(SUMMARYMODE, row, sct.get(MODE,null));
445                                qry.setAtEL(SUMMARYTYPE, row, sct.get(KeyConstants._type,null));
446                        }
447                        else qry.setAtEL(SUMMARY, row, getValue(value));
448                }
449                else if(key.equals(TITLE)) {
450                        qry.setAtEL(TITLE, row, getValue(value));
451                }
452
453                // Dublin Core
454                if(key.getLowerString().startsWith("dc_")){
455                        
456                        if(key.equals(DC_CONTRIBUTOR)) {
457                                qry.setAtEL(DC_CONTRIBUTOR, row, getValue(value));
458                        }
459                        else if(key.equals(DC_COVERAGE)) {
460                                qry.setAtEL(DC_COVERAGE, row, getValue(value));
461                        }
462                        else if(key.equals(DC_CREATOR)) {
463                                qry.setAtEL(DC_CREATOR, row, getValue(value));
464                        }
465                        else if(key.equals(DC_DATE)) {
466                                qry.setAtEL(DC_DATE, row, getValue(value));
467                        }
468                        else if(key.equals(DC_DESCRIPTION)) {
469                                qry.setAtEL(DC_DESCRIPTION, row, getValue(value));
470                        }
471                        else if(key.equals(DC_FORMAT)) {
472                                qry.setAtEL(DC_FORMAT, row, getValue(value));
473                        }
474                        else if(key.equals(DC_IDENTIFIER)) {
475                                qry.setAtEL(DC_IDENTIFIER, row, getValue(value));
476                        }
477                        else if(key.equals(DC_LANGUAGE)) {
478                                qry.setAtEL(DC_LANGUAGE, row, getValue(value));
479                        }
480                        else if(key.equals(DC_PUBLISHER)) {
481                                qry.setAtEL(DC_PUBLISHER, row, getValue(value));
482                        }
483                        else if(key.equals(DC_RELATION)) {
484                                qry.setAtEL(DC_RELATION, row, getValue(value));
485                        }
486                        else if(key.equals(DC_RIGHT)) {
487                                qry.setAtEL(DC_RIGHT, row, getValue(value));
488                        }
489                        else if(key.equals(DC_SOURCE)) {
490                                qry.setAtEL(DC_SOURCE, row, getValue(value));
491                        }
492                        else if(key.equals(DC_SUBJECT_TAXONOMYURI)) {
493                                qry.setAtEL(DC_SUBJECT_TAXONOMYURI, row, getValue(value));
494                        }
495                        else if(key.equals(DC_SUBJECT)) {
496                                qry.setAtEL(DC_SUBJECT_VALUE, row, getValue(value));
497                        }
498                        else if(key.equals(DC_TITLE)) {
499                                qry.setAtEL(DC_TITLE, row, getValue(value));
500                        }
501                        else if(key.equals(DC_TYPE)) {
502                                qry.setAtEL(DC_TYPE, row, getValue(value));
503                        }
504                }
505                
506        }
507
508
509        public static Object getValue(Object value) {
510                return getValue(value, false);
511        }
512        public static Object getValue(Object value,boolean includeChildren) {
513                if(value instanceof Struct)return getValue((Struct)value,includeChildren);
514                return Caster.toString(value,null);
515        }
516
517        public static Object getValue(Struct sct,boolean includeChildren) {
518                Object obj = sct.get(KeyConstants._value, null);
519                if(obj==null)obj=sct.get(TEXT,null);
520                return obj;
521        }
522
523        private static Struct toStruct(Object value) {
524                if(value instanceof Struct) return (Struct) value; 
525                
526                if(value instanceof Array)      {
527                        Struct sct=new StructImpl(),row;
528                        Array arr = (Array)value;
529                        int len=arr.size();
530                        //Key[] keys;
531                        Iterator<Entry<Key, Object>> it;
532                        Entry<Key, Object> e;
533                        String nw;
534                        Object ext;
535                        for(int i=1;i<=len;i++){
536                                row=Caster.toStruct(arr.get(i,null),null,false);
537                                if(row==null)continue;
538                                it = row.entryIterator();
539                                //keys = row.keys();
540                                while(it.hasNext()){
541                                        e = it.next();
542                                        ext=sct.get(e.getKey(),null);
543                                        nw=Caster.toString(e.getValue(),null);
544                                        if(nw!=null){
545                                                if(ext==null) sct.setEL(e.getKey(), nw);
546                                                else if(ext instanceof CastableArray){
547                                                        ((CastableArray)ext).appendEL(nw);
548                                                }
549                                                else {
550                                                        CastableArray ca=new CastableArray();
551                                                        ca.appendEL(Caster.toString(ext,null));
552                                                        ca.appendEL(nw);
553                                                        sct.setEL(e.getKey(), ca);
554                                                }
555                                                
556                                        }
557                                }
558                        }
559                        return sct;
560                }
561                
562                
563                return null;
564        }
565
566        public static Query toQuery(Query qry) {
567                return qry;
568        }
569}