OWL replace object and data property value - java

I've written this code to replace object property value:
public void changeObjectPropertyValue(String ind, String propertyFragment, String newValueFragment) {
OWLNamedIndividual individualToReplaceValueOn = factory.getOWLNamedIndividual(prefix + ind);
OWLNamedIndividual newValueInd = factory.getOWLNamedIndividual(prefix + newValueFragment);
OWLObjectProperty theObjectProperty = factory.getOWLObjectProperty(prefix + propertyFragment);
OWLIndividual theOldValue = EntitySearcher.getObjectPropertyValues(individualToReplaceValueOn, theObjectProperty, ont).findFirst().get();
OWLAxiom oldAxiom = factory.getOWLObjectPropertyAssertionAxiom(
theObjectProperty,
individualToReplaceValueOn,
theOldValue);
OWLAxiom newAxiom = factory.getOWLObjectPropertyAssertionAxiom(
theObjectProperty,
individualToReplaceValueOn,
newValueInd);
List<OWLOntologyChange> changes = new Vector<OWLOntologyChange>();
changes.add(new RemoveAxiom(ont, oldAxiom));
changes.add(new AddAxiom(ont, newAxiom));
manager.applyChanges(changes);
}
I want to know if this is a correct way to replace value and if there is a method in OWLAPI library to do this?

This is correct - and the only way to do this sort of changes in OWL API. Axioms are immutable objects, so there is no other way to modify an axiom than recreating it and changing the parts that need modifying in the process.

Related

How do I read Windows Event Log field names using JNA?

I am using JNA to read Windows event logs. I can get a fair amount of data out of each record but I can't quite get the field names.
To read logs I am doing
EventLogIterator iter = new EventLogIterator("Security");
while(iter.hasNext()) {
EventLogRecord record = iter.next();
System.out.println("Event ID: " + record.getEventId()
+ ", Event Type: " + record.getType()
+ ", Event Source: " + record.getSource());
String strings[] = record.getStrings();
for(String str : strings) {
System.out.println(str);
}
}
I can get data like the id, type, and source easily. Then I can get the list of strings which may be for SubjectUserSid, SubjectUserName, etc.
I've been trying to get the data that I want with the field names. Is there an easy way to extract the field names/headers for each of the strings from record.getStrings()? I noticed there is a byte[] data variable in the record. I have tried to read this but I haven't been able to get any useful information from it. I know I can get the data length and offset for certain variables which I think I could extract the data that I want that way but I was wondering if that was correct or if there was an easier way.

Using OntProperty and DatatypeProperty - Jena Ontology

OntModel onto = ModelFactory.createOntologyModel(
OntModelSpec.OWL_MEM_MICRO_RULE_INF, null );
String inputFileName = "./src/test.xml";
InputStream in = FileManager.get().open(inputFileName);
if (in == null) {
throw new IllegalArgumentException( "File: " + inputFileName + " not found");
}
onto.read(new InputStreamReader(in), "");
//ns is the namespace...
OntClass userClass = onto.getOntClass(ns+"User");
Individual dada = onto.createIndividual(ns+"Daryl", userClass);
Property prefBathtub = onto.getProperty(ns+"prefersBathtub");
Property prefBathtubWt = onto.getProperty(ns+"prefersBathtubWeight");
dada.addLiteral(prefBathtub, true);
dada.addLiteral(prefBathtubWt, 0.30);
OutputStream out = new FileOutputStream("./src/test2.xml");
onto.write( out, "RDF/XML"); // readable rdf/xml
out.close();
How do I use OntProperty and/or DatatypeProperty instead of just Property?
By using Property do I get the same amount of expressiveness?
To get an ObjectProperty object from an ontology model, use OntModel.getObjectProperty(). Likewise for datatype properties, etc. The Ont classes are more expressive in the sense that they contain convenience API for getting, for example, the super-properties of a property, with one method call. However, as the convenience API only accesses the underlying triples in the graph, there is strictly speaking nothing you can do with an ObjectProperty that you can't do with a Property. It's just harder work!
Incidentally, Jena allows you to access other facets of an underlying RDF resource with the .as() method. So:
Property p = myModel.getProperty( "http://example.com/foo#p" );
OntProperty op = p.as( OntProperty.class );

Is there an smart way to write a fixed length flat file?

