/* * Copyright 2001-2008 Geert Bevin <gbevin[remove] at uwyn dot com> * Licensed under the Apache License, Version 2.0 (the "License") * $Id: Browse.java 3953 2008-05-08 01:04:08Z gbevin $ */ package com.uwyn.rife.crud.elements.admin; import com.uwyn.rife.cmf.ContentInfo; import com.uwyn.rife.cmf.MimeType; import com.uwyn.rife.cmf.dam.ContentQueryManager; import com.uwyn.rife.cmf.dam.OrdinalManager; import static com.uwyn.rife.crud.CrudPropertyNames.*; import com.uwyn.rife.crud.CrudSiteProcessor; import com.uwyn.rife.crud.templates.AdminTemplateTransformer; import com.uwyn.rife.crud.templates.BrowseTemplateTransformer; import com.uwyn.rife.database.DbBeanFetcher; import com.uwyn.rife.database.DbQueryManager; import com.uwyn.rife.database.DbTransactionUserWithoutResult; import com.uwyn.rife.database.querymanagers.generic.CountQuery; import com.uwyn.rife.database.querymanagers.generic.GenericQueryManager; import com.uwyn.rife.database.querymanagers.generic.GenericQueryManagerFactory; import com.uwyn.rife.database.querymanagers.generic.RestoreQuery; import com.uwyn.rife.engine.ElementContext; import com.uwyn.rife.engine.exceptions.EngineException; import com.uwyn.rife.site.*; import com.uwyn.rife.template.Template; import com.uwyn.rife.tools.BeanUtils; import com.uwyn.rife.tools.Convert; import com.uwyn.rife.tools.exceptions.InnerClassException; import com.uwyn.rife.tools.exceptions.BeanUtilsException; import com.uwyn.rife.tools.exceptions.ConversionException; import java.util.Collection; import java.util.HashMap; import java.util.Map; public class Browse extends CrudElement { public AdminTemplateTransformer getTransformer() { return new BrowseTemplateTransformer(this); } public void processElement() throws EngineException { final Template template = getTemplate(); new DbQueryManager(getDatasource()).inTransaction(new DbTransactionUserWithoutResult() { public void useTransactionWithoutResult() throws InnerClassException { // setup the paging variables int paging_limit = Convert.toInt(getProperty(PAGING_LIMIT), DEFAULT_PAGING_LIMIT); int paging_span = Convert.toInt(getProperty(PAGING_SPAN), DEFAULT_PAGING_SPAN); ContentQueryManager manager = getContentQueryManager(); CountQuery count_query = manager.getCountQuery(); RestoreQuery restore_query = manager.getRestoreQuery(); prepareQueries(count_query, restore_query, paging_limit); final int count = countEntities(manager, count_query); if (0 == count) { template.setBlock("crud_content", "crud_content_none"); } else { if (paging_limit > 0) { // generated the paged navigation PagedNavigation.generateNavigation(Browse.this, template, count, paging_limit, getPagingOffset(), paging_span); } else { template.setValue("ranged_table_area", ""); } // retrieve and output the beans restoreEntities(template, count, manager, restore_query); } } }); print(template); } protected void prepareQueries(CountQuery countQuery, RestoreQuery restoreQuery, int pagingLimit) { // if this is an association that's tied through a many-to-one property to another class // filter the search on the column value ConstrainedProperty manytoone_property = getManytooneConstrainedProperty(); if (manytoone_property != null) { ConstrainedProperty.ManyToOne manytoone_constraint = manytoone_property.getManyToOne(); String input_name = manytoone_constraint.getDerivedTable() + manytoone_constraint.getColumn(); if (hasInputValue(input_name)) { try { Class property_type = BeanUtils.getPropertyType(getBeanClass(), manytoone_property.getPropertyName()); Object property_value = Convert.toType(getInput(input_name), property_type); countQuery.where(manytoone_property.getPropertyName(), "=", property_value); restoreQuery.where(manytoone_property.getPropertyName(), "=", property_value); } catch (ConversionException e) { throw new EngineException(e); } catch (BeanUtilsException e) { throw new EngineException(e); } } } // add the paging query parts if (pagingLimit > 0) { restoreQuery.limit(pagingLimit); } if (getPagingOffset() > 0) { restoreQuery.offset(getPagingOffset()); } } protected int countEntities(ContentQueryManager manager, CountQuery countQuery) { return manager.count(countQuery); } protected void restoreEntities(Template template, int count, ContentQueryManager manager, RestoreQuery restore_query) { manager.restore(restore_query, new CrudBeanFetcher(template, count)); } protected int getPagingOffset() { int offset = -1; if (hasInputValue("offset")) { offset = getInputInt("offset"); } else { offset = 0; } return offset; } public class CrudBeanFetcher extends DbBeanFetcher { protected Map<Class, String> mAssociationsColumns = null; protected Map<Class, GenericQueryManager> mAssociationQuerymanagers = null; protected Map<String, Map<String, String>> mManyToOneIdentifiers = null; protected String mIdentityProperty = null; protected Template mTemplate = null; protected int mEntityCount = 0; protected Object mIdentity = null; protected int mCounter = 1; public CrudBeanFetcher(Template template, int entityCount) { super(getDatasource(), getBeanClass()); mTemplate = template; mEntityCount = entityCount; mAssociationsColumns = prepareAssociationColumns(); mAssociationQuerymanagers = prepareAssociationQueryManagers(); mManyToOneIdentifiers = prepareManyToOneIdentifiers(template); mIdentityProperty = ConstrainedUtils.getIdentityProperty(getBeanClass()); } protected Map<Class, String> prepareAssociationColumns() { return (Map<Class, String>)getProperty(getCrudPrefix() + "-associations_columns"); } protected Map<Class, GenericQueryManager> prepareAssociationQueryManagers() { // prepare for associations and collect related data if (mAssociationsColumns != null) { Map<Class, GenericQueryManager> managers = new HashMap<Class, GenericQueryManager>(); for (Class association : mAssociationsColumns.keySet()) { managers.put(association, GenericQueryManagerFactory.getInstance(getDatasource(), association)); } return managers; } else { return null; } } protected Map<String, Map<String, String>> prepareManyToOneIdentifiers(Template template) { // prepare for many-to-one textual identifiers Constrained constrained = getDefaultBeanConstrainedInstance(); Map<String, Map<String, String>> result = new HashMap<String, Map<String, String>>(); if (constrained != null) { for (ConstrainedProperty property : (Collection<ConstrainedProperty>)constrained.getConstrainedProperties()) { // if the property isn'template present in the template, it doesn'template need to be output if (!template.hasValueId(property.getPropertyName())) { continue; } // get the textual identifier map and store it for this property Map<String, String> many_to_one_map = generateManyToOneIdentifiers(property); if (many_to_one_map != null && many_to_one_map.size() > 0) { result.put(property.getPropertyName(), many_to_one_map); } } } return result; } public boolean gotBeanInstance(Object instance) { // output the bean values mTemplate.setBean(instance); // handle constraints Constrained<ConstrainedBean, ConstrainedProperty> constrained = ConstrainedUtils.makeConstrainedInstance(instance); if (constrained != null) { // display the properties in the correct order ContentQueryManager manager = getContentQueryManager(); for (ConstrainedProperty property : constrained.getConstrainedProperties()) { // handle many-to-one properties displayConstrainedProperty(mTemplate, manager, constrained, property); } } try { mIdentity = BeanUtils.getPropertyValue(instance, mIdentityProperty); } catch (BeanUtilsException e) { throw new EngineException(e); } setOutput(getIdentityVarName(), String.valueOf(mIdentity)); String exit_edit = getCrudPrefix()+"-edit"; if (mTemplate.hasValueId(ElementContext.PREFIX_EXIT_QUERY+exit_edit)) { setExitQuery(mTemplate, exit_edit); } else if (mTemplate.hasValueId(ElementContext.PREFIX_EXIT_FORM+exit_edit)) { setExitForm(mTemplate, exit_edit); } String exit_delete = getCrudPrefix()+"-delete"; if (mTemplate.hasValueId(ElementContext.PREFIX_EXIT_QUERY+exit_delete)) { setExitQuery(mTemplate, exit_delete); } else if (mTemplate.hasValueId(ElementContext.PREFIX_EXIT_FORM+exit_delete)) { setExitForm(mTemplate, exit_delete); } displayMoveButtons(mTemplate, mEntityCount, mCounter); displayAssociations(mTemplate); appendTableRow(mTemplate); mCounter++; return true; } protected void displayConstrainedProperty(Template template, ContentQueryManager manager, Constrained<ConstrainedBean, ConstrainedProperty> constrained, ConstrainedProperty property) { if (mManyToOneIdentifiers.containsKey(property.getPropertyName())) { Map<String, String> many_to_one_map = mManyToOneIdentifiers.get(property.getPropertyName()); try { Object value = BeanUtils.getPropertyValue(constrained, property.getPropertyName()); if (value != null) { String value_string = String.valueOf(value); if (many_to_one_map.containsKey(value_string)) { template.setValue(property.getPropertyName(), template.getEncoder().encode(many_to_one_map.get(value_string))); } } } catch (BeanUtilsException e) { // if the property bean value couldn'template be retrieved, use the default value // and don'template try to obtain the textual identifier } } // handle cmf constraints if (!property.isAutoRetrieved()) { MimeType mimetype = property.getMimeType(); if (mimetype != null) { if (0 == mimetype.toString().indexOf("image/")) { ContentInfo info = manager.getContentManager().getContentInfo(manager.buildCmfPath(constrained, property.getPropertyName())); displayImageProperty(template, property, info, ""); } else if (template.hasValueId(property.getPropertyName() + "-url") && MimeType.RAW == mimetype) { String cmf_path = manager.buildCmfPath(constrained, property.getPropertyName()); displayRawProperty(template, property, cmf_path, ""); } } } } protected void displayMoveButtons(Template template, int entityCount, int counter) { // handle ordinal move buttons if (hasProperty(getCrudPrefix() + "-ordinal_property_name")) { if (mTemplate.hasValueId(ElementContext.PREFIX_EXIT_QUERY+"up")) { setExitQuery(template, "up", new String[] {"direction", OrdinalManager.UP.toString()}); } else if (mTemplate.hasValueId(ElementContext.PREFIX_EXIT_FORM+"up")) { setExitForm(template, "up", new String[] {"direction", OrdinalManager.UP.toString()}); } if (mTemplate.hasValueId(ElementContext.PREFIX_EXIT_QUERY+"down")) { setExitQuery(template, "down", new String[] {"direction", OrdinalManager.DOWN.toString()}); } else if (mTemplate.hasValueId(ElementContext.PREFIX_EXIT_FORM+"down")) { setExitForm(template, "down", new String[] {"direction", OrdinalManager.DOWN.toString()}); } int offsetted_counter = counter+getPagingOffset(); if (1 == offsetted_counter) { template.setBlock("move_disabled_up", "move_disabled"); } if (offsetted_counter == entityCount) { template.setBlock("move_disabled_down", "move_disabled"); } } } protected void displayAssociations(Template template) { if (mAssociationsColumns != null) { GenericQueryManager gqm = null; Class association = null; int counter = 1; for (Map.Entry<Class, String> association_column : mAssociationsColumns.entrySet()) { association = association_column.getKey(); gqm = mAssociationQuerymanagers.get(association); int count = gqm.count(gqm.getCountQuery() .where(association_column.getValue(), "=", mIdentity)); template.setValue("association_entrycount" + counter, count); String exit_browse = CrudSiteProcessor.CRUD_PREFIX + association.getName() + "-browse"; if (mTemplate.hasValueId(ElementContext.PREFIX_EXIT_QUERY+exit_browse)) { setExitQuery(template, exit_browse); } else if (mTemplate.hasValueId(ElementContext.PREFIX_EXIT_FORM+exit_browse)) { setExitForm(template, exit_browse); } String exit_add = CrudSiteProcessor.CRUD_PREFIX + association.getName() + "-add"; if (mTemplate.hasValueId(ElementContext.PREFIX_EXIT_QUERY+exit_add)) { setExitQuery(template, exit_add); } else if (mTemplate.hasValueId(ElementContext.PREFIX_EXIT_FORM+exit_add)) { setExitForm(template, exit_add); } counter++; } } } protected void appendTableRow(Template template) { template.appendBlock("rows", "row"); // clear the ordinal move buttons that are disabled if (hasProperty(getCrudPrefix() + "-ordinal_property_name")) { template.removeValue("move_disabled_up"); template.removeValue("move_disabled_down"); } } } }