Generic XML utility -- in java jdom - java

Please suggest me how to do the following utility in java,
Want to create the generic java class to generate the XML with JDOM.
Class is capable enough to generate the any xml structure in runtime depends on parameter pass -- How?
For example, In my module I need to create the XML which having 3 different child with one root i.e.
<Child>
<A> This is normal text </A>
<B> This is normal text </B>
<C> This is normal text </C>
</Child>
But in another module we required another XML file which having the 10 child with some attribute.
So we decided to go for generic XML utility which generate the XML file in runtime in specific folder.
Utility will help us to avoid the redundant code in the application and easy to manage as well...
Please help your friend...
Thanks
Gladiator

You can do via XStream like this:
public static String getXMLFromObject(Object toBeConverted, String classNameAlias, Map<String, String> fieldAlias,
List<String> fieldsToBeOmitted) {
StringBuilder objectAsXML = new StringBuilder();
if(toBeConverted != null){
XStream xStream = new XStream(new DomDriver());
if(classNameAlias != null && classNameAlias != "" && classNameAlias.trim().length() > 0) {
xStream.alias(classNameAlias, toBeConverted.getClass());
}
if(fieldAlias != null && !fieldAlias.isEmpty()){
for (Entry<String, String> entry : fieldAlias.entrySet()) {
xStream.aliasField(entry.getKey(), toBeConverted.getClass(), entry.getValue());
}
}
if(fieldsToBeOmitted != null && fieldsToBeOmitted.size() > 0){
for (String fieldToBeOmitted : fieldsToBeOmitted) {
xStream.omitField(toBeConverted.getClass(), fieldToBeOmitted);
}
}
objectAsXML.append(xStream.toXML(toBeConverted));
}
return objectAsXML.toString();
}
If you have control over the classes which you are going to convert into XML then I would suggest to have an interface something like XMLConvertable with some structure like
public interface XMLConvertable {
public String getClassAlias();
public List<String> getFieldToBeOmitted();
public Map<String, String> getFieldAliases();
}
In that case you don't need to send last three parameters in the above method just get it from the objectToBeConverted and also it makes more sense as every object in the system can declare itself whether it can be converted to XML or not.

Related

Write elements of a map to a CSV correctly in a simplified way in Java 8

I have a countries Map with the following design:
England=24
Spain=21
Italy=10
etc
Then, I have a different citiesMap with the following design:
London=10
Manchester=5
Madrid=7
Barcelona=4
Roma=3
etc
Currently, I am printing these results on screen:
System.out.println("\nCountries:");
Map<String, Long> countryMap = countTotalResults(orderDataList, OrderData::getCountry);
writeResultInCsv(countryMap);
countryMap.entrySet().stream().forEach(System.out::println);
System.out.println("\nCities:\n");
Map<String, Long> citiesMap = countTotalResults(orderDataList, OrderData::getCity);
writeResultInCsv(citiesMap);
citiesMap.entrySet().stream().forEach(System.out::println);
I want to write each line of my 2 maps in the same CSV file. I have the following code:
public void writeResultInCsv(Map<String, Long> resultMap) throws Exception {
File csvOutputFile = new File(RUTA_FICHERO_RESULTADO);
try (PrintWriter pw = new PrintWriter(csvOutputFile)) {
resultMap.entrySet().stream()
.map(this::convertToCSV)
.forEach(pw::println);
}
}
public String convertToCSV(String[] data) {
return Stream.of(data)
.map(this::escapeSpecialCharacters)
.collect(Collectors.joining("="));
}
public String escapeSpecialCharacters(String data) {
String escapedData = data.replaceAll("\\R", " ");
if (data.contains(",") || data.contains("\"") || data.contains("'")) {
data = data.replace("\"", "\"\"");
escapedData = "\"" + data + "\"";
}
return escapedData;
}
But I get compilation error in writeResultInCsv method, in the following line:
.map(this::convertToCSV)
This is the compilation error I get:
reason: Incompatible types: Entry is not convertible to String[]
How can I indicate the following result in a CSV file in Java 8 in a simplified way?
This is the result and design that I want my CSV file to have:
Countries:
England=24
Spain=21
Italy=10
etc
Cities:
London=10
Manchester=5
Madrid=7
Barcelona=4
Roma=3
etc
Your resultMap.entrySet() is a Set<Map.Entry<String, Long>>. You then turn that into a Stream<Map.Entry<String, Long>>, and then run .map on this. Thus, the mapper you provide there needs to map objects of type Map.Entry<String, Long> to whatever you like. but you pass the convertToCSV method to it, which maps string arrays.
Your code tries to join on comma (Collectors.joining(",")), but your desired output contains zero commas.
It feels like one of two things is going on:
you copy/pasted this code from someplace or it was provided to you and you have no idea what any of it does. I would advise tearing this code into pieces: Take each individual piece, experiment with it until you understand it, then put it back together again and now you know what you're looking at. At that point you would know that having Collectors.joining(",") in this makes no sense whatsoever, and that you're trying to map an entry of String, Long using a mapping function that maps string arrays - which obviously doesn't work.
You would know all this stuff but you haven't bothered to actually look at your code. That seems a bit surprising, so I don't think this is it. But if it is - the code you have is so unrelated to the job you want to do, that you might as well remove your code entirely and turn this question into: "I have this. I want this. How do I do it?"
NB: A text file listing key=value pairs is not usually called a CSV file.

