Read annotations content

This commit is contained in:
Georgy Litvinov 2020-04-14 12:23:19 +02:00
parent da9eb999c1
commit 167555ebbe
5 changed files with 178 additions and 120 deletions

View file

@ -27,10 +27,12 @@ import com.sun.star.lang.WrappedTargetException;
import com.sun.star.lang.XComponent;
import com.sun.star.lang.XMultiComponentFactory;
import com.sun.star.lang.XServiceInfo;
import com.sun.star.table.XCell;
import com.sun.star.text.XText;
import com.sun.star.text.XTextContent;
import com.sun.star.text.XTextDocument;
import com.sun.star.text.XTextRange;
import com.sun.star.text.XTextTable;
import com.sun.star.uno.UnoRuntime;
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_KEYWORDS = "Document keywords";
private static final short REMOVEABLE_ATTRIBUTE = 128;
private static final Object METADATA_EXTENSION = "Metadata Extension";
private XComponentContext context;
private XDesktop xDesktop;
@ -75,33 +78,25 @@ public class Document {
}
private void updateChapterMetadata() {
findAllChapters();
readMetadataInDocument();
}
private void findAllChapters() {
XEnumerationAccess enumAccess = UnoRuntime.queryInterface(XEnumerationAccess.class, text);
private void readMetadataInDocument() {
readMetadataInText(this.text);
}
private void readMetadataInText(XText curText) {
XEnumerationAccess enumAccess = UnoRuntime.queryInterface(XEnumerationAccess.class, curText);
XEnumeration textEnum = enumAccess.createEnumeration();
while (textEnum.hasMoreElements()) {
try {
XTextContent textContent = UnoRuntime.queryInterface(XTextContent.class, textEnum.nextElement());
if(isSupported(textContent, "com.sun.star.text.TextTable")) {
//TODO: Go over table to check for outline elements
readMetadataInTable(textContent);
} else
if (isSupported(textContent, "com.sun.star.style.ParagraphProperties")) {
Short outlineLevel = null;
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));
}
readMetadataInParagraph(textContent);
}
} catch (NoSuchElementException e) {
// 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 {
currentDocument = xDesktop.getCurrentComponent();
if (currentDocument == null) {

View file

@ -2,10 +2,8 @@ package pro.litvinovg.libreoffice.metadata;
import java.io.Serializable;
public class MetadataElement implements Serializable{
public class MetadataElement {
private static final long serialVersionUID = 1L;
private String name;
private String value;

View file

@ -1,43 +1,42 @@
package pro.litvinovg.libreoffice.metadata;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.Base64;
import java.util.Iterator;
import org.json.JSONException;
import org.json.JSONObject;
public class MetadataElementFactory {
public static final String METADATA_START = "## Metadata Editor extension. Outline metadata folllows: ";
public static String METADATA_PREFIX = "##";
public static String METADATA_END = "## Metadata Editor extension. Outline metadata ends.";
public static final String METADATA_START = "## Metadata Editor extension. Outline metadata in JSON folllows:";
public static final String METADATA_PREFIX = "## ";
public static final String METADATA_END = "## Outline metadata finished.";
public static boolean isValidMetadataString(String cursorContent) {
if (!cursorContent.startsWith(METADATA_PREFIX) ||
cursorContent.equals(METADATA_START) ||
cursorContent.equals(METADATA_END)){
return false;
}
String data = cursorContent.substring(cursorContent.lastIndexOf(METADATA_PREFIX));
public static MetadataElement fromString(String cursorContent){
String data = cursorContent.substring(METADATA_PREFIX.length());
System.out.println("DATA " + data);
//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) {
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;
JSONObject json = new JSONObject();
json.put(element.getName(), element.getValue());
return METADATA_PREFIX + json.toString();
}
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());
}
public boolean isJSONValid(String test) {
try {
new JSONObject(test);
} catch (JSONException e) {
return false;
}
return true;
}
}

View file

@ -1,20 +1,19 @@
package pro.litvinovg.libreoffice.metadata;
import java.io.IOException;
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.uno.UnoRuntime;
import static pro.litvinovg.libreoffice.metadata.MetadataElementFactory.*;
public class OutlineElement {
private String name;
private ArrayList<MetadataElement> metadataElements = null;
private ArrayList<MetadataElement> metadata = null;
public String getName() {
return name;
}
@ -22,69 +21,37 @@ public class OutlineElement {
private XTextRange textRange;
private boolean hasMetadataStorage = false;
private XTextRange metadataTextRange = null;
public OutlineElement(XTextRange textRange) {
this.textRange = textRange;
this.name = textRange.getString();
getMetadataStorage();
this.metadata = new ArrayList<MetadataElement>();
}
private void getMetadataStorage() {
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;
public void readMetadata(String data) {
try {
JSONObject json = new JSONObject(data);
Iterator<String> names = json.keys();
while (names.hasNext()) {
String metaName = names.next();
String metaValue = (String) json.get(metaName);
metadata.add(new MetadataElement(metaName, metaValue));
}
if (MetadataElementFactory.isValidMetadataString(cursorContent)) {
MetadataElement metadataElement = null;
try {
metadataElement = MetadataElementFactory.fromString(cursorContent);
} catch (ClassNotFoundException e) {
e.printStackTrace();
return;
} catch (IOException e) {
e.printStackTrace();
return;
}
metadataTempElements.add(metadataElement);
} else {
//If reading fails exit immediately
return;
}
cursorContent = getNextParaContent(paraCursor);
} catch (JSONException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
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;
}
public String toString() {
JSONObject json = new JSONObject();
for (MetadataElement element : metadata) {
json.put(element.getName(), element.getValue());
}
return json.toString();
}
}

View file

@ -56,6 +56,7 @@ public class EditorGUI extends JFrame {
//Component models
private DefaultTableModel docPropertiesModel;
private DefaultTableModel docCustomPropsModel;
private DefaultTableModel outlineTableModel;
private Map<String, String> docProps;
@ -64,6 +65,8 @@ public class EditorGUI extends JFrame {
private JButton btnNewButton;
private JMenuItem menuItemPupupDocUserProps;
private ArrayList<OutlineElement> outline;
private JTable tableOutline;
private JPanel panelForOutline;
/**
@ -181,9 +184,37 @@ public class EditorGUI extends JFrame {
JPanel panel = new JPanel();
tabbedPane.addTab("Документ", null, panel, null);
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);
@ -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() {
Object[][] tableArray = new Object[][] {
{null, null},