├── examples ├── data │ └── smpl.xlsx └── rules │ └── smpl.crl ├── src └── main │ ├── java │ ├── META-INF │ │ └── MANIFEST.MF │ └── ru │ │ └── icc │ │ └── td │ │ └── tabbyxl │ │ ├── preprocessing │ │ ├── headrecog │ │ │ ├── CellPointer.java │ │ │ ├── HeadRecogPreprocessor.java │ │ │ ├── Block.java │ │ │ └── WorkbookManager.java │ │ ├── Preprocessor.java │ │ └── ner │ │ │ └── NERecogPreprocessor.java │ │ ├── model │ │ ├── style │ │ │ ├── VertAlignment.java │ │ │ ├── HorzAlignment.java │ │ │ ├── BorderType.java │ │ │ ├── FillPattern.java │ │ │ ├── CBorder.java │ │ │ ├── CColor.java │ │ │ ├── CFont.java │ │ │ └── CStyle.java │ │ ├── TypeTag.java │ │ ├── exception │ │ │ ├── NotAllowedParentCycleException.java │ │ │ ├── CategoryGroupException.java │ │ │ ├── NotAllowedParentChangeException.java │ │ │ ├── ParentAssociatingException.java │ │ │ └── EntryAssociatingException.java │ │ ├── NerTag.java │ │ ├── COwned.java │ │ ├── CItem.java │ │ ├── LocalCategoryBox.java │ │ ├── CategoryTemplateManager.java │ │ ├── CEntry.java │ │ ├── CCategory.java │ │ ├── CanonicalForm.java │ │ ├── LabelGroupBox.java │ │ ├── CLabel.java │ │ └── CTable.java │ │ ├── crl2j │ │ ├── TableConsumer.java │ │ ├── rulemodel │ │ │ ├── Expression.java │ │ │ ├── Action.java │ │ │ ├── Assignment.java │ │ │ ├── Rule.java │ │ │ └── Condition.java │ │ ├── compiler │ │ │ ├── FileObjectImpl.java │ │ │ ├── CharSequenceCompilerException.java │ │ │ ├── ClassLoaderImpl.java │ │ │ ├── FileManagerImpl.java │ │ │ └── CharSequenceCompiler.java │ │ ├── parser │ │ │ ├── CRL.tokens │ │ │ └── ASTPrinter.java │ │ ├── mvngen │ │ │ ├── SpreadsheetTableExtractor.java │ │ │ └── MvnProjectGenerator.java │ │ ├── StaticImportDescriptor.java │ │ ├── CRL2JEngine.java │ │ └── Ruleset.java │ │ ├── writers │ │ ├── TableWriter.java │ │ ├── DebugTableWriter.java │ │ ├── BasicTableWriter.java │ │ └── EvaluationTableWriter.java │ │ ├── MvnGen.java │ │ ├── util │ │ ├── CRL2DRLMapper.java │ │ └── StatisticsManager.java │ │ ├── evaluation │ │ ├── EvalView.java │ │ └── Evaluator.java │ │ └── HeadRecog.java │ └── resources │ ├── pom.properties │ ├── jess.properties │ ├── drools.properties │ ├── drools-dsl.properties │ ├── mvngen │ └── pom.template │ ├── CRL.g │ └── crl.dsl ├── test.bat ├── test.sh ├── NOTICE ├── .gitignore ├── Usage.md ├── README.md └── pom.xml /examples/data/smpl.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tabbydoc/tabbyxl/HEAD/examples/data/smpl.xlsx -------------------------------------------------------------------------------- /src/main/java/META-INF/MANIFEST.MF: -------------------------------------------------------------------------------- 1 | Manifest-Version: 1.0 2 | Main-Class: ru.icc.td.tabbyxl.TabbyXL 3 | -------------------------------------------------------------------------------- /src/main/resources/pom.properties: -------------------------------------------------------------------------------- 1 | groupId = ${project.groupId} 2 | artifactId = ${project.artifactId} 3 | version = ${project.version} -------------------------------------------------------------------------------- /src/main/resources/jess.properties: -------------------------------------------------------------------------------- 1 | RULE_SERVICE_PROVIDER = jess.jsr94 2 | RULE_SERVICE_PROVIDER_IMPL = jess.jsr94.RuleServiceProviderImpl 3 | source = clp -------------------------------------------------------------------------------- /test.bat: -------------------------------------------------------------------------------- 1 | java -jar target\TabbyXL-1.1.1-jar-with-dependencies.jar -input examples\data\smpl.xlsx -ruleset examples\rules\smpl.crl -output examples\results 2 | -------------------------------------------------------------------------------- /test.sh: -------------------------------------------------------------------------------- 1 | java -jar target/TabbyXL-1.1.1-jar-with-dependencies.jar -input examples/data/smpl.xlsx -ruleset examples/rules/smpl.crl -output examples/results 2 | -------------------------------------------------------------------------------- /src/main/resources/drools.properties: -------------------------------------------------------------------------------- 1 | RULE_SERVICE_PROVIDER = http://drools.org/ 2 | RULE_SERVICE_PROVIDER_IMPL = org.drools.jsr94.rules.RuleServiceProviderImpl 3 | SOURCE = drl 4 | 5 | -------------------------------------------------------------------------------- /src/main/resources/drools-dsl.properties: -------------------------------------------------------------------------------- 1 | RULE_SERVICE_PROVIDER = http://drools.org/ 2 | RULE_SERVICE_PROVIDER_IMPL = org.drools.jsr94.rules.RuleServiceProviderImpl 3 | source = dslr 4 | DSL = src/main/resources/crl2.dsl 5 | 6 | -------------------------------------------------------------------------------- /NOTICE: -------------------------------------------------------------------------------- 1 | TabbyXL 2 | Copyright 2021 Alexey O. Shigarov (shigarov@gmail.com), Vasiliy V. Khristyuk, and Viacheslav V. Paramonov 3 | 4 | This product includes software developed by 5 | JBoss Inc (http://www.jboss.org), 6 | Apache Software Foundation (http://www.apache.org). 7 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled class file 2 | *.class 3 | 4 | # Log file 5 | *.log 6 | 7 | # Package Files # 8 | *.jar 9 | 10 | # Folders 11 | target 12 | out 13 | examples/results/* 14 | 15 | #OS junk files 16 | [Tt]humbs.db 17 | *.DS_Store 18 | 19 | # IDEA project files 20 | *.iml 21 | .idea 22 | 23 | # Backup files 24 | *.bak 25 | -------------------------------------------------------------------------------- /src/main/java/ru/icc/td/tabbyxl/preprocessing/headrecog/CellPointer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Class for storing the shift of cells in Cells model in relation to Excel sheet 3 | */ 4 | 5 | package ru.icc.td.tabbyxl.preprocessing.headrecog; 6 | 7 | final class CellPointer { 8 | int c, r; 9 | 10 | CellPointer(int[] shift) { 11 | this.c = shift[0]; 12 | this.r = shift[1]; 13 | } 14 | 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/ru/icc/td/tabbyxl/model/style/VertAlignment.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-18 Alexey O. Shigarov (shigarov@icc.ru) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package ru.icc.td.tabbyxl.model.style; 18 | 19 | public enum VertAlignment 20 | { 21 | TOP, 22 | CENTER, 23 | BOTTOM, 24 | JUSTIFY 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/ru/icc/td/tabbyxl/preprocessing/Preprocessor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Alexey O. Shigarov (shigarov@gmail.com) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package ru.icc.td.tabbyxl.preprocessing; 18 | 19 | import ru.icc.td.tabbyxl.model.CTable; 20 | 21 | public interface Preprocessor { 22 | void process(CTable table); 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/ru/icc/td/tabbyxl/model/TypeTag.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-19 Alexey O. Shigarov (shigarov@gmail.com) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package ru.icc.td.tabbyxl.model; 18 | 19 | public enum TypeTag { 20 | NUMERIC, 21 | DATE, 22 | STRING, 23 | FORMULA, 24 | BLANK, 25 | BOOLEAN, 26 | ERROR 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/ru/icc/td/tabbyxl/model/style/HorzAlignment.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-18 Alexey O. Shigarov (shigarov@icc.ru) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package ru.icc.td.tabbyxl.model.style; 18 | 19 | public enum HorzAlignment 20 | { 21 | GENERAL, 22 | LEFT, 23 | CENTER, 24 | RIGHT, 25 | FILL, 26 | JUSTIFY, 27 | CENTER_SELECTION 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/ru/icc/td/tabbyxl/model/style/BorderType.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-18 Alexey O. Shigarov (shigarov@icc.ru) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package ru.icc.td.tabbyxl.model.style; 18 | 19 | import ru.icc.td.tabbyxl.model.CCell; 20 | 21 | public enum BorderType 22 | { 23 | NONE, 24 | THIN, 25 | MEDIUM, 26 | DASHED, 27 | HAIR, 28 | THICK, 29 | DOUBLE, 30 | DOTTED, 31 | MEDIUM_DASHED, 32 | DASH_DOT, 33 | MEDIUM_DASH_DOT, 34 | DASH_DOT_DOT, 35 | MEDIUM_DASH_DOT_DOT, 36 | SLANTED_DASH_DOT 37 | } 38 | 39 | -------------------------------------------------------------------------------- /src/main/java/ru/icc/td/tabbyxl/crl2j/TableConsumer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Alexey O. Shigarov (shigarov@icc.ru) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package ru.icc.td.tabbyxl.crl2j; 18 | 19 | import ru.icc.td.tabbyxl.model.CTable; 20 | 21 | import java.util.function.Consumer; 22 | 23 | public interface TableConsumer extends Consumer, Comparable { 24 | 25 | int getOrder(); 26 | 27 | @Override 28 | default int compareTo(TableConsumer other) { 29 | return Integer.compare(this.getOrder(), other.getOrder()); 30 | } 31 | } 32 | 33 | -------------------------------------------------------------------------------- /src/main/java/ru/icc/td/tabbyxl/crl2j/rulemodel/Expression.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Alexey O. Shigarov (shigarov@icc.ru) and Vasiliy V. Khristyuk 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package ru.icc.td.tabbyxl.crl2j.rulemodel; 18 | 19 | import java.util.ArrayList; 20 | import java.util.List; 21 | 22 | public final class Expression { 23 | 24 | private List tokens = new ArrayList<>(); 25 | 26 | public void addToken(String token) { 27 | tokens.add(token); 28 | } 29 | 30 | public List getTokens() { 31 | return tokens; 32 | } 33 | 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/ru/icc/td/tabbyxl/model/exception/NotAllowedParentCycleException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-19 Alexey O. Shigarov (shigarov@gmail.com) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package ru.icc.td.tabbyxl.model.exception; 18 | 19 | import ru.icc.td.tabbyxl.model.CLabel; 20 | 21 | public final class NotAllowedParentCycleException extends ParentAssociatingException 22 | { 23 | public NotAllowedParentCycleException(CLabel child, CLabel parent, CLabel failedParent ) 24 | { 25 | super( child, parent, failedParent, "\"Label cycles are not allowed\"" ); 26 | } 27 | } 28 | 29 | -------------------------------------------------------------------------------- /src/main/java/ru/icc/td/tabbyxl/model/exception/CategoryGroupException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-19 Alexey O. Shigarov (shigarov@gmail.com) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package ru.icc.td.tabbyxl.model.exception; 18 | 19 | public final class CategoryGroupException extends IllegalStateException { 20 | public CategoryGroupException(String categoryGroupName, String labelGroupName) { 21 | super(String.format( 22 | "Labels in the same group are belong more than one categories: \"%s\" and \"%s\"", 23 | categoryGroupName, labelGroupName) 24 | ); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/ru/icc/td/tabbyxl/model/exception/NotAllowedParentChangeException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-19 Alexey O. Shigarov (shigarov@gmail.com) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package ru.icc.td.tabbyxl.model.exception; 18 | 19 | import ru.icc.td.tabbyxl.model.CLabel; 20 | 21 | public final class NotAllowedParentChangeException extends ParentAssociatingException 22 | { 23 | public NotAllowedParentChangeException(CLabel child, CLabel parent, CLabel failedParent ) 24 | { 25 | super( child, parent, failedParent, "\"The label is already associated with the parent label\"" ); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/ru/icc/td/tabbyxl/model/NerTag.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Alexey O. Shigarov (shigarov@gmail.com) and Viacheslav V. Paramonov 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package ru.icc.td.tabbyxl.model; 18 | 19 | public enum NerTag { 20 | 21 | // 12 entity classes provided by Stanford NLP for English, by default 22 | 23 | PERSON, 24 | LOCATION, 25 | ORGANIZATION, 26 | MISC, 27 | 28 | MONEY, 29 | NUMBER, 30 | ORDINAL, 31 | PERCENT, 32 | 33 | DATE, 34 | TIME, 35 | DURATION, 36 | SET, 37 | 38 | // A class of named entities for all rest cases 39 | 40 | NONE; 41 | } 42 | -------------------------------------------------------------------------------- /src/main/java/ru/icc/td/tabbyxl/model/COwned.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-18 Alexey O. Shigarov (shigarov@gmail.com) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package ru.icc.td.tabbyxl.model; 18 | 19 | public abstract class COwned { 20 | private CTable owner; 21 | 22 | protected CTable getOwner() { 23 | return owner; 24 | } 25 | 26 | protected void setOwner(CTable owner) { 27 | if (null == owner) 28 | throw new NullPointerException("The owner cannot be null"); 29 | this.owner = owner; 30 | } 31 | 32 | protected COwned(CTable owner) { 33 | super(); 34 | setOwner(owner); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/main/java/ru/icc/td/tabbyxl/model/exception/ParentAssociatingException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-19 Alexey O. Shigarov (shigarov@gmail.com) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package ru.icc.td.tabbyxl.model.exception; 18 | 19 | import ru.icc.td.tabbyxl.model.CLabel; 20 | 21 | public abstract class ParentAssociatingException extends Exception 22 | { 23 | protected ParentAssociatingException(CLabel child, CLabel parent, CLabel failedParent, String message ) 24 | { 25 | super( String.format( "%s [child: \"%s\"; parent: \"%s\"; failed parent: \"%s\"]", 26 | message, child.getValue(), parent.getValue(), failedParent.getValue() ) ); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/ru/icc/td/tabbyxl/writers/TableWriter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-18 Alexey O. Shigarov (shigarov@gmail.com) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package ru.icc.td.tabbyxl.writers; 18 | 19 | import ru.icc.td.tabbyxl.model.CTable; 20 | 21 | import java.io.File; 22 | import java.io.IOException; 23 | 24 | public abstract class TableWriter 25 | { 26 | protected File outputFile; 27 | 28 | public void setOutputFile(File outputFile) { 29 | this.outputFile = outputFile; 30 | } 31 | 32 | public abstract void write(CTable table) throws IOException; 33 | 34 | public TableWriter(File outputFile) 35 | { 36 | setOutputFile(outputFile); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /examples/rules/smpl.crl: -------------------------------------------------------------------------------- 1 | rule #1 2 | when 3 | cell corner: cl == 1, rt == 1 4 | cell c: rb <= corner.rb, cl > corner.cr 5 | then 6 | set tag "head" to c 7 | new label c 8 | end 9 | 10 | rule #2 11 | when 12 | cell corner: cl == 1, rt == 1 13 | cell c: cr <= corner.cr, rt > corner.rb 14 | then 15 | set tag "stub" to c 16 | new label c 17 | end 18 | 19 | rule #3 20 | when 21 | cell corner: cl == 1, rt == 1 22 | cell c: cl > corner.cr, rt > corner.rb 23 | then 24 | set tag "body" to c 25 | new entry c 26 | end 27 | 28 | rule #4 29 | when 30 | cell c1: tag == "stub" 31 | cell c2: tag == "stub", cl == c1.cl, cr == c1.cr 32 | then 33 | group c1.label with c2.label 34 | end 35 | 36 | rule #5 37 | when 38 | cell c1: tag == "head" 39 | cell c2: tag == "head", rt == c1.rt, rb == c1.rb 40 | then 41 | group c1.label with c2.label 42 | end 43 | 44 | rule #6 45 | when 46 | cell c1: tag == "stub" 47 | cell c2: tag == "body", rt >= c1.rt, rb <= c1.rb 48 | then 49 | add label c1.label to c2.entry 50 | end 51 | 52 | rule #7 53 | when 54 | cell c1: tag == "head" 55 | cell c2: tag == "body", cl >= c1.cl, cr <= c1.cr 56 | then 57 | add label c1.label to c2.entry 58 | end -------------------------------------------------------------------------------- /src/main/java/ru/icc/td/tabbyxl/model/style/FillPattern.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-18 Alexey O. Shigarov (shigarov@icc.ru) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package ru.icc.td.tabbyxl.model.style; 18 | 19 | public enum FillPattern 20 | { 21 | PATTERN_NO_FILL, 22 | PATTERN_SOLID_FOREGROUND, 23 | PATTERN_FINE_DOTS, 24 | PATTERN_ALT_BARS, 25 | PATTERN_SPARSE_DOTS, 26 | PATTERN_THICK_HORZ_BANDS, 27 | PATTERN_THICK_VERT_BANDS, 28 | PATTERN_THICK_BACKWARD_DIAG, 29 | PATTERN_THICK_FORWARD_DIAG, 30 | PATTERN_BIG_SPOTS, 31 | PATTERN_BRICKS, 32 | PATTERN_THIN_HORZ_BANDS, 33 | PATTERN_THIN_VERT_BANDS, 34 | PATTERN_THIN_BACKWARD_DIAG, 35 | PATTERN_THIN_FORWARD_DIAG, 36 | PATTERN_SQUARES, 37 | PATTERN_DIAMONDS, 38 | PATTERN_LESS_DOTS, 39 | PATTERN_LEAST_DOTS 40 | } 41 | -------------------------------------------------------------------------------- /src/main/java/ru/icc/td/tabbyxl/crl2j/rulemodel/Action.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Alexey O. Shigarov (shigarov@icc.ru) and Vasiliy V. Khristyuk 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package ru.icc.td.tabbyxl.crl2j.rulemodel; 18 | 19 | import java.util.ArrayList; 20 | import java.util.List; 21 | 22 | public final class Action { 23 | 24 | private String methodName; 25 | private List operands = new ArrayList<>(); 26 | 27 | public String getMethodName() { 28 | return methodName; 29 | } 30 | 31 | public void setMethodName(String methodName) { 32 | this.methodName = methodName; 33 | } 34 | 35 | public List getOperands() { 36 | return operands; 37 | } 38 | 39 | public void setOperands(List operands) { 40 | this.operands = operands; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/main/java/ru/icc/td/tabbyxl/crl2j/rulemodel/Assignment.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Alexey O. Shigarov (shigarov@icc.ru) and Vasiliy V. Khristyuk 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package ru.icc.td.tabbyxl.crl2j.rulemodel; 18 | 19 | import java.util.ArrayList; 20 | import java.util.List; 21 | 22 | public final class Assignment { 23 | 24 | private String identifier; 25 | private List expressions = new ArrayList<>(); 26 | 27 | public void setIdentifier(String identifier) { 28 | this.identifier = identifier; 29 | } 30 | 31 | public String getIdentifier() { 32 | return identifier; 33 | } 34 | 35 | public void addExpression (String expression) { 36 | this.expressions.add(expression); 37 | } 38 | 39 | public List getExpressions() { 40 | return expressions; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/main/java/ru/icc/td/tabbyxl/model/exception/EntryAssociatingException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-19 Alexey O. Shigarov (shigarov@gmail.com) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package ru.icc.td.tabbyxl.model.exception; 18 | 19 | import ru.icc.td.tabbyxl.model.CCategory; 20 | import ru.icc.td.tabbyxl.model.CEntry; 21 | import ru.icc.td.tabbyxl.model.CLabel; 22 | 23 | public final class EntryAssociatingException extends IllegalStateException 24 | { 25 | public EntryAssociatingException(CEntry entry, CLabel addingLabel, CLabel addedLabel, CCategory category ) 26 | { 27 | super( String.format( "%s [entry: \"%s\"; adding label: \"%s\"; added label: \"%s\"; category: \"%s\"]", 28 | "The entry is already associated with a label from the same category", 29 | entry.getValue(), addingLabel.getValue(), addedLabel.getValue(), category.getName() ) ); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/ru/icc/td/tabbyxl/MvnGen.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Alexey O. Shigarov (shigarov@gmail.com) and Vasiliy V. Khristyuk 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package ru.icc.td.tabbyxl; 18 | 19 | import org.antlr.runtime.RecognitionException; 20 | import ru.icc.td.tabbyxl.crl2j.mvngen.MvnProjectGenerator; 21 | 22 | import java.io.File; 23 | import java.io.IOException; 24 | import java.nio.file.Path; 25 | import java.nio.file.Paths; 26 | 27 | public final class MvnGen { 28 | 29 | public static void main(String[] args) { 30 | try { 31 | 32 | File crlFile = new File(args[0]); 33 | Path resultDirectory = Paths.get(args[1]); 34 | MvnProjectGenerator.generate(crlFile, resultDirectory); 35 | 36 | } catch (IOException | RecognitionException e) { 37 | e.printStackTrace(); 38 | System.exit(-1); 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/main/java/ru/icc/td/tabbyxl/model/CItem.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-19 Alexey O. Shigarov (shigarov@gmail.com) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package ru.icc.td.tabbyxl.model; 18 | 19 | public abstract class CItem extends COwned { 20 | private CCell cell; 21 | 22 | public CCell getCell() { 23 | return cell; 24 | } 25 | 26 | private void setCell(CCell cell) { 27 | this.cell = cell; 28 | } 29 | 30 | private String value; 31 | 32 | public String getValue() { 33 | return value; 34 | } 35 | 36 | public void setValue(String value) { 37 | if (null == value) 38 | this.value = ""; 39 | else 40 | this.value = value.trim().toLowerCase(); 41 | } 42 | 43 | protected CItem(CTable owner, CCell cell, String value) { 44 | super(owner); 45 | setCell(cell); 46 | setValue(value); 47 | } 48 | 49 | } 50 | -------------------------------------------------------------------------------- /src/main/java/ru/icc/td/tabbyxl/crl2j/compiler/FileObjectImpl.java: -------------------------------------------------------------------------------- 1 | package ru.icc.td.tabbyxl.crl2j.compiler; 2 | 3 | import javax.tools.SimpleJavaFileObject; 4 | import java.io.ByteArrayInputStream; 5 | import java.io.ByteArrayOutputStream; 6 | import java.io.InputStream; 7 | import java.io.OutputStream; 8 | 9 | final class FileObjectImpl extends SimpleJavaFileObject { 10 | private ByteArrayOutputStream byteCode; 11 | 12 | private CharSequence source; 13 | 14 | public FileObjectImpl(String baseName, CharSequence source) 15 | { 16 | super(CharSequenceCompiler.toURI(baseName + ".java"), Kind.SOURCE); 17 | this.source = source; 18 | } 19 | 20 | public FileObjectImpl(String name, Kind kind) 21 | { 22 | super(CharSequenceCompiler.toURI(name), kind); 23 | this.source = null; 24 | } 25 | 26 | @Override 27 | public CharSequence getCharContent(final boolean ignoredEncodingErrors) 28 | throws UnsupportedOperationException 29 | { 30 | if(source == null) 31 | throw new UnsupportedOperationException(); 32 | return source; 33 | } 34 | 35 | @Override 36 | public InputStream openInputStream() 37 | { 38 | return new ByteArrayInputStream(getByteCode()); 39 | } 40 | 41 | public byte[] getByteCode() { return byteCode.toByteArray(); } 42 | 43 | @Override 44 | public OutputStream openOutputStream() 45 | { 46 | byteCode = new ByteArrayOutputStream(); 47 | return byteCode; 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/main/java/ru/icc/td/tabbyxl/model/style/CBorder.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-18 Alexey O. Shigarov (shigarov@icc.ru) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package ru.icc.td.tabbyxl.model.style; 18 | 19 | public final class CBorder 20 | { 21 | private BorderType type; 22 | 23 | public BorderType getType() 24 | { 25 | return this.type; 26 | } 27 | 28 | public void setType( BorderType type ) 29 | { 30 | this.type = type; 31 | } 32 | 33 | private CColor color; 34 | 35 | public CColor getColor() 36 | { 37 | return this.color; 38 | } 39 | 40 | public void setColor( CColor color ) 41 | { 42 | this.color = color; 43 | } 44 | 45 | public CBorder( BorderType type, CColor color ) 46 | { 47 | this.setType( type ); 48 | this.setColor( color ); 49 | } 50 | 51 | public CBorder() 52 | { 53 | this( BorderType.NONE, null ); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/main/java/ru/icc/td/tabbyxl/crl2j/rulemodel/Rule.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Alexey O. Shigarov (shigarov@icc.ru) and Vasiliy V. Khristyuk 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package ru.icc.td.tabbyxl.crl2j.rulemodel; 18 | 19 | import java.util.ArrayList; 20 | import java.util.List; 21 | 22 | public final class Rule { 23 | 24 | private int id; 25 | private List conditions = new ArrayList<>(); 26 | private List actions = new ArrayList<>(); 27 | 28 | public int getId() { 29 | return id; 30 | } 31 | 32 | public void setId(int id) { 33 | this.id = id; 34 | } 35 | 36 | public List getConditions() { 37 | return conditions; 38 | } 39 | 40 | public void addCondition(Condition condition) { 41 | conditions.add(condition); 42 | } 43 | 44 | public List getActions() { 45 | return actions; 46 | } 47 | 48 | public void addAction(Action action) { 49 | actions.add(action); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/main/java/ru/icc/td/tabbyxl/crl2j/parser/CRL.tokens: -------------------------------------------------------------------------------- 1 | T__35=35 2 | T__36=36 3 | T__37=37 4 | T__38=38 5 | T__39=39 6 | T__40=40 7 | T__41=41 8 | T__42=42 9 | T__43=43 10 | T__44=44 11 | T__45=45 12 | T__46=46 13 | T__47=47 14 | T__48=48 15 | T__49=49 16 | T__50=50 17 | T__51=51 18 | T__52=52 19 | T__53=53 20 | T__54=54 21 | T__55=55 22 | T__56=56 23 | T__57=57 24 | T__58=58 25 | T__59=59 26 | T__60=60 27 | T__61=61 28 | T__62=62 29 | T__63=63 30 | T__64=64 31 | T__65=65 32 | T__66=66 33 | T__67=67 34 | T__68=68 35 | T__69=69 36 | T__70=70 37 | T__71=71 38 | ACTION=4 39 | ACTIONS=5 40 | ASSIGNMENT=6 41 | BRACKET=7 42 | CHAR=8 43 | COMMENT=9 44 | CONDITION=10 45 | CONDITIONS=11 46 | CONSTRAINT=12 47 | CONSTRAINTS=13 48 | EOL=14 49 | ESC_SEQ=15 50 | EXPONENT=16 51 | EXPRESSION=17 52 | FLOAT=18 53 | HEX_DIGIT=19 54 | ID=20 55 | IDENTIFIER=21 56 | IMPORT=22 57 | IMPORTS=23 58 | INT=24 59 | OCTAL_ESC=25 60 | OPERAND=26 61 | OPERATOR=27 62 | QUERY=28 63 | RULE=29 64 | RULES=30 65 | STRING=31 66 | TYPE=32 67 | UNICODE_ESC=33 68 | WS=34 69 | ','=35 70 | '.'=36 71 | '.*'=37 72 | ':'=38 73 | ';'=39 74 | 'add label'=40 75 | 'as'=41 76 | 'categories'=42 77 | 'category'=43 78 | 'cell'=44 79 | 'cells'=45 80 | 'end'=46 81 | 'entries'=47 82 | 'entry'=48 83 | 'group'=49 84 | 'import static'=50 85 | 'label'=51 86 | 'labels'=52 87 | 'merge'=53 88 | 'new entry'=54 89 | 'new label'=55 90 | 'no'=56 91 | 'of'=57 92 | 'print'=58 93 | 'printf'=59 94 | 'rule #'=60 95 | 'set category'=61 96 | 'set indent'=62 97 | 'set parent'=63 98 | 'set tag'=64 99 | 'set text'=65 100 | 'set value'=66 101 | 'split'=67 102 | 'then'=68 103 | 'to'=69 104 | 'when'=70 105 | 'with'=71 106 | -------------------------------------------------------------------------------- /Usage.md: -------------------------------------------------------------------------------- 1 | # Usage 2 | 3 | In order to run the executable JAR, you may use the following command with parameters 4 | ``` 5 | java -jar TabbyXL-1.1.1-jar-with-dependencies.jar 6 | 7 | Params: 8 | -input specify a path to an input excel workbook (*.xlsx) 9 | -sheets specify sheet indexes in the input excel workbook (e.g. "0-2,4,5,7-10") 10 | -ruleset specify a path to a ruleset file (*.dslr (CRL), *.drl (Drools), or *.clp (JESS)) 11 | -categorySpec specify a path to a directory with category specifications in YAML files (*.cat) 12 | -output specify a path to a directory for outputting results 13 | -ignoreSuperscript specify true to ignore superscript text in cells (false used by default) 14 | -useCellText specify true to use cell values as text (false used by default) 15 | -useShortNames specify true to use short names (just sheet names) for output files (false used by default) 16 | -debuggingMode specify true to turn on debugging mode (false used by default) 17 | -ruleEngineConfig specify optionally a path to a configuration file (*.properties) of a rule engine you prefer to use (e.g. Drools, JESS) 18 | (CRL-to-Java translation is used by default instead of a rule engine) 19 | -help print this usage 20 | ``` 21 | 22 | Only two parameters are mandatory 23 | * `-input ` 24 | * `-ruleset ` 25 | 26 | ## Authors 27 | 28 | * Alexey O. Shigarov 29 | * Vasiliy V. Khristyuk 30 | * Viacheslav V. Paramonov 31 | 32 | ## License 33 | Apache License, Version 2.0 -------------------------------------------------------------------------------- /src/main/java/ru/icc/td/tabbyxl/util/CRL2DRLMapper.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-18 Alexey O. Shigarov (shigarov@gmail.com) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package ru.icc.td.tabbyxl.util; 18 | 19 | import java.io.File; 20 | import java.io.FileReader; 21 | import java.io.Reader; 22 | import java.util.Scanner; 23 | 24 | import org.drools.compiler.compiler.DrlParser; 25 | 26 | public final class CRL2DRLMapper { 27 | public static void main(String[] args) { 28 | CRL2DRLMapper mapper = new CRL2DRLMapper(); 29 | try { 30 | String crlRulesetPath = args[0]; 31 | String dslPath = args[1]; 32 | String drlRuleset = mapper.expandDRL(crlRulesetPath, dslPath); 33 | System.out.println(drlRuleset); 34 | } 35 | catch (Exception e) { 36 | e.printStackTrace(); 37 | } 38 | } 39 | 40 | public String expandDRL(String crlRulesetPath, String dslPath) throws Exception { 41 | Reader dslReader = new FileReader(dslPath); 42 | String drl = new Scanner(new File( crlRulesetPath), "UTF-8").useDelimiter("\\A").next(); 43 | DrlParser parser = new DrlParser(); 44 | return parser.getExpandedDRL(drl, dslReader); 45 | } 46 | } -------------------------------------------------------------------------------- /src/main/java/ru/icc/td/tabbyxl/crl2j/compiler/CharSequenceCompilerException.java: -------------------------------------------------------------------------------- 1 | package ru.icc.td.tabbyxl.crl2j.compiler; 2 | 3 | import javax.tools.DiagnosticCollector; 4 | import javax.tools.JavaFileObject; 5 | import java.util.Collection; 6 | import java.util.Collections; 7 | import java.util.HashSet; 8 | import java.util.Set; 9 | 10 | public class CharSequenceCompilerException extends Exception { 11 | private static final long serialVersion = 1L; 12 | 13 | private Set classNames; 14 | 15 | transient private DiagnosticCollector diagnostics; 16 | 17 | public CharSequenceCompilerException(String message, Set classNames, Throwable cause, DiagnosticCollector diagnostics) 18 | { 19 | super(message, cause); 20 | setClassNames(classNames); 21 | setDiagnostics(diagnostics); 22 | } 23 | 24 | public CharSequenceCompilerException(String message, Set classNames, DiagnosticCollector diagnostics) 25 | { 26 | super(message); 27 | setClassNames(classNames); 28 | setDiagnostics(diagnostics); 29 | } 30 | 31 | public CharSequenceCompilerException(Set classNames, Throwable cause, DiagnosticCollector diagnostics) 32 | { 33 | super(cause); 34 | setClassNames(classNames); 35 | setDiagnostics(diagnostics); 36 | } 37 | 38 | private void setClassNames(Set classNames) 39 | { 40 | this.classNames = new HashSet(classNames); 41 | } 42 | 43 | private void setDiagnostics(DiagnosticCollector diagnostics) 44 | { 45 | this.diagnostics = diagnostics; 46 | } 47 | 48 | public DiagnosticCollector getDiagnostics() { 49 | return diagnostics; 50 | } 51 | 52 | public Collection getClassNames() { return Collections.unmodifiableSet(classNames); } 53 | } 54 | -------------------------------------------------------------------------------- /src/main/java/ru/icc/td/tabbyxl/model/LocalCategoryBox.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-18 Alexey O. Shigarov (shigarov@gmail.com) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package ru.icc.td.tabbyxl.model; 18 | 19 | import java.util.*; 20 | 21 | public final class LocalCategoryBox extends COwned { 22 | private Set categories = new HashSet(); 23 | 24 | public Iterator getCategories() { 25 | return categories.iterator(); 26 | } 27 | 28 | public List getCategoryList() { 29 | List res = new ArrayList(); 30 | Iterator iterator = categories.iterator(); 31 | while (iterator.hasNext()) 32 | res.add((CCategory) iterator.next()); 33 | return res; 34 | } 35 | 36 | int numOfCategories() { 37 | return this.categories.size(); 38 | } 39 | 40 | CCategory newCategory(String categoryName) { 41 | CCategory category = new CCategory(getOwner(), categoryName); 42 | // TODO testing is needed: an adding category must have an unique name among all added categories 43 | if (categories.add(category)) { 44 | return category; 45 | } 46 | return null; 47 | } 48 | 49 | CCategory findCategory(String categoryName) { 50 | categoryName = categoryName.toLowerCase(); 51 | 52 | for (CCategory c : categories) { 53 | if (c.getName().equalsIgnoreCase(categoryName)) { 54 | return c; 55 | } 56 | } 57 | return null; 58 | } 59 | 60 | LocalCategoryBox(CTable owner) { 61 | super(owner); 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /src/main/java/ru/icc/td/tabbyxl/crl2j/compiler/ClassLoaderImpl.java: -------------------------------------------------------------------------------- 1 | package ru.icc.td.tabbyxl.crl2j.compiler; 2 | 3 | import javax.tools.JavaFileObject; 4 | import java.io.ByteArrayInputStream; 5 | import java.io.InputStream; 6 | import java.util.Collection; 7 | import java.util.Collections; 8 | import java.util.HashMap; 9 | import java.util.Map; 10 | 11 | final class ClassLoaderImpl extends ClassLoader { 12 | private Map classes = new HashMap<>(); 13 | 14 | public ClassLoaderImpl(ClassLoader parentClassLoader) 15 | { 16 | super(parentClassLoader); 17 | } 18 | 19 | public Collection files() 20 | { 21 | return Collections.unmodifiableCollection(classes.values()); 22 | } 23 | 24 | @Override 25 | protected Class findClass(String className) throws ClassNotFoundException 26 | { 27 | FileObjectImpl file = (FileObjectImpl) classes.get(className); 28 | if(file != null) 29 | { 30 | byte[] bytes = ((FileObjectImpl)file).getByteCode(); 31 | return defineClass(className, bytes, 0, bytes.length); 32 | } 33 | 34 | try 35 | { 36 | Class c = Class.forName(className); 37 | return c; 38 | }catch ( ClassNotFoundException e ) {} 39 | 40 | return super.findClass(className); 41 | } 42 | 43 | public void add(String className, JavaFileObject file) 44 | { 45 | classes.put(className, file); 46 | } 47 | 48 | @Override 49 | protected synchronized Class loadClass(String name, boolean resolve) 50 | throws ClassNotFoundException 51 | { 52 | return super.loadClass(name, resolve); 53 | } 54 | 55 | @Override 56 | public InputStream getResourceAsStream(String name) 57 | { 58 | if(name.endsWith(".class")) 59 | { 60 | String className = name.substring(0, name.length() - ".class".length()).replace('/','.'); 61 | FileObjectImpl file = (FileObjectImpl) classes.get(className); 62 | if(file != null) 63 | return new ByteArrayInputStream(file.getByteCode()); 64 | } 65 | return super.getResourceAsStream(name); 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /src/main/java/ru/icc/td/tabbyxl/crl2j/mvngen/SpreadsheetTableExtractor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Alexey O. Shigarov (shigarov@icc.ru) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package ru.icc.td.tabbyxl.crl2j.mvngen; 18 | 19 | import ru.icc.td.tabbyxl.DataLoader; 20 | import ru.icc.td.tabbyxl.crl2j.TableConsumer; 21 | import ru.icc.td.tabbyxl.model.CTable; 22 | 23 | import java.io.File; 24 | import java.io.IOException; 25 | import java.util.*; 26 | 27 | public final class SpreadsheetTableExtractor { 28 | 29 | private final SortedSet tableConsumers = new TreeSet<>(); 30 | 31 | public void register(TableConsumer tableConsumer) { 32 | tableConsumers.add(tableConsumer); 33 | } 34 | 35 | public CTable[] extract(File excelFile) throws IOException { 36 | 37 | // Load a workbook 38 | 39 | DataLoader dataLoader = DataLoader.getInstance(); 40 | dataLoader.loadWorkbook(excelFile); 41 | 42 | List extractedTables = new ArrayList<>(); 43 | 44 | // Process all sheets of the workbook 45 | 46 | for (int i = 0; i < dataLoader.numOfSheets(); i++) { 47 | dataLoader.goToSheet(i); 48 | 49 | // Canonicalize all tables placed on the current sheet 50 | 51 | while (true) { 52 | CTable table = dataLoader.nextTable(); 53 | if (null == table) break; 54 | 55 | tableConsumers.forEach(consumer -> consumer.accept(table)); 56 | table.update(); 57 | extractedTables.add(table); 58 | } 59 | } 60 | 61 | return extractedTables.isEmpty() ? null : extractedTables.toArray(new CTable[]{}); 62 | } 63 | 64 | } 65 | -------------------------------------------------------------------------------- /src/main/java/ru/icc/td/tabbyxl/crl2j/StaticImportDescriptor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Alexey O. Shigarov (shigarov@icc.ru) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package ru.icc.td.tabbyxl.crl2j; 18 | 19 | import java.util.regex.Pattern; 20 | 21 | final class StaticImportDescriptor { 22 | private String packageName; 23 | private String className; 24 | private String memberName; 25 | 26 | public String getPackageName() { 27 | return packageName; 28 | } 29 | 30 | public String getClassName() { 31 | return className; 32 | } 33 | 34 | public String getMemberName() { 35 | return memberName; 36 | } 37 | 38 | private StaticImportDescriptor() { 39 | } 40 | 41 | private static final Pattern validator; 42 | 43 | static { 44 | String regex = "import(\\s)+static(\\s)+(\\w+(\\.)?\\w+)+\\.((\\w)+|\\*)"; 45 | validator = Pattern.compile(regex); 46 | } 47 | 48 | static StaticImportDescriptor parseStaticImportStatement(final String statement) { 49 | if (!validator.matcher(statement).matches()) return null; 50 | 51 | StaticImportDescriptor desc = new StaticImportDescriptor(); 52 | 53 | String imported = statement.replaceFirst("import(\\s)+static(\\s)+", ""); 54 | 55 | int posOfLastDot = imported.lastIndexOf('.'); 56 | desc.memberName = imported.substring(posOfLastDot + 1, imported.length()); 57 | 58 | imported = imported.substring(0, posOfLastDot); 59 | posOfLastDot = imported.lastIndexOf('.'); 60 | desc.className = imported.substring(posOfLastDot + 1, imported.length()); 61 | 62 | desc.packageName = imported.substring(0, posOfLastDot); 63 | 64 | return desc; 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /src/main/java/ru/icc/td/tabbyxl/preprocessing/headrecog/HeadRecogPreprocessor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Alexey O. Shigarov (shigarov@gmail.com) and Viacheslav V. Paramonov 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package ru.icc.td.tabbyxl.preprocessing.headrecog; 18 | 19 | import org.apache.poi.ss.usermodel.Workbook; 20 | import org.apache.poi.xssf.usermodel.XSSFWorkbook; 21 | import ru.icc.td.tabbyxl.model.CTable; 22 | import ru.icc.td.tabbyxl.preprocessing.Preprocessor; 23 | 24 | import java.io.File; 25 | import java.io.FileInputStream; 26 | import java.io.FileOutputStream; 27 | import java.io.IOException; 28 | 29 | public final class HeadRecogPreprocessor implements Preprocessor { 30 | 31 | private File output; 32 | private Workbook workbook; 33 | 34 | public HeadRecogPreprocessor(File output) throws IOException { 35 | this.output = output; 36 | workbook = createWorkbook(output); 37 | } 38 | 39 | private Workbook createWorkbook(File srcFile) throws IOException { 40 | Workbook workbook; 41 | FileInputStream fin = new FileInputStream(srcFile); 42 | workbook = new XSSFWorkbook(fin); 43 | return workbook; 44 | } 45 | 46 | @Override 47 | public void process(CTable table) { 48 | new HeadRecogAlgorithms(table, workbook).analyze(); 49 | } 50 | 51 | public void saveWorkbook() { 52 | String path = output.getAbsolutePath(); 53 | try { 54 | File file = new File(path); 55 | try (FileOutputStream out = new FileOutputStream(file)) { 56 | workbook.write(out); 57 | System.out.println("All changes were written successfully"); 58 | } 59 | } catch (IOException e) { 60 | e.printStackTrace(); 61 | } 62 | } 63 | 64 | } 65 | -------------------------------------------------------------------------------- /src/main/java/ru/icc/td/tabbyxl/crl2j/rulemodel/Condition.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Alexey O. Shigarov (shigarov@icc.ru) and Vasiliy V. Khristyuk 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package ru.icc.td.tabbyxl.crl2j.rulemodel; 18 | 19 | import java.util.ArrayList; 20 | import java.util.List; 21 | 22 | public final class Condition { 23 | 24 | public enum Quantifier { 25 | EXIST, NOT_EXIST 26 | } 27 | 28 | private int id; 29 | private Quantifier quantifier; 30 | private Class queriedType; 31 | private String identifier; 32 | private List constraints = new ArrayList<>(); 33 | private List assignments = new ArrayList<>(); 34 | 35 | public int getId() { 36 | return id; 37 | } 38 | 39 | public void setId(int id) { 40 | this.id = id; 41 | } 42 | 43 | public Quantifier getQuantifier() { 44 | return quantifier; 45 | } 46 | 47 | public void setQuantifier(Quantifier quantifier) { 48 | this.quantifier = quantifier; 49 | } 50 | 51 | public void setQueriedType(Class queriedType) { 52 | this.queriedType = queriedType; 53 | } 54 | 55 | public Class getQueriedType() { 56 | return queriedType; 57 | } 58 | 59 | public void setIdentifier(String identifier) { 60 | this.identifier = identifier; 61 | } 62 | 63 | public String getIdentifier() { 64 | return identifier; 65 | } 66 | 67 | public void addConstraint(Expression constraint) { 68 | this.constraints.add(constraint); 69 | } 70 | 71 | public List getConstraints() { 72 | return constraints; 73 | } 74 | 75 | public void addAssignment(Assignment assignment) { 76 | this.assignments.add(assignment); 77 | } 78 | 79 | public List getAssignments() { 80 | return assignments; 81 | } 82 | 83 | } 84 | -------------------------------------------------------------------------------- /src/main/java/ru/icc/td/tabbyxl/crl2j/parser/ASTPrinter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018-19 Alexey O. Shigarov (shigarov@icc.ru) and Vasiliy V. Khristyuk 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package ru.icc.td.tabbyxl.crl2j.parser; 18 | 19 | import org.antlr.runtime.tree.Tree; 20 | 21 | import java.nio.ByteBuffer; 22 | import java.nio.CharBuffer; 23 | import java.nio.charset.Charset; 24 | 25 | public final class ASTPrinter { 26 | 27 | private static final char FIRST_CHAR, MIDDLE_CHAR, LAST_CHAR; 28 | 29 | static { 30 | Charset charSet = Charset.forName("CP866"); 31 | CharBuffer charBuff = charSet.decode(ByteBuffer.wrap(new byte[]{(byte) 0xB3, (byte) 0xC3, (byte) 0xC0})); 32 | FIRST_CHAR = charBuff.charAt(0); 33 | MIDDLE_CHAR = charBuff.charAt(1); 34 | LAST_CHAR = charBuff.charAt(2); 35 | } 36 | 37 | private static String traceSubTree(Tree node, String id, boolean root) { 38 | 39 | final String lineSeparator = System.lineSeparator(); 40 | if (node == null) return ""; 41 | StringBuilder result = new StringBuilder(id); 42 | StringBuilder identifier = new StringBuilder(id); 43 | 44 | if (!root) { 45 | if (node.getChildIndex() < node.getParent().getChildCount() - 1) { 46 | result.append(MIDDLE_CHAR).append(" "); 47 | identifier.append(FIRST_CHAR).append(" "); 48 | } else { 49 | result.append(LAST_CHAR).append(" "); 50 | identifier.append(" "); 51 | } 52 | } 53 | 54 | result.append(node.getText()).append(lineSeparator); 55 | 56 | for (int i = 0; i < node.getChildCount(); i ++) { 57 | result.append(traceSubTree(node.getChild(i), identifier.toString(), false)); 58 | } 59 | 60 | return result.toString(); 61 | } 62 | 63 | private static String traceTree(Tree node) { 64 | return traceSubTree(node, "", true); 65 | } 66 | 67 | public static String trace(Tree node) { 68 | return traceTree(node); 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /src/main/resources/mvngen/pom.template: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | 8 | %s 9 | %s 10 | %s 11 | %s 12 | %s 13 | %s 14 | %s 15 | 16 | 17 | ${generatedGroupId} 18 | ${generatedArtifactId} 19 | 1.0 20 | 21 | 22 | 23 | 24 | org.apache.maven.plugins 25 | maven-compiler-plugin 26 | 3.7.0 27 | 28 | 1.8 29 | 1.8 30 | 31 | 32 | 33 | maven-assembly-plugin 34 | 3.0.0 35 | 36 | 37 | 38 | ${generatedMainClass} 39 | true 40 | 41 | 42 | 43 | jar-with-dependencies 44 | 45 | 46 | 47 | 48 | make-assembly 49 | package 50 | 51 | single 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | tabbyxl 62 | ${tabbyxlPath} 63 | 64 | 65 | 66 | 67 | 68 | ${tabbyxlGroupId} 69 | ${tabbyxlArtifactId} 70 | ${tabbyxlVersion} 71 | 72 | 73 | 74 | -------------------------------------------------------------------------------- /src/main/java/ru/icc/td/tabbyxl/model/style/CColor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-18 Alexey O. Shigarov (shigarov@icc.ru) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package ru.icc.td.tabbyxl.model.style; 18 | 19 | public final class CColor 20 | { 21 | private int r; 22 | private int g; 23 | private int b; 24 | 25 | public CColor( String hexRGB ) 26 | { 27 | super(); 28 | 29 | String hexR = String.format( "#%s", hexRGB.substring( 0, 2 ) ); 30 | String hexG = String.format( "#%s", hexRGB.substring( 2, 4 ) ); 31 | String hexB = String.format( "#%s", hexRGB.substring( 4, 6 ) ); 32 | 33 | this.r = Integer.decode( hexR ); 34 | this.g = Integer.decode( hexG ); 35 | this.b = Integer.decode( hexB ); 36 | } 37 | 38 | public CColor ( byte[] rgbWithHint) { 39 | super(); 40 | 41 | if (rgbWithHint[0] >= 0) { 42 | this.r = rgbWithHint[0]; 43 | } else { 44 | this.r = 256 + rgbWithHint[0]; 45 | } 46 | if (rgbWithHint[1] >= 0) { 47 | this.g = rgbWithHint[1]; 48 | } else { 49 | this.g = 256 + rgbWithHint[1]; 50 | } 51 | if (rgbWithHint[2] >= 0) { 52 | this.b = rgbWithHint[2]; 53 | } else { 54 | this.b = 256 + rgbWithHint[2]; 55 | } 56 | } 57 | 58 | String toHexRGBString() 59 | { 60 | String hexR = Integer.toHexString( r ); 61 | String hexG = Integer.toHexString( g ); 62 | String hexB = Integer.toHexString( b ); 63 | 64 | return String.format( "#%s%s%s", hexR, hexG, hexB ); 65 | } 66 | 67 | public String toString() 68 | { 69 | return toHexRGBString(); 70 | } 71 | 72 | @Override 73 | public int hashCode() 74 | { 75 | final int prime = 31; 76 | int result = 1; 77 | result = prime * result + b; 78 | result = prime * result + g; 79 | result = prime * result + r; 80 | return result; 81 | } 82 | 83 | @Override 84 | public boolean equals(Object obj) 85 | { 86 | if (this == obj) return true; 87 | if (obj == null) return false; 88 | if ( getClass() != obj.getClass() ) return false; 89 | 90 | CColor other = ( CColor ) obj; 91 | 92 | if ( b != other.b ) return false; 93 | if ( g != other.g ) return false; 94 | if ( r != other.r ) return false; 95 | 96 | return true; 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /src/main/java/ru/icc/td/tabbyxl/writers/DebugTableWriter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Alexey O. Shigarov (shigarov@gmail.com) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package ru.icc.td.tabbyxl.writers; 18 | 19 | import org.apache.poi.ss.usermodel.Cell; 20 | import org.apache.poi.ss.usermodel.Sheet; 21 | import org.apache.poi.ss.usermodel.Workbook; 22 | import ru.icc.td.tabbyxl.model.*; 23 | 24 | import java.io.File; 25 | import java.util.function.BiConsumer; 26 | 27 | public final class DebugTableWriter extends BasicTableWriter { 28 | 29 | @Override 30 | protected Workbook writeToWorkbook(CTable table) { 31 | Workbook workbook = super.writeToWorkbook(table); 32 | 33 | CanonicalForm cf = table.toCanonicalForm(); 34 | 35 | // Write Ner Tag Sheet 36 | 37 | Sheet sheet1 = workbook.createSheet("NER TAGS"); 38 | BiConsumer setCellValByNerTag = (item, excelCell) -> { 39 | CCell cell = item.getCell(); 40 | String s; 41 | if (null != cell){ 42 | NerTag tag = cell.getNerTag(); 43 | s = null == tag ? null : tag.toString(); 44 | } else { 45 | s = null; 46 | } 47 | excelCell.setCellValue(s); 48 | }; 49 | writeCanonicalForm(sheet1, cf, setCellValByNerTag); 50 | 51 | // Write Type Tag Sheet 52 | 53 | Sheet sheet2 = workbook.createSheet("TYPE TAGS"); 54 | BiConsumer setCellValByTypeTag = (item, excelCell) -> { 55 | CCell cell = item.getCell(); 56 | String s; 57 | if (null != cell) { 58 | TypeTag tag = cell.getTypeTag(); 59 | s = null == tag ? null : tag.toString(); 60 | } else { 61 | s = null; 62 | } 63 | excelCell.setCellValue(s); 64 | }; 65 | writeCanonicalForm(sheet2, cf, setCellValByTypeTag); 66 | 67 | // Write Type Tag Sheet 68 | 69 | Sheet sheet3 = workbook.createSheet("USER-DEFINED TAGS"); 70 | BiConsumer setCellValByTag = (item, excelCell) -> { 71 | CCell cell = item.getCell(); 72 | String s; 73 | if (null != cell) { 74 | s = cell.getTag(); 75 | } else { 76 | s = null; 77 | } 78 | excelCell.setCellValue(s); 79 | }; 80 | writeCanonicalForm(sheet3, cf, setCellValByTag); 81 | 82 | return workbook; 83 | } 84 | 85 | public DebugTableWriter(File outputFile) { 86 | super(outputFile); 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /src/main/java/ru/icc/td/tabbyxl/preprocessing/headrecog/Block.java: -------------------------------------------------------------------------------- 1 | package ru.icc.td.tabbyxl.preprocessing.headrecog; 2 | 3 | import ru.icc.td.tabbyxl.model.CCell; 4 | import ru.icc.td.tabbyxl.model.style.CBorder; 5 | import ru.icc.td.tabbyxl.model.style.CStyle; 6 | import ru.icc.td.tabbyxl.model.style.HorzAlignment; 7 | 8 | final class Block { 9 | private int top, bottom, left, right; 10 | private String label = null; 11 | private CStyle cStyle; 12 | 13 | Block(CCell cCell) { 14 | top = cCell.getRt(); 15 | bottom = cCell.getRb(); 16 | left = cCell.getCl(); 17 | right = cCell.getCr(); 18 | cStyle = cCell.getStyle(); 19 | label = cCell.getText(); 20 | } 21 | 22 | Block(int top, int bottom, int left, int right) { 23 | this.top = top; 24 | this.bottom = bottom; 25 | this.left = left; 26 | this.right = right; 27 | cStyle = new CStyle(); 28 | } 29 | 30 | String getText() { 31 | return this.label; 32 | } 33 | 34 | void setText(String label) { 35 | this.label = label.trim(); 36 | } 37 | 38 | void setLeftBorderStyle(CBorder leftBorderStyle) { 39 | cStyle.setLeftBorder(leftBorderStyle); 40 | } 41 | 42 | void setRightBorderStyle(CBorder rightBorderStyle) { 43 | cStyle.setRightBorder(rightBorderStyle); 44 | } 45 | 46 | void setTopBorderStyle(CBorder topBorderStyle) { 47 | cStyle.setTopBorder(topBorderStyle); 48 | } 49 | 50 | void setBottomBorderStyle(CBorder bottomBorderStyle) { 51 | cStyle.setBottomBorder(bottomBorderStyle); 52 | } 53 | 54 | void setHAlignment(HorzAlignment hAligment) { 55 | cStyle.setHorzAlignment(hAligment); 56 | } 57 | 58 | int getTop() { 59 | return top; 60 | } 61 | 62 | int getBottom() { 63 | return bottom; 64 | } 65 | 66 | void setBottom(int bottom) { 67 | this.bottom = bottom; 68 | } 69 | 70 | int getLeft() { 71 | return left; 72 | } 73 | 74 | int getRight() { 75 | return right; 76 | } 77 | 78 | void setRight(int right) { 79 | this.right = right; 80 | } 81 | 82 | void increaseBlockSize(CCell cCell) { 83 | if (cCell == null) return; 84 | if (cCell.getRb() > bottom) bottom = cCell.getRb(); 85 | if (cCell.getCr() > right) right = cCell.getCr(); 86 | 87 | } 88 | 89 | CCell mergeWithCell(CCell cell) { 90 | String text; 91 | 92 | if (null == cell) 93 | throw new NullPointerException("The merging cell is null"); 94 | 95 | if (null == this) 96 | throw new NullPointerException("The merging block is null"); 97 | 98 | int l = Math.min(left, cell.getCl()); 99 | int t = Math.min(top, cell.getRt()); 100 | int r = Math.max(right, cell.getCr()); 101 | int b = Math.max(bottom, cell.getRb()); 102 | text = (cell.getText().trim() + " " + this.getText().trim()).trim(); 103 | cell.setCl(l); 104 | cell.setRt(t); 105 | cell.setCr(r); 106 | cell.setRb(b); 107 | cell.setText(text); 108 | this.setRightBorderStyle(cell.getStyle().getLeftBorder()); 109 | cell.setStyle(this.cStyle); 110 | return cell; 111 | } 112 | 113 | boolean compareWith(Block block) { 114 | return (this.left == block.left) && (this.right == block.right) && 115 | (this.top == block.top) && (this.bottom == block.bottom); 116 | } 117 | 118 | } 119 | -------------------------------------------------------------------------------- /src/main/java/ru/icc/td/tabbyxl/crl2j/compiler/FileManagerImpl.java: -------------------------------------------------------------------------------- 1 | package ru.icc.td.tabbyxl.crl2j.compiler; 2 | 3 | import javax.tools.*; 4 | import java.io.IOException; 5 | import java.net.URI; 6 | import java.util.ArrayList; 7 | import java.util.HashMap; 8 | import java.util.Map; 9 | import java.util.Set; 10 | 11 | import javax.tools.ForwardingJavaFileManager; 12 | 13 | final class FileManagerImpl extends ForwardingJavaFileManager { 14 | private ClassLoaderImpl classLoader; 15 | 16 | private Map fileObjects = new HashMap<>(); 17 | 18 | public FileManagerImpl(JavaFileManager fileManager, ClassLoaderImpl classLoader) 19 | { 20 | super(fileManager); 21 | this.classLoader = classLoader; 22 | } 23 | 24 | public ClassLoader getClassLoader() { return classLoader; } 25 | 26 | @Override 27 | public FileObject getFileForInput(Location location, String packageName, String name) throws IOException 28 | { 29 | FileObject object = fileObjects.get(uri(location, packageName, name)); 30 | if(object != null) return object; 31 | return super.getFileForInput(location, packageName, name); 32 | } 33 | 34 | public void putFileForInput(StandardLocation location, String packageName, String name, JavaFileObject fileObject) 35 | { 36 | fileObjects.put(uri(location, packageName, name), fileObject); 37 | } 38 | 39 | private URI uri(Location location, String packageName, String name) 40 | { 41 | return CharSequenceCompiler.toURI(location.getName() + '/' + packageName + '/' + name); 42 | } 43 | 44 | @Override 45 | public JavaFileObject getJavaFileForOutput(Location location, String fileName, JavaFileObject.Kind kind, FileObject outputFile) 46 | throws IOException 47 | { 48 | JavaFileObject file = new FileObjectImpl(fileName, kind); 49 | classLoader.add(fileName, file); 50 | return file; 51 | } 52 | 53 | @Override 54 | public ClassLoader getClassLoader(JavaFileManager.Location location) { return classLoader; } 55 | 56 | @Override 57 | public String inferBinaryName(Location location, JavaFileObject file) 58 | { 59 | String res; 60 | if(file instanceof FileObjectImpl) res = file.getName(); 61 | else res = super.inferBinaryName(location, file); 62 | return res; 63 | } 64 | 65 | @Override 66 | public Iterable list(Location location, String packageName, Set kinds, boolean recurse) 67 | throws IOException 68 | { 69 | Iterable res = super.list(location, packageName, kinds, recurse); 70 | ArrayList files = new ArrayList<>(); 71 | if(location == StandardLocation.CLASS_PATH && kinds.contains(JavaFileObject.Kind.CLASS)) 72 | { 73 | for(JavaFileObject file : fileObjects.values()) 74 | { 75 | if(file.getKind() == JavaFileObject.Kind.CLASS && file.getName().startsWith(packageName)) 76 | files.add(file); 77 | } 78 | files.addAll(classLoader.files()); 79 | } 80 | else if(location == StandardLocation.SOURCE_PATH && kinds.contains(JavaFileObject.Kind.SOURCE)) 81 | { 82 | for(JavaFileObject file : fileObjects.values()) 83 | { 84 | if(file.getKind() == JavaFileObject.Kind.SOURCE && file.getName().startsWith(packageName)) 85 | files.add(file); 86 | } 87 | } 88 | for(JavaFileObject file : res) files.add(file); 89 | return files; 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /src/main/java/ru/icc/td/tabbyxl/model/CategoryTemplateManager.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-18 Alexey O. Shigarov (shigarov@gmail.com) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package ru.icc.td.tabbyxl.model; 18 | 19 | import org.yaml.snakeyaml.TypeDescription; 20 | import org.yaml.snakeyaml.Yaml; 21 | import org.yaml.snakeyaml.constructor.Constructor; 22 | 23 | import java.io.*; 24 | import java.util.ArrayList; 25 | import java.util.List; 26 | 27 | public final class CategoryTemplateManager { 28 | private static Yaml yaml; 29 | 30 | static { 31 | Constructor constructor = new Constructor(CategoryTemplate.class); 32 | TypeDescription typeDesc = new TypeDescription(CategoryTemplate.class); 33 | typeDesc.putListPropertyType("constraints", String.class); 34 | typeDesc.putListPropertyType("labels", String.class); 35 | constructor.addTypeDescription(typeDesc); 36 | yaml = new Yaml(constructor); 37 | } 38 | 39 | private final List templates = new ArrayList(); 40 | 41 | public void load(File categoryDescFile) throws IOException { 42 | Reader reader = new FileReader(categoryDescFile); 43 | 44 | for (Object template : yaml.loadAll(reader)) 45 | templates.add((CategoryTemplate) template); 46 | 47 | 48 | reader.close(); 49 | } 50 | 51 | public void createCategories(CTable table) { 52 | final LocalCategoryBox localCategoryBox = table.getLocalCategoryBox(); 53 | for (CategoryTemplate desc : templates) { 54 | CCategory category = localCategoryBox.newCategory(desc.getName()); 55 | 56 | for (String constraint : desc.getConstraints()) 57 | category.addConstraint(constraint); 58 | 59 | for (String labelValue : desc.getLabels()) 60 | category.newLabel(labelValue); 61 | } 62 | } 63 | 64 | public boolean hasAtLeastOneCategoryTemplate() { 65 | return templates.size() > 0; 66 | } 67 | 68 | private static final CategoryTemplateManager INSTANCE = new CategoryTemplateManager(); 69 | 70 | private CategoryTemplateManager() { 71 | } 72 | 73 | public static CategoryTemplateManager getInstance() { 74 | return INSTANCE; 75 | } 76 | 77 | public void release() { 78 | templates.clear(); 79 | } 80 | 81 | public static class CategoryTemplate { 82 | private String name; 83 | 84 | public String getName() { 85 | return name; 86 | } 87 | 88 | public void setName(String name) { 89 | this.name = name; 90 | } 91 | 92 | private List constraints; 93 | 94 | public List getConstraints() { 95 | return constraints; 96 | } 97 | 98 | public void setConstraints(List constraints) { 99 | this.constraints = constraints; 100 | } 101 | 102 | private List labels; 103 | 104 | public List getLabels() { 105 | return labels; 106 | } 107 | 108 | public void setLabels(List labels) { 109 | this.labels = labels; 110 | } 111 | 112 | public CategoryTemplate() { 113 | } 114 | 115 | ; 116 | } 117 | 118 | } 119 | -------------------------------------------------------------------------------- /src/main/java/ru/icc/td/tabbyxl/writers/BasicTableWriter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-19 Alexey O. Shigarov (shigarov@gmail.com) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package ru.icc.td.tabbyxl.writers; 18 | 19 | import org.apache.poi.ss.usermodel.Cell; 20 | import org.apache.poi.ss.usermodel.Row; 21 | import org.apache.poi.ss.usermodel.Sheet; 22 | import org.apache.poi.ss.usermodel.Workbook; 23 | import org.apache.poi.xssf.usermodel.XSSFWorkbook; 24 | import ru.icc.td.tabbyxl.model.CLabel; 25 | import ru.icc.td.tabbyxl.model.CTable; 26 | import ru.icc.td.tabbyxl.model.CItem; 27 | import ru.icc.td.tabbyxl.model.CanonicalForm; 28 | import ru.icc.td.tabbyxl.model.CanonicalForm.Record; 29 | 30 | import java.io.File; 31 | import java.io.FileOutputStream; 32 | import java.io.IOException; 33 | import java.util.List; 34 | import java.util.function.BiConsumer; 35 | 36 | public class BasicTableWriter extends TableWriter { 37 | 38 | protected Workbook writeToWorkbook(CTable table) { 39 | Workbook workbook = new XSSFWorkbook(); 40 | 41 | // Write the canonical form of a table 42 | CanonicalForm cf = table.toCanonicalForm(); 43 | 44 | Sheet sheet = workbook.createSheet("CANONICAL FORM"); 45 | BiConsumer setCellVal = (item, excelCell) -> { 46 | String value = ""; 47 | 48 | if (item instanceof CLabel) { 49 | CLabel label = (CLabel) item; 50 | value = label.getCompoundValue(); 51 | } else { 52 | value = item.getValue(); 53 | } 54 | 55 | excelCell.setCellValue(value); 56 | }; 57 | 58 | writeCanonicalForm(sheet, cf, setCellVal); 59 | 60 | return workbook; 61 | } 62 | 63 | protected void writeCanonicalForm(Sheet sheet, CanonicalForm cf, BiConsumer consumer) { 64 | 65 | // Write header 66 | 67 | String[] header = cf.getHeaderStrings(); 68 | Row excelRow = sheet.createRow(0); 69 | 70 | for (int i = 0; i < header.length; i++) { 71 | excelRow.createCell(i).setCellValue(header[i]); 72 | excelRow.createCell(i).setCellValue(header[i]); 73 | } 74 | 75 | // Write rows 76 | 77 | List records = cf.getRecords(); 78 | 79 | int i = 1; 80 | 81 | for (Record record : records) { 82 | excelRow = sheet.createRow(i); 83 | 84 | CItem[] items = record.getItems(); 85 | 86 | for (int j = 0; j < items.length; j++) { 87 | CItem item = items[j]; 88 | if (null != item) { 89 | Cell excelCell = excelRow.createCell(j); 90 | consumer.accept(item, excelCell); 91 | } 92 | } 93 | i++; 94 | } 95 | 96 | for (i = 0; i < header.length; i++) { 97 | sheet.autoSizeColumn(i); 98 | } 99 | } 100 | 101 | @Override 102 | public void write(CTable table) throws IOException { 103 | Workbook workbook = writeToWorkbook(table); 104 | FileOutputStream fileOut = new FileOutputStream(outputFile); 105 | workbook.write(fileOut); 106 | fileOut.close(); 107 | } 108 | 109 | public BasicTableWriter(File outputFile) { 110 | super(outputFile); 111 | } 112 | } 113 | -------------------------------------------------------------------------------- /src/main/java/ru/icc/td/tabbyxl/model/CEntry.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-19 Alexey O. Shigarov (shigarov@gmail.com) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package ru.icc.td.tabbyxl.model; 18 | 19 | import ru.icc.td.tabbyxl.model.exception.EntryAssociatingException; 20 | 21 | import java.util.*; 22 | 23 | public final class CEntry extends CItem { 24 | private Map labels = new HashMap(); 25 | 26 | public Iterator getLabels() { 27 | return labels.values().iterator(); 28 | } 29 | 30 | private Set candidates = new HashSet(); 31 | 32 | public int numOfLabels() { 33 | return labels.size(); 34 | } 35 | 36 | void categoryActivated(CLabel label) { 37 | if (candidates.contains(label)) { 38 | addLabel(label); 39 | candidates.remove(label); 40 | } 41 | } 42 | 43 | public void addLabel(CLabel label) { 44 | if (null == label) 45 | throw new NullPointerException("The adding label cannot be null"); 46 | 47 | CCategory category = label.getCategory(); 48 | 49 | if (null == category) { 50 | if (candidates.add(label)) { 51 | label.addListener(this); 52 | } else { 53 | // TODO generating the warning: "The label candidate set already contains this label" 54 | } 55 | } else { 56 | if (labels.containsKey(category)) { 57 | CLabel addedLabel = labels.get(category); 58 | throw new EntryAssociatingException(this, label, addedLabel, category); 59 | } else { 60 | labels.put(category, label); 61 | } 62 | } 63 | } 64 | 65 | public void addLabel(String labelValue, CCategory category) { 66 | CLabel label = category.findLabel(labelValue); 67 | 68 | if (label == null) { 69 | label = category.newLabel(labelValue); 70 | } 71 | addLabel(label); 72 | } 73 | 74 | public void addLabel(String labelValue, String categoryName) { 75 | LocalCategoryBox localCategoryBox = getOwner().getLocalCategoryBox(); 76 | 77 | CCategory category = localCategoryBox.findCategory(categoryName); 78 | if (category == null) { 79 | category = localCategoryBox.newCategory(categoryName); 80 | } 81 | addLabel(labelValue, category); 82 | } 83 | 84 | public CEntry(CTable owner, CCell cell, String value) { 85 | super(owner, cell, value); 86 | } 87 | 88 | public String trace() { 89 | final String separator = "; "; 90 | final StringBuilder sb = new StringBuilder(); 91 | 92 | String s1 = String.format("entry=\"%s\"", getValue()); 93 | sb.append(s1).append(separator); 94 | 95 | CCell c = this.getCell(); 96 | String s2 = String.format("address=%s", c.address()); 97 | sb.append(s2).append(separator); 98 | 99 | sb.append("labels={"); 100 | Iterator labels = this.labels.values().iterator(); 101 | while (labels.hasNext()) { 102 | CLabel label = labels.next(); 103 | sb.append('"').append(label.getValue()).append('"'); 104 | if (labels.hasNext()) 105 | sb.append(", "); 106 | } 107 | sb.append("}"); 108 | 109 | return sb.toString(); 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /src/main/java/ru/icc/td/tabbyxl/preprocessing/headrecog/WorkbookManager.java: -------------------------------------------------------------------------------- 1 | package ru.icc.td.tabbyxl.preprocessing.headrecog; 2 | 3 | import org.apache.poi.ss.usermodel.*; 4 | import org.apache.poi.ss.util.CellRangeAddress; 5 | 6 | import static org.apache.poi.ss.usermodel.HorizontalAlignment.CENTER; 7 | import static org.apache.poi.ss.usermodel.HorizontalAlignment.FILL; 8 | 9 | final class WorkbookManager { 10 | private Workbook workbook; 11 | private String sheetName = "."; 12 | 13 | public WorkbookManager(Workbook workbook, String sheetName) { 14 | this.workbook = workbook; 15 | this.sheetName = sheetName; 16 | } 17 | 18 | //Merge area 19 | private String concatCellsValue(String curVal, Cell cell) { 20 | DataFormatter df = new DataFormatter(); 21 | String cellValue, val = ""; 22 | cellValue = df.formatCellValue(cell).trim(); 23 | val = (curVal.isEmpty()) ? cellValue : curVal.trim() + " " + cellValue; 24 | return val; 25 | } 26 | 27 | boolean mergeCells(Block blockToMerge, CellPointer cellShift) { 28 | try { 29 | //If one cell then nothing to merge 30 | if ((blockToMerge.getLeft() == blockToMerge.getRight()) && 31 | (blockToMerge.getTop() == blockToMerge.getBottom())) 32 | return true; 33 | 34 | Sheet sheet = workbook.getSheet(sheetName); 35 | 36 | int startCol = blockToMerge.getLeft() + cellShift.c - 1; 37 | int endCol = blockToMerge.getRight() + cellShift.c - 1; 38 | int startCell = blockToMerge.getTop() + cellShift.r - 1; 39 | int endCell = blockToMerge.getBottom() + cellShift.r - 1; 40 | CellRangeAddress reg; 41 | boolean isMerge; 42 | String val =""; 43 | Cell cell; 44 | Row row; 45 | CellStyle cellStyle; 46 | 47 | for (int r = startCell; r <= endCell; r++) { 48 | for (int c = startCol; c <= endCol; c++) { 49 | row = sheet.getRow(r); 50 | cell = row.getCell(c, Row.MissingCellPolicy.CREATE_NULL_AS_BLANK); 51 | val = concatCellsValue(val, cell); 52 | cell.setCellValue(""); 53 | cell.setBlank(); 54 | } 55 | } 56 | do { 57 | isMerge = false; 58 | 59 | for (int r = 0; r < sheet.getNumMergedRegions(); r++) { 60 | reg = sheet.getMergedRegion(r); 61 | 62 | if ((reg.getFirstRow() >= startCell) && (reg.getFirstColumn() >= startCol) && 63 | (reg.getLastRow() <= endCell) && (reg.getLastColumn() <= endCol)) { 64 | isMerge = true; //There is a merge region in the area 65 | sheet.removeMergedRegion(r); 66 | } 67 | } 68 | } while (isMerge != false); 69 | 70 | CellRangeAddress cellAddresses = new CellRangeAddress(startCell, endCell, startCol, endCol); 71 | int mergedRegion = sheet.addMergedRegion(cellAddresses); 72 | 73 | if (mergedRegion >= 0) { 74 | //Set value to new merged cell 75 | row = sheet.getRow(startCell); 76 | cell = row.getCell(startCol, Row.MissingCellPolicy.CREATE_NULL_AS_BLANK); 77 | cell.setCellValue(val); 78 | cellStyle = cell.getCellStyle(); 79 | cellStyle.setAlignment(CENTER); 80 | cellStyle.setWrapText(true); 81 | 82 | if (endCol-startCol > 5) 83 | cellStyle.setAlignment(FILL); 84 | 85 | if (cellStyle != null) { 86 | //TODO Check the necessity of Borders 87 | cell.setCellStyle(cellStyle); 88 | } 89 | } 90 | return true; 91 | 92 | } catch (Exception e) { 93 | System.out.println(String.format("Cell merge error: %s", e.getMessage())); 94 | return false; 95 | } 96 | } 97 | 98 | } 99 | -------------------------------------------------------------------------------- /src/main/java/ru/icc/td/tabbyxl/preprocessing/ner/NERecogPreprocessor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Alexey O. Shigarov (shigarov@gmail.com), Viacheslav V. Paramonov, and Vasiliy V. Khristyuk 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package ru.icc.td.tabbyxl.preprocessing.ner; 18 | 19 | import edu.stanford.nlp.pipeline.CoreDocument; 20 | import edu.stanford.nlp.pipeline.StanfordCoreNLP; 21 | 22 | import ru.icc.td.tabbyxl.model.CCell; 23 | import ru.icc.td.tabbyxl.model.CTable; 24 | import ru.icc.td.tabbyxl.model.NerTag; 25 | import ru.icc.td.tabbyxl.model.TypeTag; 26 | import ru.icc.td.tabbyxl.preprocessing.Preprocessor; 27 | 28 | import java.util.Properties; 29 | 30 | public final class NERecogPreprocessor implements Preprocessor { 31 | 32 | private static final StanfordCoreNLP pipeline; 33 | 34 | static { 35 | // Set up pipeline properties 36 | Properties props = new Properties(); 37 | props.setProperty("annotators", "tokenize,ssplit,pos,lemma,ner"); 38 | 39 | props.setProperty("ssplit.isOneSentence", "true"); 40 | props.setProperty("ner.useSUTime", "false"); 41 | 42 | // Disable fine grained ner 43 | props.setProperty("ner.applyFineGrained", "false"); 44 | 45 | // Set up pipeline 46 | pipeline = new StanfordCoreNLP(props); 47 | } 48 | 49 | private boolean withRecoveringMissingTypes; 50 | 51 | public NERecogPreprocessor(boolean withRecoveringMissingTypes) { 52 | this.withRecoveringMissingTypes = withRecoveringMissingTypes; 53 | } 54 | 55 | @Override 56 | public void process(CTable table) { 57 | // Extracting named entity from each cell 58 | 59 | // We use NER-preprocessor based on "Stanford CoreNLP" library. 60 | // Have patience in process-time, it can take a long time to load the required NER-models 61 | // (up to several minutes) before table processing starts for the first time. 62 | System.out.println("NER is in progress, it can take a long time (up to 1-2 minutes) for the first time"); 63 | 64 | System.out.println(); 65 | 66 | for (CCell cell : table.getCellList()) { 67 | String text = cell.getText(); 68 | NerTag nerTag = recognizeNamedEntity(text); 69 | cell.setNerTag(nerTag); 70 | 71 | if (withRecoveringMissingTypes) { 72 | TypeTag recognizedTypeTag = toTypeTag(cell.getNerTag()); 73 | cell.setTypeTag(recognizedTypeTag); 74 | } 75 | } 76 | 77 | System.out.println(); 78 | System.out.println("NER is completed successfully"); 79 | System.out.println(); 80 | } 81 | 82 | private NerTag recognizeNamedEntity(String text) { 83 | if (null == text || text.isEmpty()) return null; 84 | 85 | // If the sentence is too long then skip running the annotator 86 | if (text.length() > 100) return NerTag.NONE; 87 | 88 | CoreDocument doc = new CoreDocument(text); 89 | pipeline.annotate(doc); 90 | 91 | String tag = doc.tokens().get(0).ner(); 92 | 93 | try { 94 | return NerTag.valueOf(tag); 95 | } catch (IllegalArgumentException e) { 96 | return NerTag.NONE; 97 | } 98 | } 99 | 100 | private TypeTag toTypeTag(NerTag nerTag) { 101 | switch (nerTag) { 102 | case NUMBER : return TypeTag.NUMERIC; 103 | case DATE : return TypeTag.DATE; 104 | default: return TypeTag.STRING; 105 | } 106 | } 107 | 108 | } 109 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # TabbyXL 2 | 3 | A software platform for rule-based transformation spreadsheet data from arbitrary to relational tables. 4 | 5 | ## Version 6 | 1.1.1 7 | 8 | ## Building with Apache Maven 9 | 10 | First, you need to clone the project into your directory 11 | 12 | ```bash 13 | git clone https://github.com/tabbydoc/tabbyxl.git 14 | ``` 15 | 16 | In order to build the executable JAR with dependencies, change to the project directory, where is pom.xml, and run the following command 17 | 18 | ```bash 19 | mvn clean install 20 | ``` 21 | 22 | *We recommend you to use Apache Maven 3.6.0 or more and JDK 8 or more* 23 | 24 | You may test the newly compiled and packaged JAR file with the following command: 25 | 26 | ```bash 27 | java -jar target/TabbyXL-1.1.1-jar-with-dependencies.jar -input examples/data/smpl.xlsx -ruleset examples/rules/smpl.crl -output examples/results 28 | ``` 29 | 30 | or run the testing script 31 | 32 | ```bash 33 | ./test.sh 34 | ``` 35 | 36 | On Windows use the batch file 37 | 38 | ```bash 39 | test.bat 40 | ``` 41 | 42 | *Note that, with this option, you should run `java` included in JDK, not JRE. Otherwise, you get the following message:* 43 | 44 | ``` 45 | Exception in thread "main" java.lang.IllegalStateException 46 | at ru.icc.td.tabbyxl.crl2j.compiler.CharSequenceCompiler.(CharSequenceCompiler.java:44) 47 | at ru.icc.td.tabbyxl.crl2j.RuleCodeGen.compileAllRules(RuleCodeGen.java:38) 48 | at ru.icc.td.tabbyxl.TabbyXL.loadCRL2J(TabbyXL.java:638) 49 | at ru.icc.td.tabbyxl.TabbyXL.runRulesetWithCRL2J(TabbyXL.java:648) 50 | at ru.icc.td.tabbyxl.TabbyXL.main(TabbyXL.java:487) 51 | ``` 52 | 53 | *If you see this message, then, please, check that you run `java` included in JDK. You also can try to use `"%JAVA_HOME%/bin/java"` instead of `java` as follows.* 54 | 55 | ```bash 56 | "%JAVA_HOME%/bin/java" -jar target/TabbyXL-1.1.1-jar-with-dependencies.jar -input examples/data/smpl.xlsx -ruleset examples/rules/smpl.crl -output examples/results 57 | ``` 58 | 59 | If the program prints at the end something like this 60 | 61 | ``` 62 | Total number of 63 | tables: 4 64 | cells: 105 65 | not empty cells: 99 66 | labels: 50 67 | entries: 51 68 | label-label pairs: 0 69 | entry-label pairs: 219 70 | category-label pairs: 50 71 | categories: 17 72 | label groups: 17 73 | ``` 74 | 75 | then it works. 76 | 77 | ## Usage 78 | 79 | In order to run the executable JAR, you may use the following command with parameters 80 | 81 | ``` 82 | java -jar target/TabbyXL-1.1.1-jar-with-dependencies.jar 83 | 84 | Params: 85 | -input specify a path to an input excel workbook (*.xlsx) 86 | -sheets specify sheet indexes in the input excel workbook (e.g. "0-2,4,5,7-10") 87 | -ruleset specify a path to a ruleset file (e.g. *.crl (CRL), *.drl or *.dslr (Drools), or *.clp (JESS)) 88 | -categorySpec specify a path to a directory with category specifications in YAML files (*.cat) 89 | -output specify a path to a directory for outputting results 90 | -ignoreSuperscript specify true to ignore superscript text in cells (false used by default) 91 | -useCellText specify true to use cell values as text (false used by default) 92 | -useShortNames specify true to use short names (just sheet names) for output files (false used by default) 93 | -debuggingMode specify true to turn on debugging mode (false used by default) 94 | -ruleEngineConfig specify optionally a path to a configuration file (*.properties) of a rule engine you prefer to use (e.g. Drools, JESS) 95 | (CRL-to-Java translation is used by default instead of a rule engine) 96 | -help print this usage 97 | ``` 98 | 99 | Only two parameters are mandatory 100 | * `-input ` 101 | * `-ruleset ` 102 | 103 | *We recommend you to use JRE 8 or more* 104 | 105 | ## Authors 106 | 107 | * Alexey O. Shigarov 108 | * Vasiliy V. Khristyuk 109 | * Viacheslav V. Paramonov 110 | 111 | ## License 112 | Apache License, Version 2.0 113 | -------------------------------------------------------------------------------- /src/main/java/ru/icc/td/tabbyxl/model/style/CFont.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-18 Alexey O. Shigarov (shigarov@icc.ru) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package ru.icc.td.tabbyxl.model.style; 18 | 19 | public final class CFont 20 | { 21 | private String name; 22 | 23 | public String getName() 24 | { 25 | return this.name; 26 | } 27 | 28 | public void setName( String name ) 29 | { 30 | this.name = name; 31 | } 32 | 33 | private CColor color; 34 | 35 | public CColor getColor() 36 | { 37 | return this.color; 38 | } 39 | 40 | public void setColor( CColor color ) 41 | { 42 | this.color = color; 43 | } 44 | 45 | // a font height in unit's of 1/20th of a point. 46 | private short height; 47 | 48 | public short getHeight() 49 | { 50 | return this.height; 51 | } 52 | 53 | // set the font height in unit's of 1/20th of a point. 54 | public void setHeight( short height ) 55 | { 56 | this.height = height; 57 | } 58 | 59 | // a font height 60 | private short heightInPoints; 61 | 62 | public short getHeightInPoints() 63 | { 64 | return this.heightInPoints; 65 | } 66 | 67 | public void setHeightInPoints( short heightInPoints ) 68 | { 69 | this.heightInPoints = heightInPoints; 70 | } 71 | 72 | private boolean normal; 73 | 74 | public boolean isNormal() 75 | { 76 | return ! ( this.bold || this.italic || this.underline || this.doubleUnderline || this.strikeout ); 77 | } 78 | 79 | private boolean bold; 80 | 81 | /** 82 | * @return the bold 83 | */ 84 | public boolean isBold() 85 | { 86 | return this.bold; 87 | } 88 | 89 | /** 90 | * @param bold the bold to set 91 | */ 92 | public void setBold( boolean bold ) 93 | { 94 | this.bold = bold; 95 | } 96 | 97 | private boolean italic; 98 | 99 | public boolean isItalic() 100 | { 101 | return this.italic; 102 | } 103 | 104 | public void setItalic( boolean italic ) 105 | { 106 | this.italic = italic; 107 | } 108 | 109 | private boolean strikeout; 110 | 111 | public boolean isStrikeout() 112 | { 113 | return this.strikeout; 114 | } 115 | 116 | public void setStrikeout( boolean strikeout ) 117 | { 118 | this.strikeout = strikeout; 119 | } 120 | 121 | private boolean underline; 122 | 123 | public boolean getUnderline() 124 | { 125 | return this.underline; 126 | } 127 | 128 | public void setUnderline( boolean underline ) 129 | { 130 | this.underline = underline; 131 | } 132 | 133 | private boolean doubleUnderline; 134 | 135 | /** 136 | * @return the doubleUnderline 137 | */ 138 | public boolean isDoubleUnderline() 139 | { 140 | return this.doubleUnderline; 141 | } 142 | 143 | /** 144 | * @param doubleUnderline the doubleUnderline to set 145 | */ 146 | public void setDoubleUnderline( boolean doubleUnderline ) 147 | { 148 | this.doubleUnderline = doubleUnderline; 149 | } 150 | 151 | @Override 152 | public String toString() 153 | { 154 | String sName = "\"" + this.name + "\""; 155 | 156 | String sColor; 157 | if ( null != this.color ) 158 | sColor = String.format( "C=%s", this.color.toHexRGBString() ); 159 | else 160 | sColor = "C=none"; 161 | 162 | String sHeight = String.format( "H=%s", Short.toString( this.height) ); 163 | String sHeightInPoints = String.format( "Hp=%s", Short.toString( this.heightInPoints) ); 164 | 165 | String sBold = String.format( "B=%b", this.bold ); 166 | String sItalic = String.format( "I=%b", this.italic ); 167 | String sStrikeout = String.format( "S=%b", this.strikeout ); 168 | String sUnderline = String.format( "U=%b", this.underline ); 169 | String sDoubleUnderline = String.format( "UU=%b", this.doubleUnderline ); 170 | 171 | return String.format( "CFont [%s %s %s %s %s %s %s %s %s]", 172 | sName, sColor, sHeight, sHeightInPoints, sBold, sItalic, sStrikeout, 173 | sUnderline, sDoubleUnderline); 174 | } 175 | 176 | } 177 | 178 | -------------------------------------------------------------------------------- /src/main/java/ru/icc/td/tabbyxl/model/CCategory.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-18 Alexey O. Shigarov (shigarov@gmail.com) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package ru.icc.td.tabbyxl.model; 18 | 19 | import java.net.URI; 20 | import java.util.*; 21 | 22 | public final class CCategory extends COwned implements Cloneable { 23 | private String name; 24 | 25 | public String getName() { 26 | return name; 27 | } 28 | 29 | public void setName(String name) { 30 | if (null == name) 31 | throw new NullPointerException("The category name cannot be null"); 32 | 33 | name = name.trim(); 34 | 35 | if (name.isEmpty()) 36 | throw new IllegalArgumentException("The category name cannot be empty"); 37 | 38 | this.name = name; //this.name = name.toUpperCase(); 39 | } 40 | 41 | private URI reference; 42 | 43 | public URI getReference() { 44 | return reference; 45 | } 46 | 47 | public void setReference(URI reference) { 48 | this.reference = reference; 49 | } 50 | 51 | private Set labels = new LinkedHashSet(); 52 | 53 | public Iterator getLabels() { 54 | return this.labels.iterator(); 55 | } 56 | 57 | public CLabel findLabel(String labelValue) { 58 | for (CLabel l : labels) { 59 | if (l.getValue().equalsIgnoreCase(labelValue)) { 60 | return l; 61 | } 62 | } 63 | return null; 64 | } 65 | 66 | public boolean hasLabel(String labelValue) { 67 | for (CLabel l : labels) { 68 | if (labelValue.equalsIgnoreCase(l.getValue())) 69 | return true; 70 | } 71 | return false; 72 | } 73 | 74 | public boolean canHaveLabel(String labelValue) { 75 | // TODO Implementation 76 | return false; 77 | } 78 | 79 | public CLabel newLabel(String value) { 80 | CLabel label = new CLabel(getOwner(), value); 81 | label.setCategory(this); 82 | return label; 83 | } 84 | 85 | protected boolean addLabel(CLabel label) { 86 | if (satisfy(label)) { 87 | return this.labels.add(label); 88 | } else { 89 | return false; 90 | } 91 | } 92 | 93 | private boolean satisfy(CLabel label) { 94 | // TODO implementation: is a label satisfied to constraints 95 | return true; 96 | } 97 | 98 | private List constraints = new ArrayList(); 99 | 100 | public void addConstraint(String constraint) { 101 | constraints.add(constraint); 102 | } 103 | 104 | public CCategory(CTable owner, String name) { 105 | super(owner); 106 | setName(name); 107 | } 108 | 109 | CCategory(String name) { 110 | this(null, name); 111 | } 112 | 113 | // TODO reading BLANK_PADDING from settings 114 | private static final String BLANK_PADDING = "null"; 115 | 116 | public String trace() { 117 | final String separator = "; "; 118 | StringBuilder sb = new StringBuilder(); 119 | 120 | String s1 = String.format("category=\"%s\"", getName()); 121 | sb.append(s1).append(separator); 122 | 123 | sb.append("labels={"); 124 | int i = 0; 125 | Iterator labels = this.labels.iterator(); 126 | while (labels.hasNext()) { 127 | String s = labels.next().getValue(); 128 | if (s.isEmpty()) s = BLANK_PADDING; 129 | sb.append('"').append(s).append('"'); 130 | if (i < this.labels.size() - 1) { 131 | sb.append(',').append(' '); 132 | i++; 133 | } 134 | } 135 | sb.append("}"); 136 | return sb.toString(); 137 | } 138 | 139 | @Override 140 | protected Object clone() throws CloneNotSupportedException { 141 | // TODO implementation 142 | return super.clone(); 143 | } 144 | 145 | @Override 146 | public boolean equals(Object o) { 147 | if (this == o) return true; 148 | if (o == null || getClass() != o.getClass()) return false; 149 | 150 | CCategory category = (CCategory) o; 151 | 152 | if (!name.equals(category.name)) return false; 153 | 154 | return true; 155 | } 156 | 157 | @Override 158 | public int hashCode() { 159 | return name.hashCode(); 160 | } 161 | } 162 | -------------------------------------------------------------------------------- /src/main/java/ru/icc/td/tabbyxl/evaluation/EvalView.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-18 Alexey O. Shigarov (shigarov@gmail.com) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package ru.icc.td.tabbyxl.evaluation; 18 | 19 | import dnl.utils.text.table.TextTable; 20 | 21 | import java.io.ByteArrayOutputStream; 22 | import java.io.PrintStream; 23 | import java.nio.charset.StandardCharsets; 24 | 25 | final class EvalView { 26 | private int numOfGroundTruthEntries; 27 | private int numOfResultEntries; 28 | private int numOfCorrectEntries; 29 | 30 | private int numOfGroundTruthLabels; 31 | private int numOfResultLabels; 32 | private int numOfCorrectLabels; 33 | 34 | private int numOfGroundTruthELPairs; 35 | private int numOfResultELPairs; 36 | private int numOfCorrectELPairs; 37 | 38 | private int numOfGroundTruthLLPairs; 39 | private int numOfResultLLPairs; 40 | private int numOfCorrectLLPairs; 41 | 42 | public void increment(EvalView evalView) { 43 | numOfGroundTruthEntries += evalView.numOfGroundTruthEntries; 44 | numOfResultEntries += evalView.numOfResultEntries; 45 | numOfCorrectEntries += evalView.numOfCorrectEntries; 46 | 47 | numOfGroundTruthLabels += evalView.numOfGroundTruthLabels; 48 | numOfResultLabels += evalView.numOfResultLabels; 49 | numOfCorrectLabels += evalView.numOfCorrectLabels; 50 | 51 | numOfGroundTruthELPairs += evalView.numOfGroundTruthELPairs; 52 | numOfResultELPairs += evalView.numOfResultELPairs; 53 | numOfCorrectELPairs += evalView.numOfCorrectELPairs; 54 | 55 | numOfGroundTruthLLPairs += evalView.numOfGroundTruthLLPairs; 56 | numOfResultLLPairs += evalView.numOfResultLLPairs; 57 | numOfCorrectLLPairs += evalView.numOfCorrectLLPairs; 58 | } 59 | 60 | private String fractionAsString(int numerator, int denominator) { 61 | float f = (float) numerator / (float) denominator; 62 | return String.format("%s (%d/%d)", Float.toString(f), numerator, denominator); 63 | } 64 | 65 | public String trace() { 66 | final String[] columnNames = {"", "entries", "labels", "entry-label pairs", "label-label pairs"}; 67 | 68 | String r1 = fractionAsString(numOfCorrectEntries, numOfGroundTruthEntries); 69 | String r2 = fractionAsString(numOfCorrectLabels, numOfGroundTruthLabels); 70 | String r3 = fractionAsString(numOfCorrectELPairs, numOfGroundTruthELPairs); 71 | String r4 = fractionAsString(numOfCorrectLLPairs, numOfGroundTruthLLPairs); 72 | final String[] recallRecord = {"recall", r1, r2, r3, r4}; 73 | 74 | String p1 = fractionAsString(numOfCorrectEntries, numOfResultEntries); 75 | String p2 = fractionAsString(numOfCorrectLabels, numOfResultLabels); 76 | String p3 = fractionAsString(numOfCorrectELPairs, numOfResultELPairs); 77 | String p4 = fractionAsString(numOfCorrectLLPairs, numOfResultLLPairs); 78 | final String[] precisionRecord = {"precision", p1, p2, p3, p4}; 79 | 80 | final Object[][] data = {recallRecord, precisionRecord}; 81 | TextTable tt = new TextTable(columnNames, data); 82 | 83 | ByteArrayOutputStream baos = new ByteArrayOutputStream(); 84 | PrintStream ps = new PrintStream(baos); 85 | tt.printTable(ps, 0); 86 | return new String(baos.toByteArray(), StandardCharsets.UTF_8); 87 | } 88 | 89 | public EvalView() { 90 | } 91 | 92 | public EvalView(EvalBox evalBox) { 93 | numOfGroundTruthEntries = evalBox.entryEval.numOfAllCasesInGroundTruth(); 94 | numOfResultEntries = evalBox.entryEval.numOfAllCasesInResult(); 95 | numOfCorrectEntries = evalBox.entryEval.numOfCorrectCases(); 96 | 97 | numOfGroundTruthLabels = evalBox.labelEval.numOfAllCasesInGroundTruth(); 98 | numOfResultLabels = evalBox.labelEval.numOfAllCasesInResult(); 99 | numOfCorrectLabels = evalBox.labelEval.numOfCorrectCases(); 100 | 101 | numOfGroundTruthELPairs = evalBox.elPairEval.numOfAllCasesInGroundTruth(); 102 | numOfResultELPairs = evalBox.elPairEval.numOfAllCasesInResult(); 103 | numOfCorrectELPairs = evalBox.elPairEval.numOfCorrectCases(); 104 | 105 | numOfGroundTruthLLPairs = evalBox.llPairEval.numOfAllCasesInGroundTruth(); 106 | numOfResultLLPairs = evalBox.llPairEval.numOfAllCasesInResult(); 107 | numOfCorrectLLPairs = evalBox.llPairEval.numOfCorrectCases(); 108 | } 109 | } 110 | -------------------------------------------------------------------------------- /src/main/java/ru/icc/td/tabbyxl/model/CanonicalForm.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-19 Alexey O. Shigarov (shigarov@gmail.com) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package ru.icc.td.tabbyxl.model; 18 | 19 | import dnl.utils.text.table.TextTable; 20 | 21 | import java.util.*; 22 | 23 | public final class CanonicalForm { 24 | private List header = new ArrayList<>(); 25 | private List records = new ArrayList<>(); 26 | private List categories = new ArrayList<>(); 27 | 28 | private static final String defaultDataColumnName = "DATA"; 29 | 30 | CanonicalForm(CTable table) { 31 | 32 | categories = table.getLocalCategoryBox().getCategoryList(); 33 | 34 | // Fill header by using categories 35 | header.add(defaultDataColumnName); 36 | for (CCategory category : categories) 37 | header.add(category.getName()); 38 | 39 | // Fill rows by using entries 40 | Iterator entries = table.getEntries(); 41 | while (entries.hasNext()) { 42 | CEntry entry = entries.next(); 43 | Record record = new Record(entry); 44 | records.add(record); 45 | } 46 | } 47 | 48 | public List getHeader() { 49 | return header; 50 | } 51 | 52 | public String[] getHeaderStrings() { 53 | String[] strings = new String[header.size()]; 54 | strings = header.toArray(strings); 55 | 56 | return strings; 57 | } 58 | 59 | public List getRecords() { 60 | return records; 61 | } 62 | 63 | public void print() { 64 | String[] columnNames = getHeaderStrings(); 65 | 66 | final int numOfCols = header.size(); 67 | final int numOfRows = records.size(); 68 | 69 | Object[][] data = null; 70 | if (records.size() > 0) { 71 | data = new Object[numOfRows][numOfCols]; 72 | 73 | for (int i = 0; i < records.size(); i++) { 74 | data[i] = records.get(i).getStrings(); 75 | } 76 | } 77 | TextTable tt = new TextTable(columnNames, data); 78 | 79 | // this adds the numbering on the left 80 | // tt.setAddRowNumbering(true); 81 | // sort by the first column 82 | // tt.setSort(0); 83 | 84 | tt.printTable(); 85 | } 86 | 87 | public String trace() { 88 | StringBuilder sb = new StringBuilder(); 89 | final String EOL = "\r\n"; 90 | 91 | for (String s : header) { 92 | sb.append(s.toUpperCase()).append('\t'); 93 | } 94 | 95 | sb.append(EOL); 96 | 97 | for (Record record : records) { 98 | for (String s : record.getStrings()) { 99 | sb.append(s).append('\t'); 100 | } 101 | sb.append(EOL); 102 | } 103 | 104 | return sb.toString(); 105 | } 106 | 107 | public class Record { 108 | private static final String padding = ""; 109 | private CItem[] items; 110 | 111 | private Record(CEntry entry) { 112 | final int numOfCols = categories.size() + 1; 113 | items = new CItem[numOfCols]; 114 | 115 | items[0] = entry; 116 | 117 | Iterator labels = entry.getLabels(); 118 | while (labels.hasNext()) { 119 | CLabel label = labels.next(); 120 | for (int i = 0; i < categories.size(); i++) { 121 | CCategory category = categories.get(i); 122 | if (label.getCategory().equals(category)) { 123 | items[i + 1] = label; 124 | } 125 | } 126 | } 127 | } 128 | 129 | public CItem[] getItems() { 130 | return items; 131 | } 132 | 133 | public String[] getStrings() { 134 | 135 | String[] strings = new String[items.length]; 136 | Arrays.fill(strings, padding); 137 | 138 | CItem item; 139 | 140 | // Fill strings by using an entry 141 | item = items[0]; 142 | if (null != item) 143 | strings[0] = item.getValue(); 144 | 145 | // Fill strings by using labels 146 | for (int i = 1; i < items.length; i++) { 147 | item = items[i]; 148 | if (null != item) { 149 | CLabel label = (CLabel) item; 150 | strings[i] = label.getCompoundValue(); 151 | } 152 | } 153 | 154 | return strings; 155 | } 156 | } 157 | 158 | } 159 | -------------------------------------------------------------------------------- /src/main/java/ru/icc/td/tabbyxl/crl2j/compiler/CharSequenceCompiler.java: -------------------------------------------------------------------------------- 1 | package ru.icc.td.tabbyxl.crl2j.compiler; 2 | 3 | import javax.tools.*; 4 | import java.net.URI; 5 | import java.util.ArrayList; 6 | import java.util.HashMap; 7 | import java.util.List; 8 | import java.util.Map; 9 | 10 | public final class CharSequenceCompiler { 11 | private static final String JAVA_EXT = ".java"; 12 | 13 | private ClassLoaderImpl classLoader; 14 | 15 | private JavaCompiler compiler; 16 | 17 | private List options; 18 | 19 | private DiagnosticCollector diagnostics; 20 | 21 | private FileManagerImpl fileManagerImpl; 22 | 23 | public CharSequenceCompiler(ClassLoader classLoader, Iterable options) 24 | { 25 | compiler = ToolProvider.getSystemJavaCompiler(); 26 | if(compiler == null) 27 | { 28 | throw new IllegalStateException(); 29 | } 30 | 31 | this.classLoader = new ClassLoaderImpl(classLoader); 32 | diagnostics = new DiagnosticCollector<>(); 33 | 34 | JavaFileManager standartFileManager = compiler.getStandardFileManager(diagnostics, null, null); 35 | 36 | fileManagerImpl = new FileManagerImpl(standartFileManager, this.classLoader); 37 | 38 | this.options = new ArrayList<>(); 39 | if(options != null) 40 | { 41 | for(String option:options) 42 | { 43 | this.options.add(option); 44 | } 45 | } 46 | } 47 | 48 | public synchronized Class compile(String qualifiedClassName, 49 | CharSequence source, 50 | DiagnosticCollector diagnosticList, 51 | Class... types) throws CharSequenceCompilerException, ClassCastException 52 | { 53 | if(diagnosticList != null) diagnostics = diagnosticList; 54 | else diagnostics = new DiagnosticCollector<>(); 55 | 56 | Map classes = new HashMap<>(1); 57 | classes.put(qualifiedClassName, source); 58 | 59 | Map> compiled = compile(classes, diagnosticList); 60 | Class newClass = compiled.get(qualifiedClassName); 61 | return castable(newClass, types); 62 | } 63 | 64 | private synchronized Map> compile(Map classes, 65 | DiagnosticCollector diagnosticList) 66 | throws CharSequenceCompilerException 67 | { 68 | List sources = new ArrayList<>(); 69 | for(Map.Entry entry : classes.entrySet()) 70 | { 71 | String fullClassName = entry.getKey(); 72 | CharSequence javaSource = entry.getValue(); 73 | if(javaSource != null) 74 | { 75 | int dotPos = fullClassName.lastIndexOf('.'); 76 | String className = dotPos == -1 ? fullClassName : fullClassName.substring(dotPos+1); 77 | String packageName = dotPos == -1 ? "" : fullClassName.substring(0, dotPos); 78 | FileObjectImpl source = new FileObjectImpl(className, javaSource); 79 | sources.add(source); 80 | fileManagerImpl.putFileForInput(StandardLocation.SOURCE_PATH, packageName, className + JAVA_EXT, source); 81 | } 82 | } 83 | 84 | JavaCompiler.CompilationTask task = compiler.getTask(null, fileManagerImpl, diagnostics, options, null, sources); 85 | Boolean res = task.call(); 86 | 87 | if(res == null || !res.booleanValue()) 88 | { 89 | throw new CharSequenceCompilerException("Compilation failed.", classes.keySet(), diagnostics); 90 | } 91 | try 92 | { 93 | Map> compiled = new HashMap<>(); 94 | for(String className:classes.keySet()) 95 | { 96 | Class newClass = loadClass(className); 97 | compiled.put(className, newClass); 98 | } 99 | return compiled; 100 | } catch (ClassNotFoundException e) 101 | { 102 | throw new CharSequenceCompilerException(classes.keySet(), e, diagnostics); 103 | } catch (IllegalArgumentException e) 104 | { 105 | throw new CharSequenceCompilerException(classes.keySet(), e, diagnostics); 106 | } catch (SecurityException e) 107 | { 108 | throw new CharSequenceCompilerException(classes.keySet(), e, diagnostics); 109 | } 110 | } 111 | 112 | public static URI toURI(String name) 113 | { 114 | try 115 | { 116 | return URI.create(name); 117 | }catch (Exception e) 118 | { 119 | throw new RuntimeException(e); 120 | } 121 | } 122 | 123 | public Class loadClass(String className) throws ClassNotFoundException 124 | { 125 | return (Class) classLoader.loadClass(className); 126 | } 127 | 128 | private Class castable(Class newClass, Class... types) throws ClassCastException 129 | { 130 | for(Class type : types) 131 | if(!type.isAssignableFrom(newClass)) throw new ClassCastException(type.getName()); 132 | return newClass; 133 | } 134 | 135 | public ClassLoader getClassLoader() { return fileManagerImpl.getClassLoader(); } 136 | } 137 | -------------------------------------------------------------------------------- /src/main/java/ru/icc/td/tabbyxl/crl2j/CRL2JEngine.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018-19 Alexey O. Shigarov (shigarov@icc.ru) and Vasiliy V. Khristyuk 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package ru.icc.td.tabbyxl.crl2j; 18 | 19 | import org.antlr.runtime.ANTLRFileStream; 20 | import org.antlr.runtime.CommonTokenStream; 21 | import org.antlr.runtime.RecognitionException; 22 | import org.antlr.runtime.tree.Tree; 23 | import org.apache.commons.lang.StringUtils; 24 | 25 | import ru.icc.td.tabbyxl.crl2j.compiler.CharSequenceCompiler; 26 | import ru.icc.td.tabbyxl.crl2j.compiler.CharSequenceCompilerException; 27 | import ru.icc.td.tabbyxl.crl2j.parser.CRLLexer; 28 | import ru.icc.td.tabbyxl.crl2j.parser.CRLParser; 29 | import ru.icc.td.tabbyxl.crl2j.parser.ASTPrinter; 30 | import ru.icc.td.tabbyxl.model.CTable; 31 | 32 | import javax.tools.JavaFileObject; 33 | import java.io.File; 34 | import java.io.IOException; 35 | import java.util.*; 36 | 37 | public final class CRL2JEngine { 38 | 39 | private static final String filledLine = StringUtils.repeat("=", 100); 40 | private static final CharSequenceCompiler compiler; 41 | public static final String PACKAGE_NAME_BY_DEFAULT = "generated"; 42 | 43 | static { 44 | compiler = new CharSequenceCompiler(ClassLoader.getSystemClassLoader(), null); 45 | } 46 | 47 | private Map sourceCodeUnits; 48 | private SortedSet tableConsumers = new TreeSet<>(); 49 | 50 | private String packageName; 51 | 52 | public CRL2JEngine() { 53 | this(PACKAGE_NAME_BY_DEFAULT); 54 | } 55 | 56 | public CRL2JEngine(String packageName) { 57 | this.packageName = packageName; 58 | } 59 | 60 | public String getPackageName() { 61 | return packageName; 62 | } 63 | 64 | private Tree parse(File crlFile) throws IOException, RecognitionException { 65 | 66 | ANTLRFileStream fileStream = new ANTLRFileStream(crlFile.getPath()); 67 | 68 | // Tokenize CRL 69 | 70 | CRLLexer lexer = new CRLLexer(fileStream); 71 | CommonTokenStream tokenStream = new CommonTokenStream(lexer); 72 | 73 | // Parse CRL 74 | 75 | CRLParser parser = new CRLParser(tokenStream); 76 | 77 | return (Tree) parser.ruleset().getTree(); 78 | } 79 | 80 | private void generateJavaFiles(Tree ast) { 81 | 82 | // Analyze and interpret AST to create a Ruleset model 83 | 84 | Ruleset ruleset = new Ruleset(ast); 85 | 86 | // Generate Java source code from the Ruleset model 87 | 88 | CodeGenerator codeGenerator = new CodeGenerator(getPackageName(), ruleset); 89 | sourceCodeUnits = codeGenerator.generateSourceCode(); 90 | } 91 | 92 | private void createTableConsumers(Map sourceCodeUnits) throws CharSequenceCompilerException { 93 | try { 94 | 95 | for (String qualifiedClassName : sourceCodeUnits.keySet()) { 96 | Class[] prototype = new Class[]{TableConsumer.class}; 97 | JavaFileObject sourceCodeUnit = sourceCodeUnits.get(qualifiedClassName); 98 | CharSequence sourceCode = sourceCodeUnit.getCharContent(true); 99 | Class clazz = compiler.compile(qualifiedClassName, sourceCode, null, prototype); 100 | 101 | TableConsumer instance = clazz.newInstance(); 102 | tableConsumers.add(instance); 103 | } 104 | 105 | } catch (IOException | IllegalAccessException | InstantiationException e) { 106 | e.printStackTrace(); 107 | System.exit(-1); 108 | } 109 | 110 | } 111 | 112 | public void loadRules(File crlFile) throws IOException, RecognitionException { 113 | 114 | // Parse the CRL ruleset to AST 115 | 116 | Tree ast = parse(crlFile); 117 | 118 | if (false) { 119 | System.out.println("This AST was produced from the ruleset"); 120 | System.out.println(ASTPrinter.trace(ast)); 121 | System.out.println(filledLine); 122 | System.out.println(); 123 | } 124 | 125 | // Interpret AST to create Java files 126 | 127 | generateJavaFiles(ast); 128 | 129 | if (true) { 130 | System.out.println("This Java source code was generated from the ruleset"); 131 | System.out.println(filledLine); 132 | System.out.println(); 133 | 134 | for (JavaFileObject sourceCodeUnit : sourceCodeUnits.values()) { 135 | System.out.println(sourceCodeUnit.getCharContent(true)); 136 | System.out.println(filledLine); 137 | System.out.println(); 138 | } 139 | } 140 | 141 | // Compile Java files to Java classes and create their instances 142 | 143 | try { 144 | createTableConsumers(sourceCodeUnits); 145 | } catch (CharSequenceCompilerException e) { 146 | System.err.println("The generated java files could not be compiled"); 147 | e.printStackTrace(); 148 | } 149 | } 150 | 151 | public Map getSourceCodeUnits() { 152 | return sourceCodeUnits; 153 | } 154 | 155 | public void processTable(CTable table) { 156 | tableConsumers.forEach(tc -> tc.accept(table)); 157 | } 158 | } 159 | -------------------------------------------------------------------------------- /src/main/java/ru/icc/td/tabbyxl/evaluation/Evaluator.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-18 Alexey O. Shigarov (shigarov@gmail.com) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package ru.icc.td.tabbyxl.evaluation; 18 | 19 | import org.apache.poi.ss.usermodel.Workbook; 20 | import org.apache.poi.xssf.usermodel.XSSFWorkbook; 21 | 22 | import java.io.File; 23 | import java.io.FileInputStream; 24 | import java.io.IOException; 25 | import java.nio.file.Paths; 26 | import java.util.ArrayList; 27 | import java.util.List; 28 | 29 | public final class Evaluator { 30 | public static void main(String[] args) throws IOException { 31 | File resultDirectory = new File(args[0]); 32 | File groundTruthDirectory = new File(args[1]); 33 | 34 | File[] listOfExcelFiles = resultDirectory.listFiles(e -> e.getName().endsWith(".xlsx")); 35 | Evaluator e = new Evaluator(); 36 | 37 | for (File resultExcelFile : listOfExcelFiles) { 38 | if (resultExcelFile.isFile()) { 39 | String name = resultExcelFile.getName(); 40 | System.out.println("FILE: " + name); 41 | String gtDirectoryPath = groundTruthDirectory.getAbsolutePath(); 42 | String resultExcelFileName = resultExcelFile.getName(); 43 | File gtExcelFile = Paths.get(gtDirectoryPath, resultExcelFileName).toFile(); 44 | e.load(resultExcelFile, gtExcelFile); 45 | e.evaluate(name); 46 | } 47 | } 48 | 49 | System.out.println("SUMMARY OF RESULTS:"); 50 | System.out.println(RESULT.trace()); 51 | 52 | System.out.println("SUMMARY OF ERRORS:"); 53 | System.out.println(); 54 | System.out.printf("Tables processed with errors, total = %d%n", e.totalOfTablesWithErrors); 55 | System.out.printf("False negatives, total = %d in %d tables%n", e.sumOfFalseNegatives, e.totalOfTablesWithFalseNegatives); 56 | System.out.printf("False positives, total = %d in %d tables%n", e.sumOfFalsePositives, e.totalOfTablesWithFalsePositives); 57 | 58 | if (e.errorSummary.size() > 0) { 59 | System.out.println(); 60 | System.out.println("List of tables processed with errors:"); 61 | int count = 0; 62 | for (String s : e.errorSummary) 63 | System.out.printf("\t%d\t%s%n", ++count, s); 64 | } 65 | } 66 | 67 | private Workbook resWorkbook; 68 | private Workbook gtWorkbook; 69 | 70 | private Evaluator() { 71 | } 72 | 73 | private void load(File resultWorkbookFile, File groundTruthWorkbookFile) throws IOException { 74 | loadResultWorkbook(resultWorkbookFile); 75 | loadGroundTruthWorkbook(groundTruthWorkbookFile); 76 | } 77 | 78 | private void loadResultWorkbook(File resultWorkbookFile) throws IOException { 79 | resWorkbook = loadWorkbook(resultWorkbookFile); 80 | } 81 | 82 | private void loadGroundTruthWorkbook(File groundTruthWorkbookFile) throws IOException { 83 | gtWorkbook = loadWorkbook(groundTruthWorkbookFile); 84 | } 85 | 86 | private Workbook loadWorkbook(File excelFile) throws IOException { 87 | Workbook workbook = null; 88 | FileInputStream fin = new FileInputStream(excelFile); 89 | workbook = new XSSFWorkbook(fin); 90 | 91 | return workbook; 92 | } 93 | 94 | private static final EvalView RESULT = new EvalView(); 95 | 96 | private static final String ERROR_PRINTING_TEMPLATE = "Errors (false negatives, total = %d; false positives, total = %d):%n"; 97 | private static final String ERROR_SUMMARY_TEMPLATE = "%s\t(false negatives, total = %d;\tfalse positives, total = %d)"; 98 | private final List errorSummary = new ArrayList<>(); 99 | private int sumOfFalseNegatives = 0; 100 | private int sumOfFalsePositives = 0; 101 | private int totalOfTablesWithErrors = 0; 102 | private int totalOfTablesWithFalseNegatives = 0; 103 | private int totalOfTablesWithFalsePositives = 0; 104 | 105 | private void evaluate(String name) throws IllegalStateException { 106 | if (null == resWorkbook) 107 | throw new IllegalStateException("The result workbook has not been loaded"); 108 | 109 | if (null == gtWorkbook) 110 | throw new IllegalStateException("The ground truth workbook has not been loaded"); 111 | 112 | EvalBox box = EvalBox.evaluate(gtWorkbook, resWorkbook); 113 | EvalView view = box.createEvalView(); 114 | System.out.println("Results:"); 115 | System.out.println(view.trace()); 116 | if (box.hasErrors()) { 117 | int totalFalseNegatives = box.totalFalseNegatives(); 118 | int totalFalsePositives = box.totalFalsePositives(); 119 | 120 | sumOfFalseNegatives += totalFalseNegatives; 121 | sumOfFalsePositives += totalFalsePositives; 122 | 123 | if (totalFalseNegatives > 0) totalOfTablesWithFalseNegatives++; 124 | if (totalFalsePositives > 0) totalOfTablesWithFalsePositives++; 125 | if (totalFalseNegatives + totalFalsePositives > 0) totalOfTablesWithErrors++; 126 | 127 | errorSummary.add(String.format(ERROR_SUMMARY_TEMPLATE, name, totalFalseNegatives, totalFalsePositives)); 128 | System.out.printf(ERROR_PRINTING_TEMPLATE, totalFalseNegatives, totalFalsePositives); 129 | System.out.println(box.traceErrors()); 130 | } 131 | System.out.println(); 132 | RESULT.increment(view); 133 | } 134 | } 135 | -------------------------------------------------------------------------------- /src/main/resources/CRL.g: -------------------------------------------------------------------------------- 1 | grammar CRL; 2 | 3 | options { 4 | 5 | language=Java; 6 | TokenLabelType=CommonToken; 7 | output=AST; 8 | ASTLabelType=CommonTree; 9 | backtrack = true; 10 | } 11 | 12 | tokens { 13 | IMPORTS; 14 | IMPORT; 15 | RULES; 16 | RULE; 17 | CONDITIONS; 18 | CONDITION; 19 | TYPE; 20 | QUERY; 21 | IDENTIFIER; 22 | CONSTRAINTS; 23 | CONSTRAINT; 24 | ASSIGNMENT; 25 | EXPRESSION; 26 | ACTIONS; 27 | ACTION; 28 | OPERAND; 29 | } 30 | 31 | @header { 32 | package ru.icc.td.tabbyxl.crl2j.parsing; 33 | } 34 | 35 | @lexer::header { 36 | package ru.icc.td.tabbyxl.crl2j.parsing; 37 | } 38 | 39 | // parser 40 | 41 | ruleset 42 | : importing* 43 | rule* 44 | -> ^(IMPORTS importing*) ^(RULES rule*) 45 | ; 46 | 47 | importing 48 | scope { 49 | String value; 50 | } 51 | @init { $importing::value = "import static "; } 52 | : 'import static' id = ID { $importing::value+=$id.text; } ('.' id = ID { $importing::value+="."+$id.text; } )* ('.*' { $importing::value+=".*"; })? ';'? EOL 53 | -> IMPORT [$importing::value] 54 | ; 55 | 56 | rule 57 | : 'rule #' num=INT EOL 58 | 'when' EOL 59 | condition* 60 | 'then' EOL 61 | action* 62 | 'end' EOL? 63 | -> ^(RULE[$num] ^(CONDITIONS condition*) ^(ACTIONS action*)) 64 | ; 65 | 66 | condition 67 | scope { 68 | String quantifier; 69 | String id; 70 | } 71 | @init { 72 | $condition::quantifier = "EXIST"; 73 | $condition::id = null; 74 | } 75 | : ('no' { $condition::quantifier = "NOT_EXIST"; })? 76 | query 77 | ( idntfr = ID { $condition::id = $idntfr.text; } )? { $condition::id = ( ($condition::id == null)? "null":$condition::id ); } 78 | ( 79 | ':' 80 | ( (constraint (',' constraint)* (',' assignment)? ) | assignment ) 81 | )? EOL 82 | -> ^( CONDITION TYPE[$condition::quantifier] query IDENTIFIER[$condition::id] ^(CONSTRAINTS ^(CONSTRAINT constraint)*) ^(ASSIGNMENT assignment?) ) 83 | ; 84 | 85 | query 86 | : ('cell'|'cells') -> QUERY["CCell"] 87 | |('label'|'labels') -> QUERY["CLabel"] 88 | |('entry'|'entries') -> QUERY["CEntry"] 89 | |('category'|'categories') -> QUERY["CCategory"] 90 | ; 91 | 92 | constraint 93 | : (~(','|EOL|':'))+ 94 | ; 95 | 96 | assignment 97 | : id = ID ':' expression 98 | -> IDENTIFIER[$id] ^(EXPRESSION expression) 99 | ; 100 | 101 | expression 102 | : ( ESC_SEQ| ~(EOL))+ 103 | ; 104 | 105 | action 106 | : set_tag 107 | |set_text 108 | |set_indent 109 | |split 110 | |merge 111 | |new_entry 112 | |set_value 113 | |set_category 114 | |set_parent 115 | |group 116 | |add_label 117 | |new_label 118 | |print 119 | ; 120 | 121 | operand 122 | : ( STRING | ESC_SEQ | ~('to'|'with'|'as'|'of'|EOL))+ 123 | ; 124 | 125 | set_tag 126 | : 'set tag' op1 = operand 'to' op2 = operand EOL 127 | -> ^(ACTION["setTag"] ^(OPERAND $op2) ^(OPERAND $op1)) 128 | ; 129 | 130 | set_text 131 | : 'set text' op1 = operand 'to' op2 = operand EOL 132 | -> ^(ACTION["setText"] ^(OPERAND $op2) ^(OPERAND $op1)) 133 | ; 134 | 135 | set_indent 136 | : 'set indent' op1 = operand 'to' op2 = operand EOL 137 | -> ^(ACTION["setIndent"] ^(OPERAND $op2) ^(OPERAND $op1)) 138 | ; 139 | 140 | split 141 | : 'split' operand EOL 142 | -> ^( ACTION["split"] ^(OPERAND operand)) 143 | ; 144 | 145 | merge 146 | : 'merge' op1 = operand 'with' op2 = operand EOL 147 | -> ^(ACTION["merge"] ^(OPERAND $op2) ^(OPERAND $op1)) 148 | ; 149 | 150 | new_entry 151 | : 'new entry' op1 = operand ('as' op2 = operand)? EOL 152 | -> ^(ACTION["newEntry"] ^(OPERAND $op1) ^(OPERAND $op2)?) 153 | ; 154 | 155 | set_value 156 | : 'set value' op1 = operand 'to' op2 = operand EOL 157 | -> ^(ACTION["setValue"] ^(OPERAND $op2) ^(OPERAND $op1)) 158 | ; 159 | 160 | set_category 161 | : 'set category' op1 = operand 'to' op2 = operand EOL 162 | -> ^(ACTION["setCategory"] ^(OPERAND $op2) ^(OPERAND $op1)) 163 | ; 164 | 165 | set_parent 166 | : 'set parent' op1 = operand 'to' op2 = operand EOL 167 | -> ^(ACTION["setParent"] ^(OPERAND $op2) ^(OPERAND $op1)) 168 | ; 169 | 170 | group 171 | : 'group' op1 = operand 'with' op2 = operand EOL 172 | -> ^(ACTION["group"] ^(OPERAND $op1) ^(OPERAND $op2)) 173 | ; 174 | 175 | add_label 176 | : 'add label' op1 = operand ('of' op2 = operand)? 'to' op3 = operand EOL 177 | -> ^(ACTION["addLabel"] ^(OPERAND $op3) ^(OPERAND $op1) ^(OPERAND $op2)?) 178 | ; 179 | 180 | new_label 181 | : 'new label' op1 = operand ('as' op2 = operand)? EOL 182 | -> ^(ACTION["newLabel"] ^(OPERAND $op1) ^(OPERAND $op2)?) 183 | ; 184 | 185 | print 186 | : name = ('print'|'printf') operand EOL 187 | -> ^(ACTION[$name] ^(OPERAND operand)) 188 | ; 189 | 190 | //lexer 191 | 192 | ID : ('a'..'z'|'A'..'Z'|'_'|'$') ('a'..'z'|'A'..'Z'|'0'..'9'|'_'|'$')* 193 | ; 194 | 195 | INT : '0'..'9'+ 196 | ; 197 | 198 | FLOAT 199 | : ('0'..'9')+ '.' ('0'..'9')* EXPONENT? 200 | | '.' ('0'..'9')+ EXPONENT? 201 | | ('0'..'9')+ EXPONENT 202 | ; 203 | 204 | COMMENT 205 | : '//' ~('\n'|'\r')* '\r'? '\n' {$channel=HIDDEN;} 206 | | '/*' ( options {greedy=false;} : . )* '*/' {$channel=HIDDEN;} 207 | ; 208 | 209 | WS : ( ' ' 210 | | '\t' 211 | ) {$channel=HIDDEN;} 212 | ; 213 | 214 | STRING 215 | : '"' ( ESC_SEQ | ~('\\'|'"') )* '"' 216 | ; 217 | 218 | CHAR: '\'' ( ESC_SEQ | ~('\''|'\\') ) '\'' 219 | ; 220 | 221 | OPERATOR 222 | : ('='|'>'|'<'|'&'|'|'|'+'|'-'|'*'|'/'|'%'|'!')+ 223 | ; 224 | 225 | BRACKET 226 | : '('|')'|'['|']'|'{'|'}' 227 | ; 228 | 229 | EOL 230 | : (('\r')? '\n')+ 231 | ; 232 | 233 | fragment 234 | EXPONENT : ('e'|'E') ('+'|'-')? ('0'..'9')+ ; 235 | 236 | fragment 237 | HEX_DIGIT : ('0'..'9'|'a'..'f'|'A'..'F') ; 238 | 239 | fragment 240 | ESC_SEQ 241 | : '\\' ('b'|'f'|'t'|'\"'|'\''|'\\') 242 | | UNICODE_ESC 243 | | OCTAL_ESC 244 | ; 245 | 246 | fragment 247 | OCTAL_ESC 248 | : '\\' ('0'..'3') ('0'..'7') ('0'..'7') 249 | | '\\' ('0'..'7') ('0'..'7') 250 | | '\\' ('0'..'7') 251 | ; 252 | 253 | fragment 254 | UNICODE_ESC 255 | : '\\' 'u' HEX_DIGIT HEX_DIGIT HEX_DIGIT HEX_DIGIT 256 | ; 257 | 258 | -------------------------------------------------------------------------------- /src/main/java/ru/icc/td/tabbyxl/util/StatisticsManager.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-19 Alexey O. Shigarov (shigarov@gmail.com) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package ru.icc.td.tabbyxl.util; 18 | 19 | import ru.icc.td.tabbyxl.model.CTable; 20 | 21 | import java.util.HashMap; 22 | import java.util.Map; 23 | 24 | public final class StatisticsManager { 25 | private static final StatisticsManager INSTANCE = new StatisticsManager(); 26 | 27 | private static final String eol = System.lineSeparator(); 28 | private static final String tab = "\t"; 29 | 30 | private int numOfTables; 31 | private int numOfCells; 32 | private int numOfNotEmptyCells; 33 | private int numOfEntries; 34 | private int numOfLabels; 35 | 36 | private int numOfLL; 37 | private int numOfEL; 38 | private int numOfCL; 39 | 40 | private int numOfCategories; 41 | private int numOfLabelGroups; 42 | 43 | private final Map map = new HashMap(); 44 | 45 | public Statistics collect(CTable table) { 46 | Statistics statistics = new Statistics(); 47 | statistics.collect(table); 48 | map.put(table, statistics); 49 | numOfTables++; 50 | 51 | // Incrementing statistics using the table 52 | numOfCells += statistics.numOfCells; 53 | numOfNotEmptyCells += statistics.numOfNotEmptyCells; 54 | numOfEntries += statistics.numOfEntries; 55 | numOfLabels += statistics.numOfLabels; 56 | 57 | numOfLL += statistics.numOfLL; 58 | numOfEL += statistics.numOfEL; 59 | numOfCL += statistics.numOfCL; 60 | 61 | numOfCategories += statistics.numOfCategories; 62 | numOfLabelGroups += statistics.numOfLabelGroups; 63 | 64 | return statistics; 65 | } 66 | 67 | public String trace() { 68 | final StringBuilder sb = new StringBuilder(); 69 | 70 | sb.append("Statistics:").append(eol).append(eol); 71 | 72 | sb.append(tab).append("Total number of").append(eol); 73 | sb.append(tab).append("tables: ").append(numOfTables).append(eol); 74 | sb.append(tab).append("cells: ").append(numOfCells).append(eol); 75 | sb.append(tab).append("not empty cells: ").append(numOfNotEmptyCells).append(eol); 76 | sb.append(tab).append("labels: ").append(numOfLabels).append(eol); 77 | sb.append(tab).append("entries: ").append(numOfEntries).append(eol); 78 | 79 | sb.append(tab).append("label-label pairs: ").append(numOfLL).append(eol); 80 | sb.append(tab).append("entry-label pairs: ").append(numOfEL).append(eol); 81 | sb.append(tab).append("category-label pairs: ").append(numOfCL).append(eol); 82 | 83 | sb.append(tab).append("categories: ").append(numOfCategories).append(eol); 84 | sb.append(tab).append("label groups: ").append(numOfLabelGroups).append(eol); 85 | 86 | return sb.toString(); 87 | } 88 | 89 | public String trace(CTable table) { 90 | Statistics statistics = map.get(table); 91 | if (null != statistics) return statistics.trace(); 92 | else return null; 93 | } 94 | 95 | private StatisticsManager() { 96 | } 97 | 98 | public static StatisticsManager getInstance() { 99 | return INSTANCE; 100 | } 101 | 102 | public class Statistics { 103 | private CTable table; 104 | private StatisticsManager manager; 105 | 106 | private int numOfCells; 107 | private int numOfNotEmptyCells; 108 | private int numOfEntries; 109 | private int numOfLabels; 110 | 111 | private int numOfLL; 112 | private int numOfEL; 113 | private int numOfCL; 114 | 115 | private int numOfCategories; 116 | private int numOfLabelGroups; 117 | 118 | public void collect(CTable table) { 119 | this.table = table; 120 | // Collecting statistics from the table 121 | numOfCells = table.numOfCells(); 122 | numOfNotEmptyCells = table.numOfNotEmptyCells(); 123 | numOfEntries = table.numOfEntries(); 124 | numOfLabels = table.numOfLabels(); 125 | 126 | numOfLL = table.numOfLL(); 127 | numOfEL = table.numOfEL(); 128 | numOfCL = table.numOfCL(); 129 | 130 | numOfCategories = table.numOfCategories(); 131 | numOfLabelGroups = table.numOfLabelGroups(); 132 | } 133 | 134 | public String trace() { 135 | final StringBuilder sb = new StringBuilder(); 136 | 137 | sb.append("Number of").append(eol); 138 | sb.append(tab).append("cells: ").append(numOfCells).append(eol); 139 | sb.append(tab).append("not empty cells: ").append(numOfNotEmptyCells).append(eol); 140 | sb.append(tab).append("labels: ").append(numOfLabels).append(eol); 141 | sb.append(tab).append("entries: ").append(numOfEntries).append(eol); 142 | 143 | sb.append(tab).append("label-label pairs: ").append(numOfLL).append(eol); 144 | sb.append(tab).append("entry-label pairs: ").append(numOfEL).append(eol); 145 | sb.append(tab).append("category-label pairs: ").append(numOfCL).append(eol); 146 | 147 | sb.append(tab).append("categories: ").append(numOfCategories).append(eol); 148 | sb.append(tab).append("label groups: ").append(numOfLabelGroups).append(eol); 149 | 150 | return sb.toString(); 151 | } 152 | 153 | private Statistics() { 154 | } 155 | 156 | ; 157 | } 158 | } 159 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 4.0.0 7 | 8 | ru.icc.td.tabbyxl 9 | TabbyXL 10 | 1.1.1 11 | jar 12 | 13 | 14 | 15 | 16 | 17 | 18 | org.apache.maven.plugins 19 | maven-compiler-plugin 20 | 3.7.0 21 | 22 | 1.8 23 | 1.8 24 | 25 | 26 | 27 | 28 | org.apache.maven.plugins 29 | maven-assembly-plugin 30 | 3.2.0 31 | 32 | 33 | package 34 | 35 | single 36 | 37 | 38 | 39 | 40 | true 41 | ru.icc.td.tabbyxl.TabbyXL 42 | 43 | 44 | 45 | jar-with-dependencies 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | src/main/resources 58 | true 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | UTF-8 68 | 7.7.0.Final 69 | 7.2.0.Final 70 | 5.0.0 71 | 72 | 73 | 74 | 75 | 76 | 77 | org.apache.poi 78 | poi 79 | ${poi.version} 80 | 81 | 82 | 83 | org.apache.poi 84 | poi-ooxml 85 | ${poi.version} 86 | 87 | 88 | 89 | org.kie 90 | kie-api 91 | ${drools.version} 92 | 93 | 94 | 95 | org.drools 96 | drools-core 97 | ${drools.version} 98 | 99 | 100 | 101 | org.drools 102 | drools-compiler 103 | ${drools.version} 104 | 105 | 106 | 107 | org.drools 108 | drools-jsr94 109 | ${drools-jsr94.version} 110 | 111 | 112 | 113 | org.slf4j 114 | slf4j-api 115 | 1.7.5 116 | 117 | 118 | 119 | org.slf4j 120 | slf4j-log4j12 121 | 1.7.5 122 | 123 | 124 | 125 | commons-cli 126 | commons-cli 127 | 1.2 128 | 129 | 130 | 131 | commons-io 132 | commons-io 133 | 2.4 134 | 135 | 136 | 137 | com.massisframework 138 | j-text-utils 139 | 0.3.4 140 | 141 | 142 | 143 | org.yaml 144 | snakeyaml 145 | 1.16 146 | 147 | 148 | 149 | org.antlr 150 | antlr-runtime 151 | 3.5.2 152 | 153 | 154 | 155 | com.google.protobuf 156 | protobuf-java 157 | 3.0.2 158 | 159 | 160 | 161 | edu.stanford.nlp 162 | stanford-corenlp 163 | 3.9.2 164 | 165 | 166 | 167 | edu.stanford.nlp 168 | stanford-corenlp 169 | 3.9.2 170 | models 171 | 172 | 173 | 174 | com.squareup 175 | javapoet 176 | 1.11.1 177 | 178 | 179 | 180 | 181 | -------------------------------------------------------------------------------- /src/main/java/ru/icc/td/tabbyxl/model/LabelGroupBox.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-18 Alexey O. Shigarov (shigarov@gmail.com) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package ru.icc.td.tabbyxl.model; 18 | 19 | import ru.icc.td.tabbyxl.model.exception.CategoryGroupException; 20 | 21 | import java.util.*; 22 | 23 | public final class LabelGroupBox extends COwned { 24 | private static final String GROUP_FIELD_NAME = "GROUP"; 25 | 26 | private Set labelPairs = new HashSet(); 27 | 28 | private List labelGroups = new ArrayList(); 29 | 30 | int numOfLabelGroups() { 31 | return labelGroups.size(); 32 | } 33 | 34 | private CCategory category; 35 | 36 | void update() { 37 | initLabelGroups(); 38 | updateCategory(); 39 | } 40 | 41 | private void updateCategory() throws CategoryGroupException { 42 | int id = 0; 43 | for (LabelGroup group : labelGroups) { 44 | CCategory groupCategory = null; 45 | for (CLabel label : group.labels) { 46 | CCategory labelCategory = label.getCategory(); 47 | if (null == groupCategory && null != labelCategory) { 48 | groupCategory = labelCategory; 49 | } 50 | if (null != groupCategory && !labelCategory.equals(groupCategory)) { 51 | // TODO generating an exception or warning 52 | throw new CategoryGroupException(groupCategory.getName(), labelCategory.getName() 53 | ); 54 | } 55 | } 56 | if (null == groupCategory) { 57 | id++; 58 | try { 59 | category = getOwner().getLocalCategoryBox().newCategory(GROUP_FIELD_NAME + id); 60 | } catch (Exception e) { 61 | // TODO is it possible? 62 | e.printStackTrace(); 63 | } 64 | } 65 | for (CLabel label : group.labels) { 66 | label.setCategory(category); 67 | } 68 | } 69 | } 70 | 71 | private LabelGroup newLabelGroup() { 72 | LabelGroup group = new LabelGroup(); 73 | labelGroups.add(group); 74 | return group; 75 | } 76 | 77 | private void initLabelGroups() { 78 | if (labelPairs.size() == 0) return; 79 | 80 | List tempPairs = new ArrayList(labelPairs.size()); 81 | tempPairs.addAll(labelPairs); 82 | 83 | Stack groupStack = new Stack(); 84 | List trash = new ArrayList(); 85 | 86 | while (tempPairs.size() > 0) { 87 | LabelPair pair0 = tempPairs.get(0); 88 | LabelGroup group = newLabelGroup(); 89 | 90 | group.addLabel(pair0.label1); 91 | group.addLabel(pair0.label2); 92 | 93 | groupStack.push(pair0.label1); 94 | groupStack.push(pair0.label2); 95 | 96 | tempPairs.remove(0); 97 | 98 | while (!groupStack.empty()) { 99 | CLabel groupedLabel = groupStack.pop(); 100 | Iterator pairs = tempPairs.iterator(); 101 | 102 | while (pairs.hasNext()) { 103 | LabelPair pair = pairs.next(); 104 | 105 | CLabel candidate = groupedLabel.equals(pair.label1) ? pair.label2 : 106 | groupedLabel.equals(pair.label2) ? pair.label1 : null; 107 | 108 | if (null == candidate) continue; 109 | 110 | if (!groupStack.contains(candidate)) { 111 | groupStack.push(candidate); 112 | group.labels.add(candidate); 113 | } 114 | trash.add(pair); 115 | pairs.remove(); 116 | } 117 | } 118 | tempPairs.removeAll(trash); 119 | trash.clear(); 120 | } 121 | } 122 | 123 | void group(CLabel label1, CLabel label2) { 124 | //if ( ! label1.equals( label2 ) ) 125 | labelPairs.add(new LabelPair(label1, label2)); 126 | } 127 | 128 | public String trace() { 129 | StringBuilder sb = new StringBuilder(); 130 | sb.append("Grouped labels:\r\n\t"); 131 | 132 | if (labelPairs.size() == 0) { 133 | sb.append("no pairs"); 134 | } else { 135 | int c = 0; 136 | for (LabelPair pair : labelPairs) { 137 | sb.append(String.format("(\"%s\", \"%s\")", pair.label1.getValue(), pair.label2.getValue())); 138 | if (c < labelPairs.size() - 1) sb.append(", "); 139 | c++; 140 | } 141 | } 142 | return sb.toString(); 143 | } 144 | 145 | LabelGroupBox(CTable owner) { 146 | //this.owner = owner; 147 | super(owner); 148 | } 149 | 150 | private class LabelGroup { 151 | private Set labels = new HashSet(); 152 | 153 | private void addLabel(CLabel label) { 154 | labels.add(label); 155 | } 156 | } 157 | 158 | private class LabelPair { 159 | private CLabel label1; 160 | private CLabel label2; 161 | 162 | private LabelPair(CLabel label1, CLabel label2) { 163 | this.label1 = label1; 164 | this.label2 = label2; 165 | } 166 | 167 | @Override 168 | public boolean equals(Object o) { 169 | if (this == o) return true; 170 | if (o == null || getClass() != o.getClass()) return false; 171 | 172 | LabelPair pair = (LabelPair) o; 173 | 174 | if (label1 == pair.label1 && label2 == pair.label2) return true; 175 | if (label1 == pair.label2 && label2 == pair.label1) return true; 176 | 177 | return false; 178 | } 179 | 180 | @Override 181 | public int hashCode() { 182 | int result = label1 != null ? label1.hashCode() : 0; 183 | result += label2 != null ? label2.hashCode() : 0; 184 | return result; 185 | } 186 | } 187 | } 188 | 189 | 190 | -------------------------------------------------------------------------------- /src/main/java/ru/icc/td/tabbyxl/model/style/CStyle.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-18 Alexey O. Shigarov (shigarov@icc.ru) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package ru.icc.td.tabbyxl.model.style; 18 | 19 | public final class CStyle 20 | { 21 | private boolean hidden; 22 | 23 | public boolean isHidden() 24 | { 25 | return this.hidden; 26 | } 27 | 28 | public void setHidden( boolean hidden ) 29 | { 30 | this.hidden = hidden; 31 | } 32 | 33 | private boolean locked; 34 | 35 | public boolean isLocked() 36 | { 37 | return this.locked; 38 | } 39 | 40 | public void setLocked( boolean locked ) 41 | { 42 | this.locked = locked; 43 | } 44 | 45 | private boolean wrapped; 46 | 47 | public boolean isWrapped() 48 | { 49 | return this.wrapped; 50 | } 51 | 52 | public void setWrapped( boolean wrapped ) 53 | { 54 | this.wrapped = wrapped; 55 | } 56 | 57 | private CFont font = new CFont(); 58 | 59 | public CFont getFont() 60 | { 61 | return this.font; 62 | } 63 | 64 | /* 65 | public void setFont( CFont font ) 66 | { 67 | this.font = font; 68 | } 69 | */ 70 | 71 | private HorzAlignment horzAlignment; 72 | 73 | public HorzAlignment getHorzAlignment() 74 | { 75 | return horzAlignment; 76 | } 77 | 78 | public void setHorzAlignment( HorzAlignment horzAlignment ) 79 | { 80 | this.horzAlignment = horzAlignment; 81 | } 82 | 83 | private VertAlignment vertAlignment; 84 | 85 | public VertAlignment getVertAlignment() 86 | { 87 | return this.vertAlignment; 88 | } 89 | 90 | public void setVertAlignment( VertAlignment vertAlignment ) 91 | { 92 | this.vertAlignment = vertAlignment; 93 | } 94 | 95 | private short rotation; 96 | 97 | public short getRotation() 98 | { 99 | return rotation; 100 | } 101 | 102 | public void setRotation( short rotation ) 103 | { 104 | this.rotation = rotation; 105 | } 106 | 107 | private short indention; 108 | 109 | public short getIndention() 110 | { 111 | return indention; 112 | } 113 | 114 | public void setIndention( short indention ) 115 | { 116 | this.indention = indention; 117 | } 118 | 119 | private FillPattern fillPattern; 120 | 121 | public FillPattern getFillPattern() 122 | { 123 | return fillPattern; 124 | } 125 | 126 | public void setFillPattern( FillPattern fillPattern ) 127 | { 128 | this.fillPattern = fillPattern; 129 | } 130 | 131 | private CColor bgColor; 132 | 133 | public String getBgColor() 134 | { 135 | if ( null == this.bgColor ) return null; 136 | return this.bgColor.toHexRGBString(); 137 | } 138 | 139 | 140 | public void setBgColor( CColor bgColor ) 141 | { 142 | this.bgColor = bgColor; 143 | } 144 | 145 | private CColor fgColor; 146 | 147 | public String getFgColor() 148 | { 149 | if ( null == this.fgColor ) return null; 150 | return this.fgColor.toHexRGBString(); 151 | } 152 | 153 | public void setFgColor( CColor fgColor ) 154 | { 155 | this.fgColor = fgColor; 156 | } 157 | 158 | private CBorder leftBorder = new CBorder(); 159 | 160 | public CBorder getLeftBorder() 161 | { 162 | return this.leftBorder; 163 | } 164 | 165 | public void setLeftBorder( CBorder leftBorder ) 166 | { 167 | this.leftBorder = leftBorder; 168 | } 169 | 170 | private CBorder rightBorder = new CBorder(); 171 | 172 | public CBorder getRightBorder() 173 | { 174 | return this.rightBorder; 175 | } 176 | 177 | public void setRightBorder( CBorder rightBorder ) 178 | { 179 | this.rightBorder = rightBorder; 180 | } 181 | 182 | private CBorder topBorder = new CBorder(); 183 | 184 | public CBorder getTopBorder() 185 | { 186 | return this.topBorder; 187 | } 188 | 189 | private CBorder bottomBorder = new CBorder(); 190 | 191 | public void setTopBorder( CBorder topBorder ) 192 | { 193 | this.topBorder = topBorder; 194 | } 195 | 196 | public CBorder getBottomBorder() 197 | { 198 | return this.bottomBorder; 199 | } 200 | 201 | public void setBottomBorder( CBorder bottomBorder ) 202 | { 203 | this.bottomBorder = bottomBorder; 204 | } 205 | 206 | @Override 207 | public String toString() 208 | { 209 | return super.toString(); 210 | } 211 | 212 | public String trace() 213 | { 214 | String sFont = String.format( "F=%s", font.toString() ); 215 | 216 | String sBgColor; 217 | if ( null != bgColor ) 218 | sBgColor = String.format( "bC=%s", bgColor.toHexRGBString() ); 219 | else 220 | sBgColor = "bC=none"; 221 | 222 | String sFgColor; 223 | if ( null != fgColor ) 224 | sFgColor = String.format( "fC=%s", fgColor.toHexRGBString() ); 225 | else 226 | sFgColor = "fC=none"; 227 | 228 | String sHzAlignment = String.format( "hA=%s", horzAlignment ); 229 | String sVtAlignment = String.format( "vA=%s", vertAlignment ); 230 | 231 | String sRotation = String.format( "R=%d", rotation ); 232 | String sIndention = String.format( "I=%d", indention ); 233 | 234 | String sHidden = String.format( "H=%b", hidden ); 235 | String sLocked = String.format( "L=%b", locked ); 236 | String sWrapped = String.format( "W=%b", wrapped ); 237 | 238 | String sLfBorder = String.format( "lB=%s", leftBorder ); 239 | String sRgBorder = String.format( "rB=%s", rightBorder ); 240 | String sTpBorder = String.format( "tB=%s", topBorder ); 241 | String sBtBorder = String.format( "bB=%s", bottomBorder ); 242 | 243 | return String.format( "CCellStyle [%s %s %s %s %s %s %s %s %s %s %s %s %s %s]", 244 | sFont, sBgColor, sFgColor, sHzAlignment, sVtAlignment, sRotation, sIndention, 245 | sHidden, sLocked, sWrapped, sLfBorder, sRgBorder, sTpBorder, sBtBorder); 246 | } 247 | } 248 | -------------------------------------------------------------------------------- /src/main/java/ru/icc/td/tabbyxl/model/CLabel.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-19 Alexey O. Shigarov (shigarov@gmail.com) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package ru.icc.td.tabbyxl.model; 18 | 19 | import ru.icc.td.tabbyxl.model.exception.NotAllowedParentChangeException; 20 | import ru.icc.td.tabbyxl.model.exception.NotAllowedParentCycleException; 21 | import ru.icc.td.tabbyxl.model.exception.ParentAssociatingException; 22 | 23 | import java.util.ArrayList; 24 | import java.util.List; 25 | 26 | public final class CLabel extends CItem { 27 | // TODO reading SEPARATOR value from settings is needed 28 | private final static String SEPARATOR = "|"; 29 | 30 | public String getCompoundValue() { 31 | if (null == parent) { 32 | return getValue(); 33 | } else { 34 | return String.format("%s %s %s", parent.getCompoundValue(), SEPARATOR, getValue()); 35 | } 36 | } 37 | 38 | private CCategory category; 39 | 40 | public CCategory getCategory() { 41 | return category; 42 | } 43 | 44 | public boolean hasCategory() { 45 | return null != category; 46 | } 47 | 48 | private boolean blocked = false; 49 | 50 | public void setCategory(CCategory category) { 51 | if (blocked) { 52 | // TODO generating the warning: "The label is already associated with a category" 53 | } else { 54 | if (category.addLabel(this)) { 55 | this.category = category; 56 | // TODO checking category conflicts in label hierarchy, setting category in label hierarchy 57 | 58 | for (CEntry entry : listeners) { 59 | entry.categoryActivated(this); 60 | } 61 | listeners = null; 62 | blocked = true; 63 | } 64 | } 65 | } 66 | 67 | public void setCategory(String categoryName) { 68 | if (null == categoryName) 69 | throw new NullPointerException("The category name cannot be null"); 70 | 71 | categoryName = categoryName.trim(); 72 | 73 | if (categoryName.isEmpty()) 74 | new IllegalArgumentException("The category name cannot be empty"); 75 | 76 | LocalCategoryBox localCategoryBox = getOwner().getLocalCategoryBox(); 77 | CCategory category = localCategoryBox.findCategory(categoryName); 78 | if (category == null) { 79 | category = localCategoryBox.newCategory(categoryName); 80 | } 81 | setCategory(category); 82 | } 83 | 84 | public void group(CLabel label) { 85 | getOwner().getLabelGroupBox().group(this, label); 86 | } 87 | 88 | public CLabel(CTable owner, CCell cell, String value) { 89 | super(owner, cell, value); 90 | } 91 | 92 | public CLabel(CTable owner, String value) { 93 | this(owner, null, value); 94 | } 95 | 96 | private CLabel parent; 97 | 98 | public CLabel getParent() { 99 | return parent; 100 | } 101 | 102 | public boolean hasParent() { 103 | return null != parent; 104 | } 105 | 106 | private List children = new ArrayList(); 107 | 108 | private void addChild(CLabel child) { 109 | children.add(child); 110 | setTerminal(); 111 | } 112 | 113 | // this is true if the label nas no child label 114 | private boolean terminal = true; 115 | 116 | public boolean isTerminal() { 117 | return terminal; 118 | } 119 | 120 | private void setTerminal() { 121 | terminal = children.size() == 0; 122 | } 123 | 124 | private boolean isDescendant(CLabel label) { 125 | for (CLabel child : children) { 126 | if (child.equals(label) || child.isDescendant(label)) { 127 | return true; 128 | } 129 | } 130 | return false; 131 | } 132 | 133 | // TODO changing exception type is needed 134 | public void setParent(CLabel parent) //throws NotAllowedParentCycleException, NotAllowedParentChangeException 135 | { 136 | if (null == parent) 137 | throw new NullPointerException("The parent label cannot be null"); 138 | 139 | try { 140 | // parent change is not allowed 141 | if (null == this.parent) { 142 | // label cycles are not allowed 143 | if (this.equals(parent) || isDescendant(parent)) { 144 | throw new NotAllowedParentCycleException(this, this.getParent(), parent); 145 | } else { 146 | // TODO checking category conflicts in label hierarchy, setting category in label hierarchy 147 | parent.addChild(this); 148 | this.parent = parent; 149 | } 150 | } else { 151 | throw new NotAllowedParentChangeException(this, this.getParent(), parent); 152 | } 153 | } catch (ParentAssociatingException e) { 154 | System.out.println("The label parent candidate has been declined: " + e.getMessage()); 155 | } 156 | } 157 | 158 | private List listeners = new ArrayList(); 159 | 160 | void addListener(CEntry entry) { 161 | listeners.add(entry); 162 | } 163 | 164 | public String trace() { 165 | final String separator = "; "; 166 | final StringBuilder sb = new StringBuilder(); 167 | final String nil = "null"; 168 | 169 | String s1 = String.format("label=\"%s\"", getValue()); 170 | sb.append(s1).append(separator); 171 | 172 | CCell c = this.getCell(); 173 | String s2 = String.format("address=%s", c.address()); 174 | sb.append(s2).append(separator); 175 | 176 | sb.append("parent="); 177 | if (null == parent) 178 | sb.append(nil); 179 | else 180 | sb.append('"').append(parent.getValue()).append('"'); 181 | sb.append(separator); 182 | 183 | sb.append("category="); 184 | if (null == category) 185 | sb.append(nil); 186 | else 187 | sb.append('"').append(category.getName()).append('"'); 188 | 189 | return sb.toString(); 190 | } 191 | 192 | } 193 | -------------------------------------------------------------------------------- /src/main/java/ru/icc/td/tabbyxl/writers/EvaluationTableWriter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-18 Alexey O. Shigarov (shigarov@gmail.com) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package ru.icc.td.tabbyxl.writers; 18 | 19 | import org.apache.poi.ss.usermodel.Cell; 20 | import org.apache.poi.ss.usermodel.Row; 21 | import org.apache.poi.ss.usermodel.Sheet; 22 | import org.apache.poi.ss.usermodel.Workbook; 23 | import ru.icc.td.tabbyxl.model.CCell; 24 | import ru.icc.td.tabbyxl.model.CEntry; 25 | import ru.icc.td.tabbyxl.model.CLabel; 26 | import ru.icc.td.tabbyxl.model.CTable; 27 | 28 | import java.io.File; 29 | import java.nio.file.Path; 30 | import java.nio.file.Paths; 31 | import java.util.Iterator; 32 | 33 | public final class EvaluationTableWriter extends BasicTableWriter 34 | { 35 | @Override 36 | protected Workbook writeToWorkbook(CTable table) 37 | { 38 | Workbook workbook = super.writeToWorkbook(table); 39 | Sheet sheet = null; 40 | Row excelRow = null; 41 | Cell excelCell = null; 42 | int i = 0; 43 | 44 | final Path sourceWorkbookPath = table.getSrcWorkbookFile().toPath(); 45 | final String sourceSheetName = table.getSrcSheetName(); 46 | final Path basePath = Paths.get(outputFile.getParent()); 47 | final Path relativePath = basePath.relativize(sourceWorkbookPath); 48 | final String template = "HYPERLINK(\"[%s]%s!%s\",\"%s\")"; 49 | 50 | // Writing the evaluation sheet of entries 51 | 52 | sheet = workbook.createSheet("ENTRIES"); 53 | excelRow = sheet.createRow(0); 54 | excelRow.createCell(0).setCellValue("ENTRY"); 55 | excelRow.createCell(1).setCellValue("PROVENANCE"); 56 | excelRow.createCell(2).setCellValue("LABELS"); 57 | 58 | Iterator entries = table.getEntries(); 59 | i = 1; 60 | while(entries.hasNext()) 61 | { 62 | CEntry entry = entries.next(); 63 | excelRow = sheet.createRow(i++); 64 | 65 | excelRow.createCell(0).setCellValue(entry.getValue()); 66 | 67 | excelCell = excelRow.createCell(1); 68 | String cellRef = entry.getCell().getProvenance(); 69 | String formula = String.format(template, relativePath, sourceSheetName, cellRef, cellRef); 70 | excelCell.setCellFormula(formula); 71 | 72 | final StringBuilder sb = new StringBuilder(); 73 | Iterator labels = entry.getLabels(); 74 | while ( labels.hasNext() ) 75 | { 76 | CLabel label = labels.next(); 77 | String value = label.getValue(); 78 | CCell cell = label.getCell(); 79 | String provenance; 80 | if (null != cell) { 81 | provenance = label.getCell().getProvenance(); 82 | } else { 83 | provenance = null; 84 | } 85 | value = String.format("\"%s [%s]\"", value, provenance); 86 | sb.append(value); 87 | if ( labels.hasNext() ) 88 | sb.append(", "); 89 | } 90 | excelRow.createCell(2).setCellValue(sb.toString()); 91 | } 92 | 93 | sheet.autoSizeColumn(0); 94 | sheet.autoSizeColumn(1); 95 | sheet.autoSizeColumn(2); 96 | 97 | // Writing the evaluation sheet of labels 98 | 99 | sheet = workbook.createSheet("LABELS"); 100 | excelRow = sheet.createRow(0); 101 | excelRow.createCell(0).setCellValue("LABEL"); 102 | excelRow.createCell(1).setCellValue("PROVENANCE"); 103 | excelRow.createCell(2).setCellValue("PARENT"); 104 | excelRow.createCell(3).setCellValue("CATEGORY"); 105 | 106 | Iterator labels = table.getLabels(); 107 | i = 1; 108 | while(labels.hasNext()) { 109 | CLabel label = labels.next(); 110 | excelRow = sheet.createRow(i++); 111 | excelRow.createCell(0).setCellValue(label.getValue()); 112 | 113 | excelCell = excelRow.createCell(1); 114 | //excelCell.setCellValue(entry.getCell().getProvenance()); 115 | String cellRef = label.getCell().getProvenance(); 116 | String formula = String.format(template, relativePath, sourceSheetName, cellRef, cellRef); 117 | excelCell.setCellFormula(formula); 118 | 119 | if (label.hasParent()) 120 | { 121 | CLabel parent = label.getParent(); 122 | String value = parent.getValue(); 123 | String provenance = parent.getCell().getProvenance(); 124 | value = String.format("%s [%s]", value, provenance); 125 | excelRow.createCell(2).setCellValue(value); 126 | } 127 | excelRow.createCell(3).setCellValue(label.getCategory().getName()); 128 | } 129 | 130 | sheet.autoSizeColumn(0); 131 | sheet.autoSizeColumn(1); 132 | sheet.autoSizeColumn(2); 133 | sheet.autoSizeColumn(3); 134 | 135 | // Writing the provenance information 136 | sheet = workbook.createSheet("INFO"); 137 | excelRow = sheet.createRow(0); 138 | excelCell = excelRow.createCell(0); 139 | excelCell.setCellValue("LINK TO THE SOURCE TABLE"); 140 | sheet.autoSizeColumn(0); 141 | excelCell = excelRow.createCell(1); 142 | 143 | String cellRef = table.getSrcStartCellRef(); 144 | String s = String.format("[%s]%s!%s", relativePath, sourceSheetName, cellRef); 145 | 146 | String formula = String.format(template, relativePath, sourceSheetName, cellRef, s); 147 | excelCell.setCellFormula(formula); 148 | 149 | // Copying the area of the source table from the source workbook to result one 150 | // Sheet sheetFrom = table.getSourceSheet(); 151 | // CellReference start = new CellReference(table.getSrcStartCellRef()); 152 | // CellReference end = new CellReference(table.getSrcEndCellRef()); 153 | // Sheet sheetTo = workbook.createSheet("SOURCE TABLE"); 154 | // copyArea(sheetFrom, start, end, sheetTo); 155 | 156 | return workbook; 157 | } 158 | 159 | public EvaluationTableWriter(File outputFile) { 160 | super(outputFile); 161 | } 162 | 163 | } 164 | -------------------------------------------------------------------------------- /src/main/java/ru/icc/td/tabbyxl/HeadRecog.java: -------------------------------------------------------------------------------- 1 | package ru.icc.td.tabbyxl; 2 | 3 | import org.apache.commons.cli.*; 4 | import org.apache.commons.io.FileUtils; 5 | import ru.icc.td.tabbyxl.model.CTable; 6 | import ru.icc.td.tabbyxl.preprocessing.headrecog.HeadRecogPreprocessor; 7 | 8 | import java.io.File; 9 | import java.io.IOException; 10 | import java.nio.file.Files; 11 | import java.util.ArrayList; 12 | import java.util.List; 13 | import java.util.regex.Pattern; 14 | 15 | public class HeadRecog { 16 | 17 | private static String input; 18 | private static String output; 19 | private static List sheetIndexes; 20 | 21 | public static void main(String[] args) { 22 | new HeadRecog().run(args); 23 | } 24 | 25 | private void run(String[] args) { 26 | 27 | try { 28 | parseCmd(args); 29 | 30 | File inputFile = new File(input); 31 | 32 | if (!inputFile.exists()) { 33 | System.err.println("The input Excel file does not exist"); 34 | System.exit(0); 35 | } else { 36 | if (!inputFile.canRead()) { 37 | System.err.println("The input Excel file cannot be read"); 38 | System.exit(0); 39 | } 40 | } 41 | 42 | System.out.println(String.format("Input Excel file: %s", inputFile.getPath())); 43 | 44 | DataLoader loader = DataLoader.getInstance(); 45 | loader.loadWorkbook(inputFile); 46 | 47 | if (sheetIndexes == null) { 48 | sheetIndexes = new ArrayList<>(); 49 | for (int i = 0; i < loader.numOfSheets(); i++) { 50 | sheetIndexes.add(i); 51 | } 52 | } 53 | 54 | HeadRecogPreprocessor hcsc; 55 | 56 | if (output == null) { 57 | System.out.println("The output file is not defined"); 58 | System.exit(0); 59 | } 60 | 61 | File outputFile = new File(output); 62 | if (!outputFile.exists()) { 63 | Files.createFile(outputFile.toPath()); 64 | } 65 | FileUtils.copyFile(inputFile, outputFile); 66 | 67 | hcsc = new HeadRecogPreprocessor(outputFile); 68 | System.out.printf("Output Excel file: %s%n", outputFile.getPath()); 69 | 70 | // Process tables 71 | for (int sheetNo : sheetIndexes) { 72 | loader.goToSheet(sheetNo); 73 | 74 | int tableNo = 0; 75 | while (true) { 76 | CTable table = loader.nextTable(); 77 | if (table == null) break; 78 | 79 | hcsc.process(table); 80 | String sheetName = table.getSrcSheetName(); 81 | System.out.printf("Table #%s in Sheet #%s (%s) was processed successfully%n", tableNo, sheetNo, sheetName); 82 | tableNo++; 83 | } 84 | } 85 | 86 | hcsc.saveWorkbook(); 87 | 88 | System.out.println(); 89 | 90 | } catch (ParseException | IOException e) { 91 | e.printStackTrace(); 92 | System.exit(1); 93 | } 94 | } 95 | 96 | private void parseCmd(String[] args) throws ParseException { 97 | 98 | CommandLineParser parser = new BasicParser(); 99 | 100 | Option inputOpt = OptionBuilder 101 | .withArgName("path") 102 | .hasArg() 103 | .withDescription("specify a path to an input excel workbook (*.xlsx)") 104 | .create("input"); 105 | 106 | Option sheetIndexesOpt = OptionBuilder 107 | .withArgName("sheet indexes") 108 | .hasArg() 109 | .withDescription("specify sheet indexes in the input excel workbook (e.g. \"0-2,4,5,7-10\")") 110 | .create("sheets"); 111 | 112 | Option outputOpt = OptionBuilder 113 | .withArgName("path") 114 | .hasArg() 115 | .withDescription("specify a path to an output excel workbook (*.xlsx)") 116 | .create("output"); 117 | 118 | Option helpOpt = OptionBuilder 119 | .withDescription("print this message") 120 | .create("help"); 121 | 122 | Options options = new Options(); 123 | options.addOption(inputOpt); 124 | options.addOption(sheetIndexesOpt); 125 | options.addOption(outputOpt); 126 | options.addOption(helpOpt); 127 | 128 | CommandLine cmd = parser.parse(options, args); 129 | 130 | if (cmd.hasOption(helpOpt.getOpt())) { 131 | HelpFormatter formatter = new HelpFormatter(); 132 | formatter.printHelp("HeadRecog", options); 133 | System.exit(0); 134 | } 135 | 136 | if (!cmd.hasOption(inputOpt.getOpt())) throw new ParseException("specify input excel file path"); 137 | input = cmd.getOptionValue(inputOpt.getOpt()); 138 | 139 | if (cmd.hasOption(sheetIndexesOpt.getOpt())) 140 | sheetIndexes = parseSheetIndexesParam(cmd.getOptionValue(sheetIndexesOpt.getOpt())); 141 | 142 | if (cmd.hasOption(outputOpt.getOpt())) output = cmd.getOptionValue(outputOpt.getOpt()); 143 | } 144 | 145 | private static List parseSheetIndexesParam(String sheetIndexesParam) { 146 | if (sheetIndexesParam != null) { 147 | if (Pattern.matches("\\d+(((,\\s?)|(-))?\\d+)*", sheetIndexesParam)) { 148 | List sheetIndexes = new ArrayList(); 149 | 150 | String[] ranges = sheetIndexesParam.split(","); 151 | 152 | for (String range : ranges) { 153 | range = range.trim(); 154 | 155 | int firstHyphenPos = range.indexOf('-'); 156 | int lastHyphenPos = range.lastIndexOf('-'); 157 | 158 | if (firstHyphenPos > -1) { 159 | String s0 = range.substring(0, firstHyphenPos); 160 | String s1 = range.substring(lastHyphenPos + 1); 161 | 162 | int initialIndex = Integer.parseInt(s0); 163 | int lastIndex = Integer.parseInt(s1); 164 | 165 | for (int i = initialIndex; i < lastIndex + 1; i++) 166 | sheetIndexes.add(i); 167 | } else { 168 | sheetIndexes.add(Integer.valueOf(range)); 169 | } 170 | } 171 | return sheetIndexes; 172 | } else { 173 | System.err.println("The sheet range is incorrect"); 174 | System.exit(0); 175 | } 176 | } 177 | // When sheetIndexes field is null, then all sheets in the input Excel workbook are processed 178 | return null; 179 | } 180 | } 181 | -------------------------------------------------------------------------------- /src/main/java/ru/icc/td/tabbyxl/crl2j/Ruleset.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018-19 Alexey O. Shigarov (shigarov@icc.ru) and Vasiliy V. Khristyuk 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package ru.icc.td.tabbyxl.crl2j; 18 | 19 | import org.antlr.runtime.tree.Tree; 20 | import ru.icc.td.tabbyxl.crl2j.rulemodel.*; 21 | import ru.icc.td.tabbyxl.model.COwned; 22 | 23 | import java.util.ArrayList; 24 | import java.util.List; 25 | 26 | final class Ruleset { 27 | 28 | private List staticImportDescriptors = new ArrayList<>(); 29 | private List rules = new ArrayList<>(); 30 | 31 | public List getStaticImportDescriptors() { 32 | return staticImportDescriptors; 33 | } 34 | 35 | public List getRules() { 36 | return rules; 37 | } 38 | 39 | public Ruleset(Tree ast) { 40 | staticImportDescriptors.addAll(Constructor.createStaticImportDescriptors(ast)); 41 | try { 42 | rules.addAll(Constructor.createRules(ast)); 43 | } catch (ClassNotFoundException e) { 44 | e.printStackTrace(); 45 | System.exit(-1); 46 | } 47 | } 48 | 49 | private static final class Constructor { 50 | 51 | static List createStaticImportDescriptors(Tree ast) { 52 | 53 | List staticImportDescriptors = new ArrayList<>(); 54 | 55 | for (int i = 0; i < ast.getChildCount(); i++) { 56 | Tree subtree = ast.getChild(i); 57 | 58 | if (subtree.getText().equals("IMPORTS")) { 59 | for (int j = 0; j < subtree.getChildCount(); j++) { 60 | String statement = subtree.getChild(j).getText(); 61 | StaticImportDescriptor importDesc = StaticImportDescriptor.parseStaticImportStatement(statement); 62 | if (null != importDesc) 63 | staticImportDescriptors.add(importDesc); 64 | } 65 | } 66 | } 67 | 68 | return staticImportDescriptors; 69 | } 70 | 71 | static List createRules(Tree ast) throws ClassNotFoundException { 72 | 73 | List rules = new ArrayList<>(); 74 | 75 | for (int i = 0; i < ast.getChildCount(); i++) { 76 | Tree subTree = ast.getChild(i); 77 | 78 | if (subTree.getText().equals("RULES")) { 79 | for (int j = 0; j < subTree.getChildCount(); j++) { 80 | rules.add(createRule(subTree.getChild(j))); 81 | } 82 | } 83 | } 84 | 85 | return rules; 86 | } 87 | 88 | static Rule createRule(Tree tree) throws ClassNotFoundException { 89 | 90 | Rule rule = new Rule(); 91 | 92 | rule.setId(Integer.parseInt(tree.getText())); 93 | 94 | for (int i = 0; i < tree.getChildCount(); i++) { 95 | Tree subtree = tree.getChild(i); 96 | 97 | if (subtree.getText().equals("CONDITIONS")) { 98 | 99 | for (int j = 0; j < subtree.getChildCount(); j++) { 100 | rule.addCondition(createCondition(subtree.getChild(j), j + 1)); 101 | } 102 | } else if (subtree.getText().equals("ACTIONS")) { 103 | 104 | for (int j = 0; j < subtree.getChildCount(); j++) { 105 | rule.addAction(createAction(subtree.getChild(j))); 106 | } 107 | } 108 | } 109 | 110 | return rule; 111 | } 112 | 113 | static Condition createCondition(Tree tree, int id) throws ClassNotFoundException { 114 | 115 | Condition condition = new Condition(); 116 | 117 | condition.setId(id); 118 | condition.setQuantifier(Condition.Quantifier.valueOf(tree.getChild(0).getText())); 119 | 120 | String simpleClassName = tree.getChild(1).getText(); 121 | Class queriedDataType = (Class) Class.forName("ru.icc.td.tabbyxl.model." + simpleClassName); 122 | condition.setQueriedType(queriedDataType); 123 | 124 | if (tree.getChild(2).getText().equals("null")) { 125 | condition.setIdentifier("id" + id); 126 | } else { 127 | condition.setIdentifier(tree.getChild(2).getText()); 128 | } 129 | 130 | Tree constraintsTree = tree.getChild(3); 131 | for (int i = 0; i < constraintsTree.getChildCount(); i++) { 132 | Tree subTree = constraintsTree.getChild(i); 133 | condition.addConstraint(createConstraint(subTree)); 134 | } 135 | 136 | Tree assignmentTree = tree.getChild(4); 137 | if (assignmentTree.getChildCount() > 0) 138 | condition.addAssignment(createAssignment(assignmentTree)); 139 | 140 | return condition; 141 | } 142 | 143 | static Expression createConstraint(Tree tree) { 144 | 145 | Expression constraint = new Expression(); 146 | 147 | for (int i = 0; i < tree.getChildCount(); i++) { 148 | constraint.addToken(tree.getChild(i).getText()); 149 | } 150 | 151 | return constraint; 152 | } 153 | 154 | static Assignment createAssignment(Tree tree) { 155 | 156 | Assignment assignment = new Assignment(); 157 | 158 | assignment.setIdentifier(tree.getChild(0).getText()); 159 | 160 | for (int i = 0; i < tree.getChild(1).getChildCount(); i++) { 161 | assignment.addExpression(tree.getChild(1).getChild(i).getText()); 162 | } 163 | 164 | return assignment; 165 | } 166 | 167 | static Action createAction(Tree tree) { 168 | 169 | Action action = new Action(); 170 | action.setMethodName(tree.getText()); 171 | 172 | List operands = new ArrayList<>(); 173 | 174 | for (int i = 0; i < tree.getChildCount(); i++) { 175 | Tree subTree = tree.getChild(i); 176 | 177 | Expression operand = new Expression(); 178 | for (int j = 0; j < subTree.getChildCount(); j++) { 179 | operand.addToken(subTree.getChild(j).getText()); 180 | } 181 | 182 | operands.add(operand); 183 | } 184 | 185 | action.setOperands(operands); 186 | 187 | return action; 188 | } 189 | } 190 | } 191 | -------------------------------------------------------------------------------- /src/main/resources/crl.dsl: -------------------------------------------------------------------------------- 1 | # Copyright 2015-18 Alexey O. Shigarov (shigarov@icc.ru) 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | # Keywords 16 | [keyword][] rule #{number:\d+} = rule "#{number}" salience -{number} 17 | 18 | #Cell querying 19 | [condition][] cell {cell:\S+}\s*: {constraints} = {cell}: CCell({constraints}); 20 | [condition][] cell {cell:\S+} = {cell} : CCell(); 21 | 22 | #Entry querying 23 | [condition][] entry {entry:\S+}\s*: {constraints} = {entry}: CEntry({constraints}); 24 | [condition][] entry {entry:\S+} = {entry} : CEntry(); 25 | 26 | #Label querying 27 | [condition][] label {label:\S+}\s*: {constraints} = {label}: CLabel({constraints}); 28 | [condition][] label {label:\S+} = {label} : CLabel(); 29 | 30 | #Category querying 31 | [condition][] category {category:\S+}\s*: {constraints} = {category}: CCategory({constraints}); 32 | [condition][] category {category:\S+} = {category}: CCategory(); 33 | 34 | #Not exists 35 | [condition][] no cells\s*: {constraints} = not (exists CCell ({constraints})); 36 | [condition][] no entries\s*: {constraints} = not (exists CEntry ({constraints})); 37 | [condition][] no labels\s*: {constraints} = not (exists CLabel ({constraints})); 38 | [condition][] no categories\s*: {constraints} = not (exists CCategory ({constraints})); 39 | 40 | #Text editing 41 | [consequence][] set text {string_expression} to {cell:\S+} = {cell}.setText({string_expression}); 42 | 43 | #Indent editing 44 | [consequence][] set indent {integer:\d+} to {cell:\S+} = {cell}.setIndent({integer}); 45 | 46 | #Cell splitting 47 | [consequence][] split {cell:\S+} = for (CCell cell: {cell}.split()) \{ insert(cell); \}; retract({cell}); 48 | 49 | #Cell merging 50 | [consequence][] merge {cell1:\S+} with {cell2:\S+} = {cell1}.merge({cell2}); retract({cell1}); 51 | 52 | #Cell tagging 53 | [consequence][] set tag {string_expression} to {cell:\S+} = {cell}.setTag({string_expression}); 54 | 55 | #Entry creating 56 | [consequence][] new entry {cell:\S+} as {string_expression} = insert({cell}.newEntry({string_expression})); 57 | [consequence][] new entry {cell:\S+} = insert({cell}.newEntry()); 58 | 59 | #Label creating 60 | [consequence][] new label {cell:\S+} as {string_expression} = insert({cell}.newLabel({string_expression})); 61 | [consequence][] new label {cell:\S+} = insert({cell}.newLabel()); 62 | 63 | #Value editing 64 | [consequence][] set value {string_expression} to {cell:\S+}\.label\[{id:\d+}\] = {cell}.getLabel({id}).setValue({string_expression}); 65 | [consequence][] set value {string_expression} to {cell:\S+}\.label = {cell}.getLabel().setValue({string_expression}); 66 | [consequence][] set value {string_expression} to {cell:\S+}\.entry\[{id:\d+}\] = {cell}.getEntry({id}).setValue({string_expression}); 67 | [consequence][] set value {string_expression} to {cell:\S+}\.entry = {cell}.getEntry().setValue({string_expression}); 68 | [consequence][] set value {string_expression} to {valuable:\S+} = {valuable}.setValue({string_expression}); 69 | 70 | #Label categorizing 71 | [consequence][] set category {category} to {cell:\S+}\.label\[{id:\d+}\] = {cell}.getLabel({id}).setCategory({category}); 72 | [consequence][] set category {category} to {cell:\S+}\.label = {cell}.getLabel().setCategory({category}); 73 | [consequence][] set category {category} to {label:\S+} = {label}.setCategory({category}); 74 | 75 | #Label-label associating 76 | [consequence][] set parent {cell1:\S+}\.label\[{index1:\d+}\] to {cell2:\S+}\.label\[{index2:\d+}\] = {cell2}.getLabel({index2}).setParent({cell1}.getLabel({index1})); 77 | [consequence][] set parent {cell1:\S+}\.label to {cell2:\S+}\.label = {cell2}.getLabel().setParent({cell1}.getLabel()); 78 | [consequence][] set parent {cell:\S+}\.label\[{id:\d+}\] to {label:\S+} = {label}.setParent({cell}.getLabel({id})); 79 | [consequence][] set parent {cell:\S+}\.label to {label:\S+} = {label}.setParent({cell}.getLabel()); 80 | [consequence][] set parent {label:\S+} to {cell:\S+}\.label\[{id:\d+}\] = {cell}.getLabel({id}).setParent({label}); 81 | [consequence][] set parent {label:\S+} to {cell:\S+}\.label = {cell}.getLabel().setParent({label}); 82 | [consequence][] set parent {label1:\S+} to {label2:\S+} = {label2}.setParent({label1}); 83 | 84 | #Label grouping 85 | [consequence][] group {cell1:\S+}\.label\[{index1:\d+}\] with {cell2:\S+}\.label\[{index2:\d+}\] = {cell2}.getLabel({index2}).group(${cell1}.getLabel({index1})); 86 | [consequence][] group {cell1:\S+}\.label with {cell2:\S+}\.label = {cell2}.getLabel().group({cell1}.getLabel()); 87 | [consequence][] group {label:\S+} with {cell:\S+}\.label\[{id:\d+}\] = {cell}.getLabel({id}).group({label}); 88 | [consequence][] group {label:\S+} with {cell:\S+}\.label = {cell}.getLabel().group({label}); 89 | [consequence][] group {cell:\S+}\.label\[{id:\d+}\] with {label:\S+} = {label}.group({cell}.getLabel({id})); 90 | [consequence][] group {cell:\S+}\.label with {label:\S+} = {label}.group({cell}.getLabel()); 91 | [consequence][] group {label1:\S+} with {label2:\S+} = {label2}.group({label1}); 92 | 93 | #Entry-label associating 94 | [consequence][] add label {label_value} of {category} to {cell:\S+}\.entry = {cell}.getEntry().addLabel({label_value}, {category}); 95 | [consequence][] add label {label_value} of {category} to {entry:\S+} = {entry}.addLabel({label_value}, {category}); 96 | [consequence][] add label {cell1:\S+}\.label\[{index1:\d+}\] to {cell2:\S+}\.entry\[{index2:\d+}\] = {cell2}.getEntry({index2}).addLabel({cell1}.getLabel({index1})); 97 | [consequence][] add label {label:\S+} to {cell:\S+}\.entry\[{id:\d+}\] = {cell}.getEntry({id}).addLabel({label}); 98 | [consequence][] add label {cell:\S+}\.label\[{id:\d+}\] to {entry:\S+} = {entry}.addLabel({cell}.getLabel({id})); 99 | [consequence][] add label {cell1:\S+}\.label to {cell2:\S+}\.entry = {cell2}.getEntry().addLabel({cell1}.getLabel()); 100 | [consequence][] add label {label:\S+} to {cell:\S+}\.entry = {cell}.getEntry().addLabel({label}); 101 | [consequence][] add label {cell:\S+}\.label to {entry:\S+} = {entry}.addLabel({cell}.getLabel()); 102 | [consequence][] add label {label:\S+} to {entry:\S+} = {entry}.addLabel({label}); 103 | 104 | #Updating facts 105 | [consequence][] update {cell:\S+}\.entry\[{id:\d+}\] = update({cell}.getEntry({id})); 106 | [consequence][] update {cell:\S+}\.entry = update({cell}.getEntry()); 107 | [consequence][] update {cell:\S+}\.label\[{id:\d+}\] = update({cell}.getLabel({id})); 108 | [consequence][] update {cell:\S+}\.label = update({cell}.getLabel()); 109 | [consequence][] update {variable:\S+} = update({variable}); 110 | [consequence][] update entry {entry:\S+} = update({entry}); update({entry}.getCell()); 111 | [consequence][] update label {label:\S+} = update({label}); update({label}.getCell()); 112 | [consequence][] update cell {cell:\S+} = update({cell});\n 113 | for (Iterator labels = {cell}.labels(); labels.hasNext();) \{ update(labels.next()); \}\n 114 | for (Iterator enties = {cell}.entries(); entries.hasNext();) \{ update(entries.next()); \} 115 | 116 | #Printing 117 | [consequence][] print {string_expression} = System.out.println({string_expression}); 118 | [consequence][] printf {string_expression} = System.out.printf({string_expression}); 119 | -------------------------------------------------------------------------------- /src/main/java/ru/icc/td/tabbyxl/model/CTable.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-19 Alexey O. Shigarov (shigarov@gmail.com) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package ru.icc.td.tabbyxl.model; 18 | 19 | import java.io.File; 20 | import java.util.*; 21 | 22 | public final class CTable { 23 | private static final String defaultCategoryName = "LABELS"; 24 | 25 | private int id; 26 | private static int numberOfAllTables; // Number of all tables 27 | 28 | public int getId() { 29 | return id; 30 | } 31 | 32 | private int numOfRows; 33 | private int numOfCols; 34 | 35 | // TODO maybe to change on Set? 36 | private List cells = new ArrayList(); 37 | 38 | public CCell getCell(int index) { 39 | return this.cells.get(index); 40 | } 41 | 42 | public Iterator getCells() { 43 | return this.cells.iterator(); 44 | } 45 | 46 | public List getCellList() { 47 | return this.cells; 48 | } 49 | 50 | public void removeCell(CCell cell) { 51 | cells.remove(cell); 52 | } 53 | 54 | public void addCell(CCell cell) { 55 | cells.add(cell); 56 | } 57 | 58 | boolean containsCell(CCell cell) { 59 | return cells.contains(cell); 60 | } 61 | 62 | private Set labels = new LinkedHashSet(); 63 | 64 | public boolean addLabel(CLabel label) { 65 | return labels.add(label); 66 | } 67 | 68 | public boolean containsLabel(CLabel label) { 69 | return labels.contains(label); 70 | } 71 | 72 | public Iterator getLabels() { 73 | return this.labels.iterator(); 74 | } 75 | 76 | private Set entries = new LinkedHashSet(); 77 | 78 | public boolean addEntry(CEntry entry) { 79 | return entries.add(entry); 80 | } 81 | 82 | public Iterator getEntries() { 83 | return this.entries.iterator(); 84 | } 85 | 86 | public boolean containsEntry(CEntry entry) { 87 | return entries.contains(entry); 88 | } 89 | 90 | public CCell newCell() { 91 | CCell cell = new CCell(this); 92 | addCell(cell); 93 | return cell; 94 | } 95 | 96 | private LocalCategoryBox localCategoryBox = new LocalCategoryBox(this); 97 | 98 | public LocalCategoryBox getLocalCategoryBox() { 99 | return localCategoryBox; 100 | } 101 | 102 | private LabelGroupBox labelGroupBox = new LabelGroupBox(this); 103 | 104 | public LabelGroupBox getLabelGroupBox() { 105 | return labelGroupBox; 106 | } 107 | 108 | public CTable(int numOfRows, int numOfCols) { 109 | this.numOfRows = numOfRows; 110 | this.numOfCols = numOfCols; 111 | 112 | numberOfAllTables++; 113 | id = numberOfAllTables; 114 | } 115 | 116 | public CanonicalForm toCanonicalForm() { 117 | if (cells.size() < 2) return null; 118 | 119 | return new CanonicalForm(this); 120 | } 121 | 122 | public String trace() { 123 | final StringBuilder sb = new StringBuilder(); 124 | final String eol = "\r\n"; 125 | final String tab = "\t"; 126 | 127 | sb.append("Cells:").append(eol); 128 | for (CCell cell : cells) { 129 | sb.append(tab).append(cell.trace()).append(eol); 130 | } 131 | 132 | sb.append("Entries:").append(eol); 133 | for (CEntry entry : entries) { 134 | sb.append(tab).append(entry.trace()).append(eol); 135 | } 136 | 137 | sb.append("Labels:").append(eol); 138 | for (CLabel label : labels) { 139 | sb.append(tab).append(label.trace()).append(eol); 140 | } 141 | 142 | sb.append(getLabelGroupBox().trace()).append(eol); 143 | 144 | sb.append("Categories:").append(eol); 145 | Iterator categories = getLocalCategoryBox().getCategories(); 146 | 147 | while (categories.hasNext()) { 148 | sb.append(tab).append(categories.next().trace()).append(eol); 149 | } 150 | 151 | return sb.toString(); 152 | } 153 | 154 | public int numOfRows() { 155 | return numOfRows; 156 | } 157 | 158 | public int numOfCols() { 159 | return numOfCols; 160 | } 161 | 162 | public int numOfCells() { 163 | return cells.size(); 164 | } 165 | 166 | public int numOfNotEmptyCells() { 167 | int count = 0; 168 | for (CCell cell : cells) { 169 | if (null == cell.getText()) 170 | continue; 171 | if (!cell.getText().isEmpty()) 172 | count++; 173 | } 174 | return count; 175 | } 176 | 177 | public int numOfEntries() { 178 | return entries.size(); 179 | } 180 | 181 | public int numOfLabels() { 182 | return labels.size(); 183 | } 184 | 185 | public int numOfCategories() { 186 | return getLocalCategoryBox().numOfCategories(); 187 | } 188 | 189 | public int numOfLabelGroups() { 190 | return getLabelGroupBox().numOfLabelGroups(); 191 | } 192 | 193 | public int numOfLL() { 194 | int count = 0; 195 | for (CLabel label : labels) { 196 | if (label.hasParent()) 197 | count++; 198 | } 199 | return count; 200 | } 201 | 202 | public int numOfEL() { 203 | int count = 0; 204 | for (CEntry entry : entries) { 205 | count += entry.numOfLabels(); 206 | } 207 | return count; 208 | } 209 | 210 | public int numOfCL() { 211 | int count = 0; 212 | for (CLabel label : labels) { 213 | if (label.hasCategory()) 214 | count++; 215 | } 216 | return count; 217 | } 218 | 219 | public void update() { 220 | labelGroupBox.update(); 221 | setDefaultCategory(); 222 | } 223 | 224 | private void setDefaultCategory() { 225 | final List uncategorizedLabels = new ArrayList(); 226 | 227 | for (CLabel label : labels) { 228 | if (null == label.getCategory()) { 229 | uncategorizedLabels.add(label); 230 | } 231 | } 232 | 233 | if (uncategorizedLabels.size() > 0) { 234 | // TODO reading the default category name from settings 235 | final CCategory category = localCategoryBox.newCategory(defaultCategoryName); 236 | 237 | for (CLabel label : uncategorizedLabels) { 238 | label.setCategory(category); 239 | } 240 | } 241 | } 242 | 243 | private File srcWorkbookFile; 244 | 245 | public File getSrcWorkbookFile() { 246 | return srcWorkbookFile; 247 | } 248 | 249 | public void setSrcWorkbookFile(File srcWorkbookFile) { 250 | this.srcWorkbookFile = srcWorkbookFile; 251 | } 252 | 253 | private String srcSheetName; 254 | 255 | public String getSrcSheetName() { 256 | return srcSheetName; 257 | } 258 | 259 | public void setSrcSheetName(String srcSheetName) { 260 | this.srcSheetName = srcSheetName; 261 | } 262 | 263 | private String srcStartCellRef; 264 | 265 | public String getSrcStartCellRef() { 266 | return srcStartCellRef; 267 | } 268 | 269 | public void setSrcStartCellRef(String srcStartCellRef) { 270 | this.srcStartCellRef = srcStartCellRef; 271 | } 272 | 273 | private String srcEndCellRef; 274 | 275 | public String getSrcEndCellRef() { 276 | return srcEndCellRef; 277 | } 278 | 279 | public void setSrcEndCellRef(String srcEndCellRef) { 280 | this.srcEndCellRef = srcEndCellRef; 281 | } 282 | } -------------------------------------------------------------------------------- /src/main/java/ru/icc/td/tabbyxl/crl2j/mvngen/MvnProjectGenerator.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Alexey O. Shigarov (shigarov@icc.ru) and Vasiliy V. Khristyuk 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package ru.icc.td.tabbyxl.crl2j.mvngen; 18 | 19 | import com.squareup.javapoet.*; 20 | import org.antlr.runtime.RecognitionException; 21 | import org.apache.commons.io.FileUtils; 22 | import org.apache.commons.io.IOUtils; 23 | import ru.icc.td.tabbyxl.crl2j.CRL2JEngine; 24 | import ru.icc.td.tabbyxl.model.CTable; 25 | import ru.icc.td.tabbyxl.writers.EvaluationTableWriter; 26 | 27 | import javax.lang.model.element.Modifier; 28 | import javax.tools.JavaFileObject; 29 | import java.io.*; 30 | import java.net.URISyntaxException; 31 | import java.nio.file.*; 32 | import java.util.Map; 33 | import java.util.Properties; 34 | 35 | public final class MvnProjectGenerator { 36 | 37 | private static final String groupId = "generated"; 38 | private static final String artifactId = "MyExtractor"; 39 | 40 | private static final String packageName = ""; // Do not change this initialization 41 | private static final String mainClassName = "SpreadsheetDataExtractorApp"; 42 | 43 | private static final Class THIS_CLASS = MvnProjectGenerator.class; 44 | 45 | private MvnProjectGenerator() { 46 | } 47 | 48 | public static void generate(File crlFile, Path projectPath) throws IOException, RecognitionException { 49 | 50 | // Generate source code of the table consumers 51 | 52 | Map sourceCodeUnits = generateSourceCode(crlFile); 53 | System.out.println("The source code was generated"); 54 | 55 | // Create or clean the project directory 56 | 57 | if (Files.notExists(projectPath)) { 58 | Files.createDirectory(projectPath); 59 | System.out.println("The project directory was created"); 60 | } else { 61 | FileUtils.cleanDirectory(projectPath.toFile()); 62 | System.out.println("The project directory was cleaned"); 63 | } 64 | 65 | // Create the source code directory 66 | 67 | Path sourceCodePath = projectPath.resolve("src").resolve("main").resolve("java"); 68 | Files.createDirectories(sourceCodePath.resolve(packageName)); 69 | 70 | // Write the generated source code of the table consumers 71 | 72 | writeSourceCode(sourceCodeUnits, sourceCodePath); 73 | System.out.println("The source code was written in java files"); 74 | 75 | // Create main-class and add it to the project 76 | 77 | JavaFileObject mainClassFile = generateMainClassSourceCode(sourceCodeUnits); 78 | writeMainClassSourceCode(mainClassFile, sourceCodePath); 79 | System.out.println("The main-class was added"); 80 | 81 | // Create pom-file and add it to the project 82 | 83 | writePomFile(projectPath); 84 | System.out.println("The pom file was added"); 85 | 86 | System.out.printf("Your project was created successfully in \"%s\"", projectPath); 87 | } 88 | 89 | private static Map generateSourceCode(File crlFile) throws RecognitionException { 90 | 91 | // Generate source code of the table consumers from rules 92 | 93 | final CRL2JEngine crl2jEngine = new CRL2JEngine(packageName); 94 | try { 95 | crl2jEngine.loadRules(crlFile); 96 | } catch (IOException e) { 97 | e.printStackTrace(); 98 | System.exit(-1); 99 | } 100 | return crl2jEngine.getSourceCodeUnits(); 101 | } 102 | 103 | private static void writeSourceCode(Map sourceCodeUnits, Path sourceCodePath) { 104 | try { 105 | for (String qualifiedClassName : sourceCodeUnits.keySet()) { 106 | 107 | JavaFileObject sourceCodeUnit = sourceCodeUnits.get(qualifiedClassName); 108 | String sourceCode = sourceCodeUnit.getCharContent(true).toString(); 109 | 110 | File sourceCodeFile = sourceCodePath.resolve(sourceCodeUnit.getName()).toFile(); 111 | BufferedWriter writer = new BufferedWriter(new FileWriter(sourceCodeFile, false)); 112 | writer.write(sourceCode); 113 | 114 | writer.close(); 115 | } 116 | } catch (IOException e) { 117 | e.printStackTrace(); 118 | System.exit(-1); 119 | } 120 | } 121 | 122 | private static JavaFileObject generateMainClassSourceCode(Map sourceCodeUnits) { 123 | 124 | CodeBlock codeBlock = CodeBlock 125 | .builder() 126 | .addStatement("$T inputExcelFile = new File(args[0])", File.class) 127 | .addStatement("$T outputDirectory = new File(args[1]).toPath()", Path.class) 128 | .addStatement("$T tables = extr.extract(inputExcelFile)", CTable[].class) 129 | .beginControlFlow("for ($T table : tables)", CTable.class) 130 | .addStatement("System.out.println(table.trace())") 131 | .addStatement("table.toCanonicalForm().print()") 132 | .addStatement("$T sheetName = table.getSrcSheetName()", String.class) 133 | .addStatement("$T outFileName = sheetName + \".xlsx\"", String.class) 134 | .addStatement("$T outPath = outputDirectory.resolve(outFileName)", Path.class) 135 | .addStatement("$T outFile = outPath.toFile()", File.class) 136 | .addStatement("$T writer = new EvaluationTableWriter(outFile)", EvaluationTableWriter.class) 137 | .addStatement("writer.write(table)") 138 | .endControlFlow() 139 | .build(); 140 | 141 | MethodSpec mainMethodSpec = MethodSpec 142 | .methodBuilder("main") 143 | .addModifiers(Modifier.PUBLIC, Modifier.STATIC) 144 | .addParameter(String[].class, "args") 145 | .addException(IOException.class) 146 | .addCode(codeBlock) 147 | .build(); 148 | 149 | FieldSpec extractorFieldSpec = FieldSpec 150 | .builder(SpreadsheetTableExtractor.class, "extr") 151 | .addModifiers(Modifier.STATIC, Modifier.FINAL) 152 | .initializer("new $T()", SpreadsheetTableExtractor.class) 153 | .build(); 154 | 155 | CodeBlock.Builder builder = CodeBlock.builder(); 156 | for (String qualifiedClassName : sourceCodeUnits.keySet()) { 157 | builder.addStatement("extr.register(new $L())", qualifiedClassName); 158 | } 159 | CodeBlock staticCodeBlock = builder.build(); 160 | 161 | TypeSpec typeSpec = TypeSpec. 162 | classBuilder(mainClassName) 163 | .addField(extractorFieldSpec) 164 | .addStaticBlock(staticCodeBlock) 165 | .addMethod(mainMethodSpec) 166 | .build(); 167 | 168 | JavaFile mainClassFile = JavaFile 169 | .builder(packageName, typeSpec) 170 | .skipJavaLangImports(true) 171 | .indent(" ") 172 | .addFileComment("This source code was generated by TabbyXL (http://tabbydoc.github.io)") 173 | .build(); 174 | 175 | return mainClassFile.toJavaFileObject(); 176 | } 177 | 178 | private static void writeMainClassSourceCode(JavaFileObject mainClassSourceCode, Path sourceCodePath) { 179 | try { 180 | String sourceCode = mainClassSourceCode.getCharContent(true).toString(); 181 | File sourceCodeFile = sourceCodePath.resolve(mainClassSourceCode.getName()).toFile(); 182 | BufferedWriter writer = new BufferedWriter(new FileWriter(sourceCodeFile, false)); 183 | writer.write(sourceCode); 184 | writer.close(); 185 | } catch (IOException e) { 186 | e.printStackTrace(); 187 | System.exit(-1); 188 | } 189 | } 190 | 191 | private static void writePomFile(Path projectPath) throws IOException { 192 | 193 | // Read pom-file template 194 | 195 | ClassLoader classLoader = THIS_CLASS.getClassLoader(); 196 | InputStream inputStream = classLoader.getResourceAsStream("mvngen/pom.template"); 197 | String pomTemplate = IOUtils.toString(inputStream); 198 | inputStream.close(); 199 | 200 | // Read pom properties 201 | 202 | Properties properties = new Properties(); 203 | properties.load(classLoader.getResourceAsStream("pom.properties")); 204 | String tabbyxlGroupId = properties.getProperty("groupId"); 205 | String tabbyxlArtifactId = properties.getProperty("artifactId"); 206 | String tabbyxlVersion = properties.getProperty("version"); 207 | 208 | // Get the path to the tabbyxl classes 209 | 210 | String path; 211 | try { 212 | path = new File(THIS_CLASS.getProtectionDomain().getCodeSource().getLocation().toURI()).getPath(); 213 | } catch (URISyntaxException e) { 214 | e.printStackTrace(); 215 | path = ""; 216 | } 217 | Path tabbyxlPath = Paths.get(path); 218 | 219 | // Fill pom-file template by using the appropriate properties 220 | 221 | String pomContent = String.format( 222 | pomTemplate, 223 | groupId, artifactId, 224 | mainClassName, 225 | tabbyxlPath.toAbsolutePath(), 226 | tabbyxlGroupId, 227 | tabbyxlArtifactId, 228 | tabbyxlVersion 229 | ); 230 | 231 | // Write pom-file 232 | 233 | final Path pathToPomFile = projectPath.resolve("pom.xml"); 234 | FileOutputStream out = new FileOutputStream(pathToPomFile.toFile()); 235 | OutputStreamWriter writer = new OutputStreamWriter(out); 236 | writer.write(pomContent); 237 | writer.flush(); 238 | writer.close(); 239 | } 240 | 241 | } 242 | --------------------------------------------------------------------------------