Leave entities as-is when parsing XML with Woodstox

I'm using Woodstox to process an XML that contains some entities (most notably >) in the value of one of the nodes. To use an extreme example, it's something like this:
<parent> < > & " &apos; </parent>
I have tried a lot of different configuration options for both WstxInputFactory (IS_REPLACING_ENTITY_REFERENCES, P_TREAT_CHAR_REFS_AS_ENTS, P_CUSTOM_INTERNAL_ENTITIES...) and WstxOutputFactory, but no matter what I try, the output is always something like this:
<parent>nbsp; < nbsp; > & " ' nbsp;</parent>
(> gets converted to >, < stays the same, loses the &...)
I'm reading the XML with an XMLEventReader created with
XMLEventReader reader = wstxInputFactory.createXMLEventReader(new StringReader(fulltext));
after configuring the WstxInputFactory.
Is there any way to configure Woodstox to just ignore all entities and output the text exactly as it was in the input String?
First of all, you need to include actual code since "output is always something like this" makes no sense without explaining exactly how are you outputting content that is parsed: you may be printing events, using some library, or perhaps using Woodstox stream or event writer.
Second: there is difference in XML between small number of pre-defined entities (lt, gt, apos, quot, amp), and arbitary user-defined entities like what nbsp here would be. Former you can use as-is, they are already defined; latter only exist if you define them in DTD.
Handling of the two groups is different, too; former will always be expanded no matter what, and this is by XML specification. Latter will be resolved (unless resolution disabled), and then expanded -- or if not defined exception will be thrown.
You can also specify custom resolver as mention by the other answer; but this will only be used for custom entities (here, ).
In the end it is also good to explain not what you are doing as much as what you are trying to achieve. That will help suggest things better than specific questions of "how do I do X" which may not be the ways to go about.
And as to configuration of Woodstox, maybe this blog entry:
https://medium.com/#cowtowncoder/configuring-woodstox-xml-parser-woodstox-specific-properties-1ce5030a5173
will help (as well as 2 others in the series) -- it covers existing configuration settings.
The basic five XML entities (quot, amp, apos, lt, gt) will be always processed. As far as I know there is no way to get the source of them with Sax.
For the other entities you can process them manually. You can capture the events until the end of the element and concatenate the values:
XMLInputFactory factory = WstxInputFactory.newInstance();
factory.setProperty(XMLInputFactory.IS_REPLACING_ENTITY_REFERENCES, Boolean.FALSE);
XMLEventReader xmlr = factory.createXMLEventReader(
this.getClass().getResourceAsStream(xmlFileName));
String value = "";
while (xmlr.hasNext()) {
XMLEvent event = xmlr.nextEvent();
if (event.isCharacters()) {
value += event.asCharacters().getData();
}
if (event.isEntityReference()) {
value += "&" + ((EntityReference) event).getName() + ";";
}
if (event.isEndElement()) {
// Assign it to the right variable
System.out.println(value);
value = "";
}
}
For your example input:
<parent> < > & " &apos; </parent>
The output will be:
< > & " '
Otherwise if you want to convert all the entities maybe you could use a custom XmlResolver for undeclared entities:
public class NaiveHtmlEntityResolver implements XMLResolver {
private static final Map<String, String> ENTITIES = new HashMap<>();
static {
ENTITIES.put("nbsp", " ");
ENTITIES.put("apos", "'");
ENTITIES.put("quot", "\"");
// and so on
}
#Override
public Object resolveEntity(String publicID,
String systemID,
String baseURI,
String namespace) throws XMLStreamException {
if (publicID == null && systemID == null) {
return ENTITIES.get(namespace);
}
return null;
}
}
And then tell Woodstox to use it for the undeclared entities:
factory.setProperty(WstxInputProperties.P_UNDECLARED_ENTITY_RESOLVER, new NaiveHtmlEntityResolver());

How can i get all the data properties of a class using OWL API?

