/* * Copyright 2012 The Solmix Project * * This is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.gnu.org/licenses/ * or see the FSF site: http://www.fsf.org. */ package org.solmix.sql; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.solmix.api.datasource.DSRequest; import org.solmix.api.exception.SlxException; import org.solmix.api.jaxb.Eoperation; import org.solmix.api.jaxb.Tfield; import org.solmix.commons.util.DataUtils; import org.solmix.fmk.velocity.Velocity; /** * * @author solmix.f@gmail.com * @version 110035 2011-3-23 */ @SuppressWarnings("unchecked") public class SQLValuesClause { private static Logger log = LoggerFactory.getLogger(SQLValuesClause.class.getName()); private final DSRequest dsRequest; private final SQLDataSource dataSource; private Map values; private List<String> returnValues; Map field2ColumnMap; private boolean batchUpdate; public SQLValuesClause(DSRequest request, SQLDataSource dataSource,boolean batchUpdate) throws SlxException { this(request, request.getContext().getValues(), dataSource, request.getContext().getCriteriaSets()); this.batchUpdate =batchUpdate; } public SQLValuesClause(DSRequest request, SQLDataSource dataSource) throws SlxException { this(request, dataSource, false); } public SQLValuesClause(DSRequest dsRequest, Map values, SQLDataSource dataSource, List constraints) throws SlxException { field2ColumnMap = null; this.dsRequest = dsRequest; this.dataSource = dataSource; field2ColumnMap = dataSource.getContext().getExpandedDs2NativeFieldMap(); // if (Assert.isNotNullAndEmpty(constraints) ) // values = DataUtils.subsetMap(values, constraints); this.values = filterValid(values); } private Map filterValid(Map data) { if (data == null) return null; Map __return = new HashMap(); List _valid = dataSource.getContext().getFieldNames(); List _invalid = new ArrayList(); for (Object o : data.keySet()) { String _name = (String) o; if (!_valid.contains(_name)) _invalid.add(_name); else __return.put(_name, data.get(_name)); } if (!_invalid.isEmpty()) log.debug("Ignored data for non-existent columns: " + _invalid.toString()); return __return; } public String getSQLStringForInsert() throws SlxException { if (size() == 0) { log.debug("no values data ,returning empty string"); return ""; } Map<String,String> _temp = new LinkedHashMap<String,String>(); // StringBuffer __return = new StringBuffer(); StringBuffer _columnList = new StringBuffer(); StringBuffer _valueList = new StringBuffer(); Map sequences = dataSource.getSequences(); SQLDriver driver = dataSource.getDriver(); // values = DataUtils.divideMap(values, new ArrayList(sequences.keySet())); if (values == null) values = new HashMap(); for (Object key : values.keySet()) { String __fieldName = (String) key; Tfield __f = dataSource.getContext().getField( __fieldName ); String nativeFieldName = (String) field2ColumnMap.get(__fieldName); String __v; if ( !driver.fieldAssignableInline( __f ) ) __v= "?" ; else if(this.batchUpdate){ __v= "?" ; }else{ __v=dataSource.sqlValueForFieldValue(__fieldName, values.get(__fieldName)); } _temp.put(dataSource.escapeColumnName(nativeFieldName), __v); addToReturnValue(__fieldName); } log.debug( "Sequences:[" + sequences + "]" ); //sequence Iterator it = sequences.keySet().iterator(); do{ if(!it.hasNext()) break; String fieldName =(String) it.next(); String columnName = (String)field2ColumnMap.get( fieldName ); boolean omitValue = false; if ( values.containsKey( fieldName ) && values.get( fieldName ) != null ) { _temp.put( dataSource.escapeColumnName( columnName ), dataSource.sqlValueForFieldValue( fieldName, values.get( fieldName ) ) ); } else if ( !omitValue ) { _temp.put(dataSource.escapeColumnName( columnName ),dataSource.getNextSequenceValue( columnName )); } } while ( true ); for(Tfield __f:dataSource.getContext().getFields()){ if(__f.getCustomInsertExpression()!=null){ String nativeFieldName = (String) field2ColumnMap.get(__f.getName()); _temp.put(dataSource.escapeColumnName(nativeFieldName), getCustomInsertExpression( __f )); } } if (_temp.isEmpty()) return null; else{ int i=0; for(String key:_temp.keySet()){ i++; _columnList.append(key); _valueList.append(_temp.get(key)); if(i<_temp.keySet().size()){ _columnList.append(','); _valueList.append(','); } } } return (new StringBuilder()).append("(").append(_columnList.toString()).append(") VALUES (").append(_valueList.toString()).append(")").toString(); } /** * @return the returnValues * @throws SlxException */ public List<String> getReturnValues() throws SlxException { if(this.returnValues==null){ Eoperation type =this.dsRequest.getContext().getOperationType(); if(type == Eoperation.UPDATE){ getSQLStringForUpdate(); }else if(type == Eoperation.ADD){ getSQLStringForInsert(); } } return returnValues; } private void addToReturnValue(String value){ if(this.returnValues==null) returnValues = new ArrayList<String>(); returnValues.add(value); } private String getCustomUpdateExpression( Tfield field ) throws SlxException { String clause = field.getCustomUpdateExpression(); return Velocity.evaluateAsString( clause, Velocity.getStandardContextMap( dsRequest ) ); } private String getCustomInsertExpression( Tfield field ) throws SlxException { String clause = field.getCustomInsertExpression(); return Velocity.evaluateAsString( clause, Velocity.getStandardContextMap( dsRequest ) ); } public boolean isEmpty() { return values == null; } public int size() { return !isEmpty() ? 1 : 0; } /** * @return */ public String getSQLStringForUpdate() { if (size() == 0) { log.debug("no data; returning empty string"); return ""; } // Map sequences = dataSource.getTable().getSequences(); // SQLDriver driver = dataSource.getDriver(); List primaryKeys = dataSource.getTable().getPrimaryKeys(); if (primaryKeys != null) { Map newValues = DataUtils.divideMap(values, primaryKeys); if (newValues != null) values = newValues; } StringBuffer __result = new StringBuffer(); for (Object key : values.keySet()) { String fieldName = (String) key; String columnName = (String) field2ColumnMap.get(fieldName); if (__result.length() != 0) __result.append(", "); __result.append(new StringBuilder().append(dataSource.escapeColumnName(columnName)).append("=").toString()); Object columnValue = values.get(fieldName); __result.append(dataSource.sqlValueForFieldValue(fieldName, columnValue)); } if (__result.toString() == null || __result.toString().isEmpty()) return null; else return __result.toString(); } }