Is there any framework/library to help writing fixed length flat files in java?
I want to write a collection of beans/entities into a flat file without worrying with convertions, padding, alignment, fillers, etcs
For example, I'd like to parse a bean like:
public class Entity{
String name = "name"; // length = 10; align left; fill with spaces
Integer id = 123; // length = 5; align left; fill with spaces
Integer serial = 321 // length = 5; align to right; fill with '0'
Date register = new Date();// length = 8; convert to yyyyMMdd
}
... into ...
name 123 0032120110505
mikhas 5000 0122120110504
superuser 1 0000120101231
...
You're not likely to encounter a framework that can cope with a "Legacy" system's format. In most cases, Legacy systems don't use standard formats, but frameworks expect them. As a maintainer of legacy COBOL systems and Java/Groovy convert, I encounter this mismatch frequently. "Worrying with conversions, padding, alignment, fillers, etcs" is primarily what you do when dealing with a legacy system. Of course, you can encapsulate some of it away into handy helpers. But most likely, you'll need to get real familiar with java.util.Formatter.
For example, you might use the Decorator pattern to create decorators to do the conversion. Below is a bit of groovy (easily convertible into Java):
class Entity{
String name = "name"; // length = 10; align left; fill with spaces
Integer id = 123; // length = 5; align left; fill with spaces
Integer serial = 321 // length = 5; align to right; fill with '0'
Date register = new Date();// length = 8; convert to yyyyMMdd
}
class EntityLegacyDecorator {
Entity d
EntityLegacyDecorator(Entity d) { this.d = d }
String asRecord() {
return String.format('%-10s%-5d%05d%tY%<tm%<td',
d.name,d.id,d.serial,d.register)
}
}
def e = new Entity(name: 'name', id: 123, serial: 321, register: new Date('2011/05/06'))
assert new EntityLegacyDecorator(e).asRecord() == 'name 123 0032120110506'
This is workable if you don't have too many of these and the objects aren't too complex. But pretty quickly the format string gets intolerable. Then you might want decorators for Date, like:
class DateYMD {
Date d
DateYMD(d) { this.d = d }
String toString() { return d.format('yyyyMMdd') }
}
so you can format with %s:
String asRecord() {
return String.format('%-10s%-5d%05d%s',
d.name,d.id,d.serial,new DateYMD(d.register))
}
But for significant number of bean properties, the string is still too gross, so you want something that understands columns and lengths that looks like the COBOL spec you were handed, so you'll write something like this:
class RecordBuilder {
final StringBuilder record
RecordBuilder(recordSize) {
record = new StringBuilder(recordSize)
record.setLength(recordSize)
}
def setField(pos,length,String s) {
record.replace(pos - 1, pos + length, s.padRight(length))
}
def setField(pos,length,Date d) {
setField(pos,length, new DateYMD(d).toString())
}
def setField(pos,length, Integer i, boolean padded) {
if (padded)
setField(pos,length, String.format("%0" + length + "d",i))
else
setField(pos,length, String.format("%-" + length + "d",i))
}
String toString() { record.toString() }
}
class EntityLegacyDecorator {
Entity d
EntityLegacyDecorator(Entity d) { this.d = d }
String asRecord() {
RecordBuilder record = new RecordBuilder(28)
record.setField(1,10,d.name)
record.setField(11,5,d.id,false)
record.setField(16,5,d.serial,true)
record.setField(21,8,d.register)
return record.toString()
}
}
After you've written enough setField() methods to handle you legacy system, you'll briefly consider posting it on GitHub as a "framework" so the next poor sap doesn't have to to it again. But then you'll consider all the ridiculous ways you've seen COBOL store a "date" (MMDDYY, YYMMDD, YYDDD, YYYYDDD) and numerics (assumed decimal, explicit decimal, sign as trailing separate or sign as leading floating character). Then you'll realize why nobody has produced a good framework for this and occasionally post bits of your production code into SO as an example... ;)
If you are still looking for a framework, check out BeanIO at http://www.beanio.org
uniVocity-parsers goes a long way to support tricky fixed-width formats, including lines with different fields, paddings, etc.
Check out this example to write imaginary client & accounts details. This uses a lookahead value to identify which format to use when writing a row:
FixedWidthFields accountFields = new FixedWidthFields();
accountFields.addField("ID", 10); //account ID has length of 10
accountFields.addField("Bank", 8); //bank name has length of 8
accountFields.addField("AccountNumber", 15); //etc
accountFields.addField("Swift", 12);
//Format for clients' records
FixedWidthFields clientFields = new FixedWidthFields();
clientFields.addField("Lookahead", 5); //clients have their lookahead in a separate column
clientFields.addField("ClientID", 15, FieldAlignment.RIGHT, '0'); //let's pad client ID's with leading zeroes.
clientFields.addField("Name", 20);
FixedWidthWriterSettings settings = new FixedWidthWriterSettings();
settings.getFormat().setLineSeparator("\n");
settings.getFormat().setPadding('_');
//If a record starts with C#, it's a client record, so we associate "C#" with the client format.
settings.addFormatForLookahead("C#", clientFields);
//Rows starting with #A should be written using the account format
settings.addFormatForLookahead("A#", accountFields);
StringWriter out = new StringWriter();
//Let's write
FixedWidthWriter writer = new FixedWidthWriter(out, settings);
writer.writeRow(new Object[]{"C#",23234, "Miss Foo"});
writer.writeRow(new Object[]{"A#23234", "HSBC", "123433-000", "HSBCAUS"});
writer.writeRow(new Object[]{"A#234", "HSBC", "222343-130", "HSBCCAD"});
writer.writeRow(new Object[]{"C#",322, "Mr Bar"});
writer.writeRow(new Object[]{"A#1234", "CITI", "213343-130", "CITICAD"});
writer.close();
System.out.println(out.toString());
The output will be:
C#___000000000023234Miss Foo____________
A#23234___HSBC____123433-000_____HSBCAUS_____
A#234_____HSBC____222343-130_____HSBCCAD_____
C#___000000000000322Mr Bar______________
A#1234____CITI____213343-130_____CITICAD_____
This is just a rough example. There are many other options available, including support for annotated java beans, which you can find here.
Disclosure: I'm the author of this library, it's open-source and free (Apache 2.0 License)
The library Fixedformat4j is a pretty neat tool to do exactly this: http://fixedformat4j.ancientprogramming.com/
Spring Batch has a FlatFileItemWriter, but that won't help you unless you use the whole Spring Batch API.
But apart from that, I'd say you just need a library that makes writing to files easy (unless you want to write the whole IO code yourself).
Two that come to mind are:
Guava
Files.write(stringData, file, Charsets.UTF_8);
Commons / IO
FileUtils.writeStringToFile(file, stringData, "UTF-8");
Don't know of any frame work but you can just use RandomAccessFile. You can position the file pointer to anywhere in the file to do your reads and writes.
I've just find a nice library that I'm using:
http://sourceforge.net/apps/trac/ffpojo/wiki
Very simple to configurate with XML or annotations!
A simple way to write beans/entities to a flat file is to use ObjectOutputStream.
public static void writeToFile(File file, Serializable object) throws IOException {
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(file));
oos.writeObject(object);
oos.close();
}
You can write to a fixed length flat file with
FileUtils.writeByteArrayToFile(new File(filename), new byte[length]);
You need to be more specific about what you want to do with the file. ;)
Try FFPOJO API as it has everything which you need to create a flat file with fixed lengths and also it will convert a file to an object and vice versa.
#PositionalRecord
public class CFTimeStamp {
String timeStamp;
public CFTimeStamp(String timeStamp) {
this.timeStamp = timeStamp;
}
#PositionalField(initialPosition = 1, finalPosition = 26, paddingAlign = PaddingAlign.RIGHT, paddingCharacter = '0')
public String getTimeStamp() {
return timeStamp;
}
#Override
public String toString() {
try {
FFPojoHelper ffPojo = FFPojoHelper.getInstance();
return ffPojo.parseToText(this);
} catch (FFPojoException ex) {
trsLogger.error(ex.getMessage(), ex);
}
return null;
}
}

