package com.ycsoft.report.query.daq.translate;
import static com.ycsoft.report.commons.ReportConstants.memory_row_max;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import com.ycsoft.commons.exception.ReportException;
import com.ycsoft.commons.helper.LoggerHelper;
import com.ycsoft.report.commons.CacheInput;
import com.ycsoft.report.commons.FileObjectInputStream;
import com.ycsoft.report.commons.ReportConstants;
import com.ycsoft.report.query.cube.CellType;
import com.ycsoft.report.query.cube.CubeHeadCell;
import com.ycsoft.report.query.cube.DimensionRolap;
import com.ycsoft.report.query.cube.DimensionType;
import com.ycsoft.report.query.cube.Measure;
import com.ycsoft.report.query.cube.impl.AbstractDataSet;
import com.ycsoft.report.query.daq.DataReader;
import com.ycsoft.report.query.key.Impl.QueryKeyValue;
/**
* cube从缓存中提取数据体
*/
public class CacheAcquisition implements CacheTranslateCube {
private boolean translate_sucess=false;
private Map<CacheKey,List<Double>> menoryMap=new HashMap<CacheKey,List<Double>>();
//private List<CacheKey> menoryList=new ArrayList<CacheKey>();
/**
* 计算转换用的权限判断的虚拟表头
* @param dataset
* @return
* @throws ReportException
*/
protected List<CacheHeadCell> createDataCotrolHead(AbstractDataSet dataset) throws ReportException {
//未使用的但有权限控制影响的维度清单
List<DimensionRolap> datacotrolRolaps=new ArrayList<DimensionRolap>();
for(DimensionRolap rolap:dataset.getCube().getDimensionRolaps()){
if(!rolap.isUsesign()&&rolap.getDim().getDimLevelControlMap().size()>0)
datacotrolRolaps.add(rolap);
}
//创建计算用cube表头
List<CacheHeadCell> headlist=new ArrayList<CacheHeadCell>();
//未使用的维度(有权限的)的虚拟表头计算
for(DimensionRolap rolap: datacotrolRolaps){
CacheHeadCell o=CacheHeadCell.createDummyHead(rolap);
headlist.add(o);
}
return headlist;
}
/**
* 计算转换用的cube表头
* @param cube
* @return
* @throws ReportException
*/
protected List<CacheHeadCell> createCacheHeadCell(AbstractDataSet dataset) throws ReportException{
List<DimensionRolap> dimrolaps= dataset.getCube().getDimensionRolaps();
//有效维清单维度列表
Map<String,DimensionRolap> rolapMap=new HashMap<String,DimensionRolap>();
for(DimensionRolap rolap:dimrolaps){
if(rolap.isUsesign()) rolapMap.put(rolap.getId(), rolap);
}
Map<String,Measure> meaMap=new HashMap<String,Measure>();
for(Measure o:dataset.getCube().getMeasures()){
meaMap.put(o.getColumnCode(), o);
}
//创建计算用cube表头
List<CacheHeadCell> headlist=new ArrayList<CacheHeadCell>();
//cacheMap用于缓存表头在权限和切片影响下维度各个层级取值和排序取值(目的是为了减少计算量)
CacheMap cacheMap=new CacheMap();
//有效维度表头计算
for(CubeHeadCell cell: dataset.getBaseHeadCells()){
if(cell.getCell_type().equals(CellType.dimension)){
CacheHeadCell o=null;
if(cell.getDim_type().equals(DimensionType.crosswise))
o=CacheHeadCell.createCrossHead(cell, rolapMap.get(cell.getDim()),cacheMap);
else if(cell.getDim_type().equals(DimensionType.vertical))
o=CacheHeadCell.createVerticalHead(cell, rolapMap.get(cell.getDim()), meaMap.get(cell.getMea_code()),cacheMap);
else if(cell.getDim_type().equals(DimensionType.measure))
o=CacheHeadCell.createMeasureHead(cell, meaMap.get(cell.getMea_code()));
else throw new ReportException("cell type error.");
headlist.add(o);
}
}
return headlist;
}
/**
* 创建CacheKey初始化用值
* @param headlist
* @param no_crosshead_start
* @param rowmap
* @return
* @throws ReportException
*/
protected CacheKey getCacheKey(List<CacheHeadCell> headlist,int no_crosshead_start,Map<String,Object> rowmap,List<CacheHeadCell> datacotrolheads) throws ReportException{
//未使用的维度的虚拟表头权限判断
for(CacheHeadCell cell: datacotrolheads){
QueryKeyValue keyvalue= cell.translateKeyValue(rowmap.get(cell.getCubemappingkey()).toString()) ;
if(keyvalue==null) return null;
}
List<Object> keylist=new ArrayList<Object>();
List<Integer> sortlist=new ArrayList<Integer>();
//判断keyvalue为空的情况
for(int i=0;i<no_crosshead_start;i++ ){
CacheHeadCell cell=headlist.get(i);
QueryKeyValue keyvalue= cell.translateKeyValue(rowmap.get(cell.getCubemappingkey()).toString()) ;
if(keyvalue==null) return null;
sortlist.add(cell.translateSortValue(keyvalue));
keylist.add(keyvalue.getId());
}
return createCacheKey(keylist,sortlist);
}
protected CacheKey createCacheKey(List<Object> keylist,List<Integer> sortlist) throws ReportException{
return new CacheKey(keylist,sortlist);
}
/**
* CacheKey 值运算
* @param valuelist
* @param headlist
* @param no_crosshead_start
* @param rowmap
* @return
* @throws ReportException
*/
protected List<Double> getCacheValue(Boolean key_sign,List<Double> valuelist,List<CacheHeadCell> headlist,int no_crosshead_start,Map<String,Object> rowmap) throws ReportException{
for(int i=no_crosshead_start;i<headlist.size();i++){
CacheHeadCell cell=headlist.get(i);
double value=0;
//数据行表头是纵向维度
if(cell.getDim_type().equals(DimensionType.vertical)){
//纵向表头存储的值与维度最低层id值逆推的当前层的值一致
QueryKeyValue keyvalue= cell.translateKeyValue(rowmap.get(cell.getCubemappingkey()).toString());
if(keyvalue!=null&&cell.getId().toString().equals(keyvalue.getId())){
value=((Number)rowmap.get(cell.getMea_code())).doubleValue();
}
}else {
//数据行表头是度量
value=((Number)rowmap.get(cell.getCubemappingkey())).doubleValue();
}
if(key_sign){
valuelist.set(i-no_crosshead_start, cell.getMeagather().gather(valuelist.get(i-no_crosshead_start),value));
}else
valuelist.add(value);
}
return valuelist;
}
/**
* CacheKey 值运算
* @param valuelist
* @param headlist
* @param no_crosshead_start
* @param rowmap
* @return
* @throws ReportException
*/
protected List<Double> getCacheValue(CacheKey cachekey,List<CacheHeadCell> headlist,int no_crosshead_start,Map<String,Object> rowmap) throws ReportException{
List<Double> valuelist=menoryMap.get(cachekey);
boolean value_exist=true;
if(valuelist==null) {
valuelist=new ArrayList<Double>();
menoryMap.put(cachekey, valuelist);
value_exist=false;
}
for(int i=no_crosshead_start;i<headlist.size();i++){
CacheHeadCell cell=headlist.get(i);
double value=0;
//数据行表头是纵向维度
if(cell.getDim_type().equals(DimensionType.vertical)){
//纵向表头存储的值与维度最低层id值逆推的当前层的值一致
QueryKeyValue keyvalue= cell.translateKeyValue(rowmap.get(cell.getCubemappingkey()).toString());
if(keyvalue!=null&&cell.getId().toString().equals(keyvalue.getId())){
value=((Number)rowmap.get(cell.getMea_code())).doubleValue();
}
}else {
//数据行表头是度量
value=((Number)rowmap.get(cell.getCubemappingkey())).doubleValue();
}
if(value_exist){
valuelist.set(i-no_crosshead_start, cell.getMeagather().gather(valuelist.get(i-no_crosshead_start),value));
}else
valuelist.add(value);
}
return valuelist;
}
/**
* 基础文件的读取queryid_base
* @param full_cache_id
* @return
* @throws IOException
* @throws ReportException
*/
protected CacheInput createBaseCacheInput(String query_cache_id) throws IOException, ReportException{
return new FileObjectInputStream(ReportConstants.REP_TEMP_TXT+ query_cache_id+ReportConstants.CACHE_BASE);
}
/**
* 非横向维表头的开始位置索引
* @param headlist
* @return
*/
protected int getNoCrossheadStart(List<CacheHeadCell> headlist){
int no_crosshead_start=0;
for(CacheHeadCell cell:headlist){
if(cell.getDim_type().equals(DimensionType.crosswise)) no_crosshead_start++ ;
else break;
}
return no_crosshead_start;
}
/**
* 从缓存文件中提取转换出cube数据体
*/
public DataReader translate(String query_cache_id,AbstractDataSet dataset) throws ReportException {
CacheInput foi=null;
try {
//维度计算用表头
List<CacheHeadCell> headlist=createCacheHeadCell(dataset);
//指标关联开始索引
int no_crosshead_start=this.getNoCrossheadStart(headlist);
//读取基础计算数据
foi=this.createBaseCacheInput(query_cache_id);
//未使用的维度权限控制的虚拟表头
List<CacheHeadCell> datacotrolheadlist=this.createDataCotrolHead(dataset);
//基础缓存文件行记录
Map<String,Object> rowmap=null;
boolean key_exist=true;
while((rowmap=(Map<String, Object>) foi.readObject())!=null){
//计算key
CacheKey cachekey=this.getCacheKey(headlist, no_crosshead_start, rowmap,datacotrolheadlist);
if(cachekey!=null){
//值运算
this.getCacheValue(cachekey, headlist, no_crosshead_start, rowmap);
//判断转换后的内存快是否超过1000行,超过则跳出
if(isMenoryMax()){
this.translate_sucess=false;
this.menoryMap.clear();
return null;
}
}
}
translate_sucess=true;
LoggerHelper.debug(this.getClass(),dataset.getAssembleDataSet());
// int i=1;
//
// for(CacheKey key: this.menoryList){
// System.out.print("\t"+i);
// for(Object o: key.getKeys())
// System.out.print("\t"+o);
// for(Double o: this.menoryMap.get(key))
// System.out.print("\t"+o);
// System.out.println();
// i++;
// }
// System.out.println("debug end.");
return new DR();
} catch (IOException e) {
throw new ReportException(e);
} catch (ClassNotFoundException e) {
throw new ReportException(e);
}finally{
if(foi!=null){
try {
foi.close();
} catch (Exception e) {
}
}
}
}
/**
* 是否达到内存限额
* @return
* @throws ReportException
*/
protected boolean isMenoryMax() throws ReportException{
return menoryMap.size()>memory_row_max?true:false;
}
public boolean isTranslateSucess() {
return translate_sucess;
}
class DR implements DataReader{
private int dr_idx=0;
private int dr_max=-1;
private List<CacheKey> menoryList=null;
public DR(){
menoryList=new ArrayList<CacheKey>(menoryMap.size());
}
public void close() throws ReportException {
if(menoryList!=null)
menoryList.clear();
menoryMap.clear();
}
public Object getObject(int i) throws ReportException {
return menoryList.get(dr_idx).getKeys().get(i-1);
}
public String getString(int i) throws ReportException {
return menoryList.get(dr_idx).getKeys().get(i-1).toString();
}
public boolean next() throws ReportException {
if(dr_max<0)
throw new ReportException("DataReader is hasnot open.");
dr_idx++;
if(dr_idx<dr_max){
CacheKey cachekey=menoryList.get(dr_idx);
cachekey.getKeys().addAll(menoryMap.get(cachekey));
return true;
}else
return false;
}
/**
* 转换成正确的格式
*/
public void open() throws ReportException {
if(translate_sucess){
dr_idx=-1;
dr_max=menoryMap.size();
Iterator<CacheKey> it=menoryMap.keySet().iterator();
while(it.hasNext()){
this.menoryList.add(it.next());
}
//执行排序
Collections.sort(menoryList);
//限制只能打开一遍
translate_sucess=false;
}else
throw new ReportException("cannot open again.");
}
}
protected Map<CacheKey, List<Double>> getMenoryMap() {
return menoryMap;
}
}