Skip to content
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,11 @@

package org.apache.fesod.excel.metadata;

import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.Objects;
import java.util.stream.Collectors;
import org.apache.fesod.excel.converters.Converter;
import org.apache.fesod.excel.enums.CacheLocationEnum;
import org.apache.fesod.excel.util.ListUtils;
Expand All @@ -39,10 +41,23 @@ public abstract class AbstractParameterBuilder<T extends AbstractParameterBuilde
* @return
*/
public T head(List<List<String>> head) {
parameter().setHead(head);
parameter().setHead(toMutableListIfNecessary(head));
return self();
}

/**
* Ensures and returns a fully mutable deep copy of head list.
*
* @param head head The source list to create a mutable copy from.
* @return A new, fully mutable deep copy, or the original list if the input is null or empty.
*/
private List<List<String>> toMutableListIfNecessary(List<List<String>> head) {
if (null == head || head.isEmpty()) {
return head;
}
return head.stream().map(ArrayList::new).collect(Collectors.toList());
}

/**
* You can only choose one of the {@link #head(List)} and {@link #head(Class)}
*
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/

package org.apache.fesod.excel.head;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import org.apache.fesod.excel.context.AnalysisContext;
import org.apache.fesod.excel.metadata.data.ReadCellData;
import org.apache.fesod.excel.read.listener.ReadListener;
import org.junit.jupiter.api.Assertions;

public class ImmutableListHeadDataListener implements ReadListener<Map<Integer, String>> {

private List<Map<Integer, String>> list = new ArrayList<Map<Integer, String>>();

@Override
public void invokeHead(Map<Integer, ReadCellData<?>> headMap, AnalysisContext context) {
Assertions.assertNotNull(context.readRowHolder().getRowIndex());
headMap.forEach((key, value) -> {
Assertions.assertEquals(value.getRowIndex(), context.readRowHolder().getRowIndex());
Assertions.assertEquals(value.getColumnIndex(), key);
});
}

@Override
public void invoke(Map<Integer, String> data, AnalysisContext context) {
list.add(data);
}

@Override
public void doAfterAllAnalysed(AnalysisContext context) {
List<List<String>> head = context.readSheetHolder().getHead();

Assertions.assertInstanceOf(ArrayList.class, head);
for (List<String> item : head) {
Assertions.assertInstanceOf(ArrayList.class, item);
}

Assertions.assertEquals(1, list.size());
Map<Integer, String> data = list.get(0);
Assertions.assertEquals("stringData", data.get(0));
Assertions.assertEquals("1", data.get(1));
Assertions.assertEquals("2025-10-31 01:01:01", data.get(2));
Assertions.assertEquals("extraData", data.get(3));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/

package org.apache.fesod.excel.head;

import java.io.File;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import org.apache.fesod.excel.FastExcel;
import org.apache.fesod.excel.util.DateUtils;
import org.apache.fesod.excel.util.TestFileUtil;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.MethodOrderer;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestMethodOrder;

@TestMethodOrder(MethodOrderer.MethodName.class)
public class ImmutableListHeadDataTest {

private static File file07;
private static File file03;
private static File fileCsv;

@BeforeAll
public static void init() {
file07 = TestFileUtil.createNewFile("listHead07.xlsx");
file03 = TestFileUtil.createNewFile("listHead03.xls");
fileCsv = TestFileUtil.createNewFile("listHeadCsv.csv");
}

@Test
public void t01ReadAndWrite07() throws Exception {
readAndWrite(file07);
}

@Test
public void t02ReadAndWrite03() throws Exception {
readAndWrite(file03);
}

@Test
public void t03ReadAndWriteCsv() throws Exception {
readAndWrite(fileCsv);
}

private void readAndWrite(File file) throws Exception {
FastExcel.write(file)
.head(head())
.registerWriteHandler(new ImmutableListHeadDataWriteHandler())
.sheet()
.doWrite(data());

FastExcel.read(file)
.head(head())
.registerReadListener(new ImmutableListHeadDataListener())
.sheet()
.doRead();
}

private List<List<String>> head() {
List<List<String>> list = new ArrayList<List<String>>();
List<String> head0 = Arrays.asList("stringTitle");
List<String> head1 = new ArrayList<String>();
head1.add("numberTitle1");
head1.add("numberTitle2");

list.add(head0);
list.add(Collections.unmodifiableList(head1));
list.add(Collections.singletonList("datetimeTitle"));
return list;
}

private List<List<Object>> data() throws ParseException {
List<List<Object>> list = new ArrayList<List<Object>>();
List<Object> data0 = new ArrayList<Object>();
data0.add("stringData");
data0.add(1);
data0.add(DateUtils.parseDate("2025-10-31 01:01:01"));
data0.add("extraData");
list.add(data0);
return list;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/

package org.apache.fesod.excel.head;

import java.util.ArrayList;
import java.util.List;
import org.apache.fesod.excel.write.handler.SheetWriteHandler;
import org.apache.fesod.excel.write.handler.context.SheetWriteHandlerContext;
import org.junit.jupiter.api.Assertions;

public class ImmutableListHeadDataWriteHandler implements SheetWriteHandler {

@Override
public void afterSheetDispose(SheetWriteHandlerContext context) {
List<List<String>> head = context.getWriteContext().writeSheetHolder().getHead();

Assertions.assertInstanceOf(ArrayList.class, head);
for (List<String> item : head) {
Assertions.assertInstanceOf(ArrayList.class, item);
}
}
}