From b7b30b38f632d65694e9aa77ba0ac846a696882c Mon Sep 17 00:00:00 2001 From: Tobias Diez Date: Sun, 12 Mar 2017 12:51:09 +0100 Subject: [PATCH 1/7] Add serialization of group details: iconCode, description, color, expanded status --- .../logic/exporter/GroupSerializer.java | 28 ++++--- .../logic/importer/util/GroupsParser.java | 28 +++++++ .../MetadataSerializationConfiguration.java | 8 +- .../jabref/model/groups/AbstractGroup.java | 9 +++ .../jabref/model/groups/ExplicitGroup.java | 11 ++- .../exporter/BibtexDatabaseWriterTest.java | 4 +- .../logic/exporter/GroupSerializerTest.java | 57 +++++++------ .../logic/importer/util/GroupsParserTest.java | 13 +++ src/test/resources/testbib/complex.bib | 79 +++++++++---------- 9 files changed, 160 insertions(+), 77 deletions(-) diff --git a/src/main/java/org/jabref/logic/exporter/GroupSerializer.java b/src/main/java/org/jabref/logic/exporter/GroupSerializer.java index dc03fa0afe4..7f1fef24039 100644 --- a/src/main/java/org/jabref/logic/exporter/GroupSerializer.java +++ b/src/main/java/org/jabref/logic/exporter/GroupSerializer.java @@ -2,8 +2,8 @@ import java.util.ArrayList; import java.util.List; -import java.util.Set; -import java.util.TreeSet; + +import javafx.scene.paint.Color; import org.jabref.logic.util.MetadataSerializationConfiguration; import org.jabref.model.groups.AbstractGroup; @@ -28,14 +28,8 @@ private String serializeExplicitGroup(ExplicitGroup group) { sb.append(group.getHierarchicalContext().ordinal()); sb.append(MetadataSerializationConfiguration.GROUP_UNIT_SEPARATOR); - // write legacy entry keys in well-defined order for CVS compatibility - Set sortedKeys = new TreeSet<>(); - sortedKeys.addAll(group.getLegacyEntryKeys()); + appendGroupDetails(sb, group); - for (String sortedKey : sortedKeys) { - sb.append(StringUtil.quote(sortedKey, MetadataSerializationConfiguration.GROUP_UNIT_SEPARATOR, MetadataSerializationConfiguration.GROUP_QUOTE_CHAR)); - sb.append(MetadataSerializationConfiguration.GROUP_UNIT_SEPARATOR); - } return sb.toString(); } @@ -55,6 +49,9 @@ private String serializeKeywordGroup(KeywordGroup group) { sb.append(MetadataSerializationConfiguration.GROUP_UNIT_SEPARATOR); sb.append(StringUtil.booleanToBinaryString(isRegex)); sb.append(MetadataSerializationConfiguration.GROUP_UNIT_SEPARATOR); + + appendGroupDetails(sb, group); + return sb.toString(); } @@ -71,9 +68,22 @@ private String serializeSearchGroup(SearchGroup group) { sb.append(MetadataSerializationConfiguration.GROUP_UNIT_SEPARATOR); sb.append(StringUtil.booleanToBinaryString(group.isRegularExpression())); sb.append(MetadataSerializationConfiguration.GROUP_UNIT_SEPARATOR); + + appendGroupDetails(sb, group); + return sb.toString(); } + private void appendGroupDetails(StringBuilder builder, AbstractGroup group) { + builder.append(StringUtil.booleanToBinaryString(group.isExpanded())); + builder.append(MetadataSerializationConfiguration.GROUP_UNIT_SEPARATOR); + builder.append(group.getColor().map(Color::toString).orElse("")); + builder.append(MetadataSerializationConfiguration.GROUP_UNIT_SEPARATOR); + builder.append(group.getIconCode().orElse("")); + builder.append(MetadataSerializationConfiguration.GROUP_UNIT_SEPARATOR); + builder.append(group.getDescription().orElse("")); + builder.append(MetadataSerializationConfiguration.GROUP_UNIT_SEPARATOR); + } /** * Returns a textual representation of this node and its children. This diff --git a/src/main/java/org/jabref/logic/importer/util/GroupsParser.java b/src/main/java/org/jabref/logic/importer/util/GroupsParser.java index c010d57e080..26cc1613b2a 100644 --- a/src/main/java/org/jabref/logic/importer/util/GroupsParser.java +++ b/src/main/java/org/jabref/logic/importer/util/GroupsParser.java @@ -84,6 +84,9 @@ public static AbstractGroup fromString(String s, Character keywordSeparator) if (s.startsWith(MetadataSerializationConfiguration.EXPLICIT_GROUP_ID)) { return GroupsParser.explicitGroupFromString(s, keywordSeparator); } + if (s.startsWith(MetadataSerializationConfiguration.LEGACY_EXPLICIT_GROUP_ID)) { + return GroupsParser.legacyExplicitGroupFromString(s, keywordSeparator); + } return null; // unknown group } @@ -120,6 +123,24 @@ private static ExplicitGroup explicitGroupFromString(String input, Character key QuotedStringTokenizer tok = new QuotedStringTokenizer(input.substring(MetadataSerializationConfiguration.EXPLICIT_GROUP_ID.length()), MetadataSerializationConfiguration.GROUP_UNIT_SEPARATOR, MetadataSerializationConfiguration.GROUP_QUOTE_CHAR); + String name = tok.nextToken(); + try { + int context = Integer.parseInt(tok.nextToken()); + ExplicitGroup newGroup = new ExplicitGroup(name, GroupHierarchyType.getByNumberOrDefault(context), keywordSeparator); + addGroupDetails(tok, newGroup); + return newGroup; + } catch (NumberFormatException exception) { + throw new ParseException("Could not parse context in " + input); + } + } + + private static ExplicitGroup legacyExplicitGroupFromString(String input, Character keywordSeparator) throws ParseException { + if (!input.startsWith(MetadataSerializationConfiguration.LEGACY_EXPLICIT_GROUP_ID)) { + throw new IllegalArgumentException("ExplicitGroup cannot be created from \"" + input + "\"."); + } + QuotedStringTokenizer tok = new QuotedStringTokenizer(input.substring(MetadataSerializationConfiguration.LEGACY_EXPLICIT_GROUP_ID.length()), + MetadataSerializationConfiguration.GROUP_UNIT_SEPARATOR, MetadataSerializationConfiguration.GROUP_QUOTE_CHAR); + String name = tok.nextToken(); try { int context = Integer.parseInt(tok.nextToken()); @@ -175,4 +196,11 @@ private static AbstractGroup searchGroupFromString(String s) { GroupHierarchyType.getByNumberOrDefault(context), StringUtil.unquote(expression, MetadataSerializationConfiguration.GROUP_QUOTE_CHAR), caseSensitive, regExp ); } + + private static void addGroupDetails(QuotedStringTokenizer tokenizer, AbstractGroup group) { + group.setExpanded(Integer.parseInt(tokenizer.nextToken()) == 1); + group.setColor(tokenizer.nextToken()); + group.setIconCode(tokenizer.nextToken()); + group.setDescription(tokenizer.nextToken()); + } } diff --git a/src/main/java/org/jabref/logic/util/MetadataSerializationConfiguration.java b/src/main/java/org/jabref/logic/util/MetadataSerializationConfiguration.java index 22178238a58..ca44c291c25 100644 --- a/src/main/java/org/jabref/logic/util/MetadataSerializationConfiguration.java +++ b/src/main/java/org/jabref/logic/util/MetadataSerializationConfiguration.java @@ -30,10 +30,16 @@ public class MetadataSerializationConfiguration { */ public static final String ALL_ENTRIES_GROUP_ID = "AllEntriesGroup:"; + /** + * Old identifier for {@link ExplicitGroup} (explicitly contained a list of {@link + * org.jabref.model.entry.BibEntry}). + */ + public static final String LEGACY_EXPLICIT_GROUP_ID = "ExplicitGroup:"; + /** * Identifier for {@link ExplicitGroup}. */ - public static final String EXPLICIT_GROUP_ID = "ExplicitGroup:"; + public static final String EXPLICIT_GROUP_ID = "StaticGroup:"; /** * Identifier for {@link SearchGroup}. diff --git a/src/main/java/org/jabref/model/groups/AbstractGroup.java b/src/main/java/org/jabref/model/groups/AbstractGroup.java index f8b5bd7ad56..259a7179a4c 100644 --- a/src/main/java/org/jabref/model/groups/AbstractGroup.java +++ b/src/main/java/org/jabref/model/groups/AbstractGroup.java @@ -8,6 +8,7 @@ import org.jabref.model.entry.BibEntry; import org.jabref.model.search.SearchMatcher; +import org.jabref.model.strings.StringUtil; /** * Base class for all groups. @@ -36,6 +37,14 @@ public Optional getColor() { return color; } + public void setColor(String colorString) { + if (StringUtil.isBlank(colorString)) { + color = Optional.empty(); + } else { + setColor(Color.valueOf(colorString)); + } + } + public void setColor(Color color) { this.color = Optional.of(color); } diff --git a/src/main/java/org/jabref/model/groups/ExplicitGroup.java b/src/main/java/org/jabref/model/groups/ExplicitGroup.java index ab3bb602ec3..9c6adaa23a6 100644 --- a/src/main/java/org/jabref/model/groups/ExplicitGroup.java +++ b/src/main/java/org/jabref/model/groups/ExplicitGroup.java @@ -45,8 +45,13 @@ public boolean equals(Object o) { return false; } ExplicitGroup other = (ExplicitGroup) o; - return Objects.equals(getName(), other.getName()) && Objects.equals(getHierarchicalContext(), - other.getHierarchicalContext()) && Objects.equals(getLegacyEntryKeys(), other.getLegacyEntryKeys()); + return Objects.equals(getName(), other.getName()) + && Objects.equals(getHierarchicalContext(), other.getHierarchicalContext()) + && Objects.equals(getIconCode(), other.getIconCode()) + && Objects.equals(getDescription(), other.getDescription()) + && Objects.equals(getColor(), other.getColor()) + && Objects.equals(isExpanded(), other.isExpanded()) + && Objects.equals(getLegacyEntryKeys(), other.getLegacyEntryKeys()); } public void clearLegacyEntryKeys() { @@ -59,7 +64,7 @@ public List getLegacyEntryKeys() { @Override public int hashCode() { - return Objects.hash(name, context, legacyEntryKeys); + return Objects.hash(name, context, legacyEntryKeys, iconCode, color, description, isExpanded); } @Override diff --git a/src/test/java/org/jabref/logic/exporter/BibtexDatabaseWriterTest.java b/src/test/java/org/jabref/logic/exporter/BibtexDatabaseWriterTest.java index 8ce78a579da..f9a5ebd70bb 100644 --- a/src/test/java/org/jabref/logic/exporter/BibtexDatabaseWriterTest.java +++ b/src/test/java/org/jabref/logic/exporter/BibtexDatabaseWriterTest.java @@ -196,7 +196,7 @@ public void writeGroups() throws Exception { assertEquals(OS.NEWLINE + "@Comment{jabref-meta: groupstree:" + OS.NEWLINE + "0 AllEntriesGroup:;" + OS.NEWLINE - + "1 ExplicitGroup:test\\;2\\;;" + OS.NEWLINE + + "1 StaticGroup:test\\;2\\;1\\;\\;\\;\\;;" + OS.NEWLINE + "}" + OS.NEWLINE, session.getStringValue()); // @formatter:on } @@ -217,7 +217,7 @@ public void writeGroupsAndEncoding() throws Exception { OS.NEWLINE + "@Comment{jabref-meta: groupstree:" + OS.NEWLINE + "0 AllEntriesGroup:;" + OS.NEWLINE - + "1 ExplicitGroup:test\\;2\\;;" + OS.NEWLINE + + "1 StaticGroup:test\\;2\\;1\\;\\;\\;\\;;" + OS.NEWLINE + "}" + OS.NEWLINE, session.getStringValue()); // @formatter:on } diff --git a/src/test/java/org/jabref/logic/exporter/GroupSerializerTest.java b/src/test/java/org/jabref/logic/exporter/GroupSerializerTest.java index 41bbe19da38..b0a7de06fc2 100644 --- a/src/test/java/org/jabref/logic/exporter/GroupSerializerTest.java +++ b/src/test/java/org/jabref/logic/exporter/GroupSerializerTest.java @@ -4,6 +4,8 @@ import java.util.Collections; import java.util.List; +import javafx.scene.paint.Color; + import org.jabref.model.groups.AllEntriesGroup; import org.jabref.model.groups.ExplicitGroup; import org.jabref.model.groups.GroupHierarchyType; @@ -39,7 +41,18 @@ public void serializeSingleAllEntriesGroup() { public void serializeSingleExplicitGroup() { ExplicitGroup group = new ExplicitGroup("myExplicitGroup", GroupHierarchyType.INDEPENDENT, ','); List serialization = groupSerializer.serializeTree(GroupTreeNode.fromGroup(group)); - assertEquals(Collections.singletonList("0 ExplicitGroup:myExplicitGroup;0;"), serialization); + assertEquals(Collections.singletonList("0 StaticGroup:myExplicitGroup;0;1;;;;"), serialization); + } + + @Test + public void serializeSingleExplicitGroupWithIconAndDescription() { + ExplicitGroup group = new ExplicitGroup("myExplicitGroup", GroupHierarchyType.INDEPENDENT, ','); + group.setIconCode("test icon"); + group.setExpanded(true); + group.setColor(Color.ALICEBLUE); + group.setDescription("test description"); + List serialization = groupSerializer.serializeTree(GroupTreeNode.fromGroup(group)); + assertEquals(Collections.singletonList("0 StaticGroup:myExplicitGroup;0;1;0xf0f8ffff;test icon;test description;"), serialization); } @Test @@ -47,35 +60,35 @@ public void serializeSingleExplicitGroup() { public void serializeSingleExplicitGroupWithEscapedSlash() { ExplicitGroup group = new ExplicitGroup("B{\\\"{o}}hmer", GroupHierarchyType.INDEPENDENT, ','); List serialization = groupSerializer.serializeTree(GroupTreeNode.fromGroup(group)); - assertEquals(Collections.singletonList("0 ExplicitGroup:B{\\\\\"{o}}hmer;0;"), serialization); + assertEquals(Collections.singletonList("0 StaticGroup:B{\\\\\"{o}}hmer;0;1;;;;"), serialization); } @Test public void serializeSingleSimpleKeywordGroup() { WordKeywordGroup group = new WordKeywordGroup("name", GroupHierarchyType.INDEPENDENT, "keywords", "test", false, ',', false); List serialization = groupSerializer.serializeTree(GroupTreeNode.fromGroup(group)); - assertEquals(Collections.singletonList("0 KeywordGroup:name;0;keywords;test;0;0;"), serialization); + assertEquals(Collections.singletonList("0 KeywordGroup:name;0;keywords;test;0;0;1;;;;"), serialization); } @Test public void serializeSingleRegexKeywordGroup() { KeywordGroup group = new RegexKeywordGroup("myExplicitGroup", GroupHierarchyType.REFINING, "author", "asdf", false); List serialization = groupSerializer.serializeTree(GroupTreeNode.fromGroup(group)); - assertEquals(Collections.singletonList("0 KeywordGroup:myExplicitGroup;1;author;asdf;0;1;"), serialization); + assertEquals(Collections.singletonList("0 KeywordGroup:myExplicitGroup;1;author;asdf;0;1;1;;;;"), serialization); } @Test public void serializeSingleSearchGroup() { SearchGroup group = new SearchGroup("myExplicitGroup", GroupHierarchyType.INDEPENDENT, "author=harrer", true, true); List serialization = groupSerializer.serializeTree(GroupTreeNode.fromGroup(group)); - assertEquals(Collections.singletonList("0 SearchGroup:myExplicitGroup;0;author=harrer;1;1;"), serialization); + assertEquals(Collections.singletonList("0 SearchGroup:myExplicitGroup;0;author=harrer;1;1;1;;;;"), serialization); } @Test public void serializeSingleSearchGroupWithRegex() { SearchGroup group = new SearchGroup("myExplicitGroup", GroupHierarchyType.INCLUDING, "author=\"harrer\"", true, false); List serialization = groupSerializer.serializeTree(GroupTreeNode.fromGroup(group)); - assertEquals(Collections.singletonList("0 SearchGroup:myExplicitGroup;2;author=\"harrer\";1;0;"), serialization); + assertEquals(Collections.singletonList("0 SearchGroup:myExplicitGroup;2;author=\"harrer\";1;0;1;;;;"), serialization); } @Test @@ -85,9 +98,9 @@ public void getTreeAsStringInSimpleTree() throws Exception { List expected = Arrays.asList( "0 AllEntriesGroup:", - "1 ExplicitGroup:ExplicitA;2;", - "1 ExplicitGroup:ExplicitParent;0;", - "2 ExplicitGroup:ExplicitNode;1;" + "1 StaticGroup:ExplicitA;2;1;;;;", + "1 StaticGroup:ExplicitParent;0;1;;;;", + "2 StaticGroup:ExplicitNode;1;1;;;;" ); assertEquals(expected, groupSerializer.serializeTree(root)); } @@ -99,19 +112,19 @@ public void getTreeAsStringInComplexTree() throws Exception { List expected = Arrays.asList( "0 AllEntriesGroup:", - "1 SearchGroup:SearchA;2;searchExpression;1;0;", - "1 ExplicitGroup:ExplicitA;2;", - "1 ExplicitGroup:ExplicitGrandParent;0;", - "2 ExplicitGroup:ExplicitB;1;", - "2 KeywordGroup:KeywordParent;0;searchField;searchExpression;1;0;", - "3 KeywordGroup:KeywordNode;0;searchField;searchExpression;1;0;", - "4 ExplicitGroup:ExplicitChild;1;", - "3 SearchGroup:SearchC;2;searchExpression;1;0;", - "3 ExplicitGroup:ExplicitC;1;", - "3 KeywordGroup:KeywordC;0;searchField;searchExpression;1;0;", - "2 SearchGroup:SearchB;2;searchExpression;1;0;", - "2 KeywordGroup:KeywordB;0;searchField;searchExpression;1;0;", - "1 KeywordGroup:KeywordA;0;searchField;searchExpression;1;0;" + "1 SearchGroup:SearchA;2;searchExpression;1;0;1;;;;", + "1 StaticGroup:ExplicitA;2;1;;;;", + "1 StaticGroup:ExplicitGrandParent;0;1;;;;", + "2 StaticGroup:ExplicitB;1;1;;;;", + "2 KeywordGroup:KeywordParent;0;searchField;searchExpression;1;0;1;;;;", + "3 KeywordGroup:KeywordNode;0;searchField;searchExpression;1;0;1;;;;", + "4 StaticGroup:ExplicitChild;1;1;;;;", + "3 SearchGroup:SearchC;2;searchExpression;1;0;1;;;;", + "3 StaticGroup:ExplicitC;1;1;;;;", + "3 KeywordGroup:KeywordC;0;searchField;searchExpression;1;0;1;;;;", + "2 SearchGroup:SearchB;2;searchExpression;1;0;1;;;;", + "2 KeywordGroup:KeywordB;0;searchField;searchExpression;1;0;1;;;;", + "1 KeywordGroup:KeywordA;0;searchField;searchExpression;1;0;1;;;;" ); assertEquals(expected, groupSerializer.serializeTree(root)); } diff --git a/src/test/java/org/jabref/logic/importer/util/GroupsParserTest.java b/src/test/java/org/jabref/logic/importer/util/GroupsParserTest.java index e74a171a30a..274ac7bfb9b 100644 --- a/src/test/java/org/jabref/logic/importer/util/GroupsParserTest.java +++ b/src/test/java/org/jabref/logic/importer/util/GroupsParserTest.java @@ -3,6 +3,8 @@ import java.util.Arrays; import java.util.List; +import javafx.scene.paint.Color; + import org.jabref.logic.importer.ParseException; import org.jabref.model.groups.AbstractGroup; import org.jabref.model.groups.ExplicitGroup; @@ -57,4 +59,15 @@ public void testImportSubGroups() throws ParseException { } + @Test + public void fromStringParsesExplicitGroupWithIconAndDesrcitpion() throws Exception { + ExplicitGroup expected = new ExplicitGroup("myExplicitGroup", GroupHierarchyType.INDEPENDENT, ','); + expected.setIconCode("test icon"); + expected.setExpanded(true); + expected.setColor(Color.ALICEBLUE); + expected.setDescription("test description"); + AbstractGroup parsed = GroupsParser.fromString("StaticGroup:myExplicitGroup;0;1;0xf0f8ffff;test icon;test description;", ','); + + assertEquals(expected, parsed); + } } diff --git a/src/test/resources/testbib/complex.bib b/src/test/resources/testbib/complex.bib index 769c1962b32..4f9cd745ec0 100644 --- a/src/test/resources/testbib/complex.bib +++ b/src/test/resources/testbib/complex.bib @@ -24,21 +24,20 @@ @ARTICLE{1102917 publisher = {Springer-Verlag} } -@INPROCEEDINGS{1137631, - author = {Gustav Bostr\"{o}m and Jaana W\"{a}yrynen and Marine Bod\'{e}n and - Konstantin Beznosov and Philippe Kruchten}, - title = {Extending XP practices to support security requirements engineering}, - booktitle = {SESS '06: Proceedings of the 2006 international workshop on Software - engineering for secure systems}, - year = {2006}, - pages = {11--18}, - address = {New York, NY, USA}, - publisher = {ACM}, +@InProceedings{1137631, + author = {Gustav Bostr\"{o}m and Jaana W\"{a}yrynen and Marine Bod\'{e}n and Konstantin Beznosov and Philippe Kruchten}, + title = {Extending XP practices to support security requirements engineering}, + booktitle = {SESS '06: Proceedings of the 2006 international workshop on Software engineering for secure systems}, + year = {2006}, + publisher = {ACM}, + location = {Shanghai, China}, + isbn = {1-59593-411-1}, + pages = {11--18}, + doi = {http://doi.acm.org/10.1145/1137627.1137631}, + address = {New York, NY, USA}, bdsk-url-1 = {http://doi.acm.org/10.1145/1137627.1137631}, - doi = {http://doi.acm.org/10.1145/1137627.1137631}, - file = {:/Volumes/iDisk/Freie Universität Berlin/Semester 9/Softwareprozesse/p11-bostrom.pdf:PDF}, - isbn = {1-59593-411-1}, - location = {Shanghai, China} + file = {:/Volumes/iDisk/Freie Universität Berlin/Semester 9/Softwareprozesse/p11-bostrom.pdf:PDF}, + groups = {StaticGroup}, } @INPROCEEDINGS{1132768, @@ -126,19 +125,19 @@ @INPROCEEDINGS{1143122 location = {Pittsburgh, Pennsylvania} } -@INPROCEEDINGS{1233448, - author = {Cheryl Hinds and Chinedu Ekwueme}, - title = {Increasing security and usability of computer systems with graphical - passwords}, - booktitle = {ACM-SE 45: Proceedings of the 45th annual southeast regional conference}, - year = {2007}, - pages = {529--530}, - address = {New York, NY, USA}, - publisher = {ACM}, +@InProceedings{1233448, + author = {Cheryl Hinds and Chinedu Ekwueme}, + title = {Increasing security and usability of computer systems with graphical passwords}, + booktitle = {ACM-SE 45: Proceedings of the 45th annual southeast regional conference}, + year = {2007}, + publisher = {ACM}, + location = {Winston-Salem, North Carolina}, + isbn = {978-1-59593-629-5}, + pages = {529--530}, + doi = {http://doi.acm.org/10.1145/1233341.1233448}, + address = {New York, NY, USA}, bdsk-url-1 = {http://doi.acm.org/10.1145/1233341.1233448}, - doi = {http://doi.acm.org/10.1145/1233341.1233448}, - isbn = {978-1-59593-629-5}, - location = {Winston-Salem, North Carolina} + groups = {StaticGroup}, } @ARTICLE{10250999, @@ -156,19 +155,19 @@ @ARTICLE{10250999 publisher = {IEEE Educational Activities Department} } -@INPROCEEDINGS{1314293, - author = {Mariusz H. Jakubowski and Ramarathnam Venkatesan}, - title = {Randomized radon transforms for biometric authentication via fingerprint - hashing}, - booktitle = {DRM '07: Proceedings of the 2007 ACM workshop on Digital Rights Management}, - year = {2007}, - pages = {90--94}, - address = {New York, NY, USA}, - publisher = {ACM}, +@InProceedings{1314293, + author = {Mariusz H. Jakubowski and Ramarathnam Venkatesan}, + title = {Randomized radon transforms for biometric authentication via fingerprint hashing}, + booktitle = {DRM '07: Proceedings of the 2007 ACM workshop on Digital Rights Management}, + year = {2007}, + publisher = {ACM}, + location = {Alexandria, Virginia, USA}, + isbn = {978-1-59593-884-8}, + pages = {90--94}, + doi = {http://doi.acm.org/10.1145/1314276.1314293}, + address = {New York, NY, USA}, bdsk-url-1 = {http://doi.acm.org/10.1145/1314276.1314293}, - doi = {http://doi.acm.org/10.1145/1314276.1314293}, - isbn = {978-1-59593-884-8}, - location = {Alexandria, Virginia, USA} + groups = {StaticGroup}, } @INPROCEEDINGS{1358810, @@ -292,8 +291,8 @@ @Comment{jabref-meta: @Comment{jabref-meta: groupstree: 0 AllEntriesGroup:; -1 ExplicitGroup:StaticGroup\;0\;1137631\;1233448\;1314293\;; -1 KeywordGroup:DynamicGroup\;0\;author\;Churchill\;0\;0\;; +1 StaticGroup:StaticGroup\;0\;1\;\;\;\;; +1 KeywordGroup:DynamicGroup\;0\;author\;Churchill\;0\;0\;1\;\;\;\;; } @Comment{jabref-meta: keypattern_article:articleTest;} From 612c7618e78805118afd1039c2ed693c7d324fd9 Mon Sep 17 00:00:00 2001 From: Tobias Diez Date: Sun, 12 Mar 2017 13:21:28 +0100 Subject: [PATCH 2/7] Add serialization and parsing of automatic groups --- .../logic/exporter/GroupSerializer.java | 36 ++++++++++++++++++ .../logic/importer/util/GroupsParser.java | 38 ++++++++++++++++++- .../MetadataSerializationConfiguration.java | 12 ++++++ .../model/groups/AutomaticKeywordGroup.java | 15 ++++++++ .../model/groups/AutomaticPersonsGroup.java | 14 +++++++ .../logic/exporter/GroupSerializerTest.java | 17 +++++++++ .../logic/importer/util/GroupsParserTest.java | 23 +++++++++++ src/test/resources/testbib/complex.bib | 1 + 8 files changed, 155 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/jabref/logic/exporter/GroupSerializer.java b/src/main/java/org/jabref/logic/exporter/GroupSerializer.java index 7f1fef24039..b174cfc31e0 100644 --- a/src/main/java/org/jabref/logic/exporter/GroupSerializer.java +++ b/src/main/java/org/jabref/logic/exporter/GroupSerializer.java @@ -8,6 +8,9 @@ import org.jabref.logic.util.MetadataSerializationConfiguration; import org.jabref.model.groups.AbstractGroup; import org.jabref.model.groups.AllEntriesGroup; +import org.jabref.model.groups.AutomaticGroup; +import org.jabref.model.groups.AutomaticKeywordGroup; +import org.jabref.model.groups.AutomaticPersonsGroup; import org.jabref.model.groups.ExplicitGroup; import org.jabref.model.groups.GroupTreeNode; import org.jabref.model.groups.KeywordGroup; @@ -117,8 +120,41 @@ private String serializeGroup(AbstractGroup group) { return serializeKeywordGroup((KeywordGroup)group); } else if (group instanceof SearchGroup) { return serializeSearchGroup((SearchGroup)group); + } else if (group instanceof AutomaticKeywordGroup) { + return serializeAutomaticKeywordGroup((AutomaticKeywordGroup)group); + } else if (group instanceof AutomaticPersonsGroup) { + return serializeAutomaticPersonsGroup((AutomaticPersonsGroup)group); } else { throw new UnsupportedOperationException("Don't know how to serialize group" + group.getClass().getName()); } } + + private String serializeAutomaticPersonsGroup(AutomaticPersonsGroup group) { + StringBuilder sb = new StringBuilder(); + sb.append(MetadataSerializationConfiguration.AUTOMATIC_PERSONS_GROUP_ID); + appendAutomaticGroupDetails(sb, group); + sb.append(StringUtil.quote(group.getField(), MetadataSerializationConfiguration.GROUP_UNIT_SEPARATOR, MetadataSerializationConfiguration.GROUP_QUOTE_CHAR)); + sb.append(MetadataSerializationConfiguration.GROUP_UNIT_SEPARATOR); + appendGroupDetails(sb, group); + return sb.toString(); + } + + private void appendAutomaticGroupDetails(StringBuilder builder, AutomaticGroup group) { + builder.append(StringUtil.quote(group.getName(), MetadataSerializationConfiguration.GROUP_UNIT_SEPARATOR, MetadataSerializationConfiguration.GROUP_QUOTE_CHAR)); + builder.append(MetadataSerializationConfiguration.GROUP_UNIT_SEPARATOR); + builder.append(group.getHierarchicalContext().ordinal()); + builder.append(MetadataSerializationConfiguration.GROUP_UNIT_SEPARATOR); + } + + private String serializeAutomaticKeywordGroup(AutomaticKeywordGroup group) { + StringBuilder sb = new StringBuilder(); + sb.append(MetadataSerializationConfiguration.AUTOMATIC_KEYWORD_GROUP_ID); + appendAutomaticGroupDetails(sb, group); + sb.append(StringUtil.quote(group.getField(), MetadataSerializationConfiguration.GROUP_UNIT_SEPARATOR, MetadataSerializationConfiguration.GROUP_QUOTE_CHAR)); + sb.append(MetadataSerializationConfiguration.GROUP_UNIT_SEPARATOR); + sb.append(group.getKeywordSeperator()); + sb.append(MetadataSerializationConfiguration.GROUP_UNIT_SEPARATOR); + appendGroupDetails(sb, group); + return sb.toString(); + } } diff --git a/src/main/java/org/jabref/logic/importer/util/GroupsParser.java b/src/main/java/org/jabref/logic/importer/util/GroupsParser.java index 26cc1613b2a..9182680f92b 100644 --- a/src/main/java/org/jabref/logic/importer/util/GroupsParser.java +++ b/src/main/java/org/jabref/logic/importer/util/GroupsParser.java @@ -8,6 +8,8 @@ import org.jabref.logic.util.MetadataSerializationConfiguration; import org.jabref.logic.util.strings.QuotedStringTokenizer; import org.jabref.model.groups.AbstractGroup; +import org.jabref.model.groups.AutomaticKeywordGroup; +import org.jabref.model.groups.AutomaticPersonsGroup; import org.jabref.model.groups.ExplicitGroup; import org.jabref.model.groups.GroupHierarchyType; import org.jabref.model.groups.GroupTreeNode; @@ -87,7 +89,41 @@ public static AbstractGroup fromString(String s, Character keywordSeparator) if (s.startsWith(MetadataSerializationConfiguration.LEGACY_EXPLICIT_GROUP_ID)) { return GroupsParser.legacyExplicitGroupFromString(s, keywordSeparator); } - return null; // unknown group + if (s.startsWith(MetadataSerializationConfiguration.AUTOMATIC_PERSONS_GROUP_ID)) { + return GroupsParser.automaticPersonsGroupFromString(s, keywordSeparator); + } + if (s.startsWith(MetadataSerializationConfiguration.AUTOMATIC_KEYWORD_GROUP_ID)) { + return GroupsParser.automaticKeywordGroupFromString(s, keywordSeparator); + } + + throw new ParseException("Unknown group: " + s); + } + + private static AbstractGroup automaticPersonsGroupFromString(String string, Character keywordSeparator) { + if (!string.startsWith(MetadataSerializationConfiguration.AUTOMATIC_PERSONS_GROUP_ID)) { + throw new IllegalArgumentException("KeywordGroup cannot be created from \"" + string + "\"."); + } + QuotedStringTokenizer tok = new QuotedStringTokenizer(string.substring(MetadataSerializationConfiguration.AUTOMATIC_PERSONS_GROUP_ID + .length()), MetadataSerializationConfiguration.GROUP_UNIT_SEPARATOR, MetadataSerializationConfiguration.GROUP_QUOTE_CHAR); + + String name = StringUtil.unquote(tok.nextToken(), MetadataSerializationConfiguration.GROUP_QUOTE_CHAR); + GroupHierarchyType context = GroupHierarchyType.getByNumberOrDefault(Integer.parseInt(tok.nextToken())); + String field = StringUtil.unquote(tok.nextToken(), MetadataSerializationConfiguration.GROUP_QUOTE_CHAR); + return new AutomaticPersonsGroup(name, context, field); + } + + private static AbstractGroup automaticKeywordGroupFromString(String string, Character keywordSeparator) { + if (!string.startsWith(MetadataSerializationConfiguration.AUTOMATIC_KEYWORD_GROUP_ID)) { + throw new IllegalArgumentException("KeywordGroup cannot be created from \"" + string + "\"."); + } + QuotedStringTokenizer tok = new QuotedStringTokenizer(string.substring(MetadataSerializationConfiguration.AUTOMATIC_KEYWORD_GROUP_ID + .length()), MetadataSerializationConfiguration.GROUP_UNIT_SEPARATOR, MetadataSerializationConfiguration.GROUP_QUOTE_CHAR); + + String name = StringUtil.unquote(tok.nextToken(), MetadataSerializationConfiguration.GROUP_QUOTE_CHAR); + GroupHierarchyType context = GroupHierarchyType.getByNumberOrDefault(Integer.parseInt(tok.nextToken())); + String field = StringUtil.unquote(tok.nextToken(), MetadataSerializationConfiguration.GROUP_QUOTE_CHAR); + Character separator = tok.nextToken().charAt(0); + return new AutomaticKeywordGroup(name, context, field, separator); } /** diff --git a/src/main/java/org/jabref/logic/util/MetadataSerializationConfiguration.java b/src/main/java/org/jabref/logic/util/MetadataSerializationConfiguration.java index ca44c291c25..ef1e1f43f65 100644 --- a/src/main/java/org/jabref/logic/util/MetadataSerializationConfiguration.java +++ b/src/main/java/org/jabref/logic/util/MetadataSerializationConfiguration.java @@ -5,6 +5,8 @@ import org.jabref.model.groups.RegexKeywordGroup; import org.jabref.model.groups.SearchGroup; import org.jabref.model.groups.WordKeywordGroup; +import org.jabref.model.groups.AutomaticPersonsGroup; +import org.jabref.model.groups.AutomaticKeywordGroup; /** * Specifies how metadata is read and written. @@ -45,4 +47,14 @@ public class MetadataSerializationConfiguration { * Identifier for {@link SearchGroup}. */ public static final String SEARCH_GROUP_ID = "SearchGroup:"; + + /** + * Identifier for {@link AutomaticPersonsGroup}. + */ + public static final String AUTOMATIC_PERSONS_GROUP_ID = "AutomaticPersonsGroup:"; + + /** + * Identifier for {@link AutomaticKeywordGroup}. + */ + public static final String AUTOMATIC_KEYWORD_GROUP_ID = "AutomaticKeywordGroup:"; } diff --git a/src/main/java/org/jabref/model/groups/AutomaticKeywordGroup.java b/src/main/java/org/jabref/model/groups/AutomaticKeywordGroup.java index 48641d24915..ea95b545770 100644 --- a/src/main/java/org/jabref/model/groups/AutomaticKeywordGroup.java +++ b/src/main/java/org/jabref/model/groups/AutomaticKeywordGroup.java @@ -1,5 +1,6 @@ package org.jabref.model.groups; +import java.util.Objects; import java.util.Optional; import java.util.Set; import java.util.stream.Collectors; @@ -32,6 +33,20 @@ public AbstractGroup deepCopy() { return new AutomaticKeywordGroup(this.name, this.context, field, this.keywordSeperator); } + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + AutomaticKeywordGroup that = (AutomaticKeywordGroup) o; + return Objects.equals(keywordSeperator, that.keywordSeperator) && + Objects.equals(field, that.field); + } + + @Override + public int hashCode() { + return Objects.hash(keywordSeperator, field); + } + @Override public Set createSubgroups(BibEntry entry) { Optional keywordList = entry.getLatexFreeField(field) diff --git a/src/main/java/org/jabref/model/groups/AutomaticPersonsGroup.java b/src/main/java/org/jabref/model/groups/AutomaticPersonsGroup.java index 5e4be74b20a..61992508ab9 100644 --- a/src/main/java/org/jabref/model/groups/AutomaticPersonsGroup.java +++ b/src/main/java/org/jabref/model/groups/AutomaticPersonsGroup.java @@ -1,5 +1,6 @@ package org.jabref.model.groups; +import java.util.Objects; import java.util.Optional; import java.util.Set; import java.util.stream.Collectors; @@ -18,6 +19,19 @@ public AutomaticPersonsGroup(String name, GroupHierarchyType context, String fie this.field = field; } + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + AutomaticPersonsGroup that = (AutomaticPersonsGroup) o; + return Objects.equals(field, that.field); + } + + @Override + public int hashCode() { + return Objects.hash(field); + } + @Override public AbstractGroup deepCopy() { return new AutomaticPersonsGroup(this.name, this.context, this.field); diff --git a/src/test/java/org/jabref/logic/exporter/GroupSerializerTest.java b/src/test/java/org/jabref/logic/exporter/GroupSerializerTest.java index b0a7de06fc2..626d7e2b7c0 100644 --- a/src/test/java/org/jabref/logic/exporter/GroupSerializerTest.java +++ b/src/test/java/org/jabref/logic/exporter/GroupSerializerTest.java @@ -7,6 +7,9 @@ import javafx.scene.paint.Color; import org.jabref.model.groups.AllEntriesGroup; +import org.jabref.model.groups.AutomaticGroup; +import org.jabref.model.groups.AutomaticKeywordGroup; +import org.jabref.model.groups.AutomaticPersonsGroup; import org.jabref.model.groups.ExplicitGroup; import org.jabref.model.groups.GroupHierarchyType; import org.jabref.model.groups.GroupTreeNode; @@ -91,6 +94,20 @@ public void serializeSingleSearchGroupWithRegex() { assertEquals(Collections.singletonList("0 SearchGroup:myExplicitGroup;2;author=\"harrer\";1;0;1;;;;"), serialization); } + @Test + public void serializeSingleAutomaticKeywordGroup() { + AutomaticGroup group = new AutomaticKeywordGroup("myAutomaticGroup", GroupHierarchyType.INDEPENDENT, "keywords", ','); + List serialization = groupSerializer.serializeTree(GroupTreeNode.fromGroup(group)); + assertEquals(Collections.singletonList("0 AutomaticKeywordGroup:myAutomaticGroup;0;keywords;,;1;;;;"), serialization); + } + + @Test + public void serializeSingleAutomaticPersonGroup() { + AutomaticPersonsGroup group = new AutomaticPersonsGroup("myAutomaticGroup", GroupHierarchyType.INDEPENDENT, "authors"); + List serialization = groupSerializer.serializeTree(GroupTreeNode.fromGroup(group)); + assertEquals(Collections.singletonList("0 AutomaticPersonsGroup:myAutomaticGroup;0;authors;1;;;;"), serialization); + } + @Test public void getTreeAsStringInSimpleTree() throws Exception { GroupTreeNode root = GroupTreeNodeTest.getRoot(); diff --git a/src/test/java/org/jabref/logic/importer/util/GroupsParserTest.java b/src/test/java/org/jabref/logic/importer/util/GroupsParserTest.java index 274ac7bfb9b..cd61cbf92a9 100644 --- a/src/test/java/org/jabref/logic/importer/util/GroupsParserTest.java +++ b/src/test/java/org/jabref/logic/importer/util/GroupsParserTest.java @@ -1,12 +1,16 @@ package org.jabref.logic.importer.util; import java.util.Arrays; +import java.util.Collections; import java.util.List; import javafx.scene.paint.Color; import org.jabref.logic.importer.ParseException; import org.jabref.model.groups.AbstractGroup; +import org.jabref.model.groups.AutomaticGroup; +import org.jabref.model.groups.AutomaticKeywordGroup; +import org.jabref.model.groups.AutomaticPersonsGroup; import org.jabref.model.groups.ExplicitGroup; import org.jabref.model.groups.GroupHierarchyType; import org.jabref.model.groups.GroupTreeNode; @@ -70,4 +74,23 @@ public void fromStringParsesExplicitGroupWithIconAndDesrcitpion() throws Excepti assertEquals(expected, parsed); } + + @Test + public void fromStringParsesAutomaticKeywordGroup() throws Exception { + AutomaticGroup expected = new AutomaticKeywordGroup("myAutomaticGroup", GroupHierarchyType.INDEPENDENT, "keywords", ','); + AbstractGroup parsed = GroupsParser.fromString("AutomaticKeywordGroup:myAutomaticGroup;0;keywords;,;1;;;;", ','); + assertEquals(expected, parsed); + } + + @Test + public void fromStringParsesAutomaticPersonGroup() throws Exception { + AutomaticPersonsGroup expected = new AutomaticPersonsGroup("myAutomaticGroup", GroupHierarchyType.INDEPENDENT, "authors"); + AbstractGroup parsed = GroupsParser.fromString("AutomaticPersonsGroup:myAutomaticGroup;0;authors;1;;;;", ','); + assertEquals(expected, parsed); + } + + @Test(expected = ParseException.class) + public void fromStringUnknownGroupThrowsException() throws Exception { + GroupsParser.fromString("0 UnknownGroup:myUnknownGroup;0;;1;;;;", ','); + } } diff --git a/src/test/resources/testbib/complex.bib b/src/test/resources/testbib/complex.bib index 4f9cd745ec0..512caeacbde 100644 --- a/src/test/resources/testbib/complex.bib +++ b/src/test/resources/testbib/complex.bib @@ -293,6 +293,7 @@ @Comment{jabref-meta: 0 AllEntriesGroup:; 1 StaticGroup:StaticGroup\;0\;1\;\;\;\;; 1 KeywordGroup:DynamicGroup\;0\;author\;Churchill\;0\;0\;1\;\;\;\;; +1 AutomaticKeywordGroup:Automatic group\;0\;author\;,\;1\;\;\;Automatic group for all authors\;; } @Comment{jabref-meta: keypattern_article:articleTest;} From b042a809f604a25d159beea716efc1425dfe613e Mon Sep 17 00:00:00 2001 From: Tobias Diez Date: Sun, 12 Mar 2017 13:30:35 +0100 Subject: [PATCH 3/7] Add changelog entry --- CHANGELOG.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 14f0e536348..f26558eea07 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -37,6 +37,11 @@ We refer to [GitHub issues](https://github.com/JabRef/jabref/issues) by using `# - We renamed "database" to "library" to have a real distinction to SQL and NoSQL databases. [#2095](https://github.com/JabRef/jabref/issues/2095) - We added MathSciNet as a ID-based fetcher in the `BibTeX -> New entry` dialog (implements a [feature request in the forum](http://discourse.jabref.org/t/allow-to-search-by-mr-number-mathscinet)) - Removed the apache.commons.collections library +- We added a few properties to a group: + - Icon (with customizable color) that is shown in the groups panel (implements a [feature request in the forum](http://discourse.jabref.org/t/assign-colors-to-groups/321)). + - Description text that is shown on mouse hover (implements old feature requests [489](https://sourceforge.net/p/jabref/feature-requests/489/) and [818](https://sourceforge.net/p/jabref/feature-requests/818/) +- We introduced "automatic groups" that automatically create subgroups based on a certain criteria (e.g. a subgroup for every author or keyword). Implements [91](https://sourceforge.net/p/jabref/feature-requests/91/), [398](https://sourceforge.net/p/jabref/feature-requests/398/) and [#1173](https://github.com/JabRef/jabref/issues/1173). +- Expansion status of groups are saved across sessions. [#1428](https://github.com/JabRef/jabref/issues/1428) - We removed the ordinals-to-superscript formatter from the recommendations for biblatex save actions [#2596](https://github.com/JabRef/jabref/issues/2596) - The `Move linked files to default file directory`-Cleanup operation respects the `File directory pattern` setting - We separated the `Move file` and `Rename Pdfs` logic and context menu entries in the `General`-Tab for the Field `file` to improve the semantics From b90480265d640c7c871f1a25515a8382d73af9d7 Mon Sep 17 00:00:00 2001 From: Tobias Diez Date: Sun, 12 Mar 2017 13:42:50 +0100 Subject: [PATCH 4/7] Fix import order --- .../jabref/logic/util/MetadataSerializationConfiguration.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/jabref/logic/util/MetadataSerializationConfiguration.java b/src/main/java/org/jabref/logic/util/MetadataSerializationConfiguration.java index ef1e1f43f65..d00ced1bdbb 100644 --- a/src/main/java/org/jabref/logic/util/MetadataSerializationConfiguration.java +++ b/src/main/java/org/jabref/logic/util/MetadataSerializationConfiguration.java @@ -1,12 +1,12 @@ package org.jabref.logic.util; import org.jabref.model.groups.AllEntriesGroup; +import org.jabref.model.groups.AutomaticKeywordGroup; +import org.jabref.model.groups.AutomaticPersonsGroup; import org.jabref.model.groups.ExplicitGroup; import org.jabref.model.groups.RegexKeywordGroup; import org.jabref.model.groups.SearchGroup; import org.jabref.model.groups.WordKeywordGroup; -import org.jabref.model.groups.AutomaticPersonsGroup; -import org.jabref.model.groups.AutomaticKeywordGroup; /** * Specifies how metadata is read and written. From 8c3558a7d342586bf20d88afdc78ff1f086aadf1 Mon Sep 17 00:00:00 2001 From: Tobias Diez Date: Wed, 15 Mar 2017 00:06:50 +0100 Subject: [PATCH 5/7] Minor code cleanup --- .../java/org/jabref/logic/importer/util/GroupsParser.java | 8 ++++---- .../org/jabref/logic/importer/util/GroupsParserTest.java | 1 - 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/src/main/java/org/jabref/logic/importer/util/GroupsParser.java b/src/main/java/org/jabref/logic/importer/util/GroupsParser.java index 9182680f92b..82b749aa1d2 100644 --- a/src/main/java/org/jabref/logic/importer/util/GroupsParser.java +++ b/src/main/java/org/jabref/logic/importer/util/GroupsParser.java @@ -90,16 +90,16 @@ public static AbstractGroup fromString(String s, Character keywordSeparator) return GroupsParser.legacyExplicitGroupFromString(s, keywordSeparator); } if (s.startsWith(MetadataSerializationConfiguration.AUTOMATIC_PERSONS_GROUP_ID)) { - return GroupsParser.automaticPersonsGroupFromString(s, keywordSeparator); + return GroupsParser.automaticPersonsGroupFromString(s); } if (s.startsWith(MetadataSerializationConfiguration.AUTOMATIC_KEYWORD_GROUP_ID)) { - return GroupsParser.automaticKeywordGroupFromString(s, keywordSeparator); + return GroupsParser.automaticKeywordGroupFromString(s); } throw new ParseException("Unknown group: " + s); } - private static AbstractGroup automaticPersonsGroupFromString(String string, Character keywordSeparator) { + private static AbstractGroup automaticPersonsGroupFromString(String string) { if (!string.startsWith(MetadataSerializationConfiguration.AUTOMATIC_PERSONS_GROUP_ID)) { throw new IllegalArgumentException("KeywordGroup cannot be created from \"" + string + "\"."); } @@ -112,7 +112,7 @@ private static AbstractGroup automaticPersonsGroupFromString(String string, Char return new AutomaticPersonsGroup(name, context, field); } - private static AbstractGroup automaticKeywordGroupFromString(String string, Character keywordSeparator) { + private static AbstractGroup automaticKeywordGroupFromString(String string) { if (!string.startsWith(MetadataSerializationConfiguration.AUTOMATIC_KEYWORD_GROUP_ID)) { throw new IllegalArgumentException("KeywordGroup cannot be created from \"" + string + "\"."); } diff --git a/src/test/java/org/jabref/logic/importer/util/GroupsParserTest.java b/src/test/java/org/jabref/logic/importer/util/GroupsParserTest.java index cd61cbf92a9..fd93d629bd6 100644 --- a/src/test/java/org/jabref/logic/importer/util/GroupsParserTest.java +++ b/src/test/java/org/jabref/logic/importer/util/GroupsParserTest.java @@ -1,7 +1,6 @@ package org.jabref.logic.importer.util; import java.util.Arrays; -import java.util.Collections; import java.util.List; import javafx.scene.paint.Color; From 0a98340e71e3840e55ca078792f1e0e07eed759d Mon Sep 17 00:00:00 2001 From: Tobias Diez Date: Thu, 16 Mar 2017 16:16:53 +0100 Subject: [PATCH 6/7] Fix tests --- .../logic/importer/util/GroupsParser.java | 25 +++++++++++++------ .../util/strings/QuotedStringTokenizer.java | 4 +-- src/test/resources/testbib/complex.bib | 4 +-- 3 files changed, 20 insertions(+), 13 deletions(-) diff --git a/src/main/java/org/jabref/logic/importer/util/GroupsParser.java b/src/main/java/org/jabref/logic/importer/util/GroupsParser.java index 82b749aa1d2..a769f6e7297 100644 --- a/src/main/java/org/jabref/logic/importer/util/GroupsParser.java +++ b/src/main/java/org/jabref/logic/importer/util/GroupsParser.java @@ -109,7 +109,9 @@ private static AbstractGroup automaticPersonsGroupFromString(String string) { String name = StringUtil.unquote(tok.nextToken(), MetadataSerializationConfiguration.GROUP_QUOTE_CHAR); GroupHierarchyType context = GroupHierarchyType.getByNumberOrDefault(Integer.parseInt(tok.nextToken())); String field = StringUtil.unquote(tok.nextToken(), MetadataSerializationConfiguration.GROUP_QUOTE_CHAR); - return new AutomaticPersonsGroup(name, context, field); + AutomaticPersonsGroup newGroup = new AutomaticPersonsGroup(name, context, field); + addGroupDetails(tok, newGroup); + return newGroup; } private static AbstractGroup automaticKeywordGroupFromString(String string) { @@ -123,7 +125,9 @@ private static AbstractGroup automaticKeywordGroupFromString(String string) { GroupHierarchyType context = GroupHierarchyType.getByNumberOrDefault(Integer.parseInt(tok.nextToken())); String field = StringUtil.unquote(tok.nextToken(), MetadataSerializationConfiguration.GROUP_QUOTE_CHAR); Character separator = tok.nextToken().charAt(0); - return new AutomaticKeywordGroup(name, context, field, separator); + AutomaticKeywordGroup newGroup = new AutomaticKeywordGroup(name, context, field, separator); + addGroupDetails(tok, newGroup); + return newGroup; } /** @@ -145,11 +149,14 @@ private static KeywordGroup keywordGroupFromString(String s, Character keywordSe String expression = StringUtil.unquote(tok.nextToken(), MetadataSerializationConfiguration.GROUP_QUOTE_CHAR); boolean caseSensitive = Integer.parseInt(tok.nextToken()) == 1; boolean regExp = Integer.parseInt(tok.nextToken()) == 1; + KeywordGroup newGroup; if (regExp) { - return new RegexKeywordGroup(name, context, field, expression, caseSensitive); + newGroup = new RegexKeywordGroup(name, context, field, expression, caseSensitive); } else { - return new WordKeywordGroup(name, context, field, expression, caseSensitive, keywordSeparator, false); + newGroup = new WordKeywordGroup(name, context, field, expression, caseSensitive, keywordSeparator, false); } + addGroupDetails(tok, newGroup); + return newGroup; } private static ExplicitGroup explicitGroupFromString(String input, Character keywordSeparator) throws ParseException { @@ -234,9 +241,11 @@ private static AbstractGroup searchGroupFromString(String s) { } private static void addGroupDetails(QuotedStringTokenizer tokenizer, AbstractGroup group) { - group.setExpanded(Integer.parseInt(tokenizer.nextToken()) == 1); - group.setColor(tokenizer.nextToken()); - group.setIconCode(tokenizer.nextToken()); - group.setDescription(tokenizer.nextToken()); + if (tokenizer.hasMoreTokens()) { + group.setExpanded(Integer.parseInt(tokenizer.nextToken()) == 1); + group.setColor(tokenizer.nextToken()); + group.setIconCode(tokenizer.nextToken()); + group.setDescription(tokenizer.nextToken()); + } } } diff --git a/src/main/java/org/jabref/logic/util/strings/QuotedStringTokenizer.java b/src/main/java/org/jabref/logic/util/strings/QuotedStringTokenizer.java index 373a84e4129..720d6fe12e2 100644 --- a/src/main/java/org/jabref/logic/util/strings/QuotedStringTokenizer.java +++ b/src/main/java/org/jabref/logic/util/strings/QuotedStringTokenizer.java @@ -47,9 +47,7 @@ public String nextToken() { } } else if (isDelimiter(c)) { // unit finished // advance index until next token or end - do { - ++index; - } while (index < contentLength && isDelimiter(content.charAt(index))); + ++index; return stringBuilder.toString(); } else { stringBuilder.append(c); diff --git a/src/test/resources/testbib/complex.bib b/src/test/resources/testbib/complex.bib index 512caeacbde..e8a50a4b43f 100644 --- a/src/test/resources/testbib/complex.bib +++ b/src/test/resources/testbib/complex.bib @@ -291,9 +291,9 @@ @Comment{jabref-meta: @Comment{jabref-meta: groupstree: 0 AllEntriesGroup:; -1 StaticGroup:StaticGroup\;0\;1\;\;\;\;; +1 StaticGroup:StaticGroup\;0\;1\;\;\;A test static group\;; 1 KeywordGroup:DynamicGroup\;0\;author\;Churchill\;0\;0\;1\;\;\;\;; -1 AutomaticKeywordGroup:Automatic group\;0\;author\;,\;1\;\;\;Automatic group for all authors\;; +1 AutomaticPersonsGroup:Automatic group (Authors)\;0\;author\;1\;\;\;Automatic group for all authors\;; } @Comment{jabref-meta: keypattern_article:articleTest;} From 2995a87a22bfe91639dc1008f42e1c5d34f21097 Mon Sep 17 00:00:00 2001 From: Tobias Diez Date: Thu, 16 Mar 2017 16:39:49 +0100 Subject: [PATCH 7/7] Fix tests part 2 --- .../java/org/jabref/logic/importer/util/GroupsParserTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/java/org/jabref/logic/importer/util/GroupsParserTest.java b/src/test/java/org/jabref/logic/importer/util/GroupsParserTest.java index fd93d629bd6..4e69fb5d223 100644 --- a/src/test/java/org/jabref/logic/importer/util/GroupsParserTest.java +++ b/src/test/java/org/jabref/logic/importer/util/GroupsParserTest.java @@ -38,7 +38,7 @@ public void fromStringThrowsParseExceptionForNotEscapedGroupName() throws Except public void testImportSubGroups() throws ParseException { List orderedData = Arrays.asList("0 AllEntriesGroup:", "1 ExplicitGroup:1;0;", - "2 ExplicitGroup:2;0;;", "0 ExplicitGroup:3;0;;"); + "2 ExplicitGroup:2;0;", "0 ExplicitGroup:3;0;"); //Create group hierarchy: // Level 0 Name: All entries // Level 1 Name: 1