How can I used named parameters in a messages.properties file?

Is there any way to have message.properties records as follows
message.myMessage=This message is for ${name} in ${location}
as opposed to
message.myMessage = This message is for {0} in {1}
When I am creating the messages, I don't neccessarily know the order / how many parameters are needed, but I am able just pass in several properties by name, and just the correct ones would be used.
After facing the very same question and poking in source code I found a "loop-hole" that makes it possible in a very easy way:
message.myMessage = This message is for {0,,name} in {1,,location}
This approach doesn't eliminate usage of numbers. The reason to use it is to give hints to translation folks.
I am afraid not, parameters are an Object array so there is no way to define names for them. If you always passes in the array of parameter in the same order though you could use them like this:
message.myMessage = This message is for {0} in {1}
message.myNameMessage = This message is for {0}
message.myLocationMessage = This message is for people in {1}
message.myAlternateMessage = The message params are location: {1}; name: {0}
Take a look at ICU4J
It allows for something like this:
message.myMessage=This message is for {name} in {location}.
And it is way more powerful than the simple replacements suggested, because can do locale aware formatting of the parameters (ie: "Subscription expires on: {expirationDate, date, long})
http://icu-project.org/apiref/icu4j/com/ibm/icu/text/MessageFormat.html
Unfortunately the MessageFormat API does not support named parameters, only argument-index:
Patterns and Their Interpretation
MessageFormat uses patterns of the following form:
MessageFormatPattern:
String
MessageFormatPattern FormatElement String
FormatElement:
{ ArgumentIndex }
{ ArgumentIndex , FormatType }
{ ArgumentIndex , FormatType , FormatStyle }
Everything is possible for those who try... I never heard about something like that for Java, but you can write it by yourself.
Please take a look at this example:
public String format(String message, String... arguments) {
for (String argument : arguments) {
String[] keyValue = argument.split("=");
if (keyValue.length != 2)
throw new IllegalArgumentException("Incorrect argument: " + argument);
String placeholder = "${" + keyValue[0] + "}";
if (!message.contains(placeholder))
throw new IllegalArgumentException(keyValue[0] + " does not exists.");
while (message.contains(placeholder))
message = message.replace(placeholder, keyValue[1]);
}
return message;
}
It is not ideal, as you actually would call it with hardcoded string (which is generally bad idea) and you would be forced to use Strings only, but it can be done. The only question is if it is practical.
It is possible using apache commons lang library.
https://commons.apache.org/proper/commons-lang/
Properties messages = ...
Map<String, String> m = new HashMap<>();
m.put("name", "Mithu");
m.put("location", "Dhaka");
StrSubstitutor sub = new StrSubstitutor(m);
String msg = sub.replace(messages.getProperty("message.myMessage"));
// msg = This message is for Mithu in Dhaka

Is it possible to get a list of workflows the document is attached to in Alfresco

I'm trying to get a list of workflows the document is attached to in an Alfresco webscript, but I am kind of stuck.
My original problem is that I have a list of files, and the current user may have workflows assigned to him with these documents. So, now I want to create a webscript that will look in a folder, take all the documents there, and assemble a list of documents together with task references, if there are any for the current user.
I know about the "workflow" object that gives me the list of workflows for the current user, but this is not a solution for my problem.
So, can I get a list of workflows a specific document is attached to?
Well, for future reference, I've found a way to get all the active workflows on a document from javascript:
var nodeR = search.findNode('workspace://SpacesStore/'+doc.nodeRef);
for each ( wf in nodeR.activeWorkflows )
{
// Do whatever here.
}
I used packageContains association to find workflows for document.
Below i posted code in Alfresco JavaScript for active workflows (as zladuric answered) and also for all workflows:
/*global search, logger, workflow*/
var getWorkflowsForDocument, getActiveWorkflowsForDocument;
getWorkflowsForDocument = function () {
"use strict";
var doc, parentAssocs, packages, packagesLen, i, pack, props, workflowId, instance, isActive;
//
doc = search.findNode("workspace://SpacesStore/8847ea95-108d-4e08-90ab-34114e7b3977");
parentAssocs = doc.getParentAssocs();
packages = parentAssocs["{http://www.alfresco.org/model/bpm/1.0}packageContains"];
//
if (packages) {
packagesLen = packages.length;
//
for (i = 0; i < packagesLen; i += 1) {
pack = packages[i];
props = pack.getProperties();
workflowId = props["{http://www.alfresco.org/model/bpm/1.0}workflowInstanceId"];
instance = workflow.getInstance(workflowId);
/* instance is org.alfresco.repo.workflow.jscript.JscriptWorkflowInstance */
isActive = instance.isActive();
logger.log(" + instance: " + workflowId + " (active: " + isActive + ")");
}
}
};
getActiveWorkflowsForDocument = function () {
"use strict";
var doc, activeWorkflows, activeWorkflowsLen, i, instance;
//
doc = search.findNode("workspace://SpacesStore/8847ea95-108d-4e08-90ab-34114e7b3977");
activeWorkflows = doc.activeWorkflows;
activeWorkflowsLen = activeWorkflows.length;
for (i = 0; i < activeWorkflowsLen; i += 1) {
instance = activeWorkflows[i];
/* instance is org.alfresco.repo.workflow.jscript.JscriptWorkflowInstance */
logger.log(" - instance: " + instance.getId() + " (active: " + instance.isActive() + ")");
}
}
getWorkflowsForDocument();
getActiveWorkflowsForDocument();
Unfortunately the javascript API doesn't expose all the workflow functions. It look like getting the list of workflow instances that are attached to a document only works in Java (or Java backed webscripts).
List<WorkflowInstance> workflows = workflowService.getWorkflowsForContent(node.getNodeRef(), true);
A usage of this can be found in the workflow list in the document details: http://svn.alfresco.com/repos/alfresco-open-mirror/alfresco/HEAD/root/projects/web-client/source/java/org/alfresco/web/ui/repo/component/UINodeWorkflowInfo.java
To get to the users who have tasks assigned you would then need to use getWorkflowPaths and getTasksForWorkflowPath methods of the WorkflowService.

Categories

Resources