Explorar o código

es聚合统计

zero hai 1 ano
pai
achega
01f2df965f

+ 1 - 0
src/main/java/cn/cslg/pas/common/dto/business/EsCountDTO.java

@@ -6,6 +6,7 @@ import java.util.List;
 
 @Data
 public class EsCountDTO {
+    private String condition;
 
     private List<EsCountDetailDTO> detailDTOS;
 }

+ 9 - 3
src/main/java/cn/cslg/pas/common/vo/business/EsCountVO.java

@@ -2,16 +2,22 @@ package cn.cslg.pas.common.vo.business;
 
 import lombok.Data;
 
+import java.util.List;
+
 @Data
 public class EsCountVO {
+    //条件
+    private String condition;
     //栏位
     private String field;
-    //搜索的栏位值1
+    //统计搜索的栏位值1
     private String valueOne;
-    //搜索的栏位值2
+    //统计搜索的栏位值2
     private String valueTwo;
     //top
     private Integer topN = 10;
     //开关
-    private Boolean ifHaveChild;
+    private Boolean ifHaveChild = false;
+    //分析搜索栏位值
+    private List<String> values;
 }

+ 8 - 2
src/main/java/cn/cslg/pas/controller/PatentController.java

@@ -55,8 +55,8 @@ public class PatentController {
 
     @Operation(summary = "统计专利库中专利")
     @PostMapping("/esCountSearch")
-    public Response esCountSearch(@RequestBody List<EsCountVO> countVOS,String condition) throws Exception {
-        EsCountDTO dto = esCountService.esCountSearch(countVOS, condition);
+    public Response esCountSearch(@RequestBody List<EsCountVO> countVOS) throws Exception {
+        EsCountDTO dto = esCountService.esCountSearch(countVOS);
         return Response.success(dto);
     }
 
@@ -81,6 +81,12 @@ public class PatentController {
         return Response.success(patentPageMessageVOS);
     }
 
+//    @Operation(summary = "esSearch")
+//    @PostMapping("/esSearch")
+//    public Response esSearch(@RequestBody List<EsCustomFieldValueDTO> customFields) throws Exception {
+//        PatentDTO patentDTO = esService.esSearch(customFields);
+//        return Response.success(patentDTO);
+//    }
 
     @Operation(summary = "esCount")
     @PostMapping("/esCount")

+ 3 - 1
src/main/java/cn/cslg/pas/factorys/EsCountBuilderFactory/IEsCountBuilder.java

@@ -2,6 +2,8 @@ package cn.cslg.pas.factorys.EsCountBuilderFactory;
 
 import co.elastic.clients.elasticsearch._types.aggregations.Aggregation;
 
+import java.text.ParseException;
+
 public interface IEsCountBuilder {
     public String field = "";
     public String valueOne = "";
@@ -10,7 +12,7 @@ public interface IEsCountBuilder {
     public String path = "";
     public Boolean ifHaveChild = false;
 
-    public Aggregation createAggregation();
+    public Aggregation createAggregation() throws Exception;
 
     public String getField();
 

+ 217 - 160
src/main/java/cn/cslg/pas/service/business/es/EsCountService.java

@@ -2,28 +2,33 @@ package cn.cslg.pas.service.business.es;
 
 import cn.cslg.pas.common.dto.business.EsCountDTO;
 import cn.cslg.pas.common.dto.business.EsCountDetailDTO;
+import cn.cslg.pas.common.utils.parseQueryToTree.expressManager;
+import cn.cslg.pas.common.utils.parseQueryToTree.operateNode;
+import cn.cslg.pas.common.utils.parseQueryToTree.treeNode;
 import cn.cslg.pas.common.vo.EsConfigVO;
 import cn.cslg.pas.common.vo.business.EsCountVO;
 import cn.cslg.pas.domain.es.Patent;
 import cn.cslg.pas.factorys.EsCountBuilderFactory.EsCountBuilderFactory;
 import cn.cslg.pas.factorys.EsCountBuilderFactory.IEsCountBuilder;
 import cn.cslg.pas.service.business.CommonService;
+import cn.cslg.pas.service.query.FormatQueryService;
 import co.elastic.clients.elasticsearch.ElasticsearchClient;
 import co.elastic.clients.elasticsearch._types.aggregations.*;
+import co.elastic.clients.elasticsearch._types.query_dsl.Query;
+import co.elastic.clients.elasticsearch._types.query_dsl.QueryBuilders;
 import co.elastic.clients.elasticsearch.core.SearchRequest;
 import co.elastic.clients.elasticsearch.core.SearchResponse;
 import com.alibaba.fastjson.JSON;
 import lombok.RequiredArgsConstructor;
+import org.apache.commons.lang3.StringUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.context.annotation.Lazy;
 import org.springframework.stereotype.Service;
 import org.springframework.util.CollectionUtils;
 
 import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Comparator;
-import java.util.List;
+import java.text.ParseException;
+import java.util.*;
 import java.util.stream.Collectors;
 
 @Service
@@ -37,6 +42,8 @@ public class EsCountService {
 
     @Autowired
     private EsCountBuilderFactory esCountBuilderFactory;
+    @Autowired
+    private FormatQueryService formatQueryService;
 
     /**
      * 查询专利库中的专利分组聚合统计
@@ -45,186 +52,100 @@ public class EsCountService {
      * @return
      * @throws Exception
      */
-    public EsCountDTO esCountSearch(List<EsCountVO> countVOS,String condition) throws Exception {
+    public EsCountDTO esCountSearch(List<EsCountVO> countVOS) throws Exception {
         EsCountDTO esCountDTO = new EsCountDTO();
         List<EsCountDetailDTO> detailDTOS = new ArrayList<>();
         for (EsCountVO vo : countVOS) {
             String field = vo.getField();
             Integer topN = vo.getTopN();
-
+            String condition = vo.getCondition();
             //查询es返回数据
             SearchRequest.Builder builder = new SearchRequest.Builder();
-            Aggregation aggregation = this.selectAggregation(builder,vo);
-            builder.aggregations("Agg", aggregation);
+            Aggregation aggregation = this.selectAggregation(builder, vo);
+            if (StringUtils.isNotEmpty(condition)) {
+                //解析检索条件
+                treeNode tree = expressManager.getInstance().Parse(condition, false);
+                //从es中检索数据
+                Query query = formatQueryService.EsQueryToQuery((operateNode) tree, "patent");
+                Aggregation filtersAgg = null;
+                if (aggregation != null) {
+                    filtersAgg = new Aggregation.Builder().filters(new FiltersAggregation.Builder()
+                            .filters(i -> i.array(Arrays.asList(query))).build())
+                            .aggregations(new HashMap() {{
+                                put("filters_agg", aggregation);
+                            }}).build();
+                } else {
+                    filtersAgg = AggregationBuilders.filter(i -> i.bool(j -> j.must(query)));
+                }
+                builder.aggregations("Agg", filtersAgg);
+            } else {
+                builder.aggregations("Agg", aggregation);
+            }
             SearchResponse<Patent> response = client.search(builder.build(), Patent.class);
 
             Aggregate agg = response.aggregations().get("Agg");
-            if (dateList.contains(field)) {
-                List<DateHistogramBucket> list = agg.dateHistogram().buckets().array();
-                List<EsCountDetailDTO> esCountDetailDTOS = new ArrayList<>();
-                list.forEach(bucket -> {
-                    EsCountDetailDTO dto = new EsCountDetailDTO();
-                    dto.setField(field);
-                    Aggregate aggregate = bucket.aggregations().get("filter_agg");
-                    dto.setName(bucket.keyAsString());
-                    dto.setNumber(bucket.docCount());
-                    if (aggregate != null) {
-                        dto.setNumber(aggregate.filter().docCount());
-                    }
-                    if (dto.getNumber() > 0) {
-                        esCountDetailDTOS.add(dto);
+            if (StringUtils.isNotEmpty(condition)) {
+                if (StringUtils.isNotEmpty(field)) {
+                    List<FiltersBucket> filtersBuckets = agg.filters().buckets().array();
+                    if (dateList.contains(field)) {
+                        filtersBuckets.forEach(filtersBucket -> {
+                            this.getFiltersCountDTO(filtersBucket, condition,detailDTOS);
+                            Aggregate filtersAgg = filtersBucket.aggregations().get("filters_agg");
+                            this.getDateCountDTOS(filtersAgg, field,topN,detailDTOS);
+                        });
+                    } else if (nestedList.contains(field)) {
+                        filtersBuckets.forEach(filtersBucket -> {
+                            this.getFiltersCountDTO(filtersBucket, condition,detailDTOS);
+                            Aggregate filtersAgg = filtersBucket.aggregations().get("filters_agg");
+                            this.getNestedCountDTOS(filtersAgg, field,detailDTOS);
+                        });
+                    } else if (childList.contains(field)) {
+                        filtersBuckets.forEach(filtersBucket -> {
+                            this.getFiltersCountDTO(filtersBucket, condition,detailDTOS);
+                            Aggregate filtersAgg = filtersBucket.aggregations().get("filters_agg");
+                            this.getChildCountDTOS(filtersAgg, field,detailDTOS);
+                        });
+                    } else {
+                        filtersBuckets.forEach(filtersBucket -> {
+                            this.getFiltersCountDTO(filtersBucket, condition,detailDTOS);
+                            Aggregate filtersAgg = filtersBucket.aggregations().get("filters_agg");
+                            this.getTermCountDTOS(filtersAgg, field, detailDTOS);
+                        });
                     }
-                });
-                if (!CollectionUtils.isEmpty(esCountDetailDTOS)) {
-                    List<EsCountDetailDTO> collect = esCountDetailDTOS.stream().sorted(Comparator.comparing(EsCountDetailDTO::getName).reversed())
-                            .limit(topN).collect(Collectors.toList());
-                    detailDTOS.addAll(collect);
+                } else {
+                    this.getFilterCountDTO(agg, condition,detailDTOS);
                 }
-            } else if (nestedList.contains(field)) {
-                Aggregate termsAgg = agg.nested().aggregations().get("terms_agg");
-                List<StringTermsBucket> list = termsAgg.sterms().buckets().array();
-                list.forEach(bucket -> {
-                    EsCountDetailDTO dto = new EsCountDetailDTO();
-                    dto.setField(field);
-                    Aggregate aggregate = bucket.aggregations().get("filter_agg");
-                    dto.setName(bucket.key().stringValue());
-                    dto.setNumber(bucket.docCount());
-                    if (aggregate != null) {
-                        dto.setNumber(aggregate.filter().docCount());
-                    }
-                    if (dto.getNumber() > 0) {
-                        detailDTOS.add(dto);
-                    }
-                });
-            } else if (childList.contains(field)) {
-                Aggregate childAgg = agg.children().aggregations().get("child_agg");
-                List<StringTermsBucket> list = childAgg.sterms().buckets().array();
-                list.forEach(bucket -> {
-                    EsCountDetailDTO dto = new EsCountDetailDTO();
-                    dto.setField(field);
-                    Aggregate aggregate = bucket.aggregations().get("filter_agg");
-                    dto.setName(bucket.key().stringValue());
-                    dto.setNumber(bucket.docCount());
-                    if (aggregate != null) {
-                        dto.setNumber(aggregate.filter().docCount());
-                    }
-                    if (dto.getNumber() > 0) {
-                        detailDTOS.add(dto);
-                    }
-                });
             } else {
-                List<StringTermsBucket> list = agg.sterms().buckets().array();
-                list.forEach(bucket -> {
-                    EsCountDetailDTO dto = new EsCountDetailDTO();
-                    dto.setField(field);
-                    Aggregate aggregate = bucket.aggregations().get("filter_agg");
-                    dto.setName(bucket.key().stringValue());
-                    dto.setNumber(bucket.docCount());
-                    if (aggregate != null) {
-                        dto.setNumber(aggregate.filter().docCount());
-                    }
-                    if (dto.getNumber() > 0) {
-                        detailDTOS.add(dto);
-                    }
-                });
-            }
-        }
-        esCountDTO.setDetailDTOS(detailDTOS);
-        return esCountDTO;
-    }
-
-    public EsCountDTO esCount(EsCountVO countVO) throws Exception {
-        EsCountDTO esCountDTO = new EsCountDTO();
-        List<EsCountDetailDTO> detailDTOS = new ArrayList<>();
-        String valueOne = countVO.getValueOne();
-        String valueTwo = countVO.getValueTwo();
-        Integer topN = countVO.getTopN();
-        String field = countVO.getField();
-
-        //查询es返回数据
-        SearchRequest.Builder builder = new SearchRequest.Builder();
-        Aggregation aggregation = this.selectAggregation(builder,countVO);
-        builder.aggregations("Agg", aggregation);
-        SearchResponse<Patent> response = client.search(builder.build(), Patent.class);
-        Aggregate agg = response.aggregations().get("Agg");
-        if (dateList.contains(field)) {
-            List<DateHistogramBucket> list = agg.dateHistogram().buckets().array();
-            List<EsCountDetailDTO> esCountDetailDTOS = new ArrayList<>();
-            list.forEach(bucket -> {
-                EsCountDetailDTO dto = new EsCountDetailDTO();
-                dto.setField(field);
-                Aggregate aggregate = bucket.aggregations().get("filter_agg");
-                dto.setName(bucket.keyAsString());
-                dto.setNumber(bucket.docCount());
-                if (aggregate != null) {
-                    dto.setNumber(aggregate.filter().docCount());
+                if (dateList.contains(field)) {
+                    this.getDateCountDTOS(agg, field,topN, detailDTOS);
+                } else if (nestedList.contains(field)) {
+                    this.getNestedCountDTOS(agg, field, detailDTOS);
+                } else if (childList.contains(field)) {
+                    this.getChildCountDTOS(agg, field, detailDTOS);
+                } else {
+                    this.getTermCountDTOS(agg, field, detailDTOS);
                 }
-                if (dto.getNumber() > 0) {
-                    esCountDetailDTOS.add(dto);
-                }
-            });
-            if (!CollectionUtils.isEmpty(esCountDetailDTOS)) {
-                List<EsCountDetailDTO> collect = esCountDetailDTOS.stream().sorted(Comparator.comparing(EsCountDetailDTO::getName).reversed()).limit(topN).collect(Collectors.toList());
-                detailDTOS.addAll(collect);
             }
-        } else if (nestedList.contains(field)) {
-            Aggregate termsAgg = agg.nested().aggregations().get("terms_agg");
-            List<StringTermsBucket> list = termsAgg.sterms().buckets().array();
-            list.forEach(bucket -> {
-                EsCountDetailDTO dto = new EsCountDetailDTO();
-                dto.setField(field);
-                Aggregate aggregate = bucket.aggregations().get("filter_agg");
-                dto.setName(bucket.key().stringValue());
-                dto.setNumber(bucket.docCount());
-                if (aggregate != null) {
-                    dto.setNumber(aggregate.filter().docCount());
-                }
-                if (dto.getNumber() > 0) {
-                    detailDTOS.add(dto);
-                }
-            });
-        } else if (childList.contains(field)) {
-            Aggregate childAgg = agg.children().aggregations().get("child_agg");
-            List<StringTermsBucket> list = childAgg.sterms().buckets().array();
-            list.forEach(bucket -> {
-                EsCountDetailDTO dto = new EsCountDetailDTO();
-                dto.setField(field);
-                Aggregate aggregate = bucket.aggregations().get("filter_agg");
-                dto.setName(bucket.key().stringValue());
-                dto.setNumber(bucket.docCount());
-                if (aggregate != null) {
-                    dto.setNumber(aggregate.filter().docCount());
-                }
-                if (dto.getNumber() > 0) {
-                    detailDTOS.add(dto);
-                }
-            });
-        } else {
-            List<StringTermsBucket> list = agg.sterms().buckets().array();
-            list.forEach(bucket -> {
-                EsCountDetailDTO dto = new EsCountDetailDTO();
-                dto.setField(field);
-                Aggregate aggregate = bucket.aggregations().get("filter_agg");
-                dto.setName(bucket.key().stringValue());
-                dto.setNumber(bucket.docCount());
-                if (aggregate != null) {
-                    dto.setNumber(aggregate.filter().docCount());
-                }
-                if (dto.getNumber() > 0) {
-                    detailDTOS.add(dto);
-                }
-            });
         }
         esCountDTO.setDetailDTOS(detailDTOS);
         return esCountDTO;
     }
 
-    public Aggregation selectAggregation(SearchRequest.Builder builder, EsCountVO vo) {
+    /**
+     * 获取聚合后的aggregation
+     *
+     * @param builder
+     * @param vo
+     * @return
+     * @throws Exception
+     */
+    public Aggregation selectAggregation(SearchRequest.Builder builder, EsCountVO vo) throws Exception {
         String valueOne = vo.getValueOne();
         String valueTwo = vo.getValueTwo();
         Integer topN = vo.getTopN();
         Boolean ifHaveChild = vo.getIfHaveChild();
         String field = vo.getField();
+        Aggregation aggregation = null;
 
         builder.index("patent");
         IEsCountBuilder iEsCountBuilder = null;
@@ -242,8 +163,144 @@ public class EsCountService {
                 String path = iEsCountBuilder.getField().substring(0, iEsCountBuilder.getField().indexOf("."));
                 iEsCountBuilder.setPath(path);
             }
+            aggregation = iEsCountBuilder.createAggregation();
+        }
+        return aggregation;
+    }
+
+    /**
+     * 获取Filter聚合返回数据
+     * @param agg
+     * @param condition
+     * @return
+     */
+    public void getFilterCountDTO(Aggregate agg,String condition,List<EsCountDetailDTO> detailDTOS) {
+        EsCountDetailDTO filterDTO = new EsCountDetailDTO();
+        filterDTO.setField("condition");
+        filterDTO.setName(condition);
+        filterDTO.setNumber(agg.filter().docCount());
+        if (filterDTO.getNumber() > 0) {
+            detailDTOS.add(filterDTO);
+        }
+    }
+
+    /**
+     * 获取Filters聚合返回数据
+     * @param filtersBucket
+     * @param condition
+     * @return
+     */
+    public void getFiltersCountDTO(FiltersBucket filtersBucket,String condition,List<EsCountDetailDTO> detailDTOS) {
+        EsCountDetailDTO filtersDTO = new EsCountDetailDTO();
+        filtersDTO.setField("condition");
+        filtersDTO.setName(condition);
+        filtersDTO.setNumber(filtersBucket.docCount());
+        if (filtersDTO.getNumber() > 0) {
+            detailDTOS.add(filtersDTO);
+        }
+    }
+
+    /**
+     * 获取Terms聚合后数据
+     *
+     * @param agg
+     * @param field
+     * @param detailDTOS
+     */
+    public void getTermCountDTOS(Aggregate agg, String field, List<EsCountDetailDTO> detailDTOS) {
+        List<StringTermsBucket> list = agg.sterms().buckets().array();
+        list.forEach(bucket -> {
+            EsCountDetailDTO dto = new EsCountDetailDTO();
+            dto.setField(field);
+            Aggregate aggregate = bucket.aggregations().get("filter_agg");
+            dto.setName(bucket.key().stringValue());
+            dto.setNumber(bucket.docCount());
+            if (aggregate != null) {
+                dto.setNumber(aggregate.filter().docCount());
+            }
+            if (dto.getNumber() > 0) {
+                detailDTOS.add(dto);
+            }
+        });
+    }
+
+    /**
+     * 获取children聚合后数据
+     *
+     * @param agg
+     * @param field
+     * @param detailDTOS
+     */
+    public void getChildCountDTOS(Aggregate agg, String field,List<EsCountDetailDTO> detailDTOS) {
+        Aggregate childAgg = agg.children().aggregations().get("child_agg");
+        List<StringTermsBucket> list = childAgg.sterms().buckets().array();
+        list.forEach(bucket -> {
+            EsCountDetailDTO dto = new EsCountDetailDTO();
+            dto.setField(field);
+            Aggregate aggregate = bucket.aggregations().get("filter_agg");
+            List<StringTermsBucket> buckets = aggregate.sterms().buckets().array();
+            for (StringTermsBucket termsBucket : buckets) {
+                dto.setName(termsBucket.key().stringValue());
+                dto.setNumber(termsBucket.docCount());
+                if (dto.getNumber() > 0) {
+                    detailDTOS.add(dto);
+                }
+            }
+        });
+    }
+
+    /**
+     * 获取dateHistogram聚合后数据
+     *
+     * @param agg
+     * @param field
+     * @param detailDTOS
+     */
+    public void getDateCountDTOS(Aggregate agg, String field,Integer topN,List<EsCountDetailDTO> detailDTOS) {
+        List<DateHistogramBucket> list = agg.dateHistogram().buckets().array();
+        List<EsCountDetailDTO> esCountDetailDTOS = new ArrayList<>();
+        list.forEach(bucket -> {
+            EsCountDetailDTO dto = new EsCountDetailDTO();
+            dto.setField(field);
+            Aggregate aggregate = bucket.aggregations().get("filter_agg");
+            dto.setName(bucket.keyAsString());
+            dto.setNumber(bucket.docCount());
+            if (aggregate != null) {
+                dto.setNumber(aggregate.filter().docCount());
+            }
+            if (dto.getNumber() > 0) {
+                esCountDetailDTOS.add(dto);
+            }
+        });
+        if (!CollectionUtils.isEmpty(esCountDetailDTOS)) {
+            List<EsCountDetailDTO> collect = esCountDetailDTOS.stream()
+                    .sorted(Comparator.comparing(EsCountDetailDTO::getName).reversed()).limit(topN).collect(Collectors.toList());
+            detailDTOS.addAll(collect);
         }
-        return iEsCountBuilder.createAggregation();
     }
 
+    /**
+     * 获取nested聚合后数据
+     *
+     * @param agg
+     * @param field
+     * @param detailDTOS
+     */
+    public void getNestedCountDTOS(Aggregate agg, String field,List<EsCountDetailDTO> detailDTOS) {
+        Aggregate termsAgg = agg.nested().aggregations().get("terms_agg");
+        List<StringTermsBucket> list = termsAgg.sterms().buckets().array();
+        list.forEach(bucket -> {
+            EsCountDetailDTO dto = new EsCountDetailDTO();
+            dto.setField(field);
+            Aggregate aggregate = bucket.aggregations().get("filter_agg");
+            dto.setName(bucket.key().stringValue());
+            dto.setNumber(bucket.docCount());
+            if (aggregate != null) {
+                dto.setNumber(aggregate.filter().docCount());
+            }
+            if (dto.getNumber() > 0) {
+                detailDTOS.add(dto);
+            }
+        });
+    }
 }

+ 18 - 18
src/test/java/cn/cslg/pas/service/EventServiceTests.java

@@ -244,7 +244,7 @@ public class EventServiceTests {
         vo2.setValueTwo("2023");
         countVOS.add(vo1);
 //        countVOS.add(vo2);
-        EsCountDTO esCountDTO = esCountService.esCountSearch(countVOS, "");
+        EsCountDTO esCountDTO = esCountService.esCountSearch(countVOS);
         System.out.println(esCountDTO);
 
     }
@@ -296,23 +296,23 @@ public class EventServiceTests {
         esCustomFieldService.addCustomField(dto);
     }
 
-//    @Test
-//    void test16() {
-//        List<EsCustomFieldValueDTO> customFields = new ArrayList<>();
-//        EsCustomFieldValueDTO dto1 = new EsCustomFieldValueDTO();
-//        dto1.setFieldId("1");
-//        dto1.setFieldValue(Arrays.asList("a", "b"));
-//        EsCustomFieldValueDTO dto2 = new EsCustomFieldValueDTO();
-//        dto2.setFieldId("2");
-//        dto2.setFieldValue(Arrays.asList("a", "b"));
-//        customFields.add(dto1);
-//        customFields.add(dto2);
-//        String s = esService.parseCustomField(customFields,Boolean.FALSE);
-//        System.out.println("结果为:" + s);
-//        System.out.println("-----------------------------");
-//        List<EsCustomFieldValueDTO> fields = new ArrayList<>();
-//
-//    }
+    @Test
+    void test16() {
+        List<EsCustomFieldValueDTO> customFields = new ArrayList<>();
+        EsCustomFieldValueDTO dto1 = new EsCustomFieldValueDTO();
+        dto1.setFieldId("1");
+        dto1.setFieldValue(Arrays.asList("a"));
+        EsCustomFieldValueDTO dto2 = new EsCustomFieldValueDTO();
+        dto2.setFieldId("2");
+        dto2.setFieldValue(Arrays.asList("a"));
+        customFields.add(dto1);
+        customFields.add(dto2);
+        String s = esService.parseCustomField(customFields,Boolean.FALSE);
+        System.out.println("结果为:" + s);
+        System.out.println("-----------------------------");
+        List<EsCustomFieldValueDTO> fields = new ArrayList<>();
+
+    }
 
     @Test
     void test17() throws IOException {