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.orm.hibernate;
020
021import java.math.BigInteger;
022import java.sql.Time;
023import java.sql.Timestamp;
024import java.sql.Types;
025import java.util.ArrayList;
026import java.util.Iterator;
027import java.util.List;
028
029import lucee.commons.lang.types.RefBoolean;
030import lucee.loader.util.Util;
031import lucee.runtime.Component;
032import lucee.runtime.ComponentScope;
033import lucee.runtime.PageContext;
034import lucee.runtime.component.Property;
035import lucee.runtime.db.SQLCaster;
036import lucee.runtime.db.SQLItem;
037import lucee.runtime.exp.PageException;
038import lucee.runtime.op.Caster;
039import lucee.runtime.orm.ORMEngine;
040import lucee.runtime.orm.ORMSession;
041import lucee.runtime.orm.ORMUtil;
042import lucee.runtime.type.Array;
043import lucee.runtime.type.Collection;
044import lucee.runtime.type.Collection.Key;
045import lucee.runtime.type.Query;
046import lucee.runtime.type.Struct;
047import lucee.runtime.type.util.QueryUtil;
048
049import org.hibernate.SessionFactory;
050import org.hibernate.metadata.ClassMetadata;
051import org.hibernate.type.Type;
052
053public class HibernateCaster {
054        
055        private static final int NULL = -178696;
056
057        public static Object toCFML(Object src) {
058                if(src==null) return null;
059                if(src instanceof Collection) return src;
060                
061                if(src instanceof List){
062                        return toCFML((List) src);
063                }
064                /*if(src instanceof Map){
065                        return toCFML(pc,(Map) src);
066                }*/
067                return src;
068        }
069        
070        public static Array toCFML(List src)  {
071        int size=src.size();
072        
073        Array trg = CommonUtil.createArray();
074        for(int i=0;i<size;i++) {
075            trg.setEL(i+1,toCFML(src.get(i)));
076        }
077        return trg;
078        }
079        
080        /*public static Object toCFML(PageContext pc,Map src) throws PageException {
081                
082                Object type =src.remove("$type$");
083                if(type instanceof String){
084                        
085                        Component cfc = toComponent(pc, (String)type);
086                        return toCFML(pc,src, cfc);
087                }
088                
089                
090                Iterator<Map.Entry<String, Object>> it = src.entrySet().iterator();
091        Struct trg=CommonUtil.createStruct();
092        Map.Entry<String, Object> entry;
093        while(it.hasNext()){
094                        entry=it.next();
095            trg.setEL(entry.getKey(),toCFML(pc,entry.getValue()));
096        }
097        return trg;
098        }*/
099        
100
101        
102        public static String getEntityName(Component cfc) {
103                
104                String name=null;
105                try {
106                        name=CommonUtil.toString(HibernateUtil.getMetaStructItem(cfc,CommonUtil.ENTITY_NAME),null);
107                } 
108                catch (Throwable t) {
109                        lucee.commons.lang.ExceptionUtil.rethrowIfNecessary(t);
110                        try {
111                                Struct md = cfc.getMetaData(CommonUtil.pc());
112                                name = CommonUtil.toString(md.get(CommonUtil.ENTITY_NAME),null);
113                                
114                        }catch (PageException e) {}
115                }
116                
117                if(!Util.isEmpty(name)) {
118                        return name;
119                }
120                return getName(cfc);
121                
122                
123        }
124
125        private static String getName(Component cfc) {
126                String name=null;
127                // MUSTMUST cfc.getName() should return the real case, this should not be needed
128                name = cfc.getPageSource().getDisplayPath();
129            name=CommonUtil.last(name, "\\/");
130            int index=name.lastIndexOf('.');
131            name= name.substring(0,index);
132                return name;
133        }
134
135        public static int cascade(ORMSession session,String cascade) throws PageException {
136                int c=cascade(cascade,-1);
137                if(c!=-1) return c;
138                throw ExceptionUtil.createException(session,null,"invalid cascade defintion ["+cascade+"], valid values are [all,all-delete-orphan,delete,delete-orphan,refresh,save-update]",null);
139        }
140        
141        public static int cascade(String cascade, int defaultValue) {
142                cascade=cascade.trim().toLowerCase();
143                if("all".equals(cascade)) return HibernateConstants.CASCADE_ALL;
144                
145                if("save-update".equals(cascade)) return HibernateConstants.CASCADE_SAVE_UPDATE;
146                if("save_update".equals(cascade)) return HibernateConstants.CASCADE_SAVE_UPDATE;
147                if("saveupdate".equals(cascade)) return HibernateConstants.CASCADE_SAVE_UPDATE;
148                
149                if("delete".equals(cascade)) return HibernateConstants.CASCADE_DELETE;
150                
151                if("delete-orphan".equals(cascade)) return HibernateConstants.CASCADE_DELETE_ORPHAN;
152                if("delete_orphan".equals(cascade)) return HibernateConstants.CASCADE_DELETE_ORPHAN;
153                if("deleteorphan".equals(cascade)) return HibernateConstants.CASCADE_DELETE_ORPHAN;
154
155                if("all-delete-orphan".equals(cascade)) return HibernateConstants.CASCADE_ALL_DELETE_ORPHAN;
156                if("all_delete_orphan".equals(cascade)) return HibernateConstants.CASCADE_ALL_DELETE_ORPHAN;
157                if("alldeleteorphan".equals(cascade)) return HibernateConstants.CASCADE_ALL_DELETE_ORPHAN;
158                
159                if("refresh".equals(cascade)) return HibernateConstants.REFRESH;
160                
161                return defaultValue;
162        }
163
164        public static int collectionType(ORMSession session,String strCollectionType) throws PageException {
165                int ct=collectionType(strCollectionType, -1);
166                if(ct!=-1) return ct;
167                throw ExceptionUtil.createException(session,null,"invalid collectionType defintion ["+strCollectionType+"], valid values are [array,struct]",null);
168        }
169        public static int collectionType(String strCollectionType, int defaultValue) {
170                strCollectionType=strCollectionType.trim().toLowerCase();
171                if("struct".equals(strCollectionType)) return HibernateConstants.COLLECTION_TYPE_STRUCT;
172                if("array".equals(strCollectionType)) return HibernateConstants.COLLECTION_TYPE_ARRAY;
173                
174                return defaultValue;
175        }
176
177        public static String toHibernateType(ColumnInfo info, String type, String defaultValue) {
178                
179                // no type defined
180                if(Util.isEmpty(type,true)) {
181                        return HibernateCaster.toHibernateType(info,defaultValue);
182                }
183                
184                // type defined
185                String tmp=HibernateCaster.toHibernateType(type,null);
186                if(tmp!=null) return tmp;
187                
188                if(info!=null){
189                        tmp=HibernateCaster.toHibernateType(info,defaultValue);
190                        return tmp;
191                }
192                return defaultValue;
193                
194                
195        }
196        
197        public static int toSQLType(String type,int defaultValue)       {
198                type=type.trim().toLowerCase();
199                type=toHibernateType(type,type);
200                if("long".equals(type)) return Types.BIGINT;
201                if("binary".equals(type)) return Types.BINARY;
202                if("boolean".equals(type)) return Types.BIT;
203                if("blob".equals(type)) return Types.BLOB;
204                if("boolean".equals(type)) return Types.BOOLEAN;
205                if("character".equals(type)) return Types.CHAR;
206                if("clob".equals(type)) return Types.CLOB;
207                if("date".equals(type)) return Types.DATE;
208                if("big_decimal".equals(type)) return Types.DECIMAL;
209                if("big_integer".equals(type)) return Types.NUMERIC;
210                if("double".equals(type)) return Types.DOUBLE;
211                if("float".equals(type)) return Types.FLOAT;
212                if("integer".equals(type)) return Types.INTEGER;
213                if("binary".equals(type)) return Types.VARBINARY;
214                if("string".equals(type)) return Types.VARCHAR;
215                if("short".equals(type)) return Types.SMALLINT;
216                if("time".equals(type)) return Types.TIME;
217                if("timestamp".equals(type)) return Types.TIMESTAMP;
218                if("byte".equals(type)) return Types.TINYINT;
219                
220                return defaultValue;
221        }
222        
223        public static String toHibernateType(ColumnInfo info, String defaultValue)      {
224                if(info==null)return defaultValue;
225                
226                String rtn = toHibernateType(info.getType(),info.getSize(), null);
227                if(rtn!=null) return rtn;
228                return toHibernateType(info.getTypeName(),defaultValue);
229        }
230        
231        public static String toHibernateType(int type, int size, String defaultValue) {
232                // MUST do better
233                switch(type){
234                case Types.ARRAY: return "";
235                case Types.BIGINT: return "long";
236                case Types.BINARY: return "binary";
237                case Types.BIT: return "boolean";
238                case Types.BLOB: return "blob";
239                case Types.BOOLEAN: return "boolean";
240                case Types.CHAR:
241                        return "string";
242                        //if(size>1) return "string";
243                        //return "character";
244                case Types.CLOB: return "clob";
245                //case Types.DATALINK: return "";
246                case Types.DATE: return "date";
247                case Types.DECIMAL: return "big_decimal";
248                //case Types.DISTINCT: return "";
249                case Types.DOUBLE: return "double";
250                case Types.FLOAT: return "float";
251                case Types.INTEGER: return "integer";
252                //case Types.JAVA_OBJECT: return "";
253                case Types.LONGVARBINARY: return "binary";
254                case Types.LONGVARCHAR: return "string";
255                //case Types.NULL: return "";
256                case Types.NUMERIC: return "big_decimal";
257                //case Types.OTHER: return "";
258                //case Types.REAL: return "";
259                //case Types.REF: return "";
260                case Types.SMALLINT: return "short";
261                //case Types.STRUCT: return "";
262                case Types.TIME: return "time";
263                case Types.TIMESTAMP: return "timestamp";
264                case Types.TINYINT: return "byte";
265                case Types.VARBINARY: return "binary";
266                case Types.NVARCHAR: return "string";
267                case Types.VARCHAR: return "string";
268                }
269                return defaultValue;
270        }
271        
272        public static String toHibernateType(ORMSession session,String type) throws PageException       {
273                String res=toHibernateType(type, null);
274                if(res==null) throw ExceptionUtil.createException(session,null,"the type ["+type+"] is not supported",null);
275                return res;
276        }
277        
278        
279        // calendar_date: A type mapping for a Calendar object that represents a date
280        //calendar: A type mapping for a Calendar object that represents a datetime.
281        public static String toHibernateType(String type, String defaultValue)  {
282                type=type.trim().toLowerCase();
283                type=Util.replace(type, "java.lang.", "", true);
284                type=Util.replace(type, "java.util.", "", true);
285                type=Util.replace(type, "java.sql.", "", true);
286                
287                // return same value
288                if("long".equals(type)) return type;
289                if("binary".equals(type)) return type;
290                if("boolean".equals(type)) return type;
291                if("blob".equals(type)) return "binary";
292                if("boolean".equals(type)) return type;
293                if("character".equals(type)) return type;
294                if("clob".equals(type)) return "text";
295                if("date".equals(type)) return type;
296                if("big_decimal".equals(type)) return type;
297                if("double".equals(type)) return type;
298                if("float".equals(type)) return type;
299                if("integer".equals(type)) return type;
300                if("binary".equals(type)) return type;
301                if("string".equals(type)) return type;
302                if("big_integer".equals(type)) return type;
303                if("short".equals(type)) return type;
304                if("time".equals(type)) return type;
305                if("timestamp".equals(type)) return type;
306                if("byte".equals(type)) return type;
307                if("binary".equals(type)) return type;
308                if("string".equals(type)) return type;
309                if("text".equals(type)) return type;
310                if("calendar".equals(type)) return type;
311                if("calendar_date".equals(type)) return type;
312                if("locale".equals(type)) return type;
313                if("timezone".equals(type)) return type;
314                if("currency".equals(type)) return type;
315                
316                if("imm_date".equals(type)) return type;
317                if("imm_time".equals(type)) return type;
318                if("imm_timestamp".equals(type)) return type;
319                if("imm_calendar".equals(type)) return type;
320                if("imm_calendar_date".equals(type)) return type;
321                if("imm_serializable".equals(type)) return type;
322                if("imm_binary".equals(type)) return type;
323                
324                // return different value
325                if("bigint".equals(type))                                               return "long";
326                if("bit".equals(type))                                          return "boolean";
327                
328                if("int".equals(type))                                          return "integer";
329                if("char".equals(type))                                         return "character";
330                
331                if("bool".equals(type))                                         return "boolean";
332                if("yes-no".equals(type))                                       return "yes_no";
333                if("yesno".equals(type))                                        return "yes_no";
334                if("yes_no".equals(type))                                       return "yes_no";
335                if("true-false".equals(type))                           return "true_false";
336                if("truefalse".equals(type))                            return "true_false";
337                if("true_false".equals(type))                           return "true_false";
338                if("varchar".equals(type))                                      return "string";
339                if("big-decimal".equals(type))                          return "big_decimal";
340                if("bigdecimal".equals(type))                           return "big_decimal";
341                if("java.math.bigdecimal".equals(type))         return "big_decimal";
342                if("big-integer".equals(type))                          return "big_integer";
343                if("biginteger".equals(type))                           return "big_integer";
344                if("bigint".equals(type))                               return "big_integer";
345                if("java.math.biginteger".equals(type))         return "big_integer";
346                if("byte[]".equals(type))                                       return "binary";
347                if("serializable".equals(type))                         return "serializable";
348                
349                if("datetime".equals(type))                             return "timestamp";
350                if("numeric".equals(type))                                      return "double";
351                if("number".equals(type))                                       return "double";
352                if("numeric".equals(type))                                      return "double";
353                if("char".equals(type))                                         return "character";
354                if("nchar".equals(type))                                        return "character";
355                if("decimal".equals(type))                                      return "double";
356                if("eurodate".equals(type))                             return "timestamp";
357                if("usdate".equals(type))                               return "timestamp";
358                if("int".equals(type))                                          return "integer";
359                if("varchar".equals(type))                                              return "string";
360                if("nvarchar".equals(type))                                             return "string";
361                
362                return defaultValue;
363                
364                // FUTURE
365                /*
366                
367                add support for 
368                - any, object,other
369                
370                add support for custom types https://issues.jboss.org/browse/LUCEE-1341
371                - array
372            - base64
373            - guid
374        - memory
375            - node, xml
376            - query
377            - struct
378        - uuid
379        - variablename, variable_name
380            - variablestring, variable_string
381            
382                */
383                
384    }
385        public static Object toHibernateValue(PageContext pc,Object value,String type) throws PageException     {
386                type=toHibernateType(type, null);
387                // return same value
388                if("long".equals(type)) 
389                        return Caster.toLong(value);
390                if("binary".equals(type) || "imm_binary".equals(type))
391                        return Caster.toBinary(value);
392                if("boolean".equals(type) || "yes_no".equals(type) || "true_false".equals(type)) 
393                        return Caster.toBoolean(value);
394                if("character".equals(type)) 
395                        return Caster.toCharacter(value);
396                if("date".equals(type) || "imm_date".equals(type)) 
397                        return Caster.toDatetime(value,pc.getTimeZone());
398                if("big_decimal".equals(type)) 
399                        return Caster.toBigDecimal(value);
400                if("double".equals(type)) 
401                        return Caster.toDouble(value);
402                if("float".equals(type)) 
403                        return Caster.toFloat(value);
404                if("integer".equals(type))
405                        return Caster.toInteger(value);
406                if("string".equals(type))
407                        return Caster.toString(value);
408                if("big_integer".equals(type))
409                        return new BigInteger(Caster.toString(value));
410                if("short".equals(type)) 
411                        return Caster.toShort(value);
412                if("time".equals(type) || "imm_time".equals(type)) 
413                        return new Time(Caster.toDate(value,pc.getTimeZone()).getTime());
414                if("timestamp".equals(type) || "imm_timestamp".equals(type))
415                        return new Timestamp(Caster.toDate(value,pc.getTimeZone()).getTime());
416                if("byte".equals(type))
417                        return Caster.toBinary(value);
418                if("text".equals(type))
419                        return Caster.toString(value);
420                if("calendar".equals(type) || "calendar_date".equals(type) || "imm_calendar".equals(type) || "imm_calendar_date".equals(type)) 
421                        return Caster.toCalendar(Caster.toDateTime(value, pc.getTimeZone()),  pc.getTimeZone(),  pc.getLocale());
422                if("locale".equals(type))
423                        return Caster.toLocale(Caster.toString(value));
424                if("timezone".equals(type))
425                        return Caster.toTimeZone(value,null);
426                if("currency".equals(type))
427                        return value;
428                
429                if("imm_serializable".equals(type))
430                        return value;
431                if("serializable".equals(type))
432                        return "serializable";
433                
434                return value;
435    }
436
437        /**
438         * translate CFMl specific types to Hibernate/SQL specific types
439         * @param engine
440         * @param ci
441         * @param value
442         * @return
443         * @throws PageException
444         */
445        public static Object toSQL(ColumnInfo ci, Object value, RefBoolean isArray) throws PageException {
446                return toSQL(ci.getType(), value,isArray);
447        }
448        
449        /**
450         * translate CFMl specific types to Hibernate/SQL specific types
451         * @param engine
452         * @param type
453         * @param value
454         * @return
455         * @throws PageException
456         */
457        public static Object toSQL(Type type, Object value, RefBoolean isArray) throws PageException {
458                int t = toSQLType(type.getName(), Types.OTHER);
459                if(t==Types.OTHER) return value;
460                return toSQL(t, value,isArray);
461        }
462
463        /**
464         * translate CFMl specific type to SQL specific types
465         * @param engine
466         * @param sqlType
467         * @param value
468         * @return
469         * @throws PageException
470         */
471        private static Object toSQL(int sqlType, Object value, RefBoolean isArray) throws PageException {
472                if(isArray!=null)isArray.setValue(false);
473                SQLItem item = CommonUtil.toSQLItem(value,sqlType);
474                try{
475                        return SQLCaster.toSqlType(item);
476                }
477                catch(PageException pe){
478                        // pherhaps it is a array of this type 
479                        if(isArray!=null && CommonUtil.isArray(value)) {
480                                Object[] src = CommonUtil.toNativeArray(value);
481                                ArrayList<Object> trg = new ArrayList<Object>();
482                                for(int i=0;i<src.length;i++){
483                                        try{
484                                                trg.add(SQLCaster.toSqlType(CommonUtil.toSQLItem(src[i],sqlType)));
485                                        }
486                                        catch(PageException inner){
487                                                throw pe;
488                                        }
489                                }
490                                isArray.setValue(true);
491                                return CommonUtil.toArray(trg);
492                                
493                        }
494                        throw pe;
495                }
496                
497        }
498
499
500        public static lucee.runtime.type.Query toQuery(PageContext pc,HibernateORMSession session, Object obj, String name) throws PageException {
501                Query qry=null;
502                // a single entity
503                if(!CommonUtil.isArray(obj)){
504                        qry= toQuery(pc,session,HibernateCaster.toComponent(obj),name,null,1,1);
505                }
506                
507                // a array of entities
508                else {
509                        Array arr=CommonUtil.toArray(obj);
510                        int len=arr.size();
511                        if(len>0) {
512                                Iterator<Object> it = arr.valueIterator();
513                                int row=1;
514                                while(it.hasNext()){
515                                        qry=toQuery(pc,session,HibernateCaster.toComponent(it.next()),name,qry,len,row++);
516                                }
517                        }
518                        else 
519                                qry=CommonUtil.createQuery(new Collection.Key[0],0,"orm");
520                }
521                
522                if(qry==null) {
523                        if(!Util.isEmpty(name))
524                                throw ExceptionUtil.createException(session,null,"there is no entity inheritance that match the name ["+name+"]",null);
525                        throw ExceptionUtil.createException(session,null,"cannot create query",null);
526                }
527                return qry;
528        }
529        
530        private static Query toQuery(PageContext pc,HibernateORMSession session,Component cfc, String entityName,Query qry, int rowcount, int row) throws PageException {
531                // inheritance mapping
532                if(!Util.isEmpty(entityName)){
533                        //String cfcName = toComponentName(HibernateCaster.toComponent(pc, entityName));
534                        return inheritance(pc,session,cfc,qry, entityName);
535                }
536                return populateQuery(pc,session,cfc,qry);
537        }
538
539
540
541
542        private static Query populateQuery(PageContext pc,HibernateORMSession session,Component cfc,Query qry) throws PageException {
543                Property[] properties = CommonUtil.getProperties(cfc,true,true,false,false);
544                String dsn = ORMUtil.getDataSourceName(pc, cfc);
545                ComponentScope scope = cfc.getComponentScope();
546                HibernateORMEngine engine=(HibernateORMEngine) session.getEngine();
547                
548                // init
549                if(qry==null){
550                        SessionFactory factory = session.getRawSessionFactory(dsn);
551                        ClassMetadata md = factory.getClassMetadata(getEntityName(cfc));
552                        Array names=CommonUtil.createArray();
553                        Array types=CommonUtil.createArray();
554                        String name;
555                        //ColumnInfo ci;
556                        int t;
557                        Object obj;
558                        Struct sct;
559                        String fieldType;
560                        for(int i=0;i<properties.length;i++){
561                                obj = properties[i].getMetaData();
562                                if(obj instanceof Struct) {
563                                        sct=(Struct) obj;
564                                        fieldType = CommonUtil.toString(sct.get(CommonUtil.FIELDTYPE,null),null);
565                                        if("one-to-many".equalsIgnoreCase(fieldType) || "many-to-many".equalsIgnoreCase(fieldType) || "many-to-one".equalsIgnoreCase(fieldType) || "one-to-one".equalsIgnoreCase(fieldType)) 
566                                                continue;
567                                        
568                                }
569                                
570                                name=HibernateUtil.validateColumnName(md, properties[i].getName(),null);
571                                //if(columnsInfo!=null)ci=(ColumnInfo) columnsInfo.get(name,null);
572                                //else ci=null;
573                                names.append(name);
574                                if(name!=null){
575                                        
576                                        t=HibernateCaster.toSQLType(HibernateUtil.getPropertyType(md, name).getName(), NULL);
577                                        if(t==NULL)
578                                                types.append("object");
579                                        else
580                                                types.append(SQLCaster.toStringType(t));
581                                }
582                                else 
583                                        types.append("object");
584                        }
585                        
586                        qry=CommonUtil.createQuery(names,types,0,getEntityName(cfc));
587                        
588                }
589                // check
590                else if(engine.getMode() == ORMEngine.MODE_STRICT){
591                        if(!qry.getName().equals(getEntityName(cfc)))
592                                throw ExceptionUtil.createException(session,null,"can only merge entities of the same kind to a query",null);
593                }
594                
595                // populate
596                Key[] names=QueryUtil.getColumnNames(qry);
597                
598                int row=qry.addRow();
599                for(int i=0;i<names.length;i++){
600                        qry.setAtEL(names[i], row, scope.get(names[i],null));
601                }
602                return qry;
603        }
604
605
606
607
608        private static Query inheritance(PageContext pc,HibernateORMSession session,Component cfc,Query qry, String entityName) throws PageException {
609                Property[] properties = cfc.getProperties(true);
610                ComponentScope scope = cfc.getComponentScope();
611                Object value;
612                Array arr;
613                for(int i=0;i<properties.length;i++){
614                        value=scope.get(CommonUtil.createKey(properties[i].getName()),null);
615                        if(value instanceof Component){
616                                qry=inheritance(pc,session,qry,cfc,(Component) value,entityName);
617                        }
618                        else if(CommonUtil.isArray(value)){
619                                arr = CommonUtil.toArray(value);
620                                Iterator<Object> it = arr.valueIterator();
621                                while(it.hasNext()){
622                                        value=it.next();
623                                        if(value instanceof Component){
624                                                qry=inheritance(pc,session,qry,cfc,(Component) value,entityName);
625                                        }
626                                }
627                        }
628                }
629                return qry;
630        }
631
632
633
634
635        private static Query inheritance(PageContext pc,HibernateORMSession session,Query qry,Component parent,Component child,String entityName) throws PageException {
636                if(getEntityName(child).equalsIgnoreCase(entityName))
637                        return populateQuery(pc,session,child,qry);
638                return inheritance(pc,session,child, qry, entityName);// MUST geh ACF auch so tief?
639        }
640
641
642        /**
643         * return the full name (package and name) of a component
644         * @param cfc
645         * @return
646         */
647        public static String toComponentName(Component cfc) {
648                return cfc.getPageSource().getComponentName();
649        }
650        
651        public static Component toComponent(Object obj) throws PageException {
652                return CommonUtil.toComponent(obj);
653        }
654}