001    /*
002     * Copyright 2011 The Kuali Foundation.
003     * 
004     * Licensed under the Educational Community License, Version 2.0 (the "License");
005     * you may not use this file except in compliance with the License.
006     * You may obtain a copy of the License at
007     * 
008     * http://www.opensource.org/licenses/ecl2.php
009     * 
010     * Unless required by applicable law or agreed to in writing, software
011     * distributed under the License is distributed on an "AS IS" BASIS,
012     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013     * See the License for the specific language governing permissions and
014     * limitations under the License.
015     */
016    package org.kuali.kfs.sys.dataaccess.impl;
017    
018    import java.lang.reflect.Field;
019    import java.util.Map;
020    
021    import org.apache.ojb.broker.PersistenceBroker;
022    import org.apache.ojb.broker.accesslayer.QueryCustomizerDefaultImpl;
023    import org.apache.ojb.broker.metadata.CollectionDescriptor;
024    import org.apache.ojb.broker.query.Criteria;
025    import org.apache.ojb.broker.query.Query;
026    import org.apache.ojb.broker.query.QueryByCriteria;
027    import org.kuali.rice.kns.util.ObjectUtils;
028    
029    public class OjbQueryCustomizer extends QueryCustomizerDefaultImpl {
030        // used to AND in additional criteria on a collection
031        protected static final String FIELD_PREFIX = "parent.";
032    
033        @Override
034        public Query customizeQuery(Object arg0, PersistenceBroker arg1, CollectionDescriptor arg2, QueryByCriteria arg3) {
035            // unfortunately OJB's default implementation has no getter for the map they construct
036            // by accessing this map, we can provide a more generic interface by looping through any attributes
037            // so, use reflection to get at the attribute anyway
038            Field field = null;
039            try {
040                field = this.getClass().getSuperclass().getDeclaredField("m_attributeList");
041            }
042            catch (Exception e) {
043                throw new RuntimeException(e);
044            }
045            field.setAccessible(true);
046            Map<String, String> m_attributeList = null;
047            try {
048                m_attributeList = (Map) field.get(this);
049            }
050            catch (Exception e) {
051                throw new RuntimeException(e);
052            }
053    
054            // now, do what we wanted to do to start with if we could've just gotten m_attributeList easily
055            Criteria criteria = arg3.getCriteria();
056            for (String key : m_attributeList.keySet()) {
057                // if beginning with FIELD_PREFIX is too hacky, or more flexibility is needed, another query customizer class can be
058                // made,
059                // and this method can be renamed to take a parameter to specify which we want to do
060                // (and the customizeQuery method here made to call the new method with the parameter).
061                // However, making another class would mean you couldn't intermix constants and field values,
062                // since OJB won't use have multiple query-customizers per collection-descriptor.
063                if (this.getAttribute(key).startsWith(FIELD_PREFIX)) {
064                    criteria.addEqualTo(key, ObjectUtils.getPropertyValue(arg0, this.getAttribute(key).substring(FIELD_PREFIX.length())));
065                }
066                else {
067                    criteria.addEqualTo(key, this.getAttribute(key));
068                }
069            }
070            arg3.setCriteria(criteria);
071            return arg3;
072        }
073    }