public void getEquivalentClassesForClass(OWLClass owlClass, OWLOntology ont) {
Stack<OWLClassAxiom> axiomStack = new Stack<OWLClassAxiom>();
axiomStack.addAll(ont.getAxioms(owlClass, null));
List<OWLClass> equivList = new ArrayList<OWLClass>();
while(!axiomStack.isEmpty()) {
OWLClassAxiom a = axiomStack.pop();
if (a.isOfType(AxiomType.EQUIVALENT_CLASSES) && a.getClassesInSignature().size() == 3) {
Iterator<OWLClass> iter = a.getClassesInSignature().iterator();
OWLClass equivClass = iter.next();
equivList.add(equivClass);
}
}
}
Now i need all the data properties that are defined on owl class i.e equivClass in my code. Is there any way to get this. I havent found any api on the given owl class.
As far as I know, you cannot directly get the data properties that have a particular class in their domain.
You can call ont.getAxioms(AxiomType.DATA_PROPERTY_DOMAIN); which will return all of the domain axioms for all data properties in your ontology, which you can then get the domain classes out of by iterating over this set of axioms.
for(OWLDataPropertyDomainAxiom d : set) {
d.getDomain();
}
where the d.getDomain(); call will return the class in the axiom. You can then check if this class matches the one you are searching for.

ASM to parse .class against the rule defined in xml

I am using ASM bytecode reader to parse .class file present in the code.
But I want to get the particular string defined in the class which inturn will be mentioned inside the xml.
So how to use XML and parse the string present in .class. As I see there is ClassReader only takes .class as a parameter not the XML or any other format.
I am using something like this:
InputStream in=String.class.getResourceAsStream("/java/lang/String.class");
ClassReader classReader=new ClassReader(in);
classReader.accept(v, 0);
please tell me is there any way to parse .class against the rule defined in xml file?
Thanks in advance...
Yashu
As I understand it, you want to do the following: You are receiving a .class file and you then want to extract some sort of information from it which is specified in an XML file. If this is so: ASM does not need to know about what kind of information you are requiring. ASM will plainly read the class file. If you plainly want to know if some specific String is part of the class's constant pool, you could use a short cut for being notified of that: Override the ClassReader's readUTF8(int, char[]) method like this:
public MyClassReader extends ClassReader {
private final Set<String> constantPoolStrings = new HashSet<String>();
// Add constructors here
#Override
public String readUTF8(int index, char[] buf) {
String value = super.readUTF8(index, buf);
constantPoolStrings.add(value);
return value;
}
public boolean hasString(String value) {
// From the details in your comment, we will need to do a fuzzy search.
for(String poolString : constantPoolStrings) {
if(poolString.contains(value)) {
return true;
}
}
return false;
}
}
Of course you have to provide some logic that knows what String you are interested in: If you for example have an XML file that contains specific words you will need to parse this file and extract these words. You can than query the MyClassReader for these Strings.

javaReflection return a list of classes that implement specific interface

I have a package which contains an interface and several classes,some classes in this package implement that interface ,In one class that does not implement that interface,I want to write a method that returns an object of all classes which implement that interface,I dont know the name of classes which implement that interface,how can I write this method?
Generally such functionality is missing in java reflection API. but your can probably implement it yourself pretty easily.
Shortly you can use systemp property java.class.path to get all classpath elements. Split it using property path.separator. Then iterate over the resulted array, read each jar file using JAR API, instantiate each Class and check if your interface isAssignableFrom(theClass).
Here is the code snippet that looks for all BSF engines available in your classpath. I wrote it for my blog post I am working on this days. This code has limitation: it works with jar files only. I believe it is enough to explain the idea.
private static Map<String, Boolean> getEngines() throws Exception {
Map<String, Boolean> result = new HashMap<String, Boolean>();
String[] pathElements = System.getProperty("java.class.path").split(System.getProperty("path.separator"));
for (String pathElement : pathElements) {
File resource = new File(pathElement);
if (!resource.isFile()) {
continue;
}
JarFile jar = new JarFile(resource);
for (Enumeration<JarEntry> e = jar.entries(); e.hasMoreElements();) {
JarEntry entry = e.nextElement();
if(entry.isDirectory()) {
continue;
}
if(!entry.getName().endsWith("Engine.class")) {
continue;
}
String className = entry.getName().replaceFirst("\\.class$", "").replace('/', '.');
try {
if(BSFEngine.class.getName().equals(className)) {
continue;
}
Class<?> clazz = Class.forName(className);
if(BSFEngine.class.isAssignableFrom(clazz) && !clazz.equals(BSFEngine.class)) {
result.put(className, true);
}
} catch (NoClassDefFoundError ex) {
// ignore...
result.put(className, false);
}
}
}
return result;
}
The method returns Map where engine class name is used as a key and boolean value indicates whether the engine is available. Engine is unavailable if it requires additional classes in classpath.
There is no straightforward solution for this problem but I suggest you to use reflections library.
Once you have it, you can just do:
Reflections reflections = new Reflections("my.project.prefix");
Set<Class<? extends SomeClassOrInterface>> subTypes =
reflections.getSubTypesOf(SomeClassOrInterface.class);
If I understand your question correctly, you need a way to check, whether particular class from the list implements some specific interface. You may use Class.getInterfaces() method for that.
If you have troubles with listing all classes from particular package, you may take a look, for example, at this question and at further links there.

Categories