Get all mailMerge fields from docx using docx4J - java

I have .docx file, containing mailMerge fields.
I want to extract all field names to List.
I saw some examples of dox4J, how to replace these fields with mapped value, but I DO NOT want to replace them, I need to read them only.
Is there a semy easy way to do that using docx4J?

Have a look at https://github.com/plutext/docx4j/blob/master/src/samples/docx4j/org/docx4j/samples/FieldsDiagnostics.java
You can also look at the code in MailMerger:
// find fields
ComplexFieldLocator fl = new ComplexFieldLocator();
new TraversalUtil(shellClone, fl);
// canonicalise and setup fieldRefs
List<FieldRef> fieldRefs = new ArrayList<FieldRef>();
canonicaliseStarts(fl, fieldRefs);
// Populate
for (FieldRef fr : fieldRefs) {
if ( fr.getFldName().equals("MERGEFIELD") ) {
String instr = extractInstr(fr.getInstructions() );
String datafieldName = getDatafieldNameFromInstr(instr);

Related

I need to display list of files generated using a method in java class into my tml file in Tapestry

I have a java class in which I have the method- getFiles() that prints a list of files in a directory. Here is the code
#Property
private String[] filesInDir;
public void getFiles(String path){
File aDirectory = new File("C://Users/A634682/report1/src/main/java/com/example/report1/reports2");
// get a listing of all files in the directory
filesInDir = aDirectory.list();
// sort the list of files (optional)
// Arrays.sort(filesInDir);
System.out.println("File list begins here >>>>>");
// have everything i need, just print it now
for ( int i=0; i<filesInDir.length; i++ )
{
System.out.println( "file: " + filesInDir[i] );
}
}
In the respective tml file, I want to print this string array containing file names in form of table on the webpage.
Any help in how I can proceed?
You can use a simple t:Loop component with your filesInDir as a source. One example can be found here: http://jumpstart.doublenegative.com.au/jumpstart/examples/tables/loop
You'd need to initialise the property before rendering starts, i.e. in setupRender().

OWL API changing IRIs of entities in axioms

I am using OWL API. My question is how can I modify IRIs of all Entities in all OWLAxiom axioms in my OWLOntology read from file. For example I want to modify all "http://xxx" to "http://yyy" in all axioms in my ontology. The selected example axiom in this ontology is:
SubClassOf(<http://xxx#A> <http://xxx#B>)
I need to receive e.g.:
SubClassOf(<http://yyy#A> <http://yyy#B>)
My question especially implies to changing the default IRI, therefore, I tried to specify:
PrefixOWLOntologyFormat prefix = (PrefixOWLOntologyFormat) manager.getOntologyFormat(ontology);
prefix.setDefaultPrefix(...new...);
but it didn't change the IRIs in axioms.
One solution is to use the OWLEntityRenamer class.
one basic usage is the following one :
OWLEntityRenamer renamer = new OWLEntityRenamer(manager, Collections.singleton(ontology));
Map<OWLEntity, IRI> entity2IRIMap = new HashMap<>();
...
ont.applyChanges(renamer.changeIRI(entity2IRIMap));
All individuals targeted by your Map<> will be rename.
If you want to rename all yours individual by a pattern, you have to queries a complet list of your individuals to build the Map<>.
Here a complete small example using OWLEntityRenamer :
final OWLOntologyManager m = OWLManager.createOWLOntologyManager();
final OWLOntology o = m.createOntology();
o.add(OWL.classAssertion(OWL.Individual("xxx:1"), OWL.Class("b:y")));
o.add(OWL.classAssertion(OWL.Individual("xxx:2"), OWL.Class("b:y")));
o.add(OWL.classAssertion(OWL.Individual("xxx:3"), OWL.Class("b:y")));
o.individualsInSignature().forEach(System.out::println);
final OWLEntityRenamer renamer = new OWLEntityRenamer(m, Collections.singleton(o));
final Map<OWLEntity, IRI> entity2IRIMap = new HashMap<>();
o.individualsInSignature().forEach(toRename ->
{
final IRI iri = toRename.getIRI();
entity2IRIMap.put(toRename, IRI.create(iri.toString().replaceFirst("xxx", "yyy")));
});
o.applyChanges(renamer.changeIRI(entity2IRIMap));
o.individualsInSignature().forEach(System.out::println);
Should print :
<xxx:3>
<xxx:2>
<xxx:1>
<yyy:3>
<yyy:2>
<yyy:1>

Parsing Properties file

I am trying to parse a Properties file that has the following format:
CarModel=Prius
CarMake=Toyota
Option1=Transmission
OptionValue1a=Manual
OptionValue1b=Automatic
Option2=Brakes
OptionValue2a=Regular
OptionValue2b=ABS
My question is, what if there are various forms of the Properties file? For instance, what if a Properties file has 3 options for Option 1, and another Properties file has 2 options for Option 1? Right now my code looks like this:
Properties props = new Properties();
FileInputStream x = new FileInputStream(filename);
props.load(x);
String carModel = props.getProperty("CarModel");
if(!carModel.equals(null)){
String carMake = props.getProperty("CarMake");
String option1 = props.getProperty("Option1");
String option1a = props.getProperty("OptionValue1a");
String option1b = props.getProperty("OptionValue1b");
etc. I'm thinking I need a lot of 'if' statements, but I'm unsure how to implement them. Any ideas?
Are you sure you want to use a properties file? I suggest using YAML.
I am trying to parse a Properties file that has the following format:
CarModel: Prius
CarMake: Toyota
Transmission:
- Manual
- Automatic
Brakes:
- Regular
- ABS
Using SnakeYAML you can do
Map<String, Object> car = (Map) new Yaml().load(new FileReader(filename));
Note the lines starting with - are turned into a list.
If you must stick with Properties, I suggest putting the list in a property.
CarModel=Prius
CarMake=Toyota
Options=Transmission Manual|Automatic,\
Brakes Regular|ABS
This way you can read the options like
String options = prop.getProperty("Options");
for(String option : options.split("\\s*,\\s*")) {
String[] parts = option.split("\\s+");
String optionType = parts[0];
String[] optionChoices = parts[1].split("[|]");
}
This way you can have any number of options with any number of choices.

how to create OSLC docs using Jena?

I need to create RDF/XML documents containing objects in the OSLC namespace.
e.g.
<oslc_disc:ServiceProviderCatalog
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:dc="http://purl.org/dc/terms/"
xmlns:oslc_disc="http://open-services.net/xmlns/discovery/1.0/"
rdf:about="{self}">
<dc:title>{catalog title}</dc:title>
<oslc_disc:details rdf:resource="{catalog details uri}" />
what is the simplest way to create this doc using the Jena API ?
( I know about Lyo, they use a JSP for this doc :-)
Thanks, Carsten
Here's a complete example to start you off. Be aware that this will be equivalent to XML output you want, but may not be identical. The order of properties, for example, may vary, and there are other ways to write the same content.
import com.hp.hpl.jena.rdf.model.*
import com.hp.hpl.jena.vocabulary.DCTerms;
public class Jena {
// Vocab items -- could use schemagen to generate a class for this
final static String OSLC_DISC_NS = "http://open-services.net/xmlns/discovery/1.0/";
final static Resource ServiceProviderCatalog =
ResourceFactory.createResource(OSLC_DISC_NS + "ServiceProviderCatalog");
final static Property details =
ResourceFactory.createProperty(OSLC_DISC_NS, "details");
public static void main(String[] args) {
// Inputs
String selfURI = "http://example.com/self";
String catalogTitle = "Catalog title";
String catalogDetailsURI = "http://example.com/catalogDetailsURI";
// Create in memory model
Model model = ModelFactory.createDefaultModel();
// Set prefixes
model.setNsPrefix("dc", DCTerms.NS);
model.setNsPrefix("oslc_disc", OSLC_DISC_NS);
// Add item of type spcatalog
Resource self = model.createResource(selfURI, ServiceProviderCatalog);
// Add the title
self.addProperty(DCTerms.title, catalogTitle);
// Add details, which points to a resource
self.addProperty(details, model.createResource(catalogDetailsURI));
// Write pretty RDF/XML
model.write(System.out, "RDF/XML-ABBREV");
}
}

How to read data from CSV if contains more than excepted separators?

I use CsvJDBC for read data from a CSV. I get CSV from web service request, so not loaded from file. I adjust these properties:
Properties props = new java.util.Properties();
props.put("separator", ";"); // separator is a semicolon
props.put("fileExtension", ".txt"); // file extension is .txt
props.put("charset", "UTF-8"); // UTF-8
My sample1.txt contains these datas:
code;description
c01;d01
c02;d02
my sample2.txt contains these datas:
code;description
c01;d01
c02;d0;;;;;2
It is optional for me deleted headers from CSV. But not optional for me change semi-colon separator.
EDIT: My query for resultSet: SELECT * FROM myCSV
I want to read code column in sample1.txt and sample2.txt with:
resultSet.getString(1)
and read full description column with many semi-colons (d0;;;;;2). Is it possible with CsvJdbc driver or need to change driver?
Thank you any advice!
This is a problem that occurs when you have messy, invalid input, which you need to try to interpret, that's being read by a too-high-level package that only handles clean input. A similar example is trying to read arbitrary HTML with an XML parser - close, but no cigar.
You can guess where I'm going: you need to pre-process your input.
The preprocessing may be very easy if you can make some assumptions about the data - for example, if there are guaranteed to be no quoted semi-colons in the first column.
You could try supercsv. We have implemented such a solution in our project. More on this can be found in http://supercsv.sourceforge.net/
and
Using CsvBeanReader to read a CSV file with a variable number of columns
Finally this problem solved without a CSVJdbc or SuperCSV driver. These drivers works fine. There are possible query data form CSV file and many features content. In my case I don't need query data from CSV. Unfortunately, sometimes the description column content one or more semi-colons and which it is my separator.
First I check code in answer of #Maher Abuthraa and modified to:
private String createDescriptionFromResult(ResultSet resultSet, int columnCount) throws SQLException {
if (columnCount > 2) {
StringBuilder data_list = new StringBuilder();
for (int ii = 2; ii <= columnCount; ii++) {
data_list.append(resultSet.getString(ii));
if (ii != columnCount)
data_list.append(";");
}
// data_list has all data from all index you are looking for ..
return data_list.toString();
} else {
// use standard way
return resultSet.getString(2);
}
}
The loop started from 2, because 1 column is code and only description column content many semi-colons. The CSVJdbc driver split columns by separator ; and these semi-colons disappears from columns data. So, I explicit add semi-colons to description, except the last column, because it is not relevant in my case.
This code work fine. But not solved my all problem. When I adjusted two columns in header of CSV I get error in row, which content more than two semi-colons. So I try adjust ignore of headers or add many column name (or simple ;) to a header. In superCSV ignore of headers option work fine.
My colleague opinion was: you are don't need CSV driver, because try load CSV which not would be CSV, if separator is sometimes relevant data.
I think my colleague has right and I loaded CSV data whith following code:
InputStream in = null;
try {
in = new ByteArrayInputStream(csvData);
List lines = IOUtils.readLines(in, "UTF-8");
Iterator it = lines.iterator();
String line = "";
while (it.hasNext()) {
line = (String) it.next();
String description = null;
String code = null;
String[] columns = line.split(";");
if (columns.length >= 2) {
code = columns[0];
String[] dest = new String[columns.length - 1];
System.arraycopy(columns, 1, dest, 0, columns.length - 1);
description = org.apache.commons.lang.StringUtils.join(dest, ";");
(...)
ok.. my solution to go and read all fields if columns are more than 2 ... like:
int ccc = meta.getColumnCount();
if (ccc > 2) {
ArrayList<String> data_list = new ArrayList<String>();
for (int ii = 1; ii < ccc; ii++) {
data_list.add(resultSet.getString(i));
}
//data_list has all data from all index you are looking for ..
} else {
//use standard way
resultSet.getString(1);
}
If the table is defined to have as many columns as there could be semi-colons in the source, ignoring the initial column definitions, then the excess semi-colons would be consumed by the database driver automatically.
The most likely reason for them to appear in the final column is because the parser returns the balance of the row to the terminator in the field.
Simply increasing the number of columns in the table to match the maximum possible in the input will avoid the need for custom parsing in the program. Try:
code;description;dummy1;dummy2;dummy3;dummy4;dummy5
c01;d01
c02;d0;;;;;2
Then, the additional ';' delimiters will be consumed by the parser correctly.

Categories