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.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) {
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -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},
|
||||
|
|
Loading…
Add table
Reference in a new issue