Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
/*
* 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.sheet.annotation.write;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
Comment on lines +22 to +25

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

import org.apache.fesod.sheet.write.builder.AbstractExcelWriterParameterBuilder;

/**
* Annotation used for indicating view(s) that the property
* that is defined by field annotated is part of.
* <p>
* An example annotation would be:
* <pre>
* &#064;ExcelView(asTypes = BasicView.class)
* // Or
* &#064;ExcelView(asNames = "BasicView")
* </pre>
* which would specify that field annotated would be included
* when processing (writing) Sheet identified by <code>BasicView.class</code> (or its subclass) or
* <code>"BasicView"</code>.
* If multiple View class or string identifiers are included, the field will be part of all of them.
* </p>
*
* @see AbstractExcelWriterParameterBuilder#groups(Class[])
* @see AbstractExcelWriterParameterBuilder#groups(String[])
*/
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface ExcelView {
Comment on lines +47 to +49

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.


/**
* View or views that annotated element is part of. Views are identified
* by classes, when a view type is selected, fields annotated with that type
* or any of subtypes are included.
*/
Comment on lines +51 to +55

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

Class<?>[] asTypes() default {};

/**
* View or views that annotated element is part of. Views are identified
* by strings.
*/
String[] asNames() default {};
}
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@
import org.apache.fesod.sheet.metadata.property.NumberFormatProperty;
import org.apache.fesod.sheet.metadata.property.StyleProperty;
import org.apache.fesod.sheet.write.metadata.holder.WriteHolder;
import org.apache.fesod.sheet.write.view.WriteViewMatcher;

