luban/src/Luban.Job.Cfg/Source/DataCreators/ExcelNamedRowDataCreator.cs

353 lines
13 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

using Luban.Common.Utils;
using Luban.Job.Cfg.Datas;
using Luban.Job.Cfg.DataSources.Excel;
using Luban.Job.Cfg.Defs;
using Luban.Job.Cfg.TypeVisitors;
using Luban.Job.Common.Types;
using Luban.Job.Common.TypeVisitors;
using System;
using System.Collections.Generic;
namespace Luban.Job.Cfg.DataCreators
{
class ExcelNamedRowDataCreator : ITypeFuncVisitor<Sheet.NamedRow, bool, bool, DType>
{
public static ExcelNamedRowDataCreator Ins { get; } = new ExcelNamedRowDataCreator();
public DType ReadExcel(Sheet.NamedRow row, TBean btype)
{
return Accept(btype, row, false, false);
}
public DType Accept(TBool type, Sheet.NamedRow x, bool multirow, bool nullable)
{
throw new NotSupportedException();
}
public DType Accept(TByte type, Sheet.NamedRow x, bool multirow, bool nullable)
{
throw new NotSupportedException();
}
public DType Accept(TShort type, Sheet.NamedRow x, bool multirow, bool nullable)
{
throw new NotSupportedException();
}
public DType Accept(TFshort type, Sheet.NamedRow x, bool multirow, bool nullable)
{
throw new NotSupportedException();
}
public DType Accept(TInt type, Sheet.NamedRow x, bool multirow, bool nullable)
{
throw new NotSupportedException();
}
public DType Accept(TFint type, Sheet.NamedRow x, bool multirow, bool nullable)
{
throw new NotSupportedException();
}
public DType Accept(TLong type, Sheet.NamedRow x, bool multirow, bool nullable)
{
throw new NotSupportedException();
}
public DType Accept(TFlong type, Sheet.NamedRow x, bool multirow, bool nullable)
{
throw new NotSupportedException();
}
public DType Accept(TFloat type, Sheet.NamedRow x, bool multirow, bool nullable)
{
throw new NotSupportedException();
}
public DType Accept(TDouble type, Sheet.NamedRow x, bool multirow, bool nullable)
{
throw new NotSupportedException();
}
public DType Accept(TEnum type, Sheet.NamedRow x, bool multirow, bool nullable)
{
throw new NotSupportedException();
}
public DType Accept(TString type, Sheet.NamedRow x, bool multirow, bool nullable)
{
throw new NotSupportedException();
}
public DType Accept(TBytes type, Sheet.NamedRow x, bool multirow, bool nullable)
{
throw new NotSupportedException();
}
public DType Accept(TText type, Sheet.NamedRow x, bool multirow, bool nullable)
{
throw new NotSupportedException();
}
private static bool IsContainerAndElementNotSepType(TType type)
{
switch (type)
{
case TArray ta: return ta.ElementType.Apply(IsNotSepTypeVisitor.Ins);
case TList tl: return tl.ElementType.Apply(IsNotSepTypeVisitor.Ins);
case TSet ts: return ts.ElementType.Apply(IsNotSepTypeVisitor.Ins);
case TMap tm: return tm.KeyType.Apply(IsNotSepTypeVisitor.Ins) && tm.ValueType.Apply(IsNotSepTypeVisitor.Ins);
default: return false;
}
throw new NotImplementedException();
}
private List<DType> CreateBeanFields(DefBean bean, Sheet.NamedRow row)
{
var list = new List<DType>();
foreach (DefField f in bean.HierarchyFields)
{
string fname = f.Name;
Sheet.Title title = row.GetTitle(fname);
if (title == null)
{
throw new Exception($"bean:'{bean.FullName}' 缺失 列:'{fname}',请检查是否写错或者遗漏");
}
// 多级标题
if (title.SubTitles.Count > 0)
{
try
{
list.Add(f.CType.Apply(this, row.GetSubTitleNamedRow(fname), f.IsMultiRow, f.IsNullable));
}
catch (DataCreateException dce)
{
dce.Push(bean, f);
throw;
}
catch (Exception e)
{
var dce = new DataCreateException(e, $"列:{fname}");
dce.Push(bean, f);
throw dce;
}
}
else
{
string sep = f.ActualSep;
if (string.IsNullOrWhiteSpace(sep) && IsContainerAndElementNotSepType(f.CType))
{
sep = ";,";
}
if (f.IsMultiRow)
{
try
{
if (f.CType.IsCollection)
{
list.Add(f.CType.Apply(MultiRowExcelDataCreator.Ins, row.GetColumnOfMultiRows(f.Name, sep, f.IsRowOrient), f.IsNullable, (DefAssembly)bean.AssemblyBase));
}
else
{
list.Add(f.CType.Apply(ExcelDataCreator.Ins, null, row.GetMultiRowStream(f.Name, sep, f.IsRowOrient), (DefAssembly)bean.AssemblyBase));
}
}
catch (DataCreateException dce)
{
dce.Push(bean, f);
throw;
}
catch (Exception e)
{
var dce = new DataCreateException(e, "");
dce.Push(bean, f);
throw dce;
}
}
else
{
ExcelStream stream = row.GetColumn(f.Name, sep, !f.CType.Apply(IsMultiData.Ins));
try
{
list.Add(f.CType.Apply(ExcelDataCreator.Ins, f, stream, (DefAssembly)bean.AssemblyBase));
}
catch (DataCreateException dce)
{
dce.Push(bean, f);
throw;
}
catch (Exception e)
{
var dce = new DataCreateException(e, stream.LastReadDataInfo);
dce.Push(bean, f);
throw dce;
}
}
}
}
return list;
}
public DType Accept(TBean type, Sheet.NamedRow row, bool multirow, bool nullable)
{
var originBean = (DefBean)type.Bean;
if (originBean.IsAbstractType)
{
string subType = row.GetColumn(DefBean.TYPE_NAME_KEY, null, true).Read().ToString().Trim();
if (subType.ToLower() == DefBean.BEAN_NULL_STR)
{
if (!type.IsNullable)
{
throw new Exception($"type:'{type}' 不是可空类型 '{type.Bean.FullName}?' , 不能为空");
}
return null;
}
string fullType = TypeUtil.MakeFullName(originBean.Namespace, subType);
DefBean implType = (DefBean)originBean.GetNotAbstractChildType(subType);
if (implType == null)
{
throw new Exception($"type:'{fullType}' 不是 bean 类型");
}
return new DBean(originBean, implType, CreateBeanFields(implType, row));
}
else
{
if (type.IsNullable)
{
string subType = row.GetColumn(DefBean.TYPE_NAME_KEY, null, true).Read().ToString().Trim();
if (subType == DefBean.BEAN_NULL_STR)
{
return null;
}
else if (subType != DefBean.BEAN_NOT_NULL_STR && subType != originBean.Name)
{
throw new Exception($"type:'{type.Bean.FullName}' 可空标识:'{subType}' 不合法(只能为{DefBean.BEAN_NOT_NULL_STR}或{DefBean.BEAN_NULL_STR}或{originBean.Name})");
}
}
return new DBean(originBean, originBean, CreateBeanFields(originBean, row));
}
}
private List<DType> ReadList(TBean elementType, Sheet.NamedRow row, bool multirow)
{
var list = new List<DType>();
// 如果是多行数据以当前title为title,每行读入一个element
if (multirow)
{
//foreach (var sub in row.GenerateSubNameRows(elementType))
foreach (var sub in Sheet.NamedRow.CreateMultiRowNamedRow(row.Rows, row.SelfTitle, elementType))
{
list.Add(this.Accept(elementType, sub, false, false));
}
}
else
{
// 如果不是多行,并且定义了子标题的话。以一个子标题所占的列,读入一个数据
//foreach (var sub in row.SelfTitle.SubTitleList)
//{
// list.Add(this.Accept(elementType, new Sheet.NamedRow(sub, row.Rows), false, false));
//}
throw new NotSupportedException("只有multi_rows=1的list,bean类型才允许有子title");
}
return list;
}
public DType Accept(TArray type, Sheet.NamedRow x, bool multirow, bool nullable)
{
if (type.ElementType is not TBean bean)
{
throw new Exception($"NamedRow 只支持 bean 类型的容器");
}
else
{
return new DArray(type, ReadList(bean, x, multirow));
}
}
public DType Accept(TList type, Sheet.NamedRow x, bool multirow, bool nullable)
{
if (type.ElementType is not TBean bean)
{
throw new Exception($"NamedRow 只支持 bean 类型的容器");
}
else
{
return new DList(type, ReadList(bean, x, multirow));
}
}
public DType Accept(TSet type, Sheet.NamedRow x, bool multirow, bool nullable)
{
throw new NotSupportedException();
}
private bool TryCreateColumnStream(Sheet.NamedRow x, Sheet.Title title, out ExcelStream stream)
{
var cells = new List<Cell>();
for (int i = title.FromIndex; i <= title.ToIndex; i++)
{
foreach (var row in x.Rows)
{
if (row.Count > i)
{
var value = row[i].Value;
if (!(value == null || (value is string s && string.IsNullOrEmpty(s))))
{
cells.Add(row[i]);
}
}
}
}
if (cells.Count > 0)
{
stream = new ExcelStream(cells, 0, cells.Count - 1, "", false);
return true;
}
stream = null;
return false;
}
public DType Accept(TMap type, Sheet.NamedRow x, bool multirow, bool nullable)
{
var map = new Dictionary<DType, DType>();
foreach (var e in x.Titles)
{
if (TryCreateColumnStream(x, e.Value, out var stream))
{
var keyData = type.KeyType.Apply(StringDataCreator.Ins, e.Key);
var valueData = type.ValueType.Apply(ExcelDataCreator.Ins, null, stream, DefAssembly.LocalAssebmly);
map.Add(keyData, valueData);
}
}
return new DMap(type, map);
}
public DType Accept(TVector2 type, Sheet.NamedRow x, bool multirow, bool nullable)
{
throw new NotSupportedException();
}
public DType Accept(TVector3 type, Sheet.NamedRow x, bool multirow, bool nullable)
{
throw new NotSupportedException();
}
public DType Accept(TVector4 type, Sheet.NamedRow x, bool multirow, bool nullable)
{
throw new NotSupportedException();
}
public DType Accept(TDateTime type, Sheet.NamedRow x, bool multirow, bool nullable)
{
throw new NotSupportedException();
}
}
}