package org.docear.plugin.core.workspace.controller; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.net.URI; import java.util.HashMap; import java.util.Locale; import java.util.Map; import org.apache.commons.io.FileUtils; import org.apache.commons.io.IOExceptionWithCause; import org.docear.plugin.core.io.ReplacingInputStream; import org.docear.plugin.core.workspace.actions.DocearProjectSettings; import org.docear.plugin.core.workspace.creator.FolderTypeLibraryCreator; import org.docear.plugin.core.workspace.creator.FolderTypeLiteratureRepositoryCreator; import org.docear.plugin.core.workspace.creator.FolderTypeLiteratureRepositoryPathCreator; import org.docear.plugin.core.workspace.creator.LinkTypeIncomingCreator; import org.docear.plugin.core.workspace.creator.LinkTypeLiteratureAnnotationsCreator; import org.docear.plugin.core.workspace.creator.LinkTypeMyPublicationsCreator; import org.docear.plugin.core.workspace.creator.LinkTypeReferencesCreator; import org.docear.plugin.core.workspace.model.DocearWorkspaceProject; import org.docear.plugin.core.workspace.node.FolderTypeLibraryNode; import org.docear.plugin.core.workspace.node.FolderTypeLiteratureRepositoryNode; import org.docear.plugin.core.workspace.node.LinkTypeIncomingNode; import org.docear.plugin.core.workspace.node.LinkTypeLiteratureAnnotationsNode; import org.docear.plugin.core.workspace.node.LinkTypeReferencesNode; import org.docear.plugin.core.workspace.node.LiteratureRepositoryPathNode; import org.freeplane.core.util.Compat; import org.freeplane.core.util.LogUtils; import org.freeplane.core.util.TextUtils; import org.freeplane.features.link.LinkController; import org.freeplane.plugin.workspace.URIUtils; import org.freeplane.plugin.workspace.model.AWorkspaceNodeCreator; import org.freeplane.plugin.workspace.model.AWorkspaceTreeNode; import org.freeplane.plugin.workspace.model.IResultProcessor; import org.freeplane.plugin.workspace.model.project.AWorkspaceProject; import org.freeplane.plugin.workspace.model.project.IWorkspaceProjectExtension; import org.freeplane.plugin.workspace.model.project.ProjectLoader; import org.freeplane.plugin.workspace.nodes.FolderLinkNode; import org.freeplane.plugin.workspace.nodes.FolderTypeMyFilesNode; import org.freeplane.plugin.workspace.nodes.LinkTypeFileNode; import org.freeplane.plugin.workspace.nodes.ProjectRootNode; public class DocearProjectLoader extends ProjectLoader { private FolderTypeLibraryCreator folderTypeLibraryCreator; private FolderTypeLiteratureRepositoryCreator folderTypeLiteratureRepositoryCreator; private FolderTypeLiteratureRepositoryPathCreator folderTypeLiteratureRepositoryPathCreator; private LinkTypeIncomingCreator linkTypeIncomingCreator; private LinkTypeLiteratureAnnotationsCreator linkTypeLiteratureAnnotationsCreator; private LinkTypeMyPublicationsCreator linkTypeMyPublicationsCreator; private LinkTypeReferencesCreator linkTypeReferencesCreator; private IResultProcessor resultProcessor; /*********************************************************************************** * CONSTRUCTORS **********************************************************************************/ public DocearProjectLoader() { super(); initDocearReadManager(); } /*********************************************************************************** * METHODS **********************************************************************************/ private void initDocearReadManager() { registerTypeCreator(ProjectLoader.WSNODE_FOLDER, FolderTypeLibraryCreator.FOLDER_TYPE_LIBRARY, getFolderTypeLibraryCreator()); registerTypeCreator(ProjectLoader.WSNODE_FOLDER, FolderTypeLiteratureRepositoryCreator.FOLDER_TYPE_LITERATUREREPOSITORY, getFolderTypeLiteratureRepositoryCreator()); registerTypeCreator(ProjectLoader.WSNODE_FOLDER, FolderTypeLiteratureRepositoryPathCreator.REPOSITORY_PATH_TYPE, getFolderTypeLiteratureRepositoryPathCreator()); registerTypeCreator(ProjectLoader.WSNODE_LINK, LinkTypeIncomingCreator.LINK_TYPE_INCOMING, getLinkTypeIncomingCreator()); registerTypeCreator(ProjectLoader.WSNODE_LINK, LinkTypeLiteratureAnnotationsCreator.LINK_TYPE_LITERATUREANNOTATIONS, getLinkTypeLiteratureAnnotationsCreator()); registerTypeCreator(ProjectLoader.WSNODE_LINK, LinkTypeMyPublicationsCreator.LINK_TYPE_MYPUBLICATIONS, getLinkTypeMyPublicationsCreator()); registerTypeCreator(ProjectLoader.WSNODE_LINK, LinkTypeReferencesCreator.LINK_TYPE_REFERENCES, getLinkTypeReferencesCreator()); } private AWorkspaceNodeCreator getFolderTypeLiteratureRepositoryPathCreator() { if (folderTypeLiteratureRepositoryPathCreator == null) { folderTypeLiteratureRepositoryPathCreator = new FolderTypeLiteratureRepositoryPathCreator(); } return folderTypeLiteratureRepositoryPathCreator; } private FolderTypeLibraryCreator getFolderTypeLibraryCreator() { if (folderTypeLibraryCreator == null) { folderTypeLibraryCreator = new FolderTypeLibraryCreator(); } return folderTypeLibraryCreator; } private FolderTypeLiteratureRepositoryCreator getFolderTypeLiteratureRepositoryCreator() { if (folderTypeLiteratureRepositoryCreator == null) { folderTypeLiteratureRepositoryCreator = new FolderTypeLiteratureRepositoryCreator(); } return folderTypeLiteratureRepositoryCreator; } private LinkTypeIncomingCreator getLinkTypeIncomingCreator() { if (linkTypeIncomingCreator == null) { linkTypeIncomingCreator = new LinkTypeIncomingCreator(); } return linkTypeIncomingCreator; } private LinkTypeLiteratureAnnotationsCreator getLinkTypeLiteratureAnnotationsCreator() { if (linkTypeLiteratureAnnotationsCreator == null) { linkTypeLiteratureAnnotationsCreator = new LinkTypeLiteratureAnnotationsCreator(); } return linkTypeLiteratureAnnotationsCreator; } private LinkTypeMyPublicationsCreator getLinkTypeMyPublicationsCreator() { if (linkTypeMyPublicationsCreator == null) { linkTypeMyPublicationsCreator = new LinkTypeMyPublicationsCreator(); } return linkTypeMyPublicationsCreator; } private LinkTypeReferencesCreator getLinkTypeReferencesCreator() { if (linkTypeReferencesCreator == null) { linkTypeReferencesCreator = new LinkTypeReferencesCreator(); } return linkTypeReferencesCreator; } public synchronized LOAD_RETURN_TYPE loadProject(AWorkspaceProject project) throws IOException { long time = System.currentTimeMillis(); try { File projectSettings = new File(URIUtils.getAbsoluteFile(project.getProjectDataPath()),"settings.xml"); if(projectSettings.exists()) { getDefaultResultProcessor().setProject(project); load(projectSettings.toURI()); project.setLoaded(); return LOAD_RETURN_TYPE.EXISTING_PROJECT; } else { createDefaultProject((DocearWorkspaceProject)project); ((ProjectRootNode)project.getModel().getRoot()).setVersion(DocearWorkspaceProject.CURRENT_PROJECT_VERSION.getVersionString()); project.setLoaded(); return LOAD_RETURN_TYPE.NEW_PROJECT; } } catch (Exception e) { throw new IOExceptionWithCause(e); } finally { LogUtils.info("project "+project.getProjectName()+" loaded in: "+(System.currentTimeMillis()-time)); } } public IResultProcessor getDefaultResultProcessor() { if(this.resultProcessor == null) { this.resultProcessor = new DocearResultProcessor(); } return this.resultProcessor; } private void createDefaultProject(DocearWorkspaceProject project) { File home = URIUtils.getFile(project.getProjectHome()); if(!home.exists()) { home.mkdirs(); } DocearProjectSettings settings = (DocearProjectSettings) project.getExtensions(DocearProjectSettings.class); ProjectRootNode root = new ProjectRootNode(); root.setProjectID(project.getProjectID()); root.setModel(project.getModel()); root.setName(home.getName()); project.getModel().setRoot(root); File _dataInfoFile = new File(URIUtils.getFile(project.getProjectDataPath()).getParentFile(), "!!!info.txt"); if(!_dataInfoFile.exists()) { createAndCopy(_dataInfoFile, "/conf/!!!info.txt"); } // create and load all default nodes FolderTypeLibraryNode libNode = new FolderTypeLibraryNode(); libNode.setName(TextUtils.getText(libNode.getClass().getName().toLowerCase(Locale.ENGLISH)+".label" )); project.getModel().addNodeTo(libNode, root); FolderLinkNode draftsNode = new FolderLinkNode(); File draftsFile = new File(URIUtils.getAbsoluteFile(project.getProjectLibraryPath()).getParentFile(), "My Drafts"); draftsFile.mkdirs(); URI draftsPath = project.getRelativeURI(draftsFile.toURI()); draftsNode.setPath(draftsPath); draftsNode.setName(TextUtils.getText(draftsNode.getClass().getName().toLowerCase(Locale.ENGLISH)+".drafts.label" )); project.getModel().addNodeTo(draftsNode, root); URI libPath = project.getRelativeURI(project.getProjectLibraryPath()); // LinkTypeIncomingNode incomNode = new LinkTypeIncomingNode(); // incomNode.setLinkPath(URIUtils.createURI(libPath.toString()+"/incoming.mm")); // incomNode.setName(TextUtils.getText(incomNode.getClass().getName().toLowerCase(Locale.ENGLISH)+".label" )); // project.getModel().addNodeTo(incomNode, libNode); LinkTypeLiteratureAnnotationsNode litNode = new LinkTypeLiteratureAnnotationsNode(); litNode.setLinkPath(URIUtils.createURI(libPath.toString()+"/literature_and_annotations.mm")); litNode.setName(TextUtils.getRawText(litNode.getClass().getName().toLowerCase(Locale.ENGLISH)+".label" )); project.getModel().addNodeTo(litNode, libNode); // LinkTypeMyPublicationsNode pubNode = new LinkTypeMyPublicationsNode(); // pubNode.setLinkPath(URIUtils.createURI(libPath.toString()+"/my_publications.mm")); // pubNode.setName(TextUtils.getText(pubNode.getClass().getName().toLowerCase(Locale.ENGLISH)+".label" )); // project.getModel().addNodeTo(pubNode, libNode); // if(settings != null && settings.includeDemoFiles()) { // LinkTypeFileNode newPaperNode = new LinkTypeFileNode(); // newPaperNode.setLinkURI(URIUtils.createURI(libPath.toString()+"/My%20New%20Paper.mm")); // newPaperNode.setName(TextUtils.getText(newPaperNode.getClass().getName().toLowerCase(Locale.ENGLISH)+".newpaper.label" )); // project.getModel().addNodeTo(newPaperNode, libNode); // } LinkTypeFileNode tempNode = new LinkTypeFileNode(); tempNode.setLinkURI(URIUtils.createURI(libPath.toString()+"/temp.mm")); tempNode.setName(TextUtils.getText(tempNode.getClass().getName().toLowerCase(Locale.ENGLISH)+".temp.label" )); tempNode.setSystem(true); project.getModel().addNodeTo(tempNode, libNode); LinkTypeFileNode trashNode = new LinkTypeFileNode(); trashNode.setLinkURI(URIUtils.createURI(libPath.toString()+"/trash.mm")); trashNode.setName(TextUtils.getText(trashNode.getClass().getName().toLowerCase(Locale.ENGLISH)+".trash.label" )); trashNode.setSystem(true); project.getModel().addNodeTo(trashNode, libNode); // expand library node by default //WorkspaceController.getCurrentModeExtension().getView().expandPath(libNode.getTreePath()); FolderTypeLiteratureRepositoryNode litRepoNode = new FolderTypeLiteratureRepositoryNode(); litRepoNode.setSystem(true); project.getModel().addNodeTo(litRepoNode, root); if(settings != null) { if(settings.useDefaultRepositoryPath()) { LiteratureRepositoryPathNode defaultPathNode = new LiteratureRepositoryPathNode(); defaultPathNode.setPath(URIUtils.createURI(project.getProjectHome().toString()+"/literature_repository")); defaultPathNode.setName(TextUtils.getText(defaultPathNode.getClass().getName().toLowerCase(Locale.ENGLISH)+".default.label" )); defaultPathNode.setSystem(true); project.getModel().addNodeTo(defaultPathNode, litRepoNode); } for (URI uri : settings.getRepositoryPathURIs()) { LiteratureRepositoryPathNode pathNode = new LiteratureRepositoryPathNode(); File file = URIUtils.getFile(uri); pathNode.setPath(project.getRelativeURI(uri)); pathNode.setName(file.getName()); pathNode.setSystem(true); project.getModel().addNodeTo(pathNode, litRepoNode); } } project.addExtension(FolderTypeLiteratureRepositoryNode.class, litRepoNode); LinkTypeReferencesNode defaultRef = new LinkTypeReferencesNode(); //use default bib file if(settings != null && settings.getBibTeXLibraryPath() != null) { File file = URIUtils.getFile(settings.getBibTeXLibraryPath()); defaultRef.setName(file.getName()); defaultRef.setLinkURI(project.getRelativeURI(settings.getBibTeXLibraryPath())); } else { defaultRef.setName(TextUtils.getText(FolderTypeMyFilesNode.class.getPackage().getName().toLowerCase(Locale.ENGLISH)+".refnode.name")); String bibName = "default"; if(settings != null && settings.getProjectName() != null) { bibName = settings.getProjectName(); } defaultRef.setLinkURI(URIUtils.createURI(libPath.toString()+"/"+bibName+".bib")); } defaultRef.setSystem(true); if(settings != null && settings.includeDemoFiles()) { LogUtils.info("copy docear tutorial files"); copyDemoFiles(project, URIUtils.getAbsoluteFile(defaultRef.getLinkURI()), (settings.getBibTeXLibraryPath() == null)); } project.getModel().addNodeTo(defaultRef, root); root.initiateMyFile(project); //misc -> help.mm root.refresh(); } private void copyDemoFiles(DocearWorkspaceProject project, File bibPath, boolean setBib) { //prepare paths File defaultFilesPath = URIUtils.getFile(project.getProjectLibraryPath()); defaultFilesPath.mkdirs(); File repoPath = new File(URIUtils.getFile(project.getProjectHome()), "literature_repository/Example PDFs"); repoPath.mkdirs(); URI relativeRepoPath = project.getRelativeURI(repoPath.toURI()); //prepare replace map Map<String, String> replaceMapping = new HashMap<String, String>(); replaceMapping.put("@PROJECT_ID@", project.getProjectID()); replaceMapping.put("@PROJECT_HOME@", project.getProjectHome().toString()); replaceMapping.put("@LITERATURE_REPO_DEMO@", cutLastSlash(relativeRepoPath.toString())); URI relativeBibURI = LinkController.toLinkTypeDependantURI(bibPath, repoPath, LinkController.LINK_RELATIVE_TO_MINDMAP); if(Compat.isWindowsOS() && relativeBibURI.getPath().startsWith("//")) { replaceMapping.put("@LITERATURE_BIB_DEMO@", (new File(relativeBibURI).getPath().replace(File.separator, File.separator+File.separator)/*+File.separator+File.separator+"Example PDFs"*/)); } else { replaceMapping.put("@LITERATURE_BIB_DEMO@", cutLastSlash(relativeBibURI.getPath().replace(":", "\\:")/*+"/Example PDFs"*/)); } boolean created = /*createAndCopy(new File(defaultFilesPath,"incoming.mm"), "/demo/template_incoming.mm", replaceMapping);//*/ createAndCopy(new File(defaultFilesPath,"literature_and_annotations.mm"), "/demo/template_litandan.mm", replaceMapping); //createAndCopy(new File(defaultFilesPath,"my_publications.mm"), "/demo/template_mypubs.mm", replaceMapping); createAndCopy(new File(defaultFilesPath,"temp.mm"), "/demo/template_temp.mm", created, replaceMapping); createAndCopy(new File(defaultFilesPath,"trash.mm"), "/demo/template_trash.mm", created, replaceMapping); if(setBib) { createAndCopy(bibPath, "/demo/docear_example.bib", true, replaceMapping); } File draftsFile = new File(URIUtils.getAbsoluteFile(project.getProjectLibraryPath()).getParentFile(), "My Drafts"); createAndCopy(new File(draftsFile, "My New Paper.mm"), "/demo/docear_example_project/My New Paper.mm", replaceMapping); createAndCopy(new File(repoPath, "Academic Search Engine Optimization (ASEO) -- Optimizing Scholarly Literature for Google Scholar and Co.pdf"), "/demo/docear_example_pdfs/Academic Search Engine Optimization (ASEO) -- Optimizing Scholarly Literature for Google Scholar and Co.pdf"); createAndCopy(new File(repoPath, "Academic search engine spam and Google Scholars resilience against it.pdf"), "/demo/docear_example_pdfs/Academic search engine spam and Google Scholars resilience against it.pdf"); createAndCopy(new File(repoPath, "An Exploratory Analysis of Mind Maps.pdf"), "/demo/docear_example_pdfs/An Exploratory Analysis of Mind Maps.pdf"); createAndCopy(new File(repoPath, "Docear -- An Academic Literature Suite.pdf"), "/demo/docear_example_pdfs/Docear -- An Academic Literature Suite.pdf"); createAndCopy(new File(repoPath, "Google Scholar's Ranking Algorithm -- An Introductory Overview.pdf"), "/demo/docear_example_pdfs/Google Scholar's Ranking Algorithm -- An Introductory Overview.pdf"); createAndCopy(new File(repoPath, "Google Scholar's Ranking Algorithm -- The Impact of Citation Counts.pdf"), "/demo/docear_example_pdfs/Google Scholar's Ranking Algorithm -- The Impact of Citation Counts.pdf"); createAndCopy(new File(repoPath, "Information Retrieval on Mind Maps -- What could it be good for.pdf"), "/demo/docear_example_pdfs/Information Retrieval on Mind Maps -- What could it be good for.pdf"); createAndCopy(new File(repoPath, "Mr. DLib -- A Machine Readable Digital Library.pdf"), "/demo/docear_example_pdfs/Mr. DLib -- A Machine Readable Digital Library.pdf"); } private String cutLastSlash(String path) { while(path.endsWith("/")) { path = path.substring(0, path.length()-1); } return path; } private boolean createAndCopy(File file, String resourcePath) { return createAndCopy(file, resourcePath, false, null); } private boolean createAndCopy(File file, String resourcePath,final Map<String, String> replaceMap) { return createAndCopy(file, resourcePath, false, replaceMap); } private boolean createAndCopy(File file, String resourcePath, boolean force,final Map<String, String> replaceMap) { try { if(!file.exists() || force) { createFile(file); InputStream is = this.getClass().getResourceAsStream(resourcePath); if(replaceMap == null) { FileUtils.copyInputStreamToFile(is, file); } else { FileUtils.copyInputStreamToFile(new ReplacingInputStream(replaceMap, is), file); } return true; } } catch (Exception e) { LogUtils.warn(e); } return false; } /** * @param file * @throws IOException */ private void createFile(File file) throws IOException { if(!file.getParentFile().exists() && !file.getParentFile().mkdirs()) { return; } file.createNewFile(); } /*********************************************************************************** * NESTED CLASSES **********************************************************************************/ private class DocearResultProcessor implements IResultProcessor { private AWorkspaceProject project; public AWorkspaceProject getProject() { return project; } public void setProject(AWorkspaceProject project) { this.project = project; } public void process(final AWorkspaceTreeNode parent, final AWorkspaceTreeNode node) { _process(parent, node); } private void _process(AWorkspaceTreeNode parent, AWorkspaceTreeNode node) { if(getProject() == null) { LogUtils.warn("Missing project container! cannot add node to a model."); return; } if(node instanceof ProjectRootNode) { getProject().getModel().setRoot(node); if(((ProjectRootNode) node).getProjectID() == null) { ((ProjectRootNode) node).setProjectID(getProject().getProjectID()); if(!DocearWorkspaceProject.CURRENT_PROJECT_VERSION.equals(getProject().getVersion())) { ((ProjectRootNode) node).initiateMyFile(getProject()); } } } else { if(parent == null) { if (!getProject().getModel().containsNode(node.getKey())) { getProject().getModel().addNodeTo(node, parent); } } else { if (!parent.getModel().containsNode(node.getKey())) { parent.getModel().addNodeTo(node, parent); } } //add myFiles after a certain node type if(node instanceof LinkTypeReferencesNode) { if(DocearWorkspaceProject.CURRENT_PROJECT_VERSION.equals(getProject().getVersion())) { ((ProjectRootNode) parent.getModel().getRoot()).initiateMyFile(getProject()); } } else if(node instanceof FolderTypeLiteratureRepositoryNode) { project.addExtension(FolderTypeLiteratureRepositoryNode.class, (IWorkspaceProjectExtension) node); } else if(node instanceof LinkTypeIncomingNode) { //WorkspaceController.getCurrentModeExtension().getView().expandPath(node.getParent().getTreePath()); } } } } }