public class ClassUtils {

Expand Down Expand Up @@ -346,23 +347,30 @@ private static FieldCache doDeclaredFields(Class<?> clazz, ConfigurationHolder c

WriteHolder writeHolder = (WriteHolder) configurationHolder;

// ignore field by grouping
WriteViewMatcher writeViewMatcher = writeHolder.writeViewMatcher();
boolean hasViews = (WriteViewMatcher.NOOP != writeViewMatcher);
// ignore field by include*/exclude*
boolean needIgnore = !CollectionUtils.isEmpty(writeHolder.excludeColumnFieldNames())
|| !CollectionUtils.isEmpty(writeHolder.excludeColumnIndexes())
|| !CollectionUtils.isEmpty(writeHolder.includeColumnFieldNames())
|| !CollectionUtils.isEmpty(writeHolder.includeColumnIndexes());
|| !CollectionUtils.isEmpty(writeHolder.includeColumnIndexes())
|| hasViews;

if (!needIgnore) {
return fieldCache;
}
// ignore filed
// ignore field
Map<Integer, FieldWrapper> tempSortedFieldMap = MapUtils.newHashMap();
int index = 0;
for (Map.Entry<Integer, FieldWrapper> entry : sortedFieldMap.entrySet()) {
Integer key = entry.getKey();
FieldWrapper field = entry.getValue();

boolean isGroupsMismatch = hasViews && !writeViewMatcher.matches(field.getField());

// The current field needs to be ignored
if (writeHolder.ignore(field.getFieldName(), entry.getKey())) {
if (isGroupsMismatch || writeHolder.ignore(field.getFieldName(), entry.getKey())) {
ignoreSet.add(field.getFieldName());
indexFieldMap.remove(index);
} else {
Expand Down Expand Up @@ -575,6 +583,7 @@ public static class FieldCacheKey {
private Collection<Integer> excludeColumnIndexes;
private Collection<String> includeColumnFieldNames;
private Collection<Integer> includeColumnIndexes;
private WriteViewMatcher writeViewMatcher;

FieldCacheKey(Class<?> clazz, ConfigurationHolder configurationHolder) {
this.clazz = clazz;
Expand All @@ -584,6 +593,7 @@ public static class FieldCacheKey {
this.excludeColumnIndexes = writeHolder.excludeColumnIndexes();
this.includeColumnFieldNames = writeHolder.includeColumnFieldNames();
this.includeColumnIndexes = writeHolder.includeColumnIndexes();
this.writeViewMatcher = writeHolder.writeViewMatcher();
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,13 @@

import java.util.ArrayList;
import java.util.Collection;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.fesod.sheet.enums.HeaderMergeStrategy;
import org.apache.fesod.sheet.metadata.AbstractParameterBuilder;
import org.apache.fesod.sheet.write.handler.WriteHandler;
import org.apache.fesod.sheet.write.metadata.WriteBasicParameter;
import org.apache.fesod.sheet.write.view.ClassBasedViewMatcher;
import org.apache.fesod.sheet.write.view.NameBasedViewMatcher;

/**
* Build ExcelBuilder
Expand Down Expand Up @@ -170,4 +173,34 @@ public T orderByIncludeColumn(Boolean orderByIncludeColumn) {
parameter().setOrderByIncludeColumn(orderByIncludeColumn);
return self();
}

/**
* Only write the fields marked by the following View class identifiers.
*
* @param types Target View class identifiers
* @throws IllegalArgumentException if the types is empty
* @return this
*/
public T groups(Class<?>... types) {
if (ArrayUtils.isEmpty(types)) {
throw new IllegalArgumentException("Types must not be empty");
}
parameter().setWriteViewMatcher(new ClassBasedViewMatcher(types));
return self();
}
Comment on lines +184 to +190

/**
* Only write to the fields marked by the following View string identifiers.
*
* @param names Target View string identifiers
* @throws IllegalArgumentException if the names is empty
* @return this
*/
public T groups(String... names) {
if (ArrayUtils.isEmpty(names)) {
throw new IllegalArgumentException("Names must not be empty");
}
parameter().setWriteViewMatcher(new NameBasedViewMatcher(names));
return self();
}
Comment on lines +199 to +205
}
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
import org.apache.fesod.sheet.enums.HeaderMergeStrategy;
import org.apache.fesod.sheet.metadata.BasicParameter;
import org.apache.fesod.sheet.write.handler.WriteHandler;
import org.apache.fesod.sheet.write.view.WriteViewMatcher;

/**
* Write basic parameter
Expand Down Expand Up @@ -92,4 +93,9 @@ public class WriteBasicParameter extends BasicParameter {
* Default is {@code false}.
*/
private Boolean orderByIncludeColumn;

/**
* view-based matcher for sheet writing.
*/
private WriteViewMatcher writeViewMatcher;
}
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@
import org.apache.fesod.sheet.write.style.SheetFreezePaneStrategy;
import org.apache.fesod.sheet.write.style.column.AbstractHeadColumnWidthStyleStrategy;
import org.apache.fesod.sheet.write.style.row.SimpleRowHeightStyleStrategy;
import org.apache.fesod.sheet.write.view.WriteViewMatcher;

/**
* Write holder configuration
Expand Down Expand Up @@ -136,6 +137,11 @@ public abstract class AbstractWriteHolder extends AbstractHolder implements Writ
*/
private List<Converter<?>> customConverterList;

/**
* view-based matcher for sheet writing.
*/
private WriteViewMatcher writeViewMatcher;

/**
* Write handler
*/
Expand Down Expand Up @@ -263,6 +269,16 @@ public AbstractWriteHolder(WriteBasicParameter writeBasicParameter, AbstractWrit
this.includeColumnIndexes = writeBasicParameter.getIncludeColumnIndexes();
}

if (writeBasicParameter.getWriteViewMatcher() == null) {
if (parentAbstractWriteHolder == null) {
this.writeViewMatcher = WriteViewMatcher.NOOP;
} else {
this.writeViewMatcher = parentAbstractWriteHolder.getWriteViewMatcher();
}
} else {
this.writeViewMatcher = writeBasicParameter.getWriteViewMatcher();
}

// Initialization property
this.excelWriteHeadProperty = new ExcelWriteHeadProperty(this, getClazz(), getHead());

Expand Down Expand Up @@ -599,4 +615,9 @@ public Collection<Integer> excludeColumnIndexes() {
public Collection<String> excludeColumnFieldNames() {
return getExcludeColumnFieldNames();
}

@Override
public WriteViewMatcher writeViewMatcher() {
return getWriteViewMatcher();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
import org.apache.fesod.sheet.enums.HeaderMergeStrategy;
import org.apache.fesod.sheet.metadata.ConfigurationHolder;
import org.apache.fesod.sheet.write.property.ExcelWriteHeadProperty;
import org.apache.fesod.sheet.write.view.WriteViewMatcher;

/**
* Get the corresponding Holder
Expand Down Expand Up @@ -115,4 +116,9 @@ public interface WriteHolder extends ConfigurationHolder {
* @return
*/
Collection<String> excludeColumnFieldNames();

/**
* view-based matcher for sheet writing.
*/
WriteViewMatcher writeViewMatcher();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
/*
* 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.sheet.write.view;

import java.lang.reflect.Field;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Optional;
import lombok.EqualsAndHashCode;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.fesod.sheet.annotation.write.ExcelView;

/**
* View matcher that resolves view-based on class
* identifiers declared in {@code @ExcelView#asTypes()}.
*/
@EqualsAndHashCode
public class ClassBasedViewMatcher implements WriteViewMatcher {

private final Collection<Class<?>> expectedGroups;

public ClassBasedViewMatcher(Class<?>... expectedGroups) {
this(ArrayUtils.isEmpty(expectedGroups) ? Collections.emptyList() : Arrays.asList(expectedGroups));
}

public ClassBasedViewMatcher(Collection<Class<?>> expectedGroups) {
if (CollectionUtils.isEmpty(expectedGroups)) {
throw new IllegalArgumentException("Type-based view groups must not be empty");
}
this.expectedGroups = Collections.unmodifiableCollection(expectedGroups);
}

@Override
public boolean matches(Field field) {
Class<?>[] fieldGroups = Optional.ofNullable(field.getAnnotation(ExcelView.class))
.map(ExcelView::asTypes)
.orElse(new Class<?>[0]);

if (ArrayUtils.isEmpty(fieldGroups)) {
return false;
}

return Arrays.stream(fieldGroups).anyMatch(fieldGroup -> expectedGroups.stream()
.anyMatch(expectedGroup -> expectedGroup.isAssignableFrom(fieldGroup)));
}
Comment on lines +62 to +64
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
/*
* 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.sheet.write.view;

import java.lang.reflect.Field;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Optional;
import lombok.EqualsAndHashCode;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.fesod.sheet.annotation.write.ExcelView;

/**
* View matcher that resolves view-based on string
* identifiers declared in {@code @ExcelView#asNames()}.
*/
@EqualsAndHashCode
public class NameBasedViewMatcher implements WriteViewMatcher {

private final Collection<String> expectedGroups;

public NameBasedViewMatcher(String... expectedGroups) {
this(ArrayUtils.isEmpty(expectedGroups) ? Collections.emptyList() : Arrays.asList(expectedGroups));
}

public NameBasedViewMatcher(Collection<String> expectedGroups) {
if (CollectionUtils.isEmpty(expectedGroups)) {
throw new IllegalArgumentException("Name-based view groups must not be empty");
}
this.expectedGroups = Collections.unmodifiableCollection(expectedGroups);
}

@Override
public boolean matches(Field field) {
String[] fieldGroups = Optional.ofNullable(field.getAnnotation(ExcelView.class))
.map(ExcelView::asNames)
.orElse(new String[0]);

if (ArrayUtils.isEmpty(fieldGroups)) {
return false;
}

return Arrays.stream(fieldGroups).anyMatch(fieldGroup -> expectedGroups.stream()
.anyMatch(expectedGroup -> expectedGroup.equals(fieldGroup)));
}
Comment on lines +62 to +64
}
Loading
Loading