Skip to content

Commit

Permalink
Provided two variants of Flatten filter, -S and -F.
Browse files Browse the repository at this point in the history
  • Loading branch information
psidnell committed Dec 10, 2014
1 parent a312997 commit de3fe2d
Show file tree
Hide file tree
Showing 18 changed files with 346 additions and 70 deletions.
51 changes: 47 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ Export from OmniFocus to various other formats:
- [Output and Formats](#output-and-formats)
- [Sorting](#sorting)
- [Pruning](#pruning)
- [Simplifying](#simplifying)
- [Flattening](#flattening)
- [Inbox and No Context](#inbox-and-no-context)
- [Command Line Options](#command-line-options)
Expand Down Expand Up @@ -471,18 +472,58 @@ Sometimes the output is cluttered with empty Contexts, Folders or Projects that

Using the **-p** option eliminates them.

### Flattening ###
### Simplifying ###

Sometimes what is a useful Folder/Context hierarchy in OmniFocus ends up making reports look cluttered.

The **-F** option flattens nested the hierarchy to just leaf Folder/Projects/Contexts and lifts sub tasks up to the level of their parent.
The **-S** option simplifies the nested the hierarchy to just leaf Folder/Projects/Contexts and lifts sub tasks up to the level of their parent.

All projects and contexts are moved to the root level, and sub tasks moved up to the level of their parent.

For example if you have:

FolderF1
FolderF2
ProjectP
TaskT1
TaskT2
TaskT3

You will get:

ProjectP
TaskT1
TaskT2
TaskT3

This can make sorting more useful. If you have a deeply nested hierarchy, compare the following:

of2 -ti 'remaining && due.soon' -ts r:flagged -ts due
of2 -ti 'remaining && due.soon' -ts r:flagged -ts due -F
of2 -ti 'remaining && due.soon' -ts r:flagged -ts due -S

### Flattening

Flattening with **-F** is an extreme form of simplifying.

For example if you have:

FolderF1
FolderF2
ProjectP
TaskT1
TaskT2
TaskT3
ProjectP2
TaskT4

You will get:

Tasks
TaskT1
TaskT2
TaskT3

The name of the resultant root node can be modified by changing the **flattenedRootName** configuration value.

### Inbox and No Context

Expand Down Expand Up @@ -597,6 +638,8 @@ a large export rather than about a second when accessing the database directly.

## Known Issues ##

- Task/Project notes are stripped back to ASCII on export because wide characters seem corrupted when I retrieve them. This could be down to the encoding OmniFocus uses or it could be an issue with the SQLite Java driver. I experimented with various obvious specific encodings but that didn't help.
- Task/Project notes are stripped back to ASCII on export because wide characters seem corrupted when I retrieve them. This could be down to the encoding OmniFocus uses or it could be an issue with the SQLite Java driver.
- Perspective data is something I haven't managed to decode.
- In OmniFocus, child Contexts/Tasks are interleaved, as are child Projects/Folders. In ofexport they are not.
- There is no way to detect if Projects are **stalled** or **pending**.
- The **modified** and **added** times are missing from the attributes.
1 change: 1 addition & 0 deletions RELEASE-NOTES.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
**[Development Version](https://github.com/psidnell/ofexport2/archive/master.zip)**

- Documentation Improvements
- Provided two variants of Flatten filter, -S and -F.

**[1.0.10 (2014-12-09)](https://github.com/psidnell/ofexport2/archive/ofexport-v2-1.0.10.zip)**

Expand Down
2 changes: 1 addition & 1 deletion bin/ofexport2
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ then
REPO="$BASEDIR"/repo
fi

CLASSPATH="$BASEDIR"/config:"$REPO"/com/fasterxml/jackson/core/jackson-core/2.4.3/jackson-core-2.4.3.jar:"$REPO"/com/fasterxml/jackson/core/jackson-databind/2.4.3/jackson-databind-2.4.3.jar:"$REPO"/com/fasterxml/jackson/core/jackson-annotations/2.4.0/jackson-annotations-2.4.0.jar:"$REPO"/com/fasterxml/jackson/dataformat/jackson-dataformat-xml/2.4.3/jackson-dataformat-xml-2.4.3.jar:"$REPO"/com/fasterxml/jackson/module/jackson-module-jaxb-annotations/2.4.3/jackson-module-jaxb-annotations-2.4.3.jar:"$REPO"/org/codehaus/woodstox/stax2-api/3.1.4/stax2-api-3.1.4.jar:"$REPO"/org/codehaus/woodstox/woodstox-core-asl/4.1.4/woodstox-core-asl-4.1.4.jar:"$REPO"/javax/xml/stream/stax-api/1.0-2/stax-api-1.0-2.jar:"$REPO"/commons-cli/commons-cli/1.2/commons-cli-1.2.jar:"$REPO"/ognl/ognl/3.0.8/ognl-3.0.8.jar:"$REPO"/javassist/javassist/3.11.0.GA/javassist-3.11.0.GA.jar:"$REPO"/org/slf4j/slf4j-api/1.7.7/slf4j-api-1.7.7.jar:"$REPO"/org/slf4j/slf4j-log4j12/1.7.7/slf4j-log4j12-1.7.7.jar:"$REPO"/log4j/log4j/1.2.17/log4j-1.2.17.jar:"$REPO"/commons-io/commons-io/2.4/commons-io-2.4.jar:"$REPO"/org/xerial/sqlite-jdbc/3.8.7/sqlite-jdbc-3.8.7.jar:"$REPO"/org/freemarker/freemarker/2.3.21/freemarker-2.3.21.jar:"$REPO"/org/springframework/spring-context/4.1.2.RELEASE/spring-context-4.1.2.RELEASE.jar:"$REPO"/org/springframework/spring-aop/4.1.2.RELEASE/spring-aop-4.1.2.RELEASE.jar:"$REPO"/aopalliance/aopalliance/1.0/aopalliance-1.0.jar:"$REPO"/org/springframework/spring-core/4.1.2.RELEASE/spring-core-4.1.2.RELEASE.jar:"$REPO"/commons-logging/commons-logging/1.1.3/commons-logging-1.1.3.jar:"$REPO"/org/springframework/spring-expression/4.1.2.RELEASE/spring-expression-4.1.2.RELEASE.jar:"$REPO"/org/springframework/spring-beans/4.1.2.RELEASE/spring-beans-4.1.2.RELEASE.jar:"$REPO"/org/psidnell/ofexport-v2/1.0.10-SNAPSHOT/ofexport-v2-1.0.10-SNAPSHOT.jar
CLASSPATH="$BASEDIR"/config:"$REPO"/com/fasterxml/jackson/core/jackson-core/2.4.3/jackson-core-2.4.3.jar:"$REPO"/com/fasterxml/jackson/core/jackson-databind/2.4.3/jackson-databind-2.4.3.jar:"$REPO"/com/fasterxml/jackson/core/jackson-annotations/2.4.0/jackson-annotations-2.4.0.jar:"$REPO"/com/fasterxml/jackson/dataformat/jackson-dataformat-xml/2.4.3/jackson-dataformat-xml-2.4.3.jar:"$REPO"/com/fasterxml/jackson/module/jackson-module-jaxb-annotations/2.4.3/jackson-module-jaxb-annotations-2.4.3.jar:"$REPO"/org/codehaus/woodstox/stax2-api/3.1.4/stax2-api-3.1.4.jar:"$REPO"/org/codehaus/woodstox/woodstox-core-asl/4.1.4/woodstox-core-asl-4.1.4.jar:"$REPO"/javax/xml/stream/stax-api/1.0-2/stax-api-1.0-2.jar:"$REPO"/commons-cli/commons-cli/1.2/commons-cli-1.2.jar:"$REPO"/ognl/ognl/3.0.8/ognl-3.0.8.jar:"$REPO"/javassist/javassist/3.11.0.GA/javassist-3.11.0.GA.jar:"$REPO"/org/slf4j/slf4j-api/1.7.7/slf4j-api-1.7.7.jar:"$REPO"/org/slf4j/slf4j-log4j12/1.7.7/slf4j-log4j12-1.7.7.jar:"$REPO"/log4j/log4j/1.2.17/log4j-1.2.17.jar:"$REPO"/commons-io/commons-io/2.4/commons-io-2.4.jar:"$REPO"/org/xerial/sqlite-jdbc/3.8.7/sqlite-jdbc-3.8.7.jar:"$REPO"/org/freemarker/freemarker/2.3.21/freemarker-2.3.21.jar:"$REPO"/org/springframework/spring-context/4.1.2.RELEASE/spring-context-4.1.2.RELEASE.jar:"$REPO"/org/springframework/spring-aop/4.1.2.RELEASE/spring-aop-4.1.2.RELEASE.jar:"$REPO"/aopalliance/aopalliance/1.0/aopalliance-1.0.jar:"$REPO"/org/springframework/spring-core/4.1.2.RELEASE/spring-core-4.1.2.RELEASE.jar:"$REPO"/commons-logging/commons-logging/1.1.3/commons-logging-1.1.3.jar:"$REPO"/org/springframework/spring-expression/4.1.2.RELEASE/spring-expression-4.1.2.RELEASE.jar:"$REPO"/org/springframework/spring-beans/4.1.2.RELEASE/spring-beans-4.1.2.RELEASE.jar:"$REPO"/org/psidnell/ofexport-v2/1.0.11-SNAPSHOT/ofexport-v2-1.0.11-SNAPSHOT.jar

ENDORSED_DIR=
if [ -n "$ENDORSED_DIR" ] ; then
Expand Down
3 changes: 3 additions & 0 deletions config/config.properties
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@
# The default value when filtering for dueSoon Tasks/Projects
dueSoon:7d

# Name of the root node when flattening hierarchies
flattenedRootName:Tasks

# --- Template Config:
# Custom properties can be added here and they can be accessed from the
# FreeMarker templates using ${config.propName}
Expand Down
2 changes: 2 additions & 0 deletions config/config.xml
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,9 @@
</bean>

<bean name="configparams" class="org.psidnell.omnifocus.ConfigParams">
<!-- Copy values we need from property file into the bean -->
<property name="dueSoon" value="${dueSoon}"/>
<property name="flattenedRootName" value="${flattenedRootName}"/>
</bean>

<!-- Node Types -->
Expand Down
2 changes: 1 addition & 1 deletion config/version.properties
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
version:1.0.11
date:2014-12-09
date:2014-12-10
5 changes: 3 additions & 2 deletions doc/Options.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
OFEXPORT2

Version: 1.0.11
Build Date: 2014-12-09
Build Date: 2014-12-10

usage: ofexport2
-h print help.
Expand Down Expand Up @@ -34,7 +34,8 @@
-an <arg> include items specified by name.
-m <arg> modify a node value.
-p prune empty folders, projects and contexts.
-F Flatten hierarchies.
-S Flatten hierarchies.
-F Simplify hierarchies.
-c context mode: filter and display context hierarchy instead of project hierarchy.
-f <arg> output in this format.
-o <arg> write output to the file.
Expand Down
Binary file not shown.
23 changes: 20 additions & 3 deletions src/main/java/org/psidnell/omnifocus/CommandLine.java
Original file line number Diff line number Diff line change
Expand Up @@ -26,23 +26,28 @@
import org.psidnell.omnifocus.model.Folder;
import org.psidnell.omnifocus.model.Project;
import org.psidnell.omnifocus.model.Task;
import org.psidnell.omnifocus.visitor.SimplifyFilter;
import org.psidnell.omnifocus.visitor.FlattenFilter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;

/**
* @author psidnell
*
* Command line processing. Contains the options themselves and the values
* the options affect.
*/
public class CommandLine {
public class CommandLine implements BeanFactoryAware {

protected static final String PRINT_HELP = "printHelp";
protected static final String PRINT_INFO = "printInfo";

protected final static Logger LOGGER = LoggerFactory.getLogger(CommandLine.class);

protected BeanFactory beanFactory;

final static Options OPTIONS = new Options();

protected static final int STARTUP = 0;
Expand All @@ -57,6 +62,7 @@ public class CommandLine {
protected OFExport ofexport = null;
protected String format = null;
protected boolean open = false;
private ConfigParams config; // NOPMD it can't see into lambdas

static {

Expand Down Expand Up @@ -209,6 +215,7 @@ public class CommandLine {
"m", true, "modify a node value.",
(m,o)->m.ofexport.addModifyExpression(o.nextValue()),
AFTER_LOAD));

// MODES

OPTIONS.addOption(new ActiveOption<CommandLine>(
Expand All @@ -217,10 +224,14 @@ public class CommandLine {
AFTER_LOAD));

OPTIONS.addOption(new ActiveOption<CommandLine>(
"F", false, "Flatten hierarchies.",
(m,o)->m.ofexport.addFilter (new FlattenFilter()),
"S", false, "Simplify hierarchies.",
(m,o)->m.ofexport.addFilter (new SimplifyFilter()),
AFTER_LOAD));

OPTIONS.addOption(new ActiveOption<CommandLine>(
"F", false, "Flatten hierarchies.",
(m,o)->m.ofexport.addFilter (new FlattenFilter(m.config)),
AFTER_LOAD));

OPTIONS.addOption(new ActiveOption<CommandLine> (
"c", false, "context mode: filter and display context hierarchy instead of project hierarchy.",
Expand Down Expand Up @@ -311,4 +322,10 @@ public void setOfexport(OFExport ofexport) {
public void setProcessor (ActiveOptionProcessor<CommandLine> processor) {
this.processor = processor;
}

@Override
public void setBeanFactory(BeanFactory beanFactory) {
this.beanFactory = beanFactory;
config = beanFactory.getBean("configparams", ConfigParams.class);
}
}
9 changes: 9 additions & 0 deletions src/main/java/org/psidnell/omnifocus/ConfigParams.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
public class ConfigParams {

private String dueSoon;
private String flattenedRootName;

public void setDueSoon(String dueSoon) {
this.dueSoon = dueSoon;
Expand All @@ -32,4 +33,12 @@ public void setDueSoon(String dueSoon) {
public String getDueSoon() {
return dueSoon;
}

public void setFlattenedRootName(String name) {
this.flattenedRootName = name;
}

public String getFlattenedRootName() {
return flattenedRootName;
}
}
17 changes: 4 additions & 13 deletions src/main/java/org/psidnell/omnifocus/Main.java
Original file line number Diff line number Diff line change
Expand Up @@ -32,23 +32,19 @@
import org.psidnell.omnifocus.model.Project;
import org.psidnell.omnifocus.sqlite.SQLiteDAO;
import org.psidnell.omnifocus.util.IOUtils;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.context.ApplicationContext;

/**
* @author psidnell
*
* The main(...) of the program. There had to be one somewhere. Well here it is.
*/
public class Main extends CommandLine implements BeanFactoryAware {
public class Main extends CommandLine {

private DataCache data;

private SQLiteDAO sqliteDAO;

private BeanFactory beanFactory;

private void loadData() throws IllegalAccessException, InvocationTargetException, InstantiationException, SQLException, IOException {
if (jsonInputFile != null) {
data = DataCache.importData(new File(jsonInputFile), beanFactory);
Expand All @@ -63,21 +59,21 @@ private void loadData() throws IllegalAccessException, InvocationTargetException
// Add root projects/folders to the fabricated root folder
for (Folder child : data.getFolders().values()) {
if (child.getProjectModeParent() == null) {
projectRoot.getFolders().add(child);
projectRoot.add(child);
}
}

for (Project child : data.getProjects().values()) {
if (child.getProjectModeParent() == null) {
projectRoot.getProjects().add(child);
projectRoot.add(child);
}
}
} else {
Context contextRoot = ofexport.getContextRoot();
// Add root contexts to the fabricated root context
for (Context child : data.getContexts().values()) {
if (child.getContextModeParent() == null) {
contextRoot.getContexts().add(child);
contextRoot.add(child);
}
}
}
Expand Down Expand Up @@ -159,9 +155,4 @@ public static void main(String[] args) throws Exception {
public void setSqliteDAO(SQLiteDAO sqliteDAO) {
this.sqliteDAO = sqliteDAO;
}

@Override
public void setBeanFactory(BeanFactory beanFactory) {
this.beanFactory = beanFactory;
}
}
2 changes: 0 additions & 2 deletions src/main/java/org/psidnell/omnifocus/OFExport.java
Original file line number Diff line number Diff line change
Expand Up @@ -70,12 +70,10 @@ public class OFExport {
public OFExport() {
projectRoot = new Folder();
projectRoot.setName("RootFolder");
projectRoot.setIsRoot(true);
projectRoot.setId("__%%RootFolder"); // to give deterministic JSON/XML output

contextRoot = new Context();
contextRoot.setName("RootContext");
contextRoot.setIsRoot(true);
contextRoot.setId("__%%RootContext"); // to give deterministic JSON/XML output
}

Expand Down
2 changes: 0 additions & 2 deletions src/main/java/org/psidnell/omnifocus/model/Node.java
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,6 @@ public interface Node {

boolean isRoot();

void setIsRoot(boolean isRoot);

boolean isMarked();

void setMarked(boolean marked);
Expand Down
14 changes: 6 additions & 8 deletions src/main/java/org/psidnell/omnifocus/model/NodeImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,6 @@ public abstract class NodeImpl extends ExpressionFunctions implements Node {

private int rank;

private boolean isRoot;

private boolean marked = false;

@Override
Expand Down Expand Up @@ -88,12 +86,12 @@ public int hashCode() {
@Override
@JsonIgnore
public boolean isRoot() {
return isRoot;
}

@Override
public void setIsRoot(boolean isRoot) {
this.isRoot = isRoot;
if (getType().equals(Folder.TYPE) && ((Folder) this).getProjectModeParent() == null) {
return true;
} else if (getType().equals(Context.TYPE) && ((Context) this).getContextModeParent() == null) {
return true;
}
return false;
}

@Override
Expand Down
Loading

0 comments on commit de3fe2d

Please sign in to comment.