/* * 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.fmk.datasource; import static org.solmix.commons.util.DataUtils.makeListIfSingle; import java.util.ArrayList; 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.datasource.DSResponse; import org.solmix.api.datasource.DataSource; import org.solmix.api.exception.SlxException; import org.solmix.commons.util.DataUtils; /** * @author solmix.f@gmail.com * @since 0.0.1 * @version 110035 2011-1-3 solmix-ds */ @SuppressWarnings("unchecked") public class DSResponseImpl implements DSResponse { private static final Logger log = LoggerFactory.getLogger(DSResponseImpl.class); private DataSource dataSource; private Object rawData; private Integer startRow; private Integer endRow; private Integer totalRows; private Object[] errors; private Status status=Status.UNSET; private Long affectedRows; private boolean invalidateCache; private String operationType; private String handlerName; public DSResponseImpl() { } public DSResponseImpl(Status status) { setStatus(status); } public DSResponseImpl(DSRequest request){ this(request,null); } public DSResponseImpl(DSRequest request, Status status) { try { DataSource ds = request.getDataSource(); setDataSource(ds); } catch (SlxException e) { // ignore } if (request != null) { setOperationType(request.getContext().getOperationType().value()); } if(status!=null) setStatus(status); } public DSResponseImpl(Object data, Status status) { this(); setRawData(data); setStatus(status); } public DSResponseImpl(DataSource dataSource) { setDataSource(dataSource); } public DSResponseImpl(DataSource dataSource, Status status) { this(dataSource); setStatus(status); } public DSResponseImpl(DataSource dataSource,DSRequest request) { setDataSource(dataSource); if(request!=null){ setOperationType(request.getContext().getOperationType().value()); } } /** * @param value */ @Override public void setOperationType(String value) { this.operationType=value; } @Override public String getOperationType(){ return this.operationType; } public DSResponseImpl(DataSource dataSource, Object data) { this(dataSource); setRawData(data); } public DSResponseImpl(DataSource dataSource, Object data, Status status) { this(dataSource, data); setStatus(status); } /** * @return the startRow */ @Override public Integer getStartRow() { return startRow; } /** * @param startRow the startRow to set */ @Override public void setStartRow(Integer startRow) { this.startRow = startRow; } /** * @return the endRow */ @Override public Integer getEndRow() { return endRow; } /** * @param endRow the endRow to set */ @Override public void setEndRow(Integer endRow) { this.endRow = endRow; } /** * @return the totalRows */ @Override public Integer getTotalRows() { return totalRows; } /** * @param totalRows the totalRows to set */ @Override public void setTotalRows(Integer totalRows) { this.totalRows = totalRows; } /** * @return the errors */ @Override public Object[] getErrors() { return errors; } /** * @param errors the errors to set */ @Override public void setErrors(Object... errors) { this.errors = errors; } /** * @return the dataSource */ @Override public DataSource getDataSource() { return dataSource; } /** * @param dataSource the dataSource to set */ @Override public void setDataSource(DataSource dataSource) { this.dataSource = dataSource; } @Override public Map<Object, Object> getSingleRecord() { if (getDataSource() == null) { throw new java.lang.IllegalStateException("Attempted to call getSingleRecord() on a DSResponse with null DataSource"); } Object singleData = null; if (rawData instanceof List<?>) { if (((List<?>) rawData).size() > 0) singleData = ((List<?>) rawData).get(0); else singleData = null; } else { singleData = rawData; } Map<Object, Object> record = getDataSource().getProperties(singleData); return record; } @Override public List<Map<Object, Object>> getRecordList() { if (getDataSource() == null) { throw new java.lang.IllegalStateException("Attempted to call getSingleRecord() on a DSResponse with null DataSource"); } List<Map<Object, Object>> target = new ArrayList<Map<Object, Object>>(); List<Object> sources = makeListIfSingle(rawData); for (Object source : sources) { if (source instanceof Map<?, ?>) { target.add((Map<Object, Object>) source); } else { target.add(getDataSource().getProperties(source)); } } return target; } protected Map<String, Object> JSResponseTransform(Map<String, Object> origMap) { if (origMap.get("status") != null) origMap.put("status", ((Status) origMap.get("status")).value()); return origMap; } /** * {@inheritDoc} * * @see org.solmix.api.datasource.DSResponse#getStatus() */ @Override public Status getStatus() { return this.status; } /** * {@inheritDoc} * * @see org.solmix.api.datasource.DSResponse#isSuccess() */ @Override public boolean isSuccess() { Status _s = this.getStatus(); return _s == Status.STATUS_SUCCESS; } /** * {@inheritDoc} * * @see org.solmix.api.datasource.DSResponse#setStatus(org.solmix.api.datasource.DSResponse.Status) */ @Override public void setStatus(Status status) { this.status = status; } /** * @return the rawData */ @Override public Object getRawData() { return rawData; } /** * @param rawData the rawData to set */ @Override public void setRawData(Object rawData) { this.rawData = rawData; } /** * {@inheritDoc} * * @see org.solmix.api.datasource.DSResponse#getSingleResult(java.lang.Class) */ @Override public <T> T getSingleResult(Class<T> type) { return _getResult(type,rawData); } /** * {@inheritDoc} * * @see org.solmix.api.datasource.DSResponse#getResultList(java.lang.Class) */ @Override public <T> List<T> getResultList(Class<T> type) { List<T> _return = new ArrayList<T>(); if (List.class.isAssignableFrom(rawData.getClass())) { for (Object obj : List.class.cast(rawData)) { _return.add(_getResult(type, obj)); } }else { try { _return.add(DataUtils.convertType(type, rawData)); } catch (Exception e) { log.error(e.getMessage()); } } return _return; } protected <T> T _getResult(Class<T> type, Object data) { if (data == null) return null; if (type.isInstance(data)) return (T) data; // First, assume that the type is Map. if (Map.class.isAssignableFrom(type)) { if (data instanceof List<?>) { if (((List<?>) data).size() == 0) { return null; } else if (((List<?>) data).get(0) instanceof Map<?, ?>) { return (T) ((List<?>) data).get(0); } } else if (data instanceof Map<?, ?>) { return (T) data; } // Then,assume that the type is List. } else if (List.class.isAssignableFrom(type)) { if (data instanceof List<?>) { return (T) data; } else { List<Object> re = new ArrayList<Object>(); re.add(data); return (T) re; } } else if (!type.isPrimitive() && !type.isInterface() && !type.isArray()) { try { if (Map.class.isAssignableFrom(data.getClass())) { Object instance = type.newInstance(); DataUtils.setProperties(Map.class.cast(data), instance, false); return (T) instance; } else if (List.class.isAssignableFrom(data.getClass())) { List<Object> datas = List.class.cast(data); int size = datas.size(); if (size > 0) { Object one = datas.get(0); T _return = null; if (type.isAssignableFrom(one.getClass())) { _return = type.cast(one); } else if (Map.class.isAssignableFrom(one.getClass())) { _return = type.newInstance(); DataUtils.setProperties((Map<?, ?>) one, _return, false); } if (size > 1) { log.warn("The data is more than one map or bean, used the first one and drop other " + (datas.size() - 1) + "(s)"); } return _return; } else { log.warn("The data is List is empty ,return object is null "); return null; } } else { return DataUtils.convertType(type, data); } } catch (Exception ee) { log.debug((new StringBuilder()).append("Tried to convert inbound nested Map to: ").append(type.getName()).append( " but DataTools.setProperties() on instantiated class failed").append(" with the following error: ").append(ee.getMessage()).toString()); } } throw new IllegalArgumentException((new StringBuilder()).append("Can't convert value of type ").append(data.getClass().getName()).append( " to target type ").append(type.getName()).toString()); } /** * {@inheritDoc} * * @see org.solmix.api.datasource.DSResponse#setAffectedRows(java.lang.Long) */ @Override public void setAffectedRows(Long affectedRows) { this.affectedRows=affectedRows; } /** * {@inheritDoc} * * @see org.solmix.api.datasource.DSResponse#getAffectedRows(java.lang.Long) */ @Override public Long getAffectedRows(Long long1) { return affectedRows; } /** * {@inheritDoc} * * @see org.solmix.api.datasource.DSResponse#setInvalidateCache(boolean) */ @Override public void setInvalidateCache(boolean invalidateCache) { this.invalidateCache=invalidateCache; } /** * {@inheritDoc} * * @see org.solmix.api.datasource.DSResponse#getInvalidateCache() */ @Override public boolean getInvalidateCache() { return invalidateCache; } /** * @return the handlerName */ @Override public String getHandlerName() { return handlerName; } /** * @param handlerName the handlerName to set */ @Override public void setHandlerName(String handlerName) { this.handlerName = handlerName; } }