Read annotations content
This commit is contained in:
parent
da9eb999c1
commit
167555ebbe
5 changed files with 178 additions and 120 deletions
|
@ -27,10 +27,12 @@ import com.sun.star.lang.WrappedTargetException;
|
||||||
import com.sun.star.lang.XComponent;
|
import com.sun.star.lang.XComponent;
|
||||||
import com.sun.star.lang.XMultiComponentFactory;
|
import com.sun.star.lang.XMultiComponentFactory;
|
||||||
import com.sun.star.lang.XServiceInfo;
|
import com.sun.star.lang.XServiceInfo;
|
||||||
|
import com.sun.star.table.XCell;
|
||||||
import com.sun.star.text.XText;
|
import com.sun.star.text.XText;
|
||||||
import com.sun.star.text.XTextContent;
|
import com.sun.star.text.XTextContent;
|
||||||
import com.sun.star.text.XTextDocument;
|
import com.sun.star.text.XTextDocument;
|
||||||
import com.sun.star.text.XTextRange;
|
import com.sun.star.text.XTextRange;
|
||||||
|
import com.sun.star.text.XTextTable;
|
||||||
import com.sun.star.uno.UnoRuntime;
|
import com.sun.star.uno.UnoRuntime;
|
||||||
import com.sun.star.uno.XComponentContext;
|
import com.sun.star.uno.XComponentContext;
|
||||||
|
|
||||||
|
@ -42,6 +44,7 @@ public class Document {
|
||||||
private static final String DOC_DESCRIPTION = "Document description";
|
private static final String DOC_DESCRIPTION = "Document description";
|
||||||
private static final String DOC_KEYWORDS = "Document keywords";
|
private static final String DOC_KEYWORDS = "Document keywords";
|
||||||
private static final short REMOVEABLE_ATTRIBUTE = 128;
|
private static final short REMOVEABLE_ATTRIBUTE = 128;
|
||||||
|
private static final Object METADATA_EXTENSION = "Metadata Extension";
|
||||||
|
|
||||||
private XComponentContext context;
|
private XComponentContext context;
|
||||||
private XDesktop xDesktop;
|
private XDesktop xDesktop;
|
||||||
|
@ -75,33 +78,25 @@ public class Document {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateChapterMetadata() {
|
private void updateChapterMetadata() {
|
||||||
findAllChapters();
|
readMetadataInDocument();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void findAllChapters() {
|
private void readMetadataInDocument() {
|
||||||
XEnumerationAccess enumAccess = UnoRuntime.queryInterface(XEnumerationAccess.class, text);
|
readMetadataInText(this.text);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void readMetadataInText(XText curText) {
|
||||||
|
XEnumerationAccess enumAccess = UnoRuntime.queryInterface(XEnumerationAccess.class, curText);
|
||||||
XEnumeration textEnum = enumAccess.createEnumeration();
|
XEnumeration textEnum = enumAccess.createEnumeration();
|
||||||
while (textEnum.hasMoreElements()) {
|
while (textEnum.hasMoreElements()) {
|
||||||
try {
|
try {
|
||||||
XTextContent textContent = UnoRuntime.queryInterface(XTextContent.class, textEnum.nextElement());
|
XTextContent textContent = UnoRuntime.queryInterface(XTextContent.class, textEnum.nextElement());
|
||||||
if(isSupported(textContent, "com.sun.star.text.TextTable")) {
|
if(isSupported(textContent, "com.sun.star.text.TextTable")) {
|
||||||
//TODO: Go over table to check for outline elements
|
readMetadataInTable(textContent);
|
||||||
} else
|
} else
|
||||||
if (isSupported(textContent, "com.sun.star.style.ParagraphProperties")) {
|
if (isSupported(textContent, "com.sun.star.style.ParagraphProperties")) {
|
||||||
Short outlineLevel = null;
|
readMetadataInParagraph(textContent);
|
||||||
XPropertySet properties = UnoRuntime.queryInterface(XPropertySet.class, textContent);
|
|
||||||
try {
|
|
||||||
outlineLevel = (Short) properties.getPropertyValue("OutlineLevel");
|
|
||||||
} catch (UnknownPropertyException e) {
|
|
||||||
System.out.println("Shouldn't be here!");
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
if (outlineLevel != null && outlineLevel > 0) {
|
|
||||||
XTextRange textRange = textContent.getAnchor();
|
|
||||||
String name = textRange.getString();
|
|
||||||
System.out.println("Outline element found! " + name);
|
|
||||||
outline.add(new OutlineElement(textRange));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} catch (NoSuchElementException e) {
|
} catch (NoSuchElementException e) {
|
||||||
// TODO Auto-generated catch block
|
// TODO Auto-generated catch block
|
||||||
|
@ -113,6 +108,64 @@ public class Document {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void readMetadataInTable(XTextContent textContent) {
|
||||||
|
XTextTable table = UnoRuntime.queryInterface(XTextTable.class, textContent);
|
||||||
|
String[] cellNames = table.getCellNames();
|
||||||
|
for (String cellName : cellNames) {
|
||||||
|
XCell cell = table.getCellByName(cellName);
|
||||||
|
XText cellText = UnoRuntime.queryInterface(XText.class, cell);
|
||||||
|
cellText.getText();
|
||||||
|
readMetadataInText(cellText);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void readMetadataInParagraph(XTextContent textContent) throws WrappedTargetException {
|
||||||
|
checkOutlineLevel(textContent);
|
||||||
|
XEnumerationAccess enumAccess = UnoRuntime.queryInterface(XEnumerationAccess.class, textContent);
|
||||||
|
XEnumeration paraEnum = enumAccess.createEnumeration();
|
||||||
|
while (paraEnum.hasMoreElements()) {
|
||||||
|
String portionType = null;
|
||||||
|
try {
|
||||||
|
XPropertySet portionPoperties = UnoRuntime.queryInterface(com.sun.star.beans.XPropertySet.class, paraEnum.nextElement());
|
||||||
|
portionType = (String) portionPoperties.getPropertyValue("TextPortionType");
|
||||||
|
if (portionType != null && portionType.equals("Annotation")) {
|
||||||
|
Object annotation = portionPoperties.getPropertyValue("TextField");
|
||||||
|
XPropertySet annotationProperties = UnoRuntime.queryInterface(XPropertySet.class, annotation);
|
||||||
|
String author = (String) annotationProperties.getPropertyValue("Author");
|
||||||
|
if (author != null && author.equals(METADATA_EXTENSION)) {
|
||||||
|
String content = (String) annotationProperties.getPropertyValue("Content");
|
||||||
|
System.out.println("Content " + content);
|
||||||
|
OutlineElement lastElement = outline.get(outline.size()-1);
|
||||||
|
lastElement.readMetadata(content);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (NoSuchElementException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
} catch (WrappedTargetException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
} catch (UnknownPropertyException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private void checkOutlineLevel(XTextContent textContent) throws WrappedTargetException {
|
||||||
|
Short outlineLevel = null;
|
||||||
|
XPropertySet properties = UnoRuntime.queryInterface(XPropertySet.class, textContent);
|
||||||
|
try {
|
||||||
|
outlineLevel = (Short) properties.getPropertyValue("OutlineLevel");
|
||||||
|
} catch (UnknownPropertyException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
if (outlineLevel != null && outlineLevel > 0) {
|
||||||
|
XTextRange textRange = textContent.getAnchor();
|
||||||
|
outline.add(new OutlineElement(textRange));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void getCurrentDocument() throws MetadataInaccessableException {
|
private void getCurrentDocument() throws MetadataInaccessableException {
|
||||||
currentDocument = xDesktop.getCurrentComponent();
|
currentDocument = xDesktop.getCurrentComponent();
|
||||||
if (currentDocument == null) {
|
if (currentDocument == null) {
|
||||||
|
|
|
@ -2,10 +2,8 @@ package pro.litvinovg.libreoffice.metadata;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
|
|
||||||
public class MetadataElement implements Serializable{
|
public class MetadataElement {
|
||||||
|
|
||||||
|
|
||||||
private static final long serialVersionUID = 1L;
|
|
||||||
private String name;
|
private String name;
|
||||||
private String value;
|
private String value;
|
||||||
|
|
||||||
|
|
|
@ -1,43 +1,42 @@
|
||||||
package pro.litvinovg.libreoffice.metadata;
|
package pro.litvinovg.libreoffice.metadata;
|
||||||
|
|
||||||
import java.io.ByteArrayInputStream;
|
import java.util.Iterator;
|
||||||
import java.io.ByteArrayOutputStream;
|
import org.json.JSONException;
|
||||||
import java.io.IOException;
|
import org.json.JSONObject;
|
||||||
import java.io.ObjectInputStream;
|
|
||||||
import java.io.ObjectOutputStream;
|
|
||||||
import java.util.Base64;
|
|
||||||
|
|
||||||
public class MetadataElementFactory {
|
public class MetadataElementFactory {
|
||||||
public static final String METADATA_START = "## Metadata Editor extension. Outline metadata folllows: ";
|
public static final String METADATA_START = "## Metadata Editor extension. Outline metadata in JSON folllows:";
|
||||||
public static String METADATA_PREFIX = "##";
|
public static final String METADATA_PREFIX = "## ";
|
||||||
public static String METADATA_END = "## Metadata Editor extension. Outline metadata ends.";
|
public static final String METADATA_END = "## Outline metadata finished.";
|
||||||
|
|
||||||
|
|
||||||
public static boolean isValidMetadataString(String cursorContent) {
|
public static MetadataElement fromString(String cursorContent){
|
||||||
if (!cursorContent.startsWith(METADATA_PREFIX) ||
|
String data = cursorContent.substring(METADATA_PREFIX.length());
|
||||||
cursorContent.equals(METADATA_START) ||
|
System.out.println("DATA " + data);
|
||||||
cursorContent.equals(METADATA_END)){
|
//TODO: Switch to Jackson or GSON
|
||||||
|
JSONObject json = new JSONObject(data);
|
||||||
|
Iterator<String> iterator = json.keys();
|
||||||
|
String name = iterator.next();
|
||||||
|
String value = json.getString(name);
|
||||||
|
return new MetadataElement(name, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String toString(MetadataElement element) {
|
||||||
|
|
||||||
|
JSONObject json = new JSONObject();
|
||||||
|
json.put(element.getName(), element.getValue());
|
||||||
|
return METADATA_PREFIX + json.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isJSONValid(String test) {
|
||||||
|
try {
|
||||||
|
new JSONObject(test);
|
||||||
|
} catch (JSONException e) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
String data = cursorContent.substring(cursorContent.lastIndexOf(METADATA_PREFIX));
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public static MetadataElement fromString(String string) throws IOException, ClassNotFoundException {
|
|
||||||
byte [] data = Base64.getDecoder().decode( string );
|
|
||||||
ObjectInputStream ois = new ObjectInputStream( new ByteArrayInputStream( data ) );
|
|
||||||
Object object = ois.readObject();
|
|
||||||
ois.close();
|
|
||||||
return (MetadataElement) object;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static String toString( MetadataElement object ) throws IOException {
|
|
||||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
|
||||||
ObjectOutputStream oos = new ObjectOutputStream( baos );
|
|
||||||
oos.writeObject( object );
|
|
||||||
oos.close();
|
|
||||||
return Base64.getEncoder().encodeToString(baos.toByteArray());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,19 +1,18 @@
|
||||||
package pro.litvinovg.libreoffice.metadata;
|
package pro.litvinovg.libreoffice.metadata;
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Iterator;
|
||||||
|
|
||||||
|
import org.json.JSONException;
|
||||||
|
import org.json.JSONObject;
|
||||||
|
|
||||||
|
|
||||||
import com.sun.star.text.XParagraphCursor;
|
|
||||||
import com.sun.star.text.XText;
|
|
||||||
import com.sun.star.text.XTextCursor;
|
|
||||||
import com.sun.star.text.XTextRange;
|
import com.sun.star.text.XTextRange;
|
||||||
import com.sun.star.uno.UnoRuntime;
|
|
||||||
import static pro.litvinovg.libreoffice.metadata.MetadataElementFactory.*;
|
|
||||||
|
|
||||||
public class OutlineElement {
|
public class OutlineElement {
|
||||||
|
|
||||||
private String name;
|
private String name;
|
||||||
private ArrayList<MetadataElement> metadataElements = null;
|
private ArrayList<MetadataElement> metadata = null;
|
||||||
|
|
||||||
public String getName() {
|
public String getName() {
|
||||||
return name;
|
return name;
|
||||||
|
@ -26,65 +25,33 @@ public class OutlineElement {
|
||||||
public OutlineElement(XTextRange textRange) {
|
public OutlineElement(XTextRange textRange) {
|
||||||
this.textRange = textRange;
|
this.textRange = textRange;
|
||||||
this.name = textRange.getString();
|
this.name = textRange.getString();
|
||||||
getMetadataStorage();
|
this.metadata = new ArrayList<MetadataElement>();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void getMetadataStorage() {
|
public void readMetadata(String data) {
|
||||||
XText curText = textRange.getText();
|
|
||||||
XTextCursor cursor = curText.createTextCursorByRange(textRange);
|
|
||||||
XParagraphCursor paraCursor = UnoRuntime.queryInterface(XParagraphCursor.class, cursor);
|
|
||||||
readMetadataBody(paraCursor);
|
|
||||||
if (metadataElements == null) {
|
|
||||||
metadataElements = new ArrayList<MetadataElement>();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void readMetadataBody(XParagraphCursor paraCursor) {
|
|
||||||
String cursorContent = getNextParaContent(paraCursor);
|
|
||||||
|
|
||||||
if (! cursorContent.equals(METADATA_START)){
|
|
||||||
System.out.println("Para doesn't have metadata start header" + cursorContent);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
ArrayList<MetadataElement> metadataTempElements = new ArrayList<MetadataElement>();
|
|
||||||
cursorContent = getNextParaContent(paraCursor);
|
|
||||||
while (cursorContent.startsWith(METADATA_PREFIX)) {
|
|
||||||
if (cursorContent.equals(METADATA_END)) {
|
|
||||||
metadataElements = metadataTempElements;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (MetadataElementFactory.isValidMetadataString(cursorContent)) {
|
|
||||||
MetadataElement metadataElement = null;
|
|
||||||
try {
|
try {
|
||||||
metadataElement = MetadataElementFactory.fromString(cursorContent);
|
JSONObject json = new JSONObject(data);
|
||||||
} catch (ClassNotFoundException e) {
|
Iterator<String> names = json.keys();
|
||||||
e.printStackTrace();
|
while (names.hasNext()) {
|
||||||
return;
|
String metaName = names.next();
|
||||||
} catch (IOException e) {
|
String metaValue = (String) json.get(metaName);
|
||||||
e.printStackTrace();
|
metadata.add(new MetadataElement(metaName, metaValue));
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
metadataTempElements.add(metadataElement);
|
} catch (JSONException e) {
|
||||||
} else {
|
e.printStackTrace();
|
||||||
//If reading fails exit immediately
|
} catch (Exception e) {
|
||||||
return;
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
cursorContent = getNextParaContent(paraCursor);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String toString() {
|
||||||
|
JSONObject json = new JSONObject();
|
||||||
|
for (MetadataElement element : metadata) {
|
||||||
|
json.put(element.getName(), element.getValue());
|
||||||
|
}
|
||||||
|
return json.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
private String getNextParaContent(XParagraphCursor paraCursor) {
|
|
||||||
boolean moved = paraCursor.gotoNextParagraph(false);
|
|
||||||
if (moved == false) {
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
moved = paraCursor.gotoEndOfParagraph(true);
|
|
||||||
if (moved == false) {
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
String cursorContent = paraCursor.getString();
|
|
||||||
return cursorContent;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -56,6 +56,7 @@ public class EditorGUI extends JFrame {
|
||||||
//Component models
|
//Component models
|
||||||
private DefaultTableModel docPropertiesModel;
|
private DefaultTableModel docPropertiesModel;
|
||||||
private DefaultTableModel docCustomPropsModel;
|
private DefaultTableModel docCustomPropsModel;
|
||||||
|
private DefaultTableModel outlineTableModel;
|
||||||
|
|
||||||
|
|
||||||
private Map<String, String> docProps;
|
private Map<String, String> docProps;
|
||||||
|
@ -64,6 +65,8 @@ public class EditorGUI extends JFrame {
|
||||||
private JButton btnNewButton;
|
private JButton btnNewButton;
|
||||||
private JMenuItem menuItemPupupDocUserProps;
|
private JMenuItem menuItemPupupDocUserProps;
|
||||||
private ArrayList<OutlineElement> outline;
|
private ArrayList<OutlineElement> outline;
|
||||||
|
private JTable tableOutline;
|
||||||
|
private JPanel panelForOutline;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -181,9 +184,37 @@ public class EditorGUI extends JFrame {
|
||||||
JPanel panel = new JPanel();
|
JPanel panel = new JPanel();
|
||||||
tabbedPane.addTab("Документ", null, panel, null);
|
tabbedPane.addTab("Документ", null, panel, null);
|
||||||
for (OutlineElement element : outline) {
|
for (OutlineElement element : outline) {
|
||||||
tabbedPane.addTab(element.getName(), null, new JPanel(), null);
|
JPanel panelForOutline = new JPanel();
|
||||||
|
tabbedPane.addTab(element.getName(), null, panelForOutline, null);
|
||||||
}
|
}
|
||||||
|
panelForOutline = new JPanel();
|
||||||
|
tabbedPane.addTab("секция", null, panelForOutline, null);
|
||||||
|
|
||||||
|
tableOutline = new JTable();
|
||||||
|
createOutlineTableModel();
|
||||||
|
tableOutline.setModel(outlineTableModel);
|
||||||
|
tableOutline.putClientProperty("terminateEditOnFocusLost", true);
|
||||||
|
tableOutline.setSurrendersFocusOnKeystroke(true);
|
||||||
|
tableOutline.setCellSelectionEnabled(true);
|
||||||
|
tableOutline.setFillsViewportHeight(true);
|
||||||
|
|
||||||
|
GroupLayout gl_panelForOutline = new GroupLayout(panelForOutline);
|
||||||
|
gl_panelForOutline.setHorizontalGroup(
|
||||||
|
gl_panelForOutline.createParallelGroup(Alignment.LEADING)
|
||||||
|
.addGroup(gl_panelForOutline.createSequentialGroup()
|
||||||
|
.addGap(34)
|
||||||
|
.addComponent(tableOutline, GroupLayout.DEFAULT_SIZE, 804, Short.MAX_VALUE)
|
||||||
|
.addGap(126))
|
||||||
|
);
|
||||||
|
gl_panelForOutline.setVerticalGroup(
|
||||||
|
gl_panelForOutline.createParallelGroup(Alignment.LEADING)
|
||||||
|
.addGroup(gl_panelForOutline.createSequentialGroup()
|
||||||
|
.addGap(85)
|
||||||
|
.addComponent(tableOutline, GroupLayout.DEFAULT_SIZE, 475, Short.MAX_VALUE)
|
||||||
|
.addGap(120))
|
||||||
|
);
|
||||||
|
panelForOutline.setLayout(gl_panelForOutline);
|
||||||
|
|
||||||
tabbedPane.setEnabledAt(0, true);
|
tabbedPane.setEnabledAt(0, true);
|
||||||
|
|
||||||
|
|
||||||
|
@ -294,6 +325,16 @@ public class EditorGUI extends JFrame {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void createOutlineTableModel() {
|
||||||
|
outlineTableModel = new DefaultTableModel(
|
||||||
|
new Object[][] {
|
||||||
|
{null, null},
|
||||||
|
},
|
||||||
|
new String[] {
|
||||||
|
"New column", "New column"
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
private void createCustomDocPropsModel() {
|
private void createCustomDocPropsModel() {
|
||||||
Object[][] tableArray = new Object[][] {
|
Object[][] tableArray = new Object[][] {
|
||||||
{null, null},
|
{null, null},
|
||||||
|
|
Loading…
Add table
Reference in a new issue