I need to do docx manipulation (find/replace on placeholders and checking/unchecking checkboxes). Since ColdFusion 10 integrates well with Java, I decided to try and use the Java library docx4j, which basically mimics the OpenXML SDK (.net platform).
I have the docx4j JAR inside a custom folder, which I have setup in my Application.cfc via JavaSettings (new in CF10, and I tried it with other JARS and it works):
<cfcomponent output="false">
<cfset this.javaSettings =
{LoadPaths = ["/myJava/lib"], loadColdFusionClassPath = true, reloadOnChange= true,
watchInterval = 100, watchExtensions = "jar,class,xml"} />
</cfcomponent>
Now, I'm trying to use this sample:https://github.com/plutext/docx4j/blob/master/src/main/java/org/docx4j/samples/VariableReplace.java
But trying to call the WordprocessingMLPackage fails with the function CreateObject() saying that particular class doesn't exist:
<cfset docObj = createObject("java","org.docx4j.openpackaging.packages.WordprocessingMLPackage") />
Any ideas? I'm not really a Java guy, but there are not many options out there for docx manipulation.
Alright. Seems like I got everything working. I just got to figure out how to do a find/replace, and everything else I want to do in a docx document. Here's my code so far to show you guys that it looks like it is working (make sure that your Application.cfc looks like the original post if you are on CF10):
<cfscript>
docPackageObj = createObject("java","org.docx4j.openpackaging.packages.WordprocessingMLPackage").init();
docObj = createObject("java","org.docx4j.openpackaging.parts.WordprocessingML.MainDocumentPart").init();
xmlUtilObj = createObject("java","org.docx4j.XmlUtils").init();
wmlDocObj = createObject("java","org.docx4j.wml.Document").init();
saveToZipFile = createObject("java","org.docx4j.openpackaging.io.SaveToZipFile").init(docPackageObj);
strFilePath = getDirectoryFromPath(getCurrentTemplatePath()) & "testDoc.docx";
wordMLPackage =
docPackageObj.load(createObject("java","java.io.File").init(javaCast("string",strFilePath)));
documentPart = wordMLPackage.getMainDocumentPart();
// unmarshallFromTemplate requires string input
strXml = xmlUtilObj.marshaltoString(documentPart.getJaxbElement(),true);
writeDump(var="#strXml#");
</cfscript>
Now, does anybody know how to cast structures in ColdFusion into hashmaps (or collections in general)? I think structures in CF are actually util.Vector, whereas hashmaps are util.HashMap. All of the examples I see with Docx4j that demonstrates find/replace in placeholders use this:
HashMap<String, String> mappings = new HashMap<String, String>();
mappings.put("colour", "green");
mappings.put("icecream", "chocolate");
Have you tried setting loadColdFusionClassPath = false instead of true? Perhaps there is a conflict with some of the JARs that ship w/ CF.
(Not really a new answer, but it is too much code for comments ..)
Here is the full code for the docx4j VariableReplace.java example
<cfscript>
saveToDisk = true;
inputFilePath = ExpandPath("./docx4j/sample-docs/word/unmarshallFromTemplateExample.docx");
outputFilePath = ExpandPath("./OUT_VariableReplace.docx");
inputFile = createObject("java", "java.io.File").init(inputFilePath);
wordMLPackage = createObject("java","org.docx4j.openpackaging.packages.WordprocessingMLPackage").load(inputFile);
documentPart = wordMLPackage.getMainDocumentPart();
XmlUtils = createObject("java","org.docx4j.XmlUtils");
xmlString = XmlUtils.marshaltoString(documentPart.getJaxbElement(),true);
mappings = createObject("java", "java.util.HashMap").init();
mappings["colour"] = "green";
mappings["icecream"] = "chocolate";
obj = XmlUtils.unmarshallFromTemplate(xmlString , mappings);
documentPart.setJaxbElement(obj);
if (saveToDisk) {
saveToZipFile = createObject("java","org.docx4j.openpackaging.io.SaveToZipFile").init(wordMLPackage);
SaveToZipFile.save( outputFilePath );
}
else {
WriteDump(XmlUtils.marshaltoString(documentPart.getJaxbElement(), true, true));
}
</cfscript>
Related
I have built a program, which takes in a provided ".class" file and parses it using the BCEL, I've learnt how to calculate the LCOM4 value now. Now I would like to know how to calculate the CBO(Coupling between object) value of the class file. I've scoured the whole web, trying to find a proper tutorial about it, but I've been unable so far (I've read the whole javadoc regarding the BCEL as well and there was a similar question on stackoverflow but it has been removed). So I would like some help with this issue, as in some detailed tutorials or code snippets that would help me understand on how to do it.
OK, here you must compute the CBO of the classes within a whole set of classes. The set can be the content of a directory, of a jar file, or all the classes in a classpath.
I would fill a Map<String,Set<String>> with the class name as the key, and the classes it refers to:
private void addClassReferees(File file, Map<String, Set<String>> refMap)
throws IOException {
try (InputStream in = new FileInputStream(file)) {
ClassParser parser = new ClassParser(in, file.getName());
JavaClass clazz = parser.parse();
String className = clazz.getClassName();
Set<String> referees = new HashSet<>();
ConstantPoolGen cp = new ConstantPoolGen(clazz.getConstantPool());
for (Method method: clazz.getMethods()) {
Code code = method.getCode();
InstructionList instrs = new InstructionList(code.getCode());
for (InstructionHandle ih: instrs) {
Instruction instr = ih.getInstruction();
if (instr instanceof FieldOrMethod) {
FieldOrMethod ref = (FieldInstruction)instr;
String cn = ref.getClassName(cp);
if (!cn.equals(className)) {
referees.add(cn);
}
}
}
}
refMap.put(className, referees);
}
}
When you've added all the classes in the map, you need to filter the referees of each class to limit them to the set of classes considered, and add the backward links:
Set<String> classes = new TreeSet<>(refMap.keySet());
for (String className: classes) {
Set<String> others = refMap.get(className);
others.retainAll(classes);
for (String other: others) {
refMap.get(other).add(className);
}
}
I'm writing an add-on that opens a dialog and I need to access the currently opened text document but I don't know how get it.
I'm using the OpenOffice plug-in in NetBeans and I started from an Add-on project. It created a class that gives me a XComponentContext instance but I don't know how to use it to get a OfficeDocument instance of the current document.
I've been googling for some time and I can't find any example that uses an existing, opened, document. They all start from a new document or a document that is loaded first so they have an URL for it.
I gave it a try based on the OpenOffice wiki (https://wiki.openoffice.org/wiki/API/Samples/Java/Office/DocumentHandling) and this is what I came up with:
private OfficeDocument getDocument() {
if (this.officeDocument == null) {
try {
// this causes the error
XMultiComponentFactory xMultiComponentFactory = this.xComponentContext.getServiceManager();
Object oDesktop = xMultiComponentFactory.createInstanceWithContext("com.sun.star.frame.Desktop", this.xComponentContext);
XComponentLoader xComponentLoader = UnoRuntime.queryInterface(XComponentLoader.class, oDesktop);
String url = "private:factory/swriter";
String targetFrameName = "_self";
int searchFlags = FrameSearchFlag.SELF;
PropertyValue[] propertyValues = new PropertyValue[1];
propertyValues[0] = new PropertyValue();
propertyValues[0].Name = "Hidden";
propertyValues[0].Value = Boolean.TRUE;
XComponent xComponent = xComponentLoader.loadComponentFromURL(url, targetFrameName, searchFlags, propertyValues);
XModel xModel = UnoRuntime.queryInterface(XModel.class, xComponent);
this.officeDocument = new OfficeDocument(xModel);
} catch (com.sun.star.uno.Exception ex) {
throw new RuntimeException(ex);
}
}
return this.officeDocument;
}
But there is something strange going on. Just having this method in my class, even if it's never been called anywhere, causes an error when adding the add-on.
(com.sun.star.depoyment.DeploymentDescription){{ Message = "Error during activation of: VaphAddOn.jar", Context = (com.sun.star.uno.XInterface) #6ce03e0 }, Cause = (any) {(com.sun.star.registry.CannotRegisterImplementationException){{ Message = "", Context = (com.sun.star.uno.XInterface) #0 }}}}
It seems this line causes the error:
XMultiComponentFactory xMultiComponentFactory = this.xComponentContext.getServiceManager();
I have no idea how to preceed.
I posted this question on the OpenOffice forum but I haven't got a response there. I'm trying my luck here now.
Use this in your code to get the current document:
import com.sun.star.frame.XDesktop;
...
XDesktop xDesktop = (XDesktop) UnoRuntime.queryInterface(XDesktop.class, oDesktop);
XComponent xComponent = xDesktop.getCurrentComponent();
I opened the BookmarkInsertion sample in NetBeans and added this code to use the current document instead of loading a new document.
As far as the error, there may be a problem with how it is getting built. A couple of things to check:
Does the Office SDK version match the Office version? Check version number and whether it's 32- or 64-bit.
Make sure that 4 .jar files (juh.jar, jurt.jar, unoil.jar, ridl.jar) are shown under Libraries in NetBeans, because they need to be included along with the add-on.
If you get frustrated with trying to get the build set up correctly, then you might find it easier to use python, since it doesn't need to be compiled. Also python does not require queryInterface().
I have a code in Java that opens a excel template by aspose library (it runs perfectly):
import com.aspose.cells.*;
import java.io.*;
public class test
{
public static void main(String[] args) throws Exception
{
System.setProperty("java.awt.headless", "true");
FileInputStream fstream = new FileInputStream("/home/vmlellis/Testes/aspose-cells/template.xlsx");
Workbook workbook = new Workbook(fstream);
workbook.save("final.xlsx");
}
}
After I run this on Ruby with RJB (Ruby Java Bridge):
require 'rjb'
#RJM Loading
JARS = Dir.glob('./jars/*.jar').join(':')
print JARS
Rjb::load(JARS, ['-Xmx512M'])
system = Rjb::import('java.lang.System')
file_input = Rjb::import('java.io.File')
file_input_stream = Rjb::import('java.io.FileInputStream')
workbook = Rjb::import('com.aspose.cells.Workbook')
system.setProperty("java.awt.headless", "true")
file_path = "/home/vmlellis/Testes/aspose-cells/template.xlsx"
file = file_input.new(file_path)
fin = file_input_stream.new(file)
wb = workbook.new(fin)
I get this error:
test.rb:57:in `new': Can't find file: java.io.FileInputStream#693a317a. (FileNotFoundException)
from aspose-test.rb:57:in `<main>'
Why? I run the same code... but in Ruby is not working! How do I fix this?
Update:
In documentation there is the the initializer: Workbook(java.io.InputStreamstream)... but it's not working in RJB. (How is this possible?)
Your program should have worked, but I could not find any reason why it didn't and I am looking into it.
Now the alternate approaches.
Approach 1
Use Workbook(String) constructor instead of Workbook(FileInputStream). This worked flawlessly at my end. The sample code is
require 'rjb'
#RJM Loading
JARS = Dir.glob('/home/saqib/cellslib/*.jar').join(':')
print JARS
Rjb::load(JARS, ['-Xmx512M'])
system = Rjb::import('java.lang.System')
workbook = Rjb::import('com.aspose.cells.Workbook')
system.setProperty("java.awt.headless", "true")
file_path = "/home/saqib/rjb/template.xlsx"
save_path = "/home/saqib/rjb/final.xlsx"
wb = workbook.new(file_path)
wb.save(save_path)
Approach 2
Write a new Java class library. Write all your Aspose.Cells related code in it. Expose very simple and basic methods that needs to be called from Ruby (RJB).
Why?
It is easy to write program in native Java language. If you use RJB, you need to perform a lot of code conversions
It is easy to debug and test in Java.
Usage of RJB will only be limited to calling methods from your own Java library. The RJB code will be small and basic.
Similar Example using own library
Create a new Java project, lets say "cellstest". Add a new public class in it.
package cellstest;
import com.aspose.cells.Workbook;
public class AsposeCellsUtil
{
public String doSomeOpOnWorkbook(String inFile, String outFile)
{
String result = "";
try
{
// Load the workbook
Workbook wb = new Workbook(inFile);
// Do some operation with this workbook
// ..................
// Save the workbook
wb.save(outFile);
// everything ok.
result = "ok";
}
catch(Exception ex)
{
// Return the exception to calling program
result = ex.toString();
}
return result;
}
}
Like this, add as many methods as you like, for each operation.
Build the project and copy the "cellstest.jar" in same folder where you copied Aspose.Cells jar files. You can return a String from your methods and check the return value in Ruby program for success or error code. The Ruby program will now be like
require 'rjb'
#RJM Loading
JARS = Dir.glob('/home/saqib/cellslib/*.jar').join(':')
print JARS
Rjb::load(JARS, ['-Xmx512M'])
system = Rjb::import('java.lang.System')
AsposeCellsUtil = Rjb::import('cellstest.AsposeCellsUtil')
system.setProperty("java.awt.headless", "true")
file_path = "/home/saqib/rjb/template.xlsx"
save_path = "/home/saqib/rjb/final.xlsx"
# initialize instance
asposeCellsUtil = AsposeCellsUtil.new()
# call methods
result = asposeCellsUtil.doSomeOpOnWorkbook(file_path, save_path)
puts result
PS. I work for Aspose as Developer Evangelist.
In your Java code, you pass a file name string into FileInputStream() constructor:
FileInputStream fstream = new FileInputStream("/home/vmlellis/Testes/aspose-cells/template.xlsx");
In your Ruby code, you pass a file object:
file = file_input.new(file_path)
fin = file_input_stream.new(file)
Have you tried to do the same thing as in Java?
fin = file_input_stream.new(file_path)
am trying to create a soap webservice method to match fingerprints using digitalpersona one touch for windows sdk java edition. I capture the featureset from an applet at the client side and compare it with my template on the server side. But I need to deserialize it and create the feature set again so that i can compare it with the template.
I dont know how to recreate the feature set so that i can use it for verification:
//This is for template retrieval: (no problem here)
String dbTemplate = result.getString("template");
byte[] byteArray = new byte[1];
byteArray = hexStringToByteArray(dbTemplate);
DPFPTemplate template = DPFPGlobal.getTemplateFactory().createTemplate();
template.deserialize(byteArray);
byte[] fsArray = new byte[1];
fsArray = hexStringToByteArray(ftSet);
//the problem is here, I've already converted it back into bytearray[] but i need to deserialize it and create the feature set again.
featureSet.deserialise(fsArray);
DPFPFeatureSet features = extractFeatures(sample, DPFPDataPurpose.DATA_PURPOSE_VERIFICATION);
//This is for matching features and template
DPFPVerification matcher = DPFPGlobal.getVerificationFactory().createVerification();
DPFPVerificationResult result1 = matcher.verify(features, template);
if (result1.isVerified()) {
return "The fingerprint was VERIFIED.";
} else {
return "The fingerprint was NOT VERIFIED.";
}
Please help me.
the best thing you can do here is not to convert the bytearray into string. if you are saving it in a database, you can automatically save it as byte array (since the blob can accept a bytearray).
you can insert it like this (just an example)
PreparedStatement st=con.prepareStatement("INSERT INTO EMPLOYEE(employee_id,template)"+"values(?,?)");
st.setInt(1,23);
st.setBytes(2, enroller.getTemplate().serialize());
Statement st = con.createStatement();
ResultSet rec = st.executeQuery("SELECT * FROM EMPLOYEE WHERE EMPLOYEE_ID=3");
Then when accessing the template, deserialize it (just follow the sdk, i think it's around page 37) Onetouch java sdk ==== link
a sample will be available below.
while(rec.next()){
blob = rec.getBlob("template");
int blobLength = (int)blob.length();
blobAsBytes = blob.getBytes(1, blobLength);
}
templater.deserialize(blobAsBytes);
verificator.setFARRequested(DPFPVerification.MEDIUM_SECURITY_FAR);
DPFPVerificationResult result = verificator.verify(fs, templater);
if (result.isVerified())
System.out.print("The fingerprint was VERIFIED.");
How can I load data from an xml file into solr using the solrj API?
Thanks Pascal. I miss worded my question, I'm actually using groovy. But in any event your approach does work, but this was my solution:
CommonsHttpSolrServer server = SolrServerSingleton.getInstance().getServer();
def dataDir = System.getProperty("user.dir");
File xmlFile = new File(dataDir+"/book.xml");
def xml = xmlFile.getText();
DirectXmlRequest xmlreq = new DirectXmlRequest( "/update", xml);
server.request(xmlreq);
server.commit();
The first arg to DirectXmlRequest is a url path, it must be "/update" and that the variable xml is a string containing the XML. For example
<add>
<doc>
<field name="title">blah</field>
</doc>
</add>
With Java 6, you can use Xpath to fetch what you need from your xml file. Then, you populate a SolrInputDocument from what you extracted from the xml. When that document contains everything you need, you submit it to Solr using the add method of SolrServer.
SolrClient client = new HttpSolrClient("http://localhost:8983/solr/jiva/");
String dataDir = System.getProperty("user.dir");
File xmlFile = new File(dataDir + "/Alovera-Juice.xml");
if (xmlFile.exists()) {
InputStream is = new FileInputStream(xmlFile);
String str = IOUtils.toString(is);
DirectXmlRequest dxr = new DirectXmlRequest("/update", str);
client.request(dxr);
client.commit();
}