I need to convert an object of Map<String,String> with keys like "some_att_name" to class object fields like someAttName.
I couldn't find an easy way to do this.
MapStruct does support this type of mapping (From Map to object) since v1.5.0.Beta1 as stated here.
What I want should look something like this (similar to how JSON converters work):
#Mapper
public interface MapToObjectMapper {
MapToObjectMapper INSTANCE = Mappers.getMapper(MapToObjectMapper.class);
#Mapping(strategy = SnakeCaseToCamelCaseStrategy.class)
MyObject toMyObject(Map<String,String> map);
}
You'll have to translate the keys by yourself, but that's not that hard. Here is how I do it:
import org.mapstruct.Mapper;
import org.mapstruct.factory.Mappers;
import java.util.Collections;
import java.util.Map;
import java.util.regex.Pattern;
import static java.util.stream.Collectors.collectingAndThen;
import static java.util.stream.Collectors.toMap;
#Mapper
public interface MapToObjectMapper {
MapToObjectMapper INSTANCE = Mappers.getMapper(MapToObjectMapper.class);
private static String snakeToCamel(String snakeCaseString) {
// You can use Guava, Apache Commons, write it yourself or just use this one
// Credits to https://stackoverflow.com/a/67605103/4494577
return Pattern.compile("_([a-z])")
.matcher(snakeCaseString)
.replaceAll(m -> m.group(1).toUpperCase());
}
MyObject toMyObject(Map<String, String> map);
default MyObject toMyObjectFromSnakeCaseMap(Map<String, String> snakeKeyPropertyMap) {
return toMyObject(snakeKeyPropertyMap.entrySet().stream()
.collect(collectingAndThen(
toMap(s -> snakeToCamel(s.getKey()), Map.Entry::getValue),
Collections::unmodifiableMap)));
}
}
Full example: https://github.com/jannis-baratheon/stackoverflow--mapstruct-snake-case-map-mapping/
Looking at the docs I can't see a 1 step mapping. I think referring to From snake_case to camelCase in Java for converting your Map's keys to camelCase and then going for a mapper without #Mapping annotations might be your best chance.
Related
Is there any sample Scala code available for creating stored procedures in Neo4j-3.0.3 ?
I have been trying to create one simple Scala based stored procedure. Below is the Error message I get when I copy my scala-jar file to the neo4j-plugins directory and start the neo4j server :
=================
Caused by: org.neo4j.kernel.lifecycle.LifecycleException: Component 'org.neo4j.kernel.impl.proc.Procedures#1ac0223' was successfully initialized, but failed to start. Please see attached cause exception.
at org.neo4j.kernel.lifecycle.LifeSupport$LifecycleInstance.start(LifeSupport.java:444)
at org.neo4j.kernel.lifecycle.LifeSupport.start(LifeSupport.java:107)
at org.neo4j.kernel.impl.factory.GraphDatabaseFacadeFactory.newFacade(GraphDatabaseFacadeFactory.java:140)
... 10 more
Caused by: org.neo4j.kernel.api.exceptions.ProcedureException: Unable to find a usable public no-argument constructor in the class `neoscala`. Please add a valid, public constructor, recompile the class and try again.
=================
The scala class that I have used is :
package neoproc
import org.neo4j.graphdb.GraphDatabaseService
import org.neo4j.procedure.Procedure;
import javax.ws.rs.core.{Context, Response}
class neoscala(#Context db: GraphDatabaseService) {
#Procedure
def alice():String = {
String.valueOf(db.execute( "MATCH (n:User) return n" ));
}
}
Your Scala class declares a constructor with a GraphDatabaseService argument, and the exception tells you that it only wants a no-argument constructor.
It's documented in both
the user documentation:
Only static fields and #Context-annotated fields are allowed in Procedure classes.
the Javadoc:
The procedure method itself can contain arbitrary Java code - but in order to work with the underlying graph, it must have access to the graph API. This is done by declaring fields in the procedure class, and annotating them with the Context annotation. Fields declared this way are automatically injected with the requested resource. This is how procedures gain access to APIs to do work with.
All fields in the class containing the procedure declaration must either be static; or it must be public, non-final and annotated with Context.
Apparently it's not possible to create a class with a public field in Scala, so you'll have to create a parent Java class with the public field, and extend it with your Scala class:
// ProcedureAdapter.java
public abstract class ScalaProcedureAdapter {
#Context
public GraphDatabaseService db;
}
// neoscala.scala
class neoscala extends ScalaProcedureAdapter {
// ...
}
Here is the solution for this :
We will create Class in scala :
class FullTextIndex extends JavaHelper {
#Procedure("example.search")
#PerformsWrites
def search(#Name("label") label: String,
#Name("query") query: String): Stream[SearchHit] = {
//declare your method
}
val nodes: Stream[Node] = db.index.forNodes(index).query(query).stream
val newFunction: java.util.function.Function[Node, SearchHit] = (node: Node) => new SearchHit(node)
nodes.map {
newFunction
}
}
private def indexName(label: String): String = {
"label-" + label
}
}
Procedure in Neo4j always return result in Stream and it is a latest feature in Java8 so we will also used Java Class for return the final result and For defining the public variable.
We will create Java class for result :
public class JavaHelper {
#Context
public GraphDatabaseService db;
#Context
public Log log;
public static class SearchHit {
//your result code here
}
You can refer knoldus blog for Neo4j User Defined Procedure for creating and storing Neo4j Procedure with Scala. Here you will also find sample code with git hub repository.
I'm trying to extend a class (SWT.java) from a Java library (SWT) that only has static final members. An excerpt from the library class:
package org.eclipse.swt;
import org.eclipse.swt.internal.*;
public class SWT {
public static final int None = 0;
// ...
public static final int MouseDown = 3;
// ...
}
My Java wrapper class that worked fine in Java land:
public class SWT extends org.eclipse.swt.SWT {
public static final int FinalizeText = 201;
public static final int ParseText = 202;
}
Now if I try to use my new SWT class in Scala, I'll get errors like this:
Error:(198, 27) value MouseDown is not a member of object my.package.SWT
table.addListener(SWT.MouseDown, periodEditListener)
^
Ideally I would like a new SWT object with which I could access both original members (e.g. MouseDown) and members I define (e.g. FinalizeText).
It seems that Scala interprets everything useful about this class as an object, which is fine if we just want to use the original SWT definitions, but you can't easily extend objects in Scala.
It has occurred to me that implicits a la pimp my library might be the way to go, but even were I to get this to work, I think the solution would not be accessible from Java (still, I have not even gotten in to work in Scala).
How to best tackle the problem? Maybe the right answer is to just define a separate, unrelated object.
I don't think there is a good way to do what you want such that:
You can neatly tie all members to an identifier (i.e. refer to the field via SWT.X instead of X)
Have it work both in Scala and Java.
You don't have to manually forward fields.
This is a documented limitation of Scala -- see access java base class's static member in scala.
In addition, I don't think the implicit route works either, because you can't treat a Java class as a value: How to access a Java static method from Scala given a type alias for that class it resides in
Probably the best way to do what you want is to manually forward the static members you need in my.package.SWT:
public class SWT extends org.eclipse.swt.SWT {
public static final int FinalizeText = 201;
public static final int ParseText = 202;
public static int getMouseDown() {
return MouseDown;
}
}
If you only care about automatically forwarding members and not about the other requirements, you can use import:
import org.eclipse.swt.SWT._
table.addListener(MouseDown, periodEditListener)
I am accepting yuzeh's answer for thoroughness, general applicability, and helpfulness, but here is what I actually did, which is slightly different:
I was very tempted by yuzeh's last suggestion for the sake of uniformity, i.e.
import org.eclipse.swt.SWT._
import my.package.SWT._
Although as my first example snippet above inadvertently shows, SWT.None unfortunately is, so bringing it into the local namespace would conflict with Option's None.
I think for now I'll just import like:
import org.eclipse.swt.SWT
import my.package.{SWT => MySWT}
If nothing else, it is a bit more clear where the constants are coming from. There, I talked myself into believing this is better :).
I mean "structural links" in the HATEOAS/hypermedia API sense. The more general question is how to augment the generated XML with data that depends on both the entity being marshalled, and also on the environment (in this case, at least the absolute URL).
I'm using Jersey 2.9 with Moxy 2.5 as the JAXB provider.
From this model:
package testing;
import java.util.ArrayList;
import java.util.List;
public class Planet {
private int id = 1;
private String name = "test";
private double radius = 3.0;
private String href;
private List<Moon> moons = new ArrayList<Moon>(0);
public void addMoon(Moon moon) {
moons.add(moon);
}
}
...plus Moon class
I want to get something like this XML (and the equivalent JSON):
<planet href="http://mytestserver/rest/planets/test">
<name>test</name>
<radius>3.0</radius>
<moons>
<moon href="http://mytestserver/rest/moons/moon1">
<name>moon1</name>
</moon>
<moon href="http://mytestserver/rest/moons/moon2">
<name>moon2</name>
</moon>
</moons>
</planet>
The model has no "href" field, nor can one be added. Ideally I could use UriBuilder to grab these paths straight from the resource classes.
So far I've come up with several possiblities. Can I ask you to consider which (if any) has the most legs, and then how you would work around the shortcomings of that method?
1. Augment the model with AspectJ (or Javassist).
And then use the existing declarative linking mechanisms in Jersey, all of which rely on there being a field in the model to receive the generated links. This obviously won't work if you don't have AspectJ in your build process and/or balk at exotic techniques like byte code manipulation.
2. Post-process the generated XML and JSON
For example, in a MessageBodyWriter:
ContextResolver<JAXBContext> resolver = providers.getContextResolver(JAXBContext.class, mediaType);
JAXBContext context = resolver.getContext(type);
Marshaller m = context.createMarshaller();
<--- here, marshall to e.g. a DOM then transform that
<--- then manipulate the JSON structures
I have absolutely no idea how to do any of that, hence the lack of code. There may be other ways to hook into the XML generation process, but as far as I can see none of Jersey's or JAXB's event handlers or interceptors actually allow you to manipulate the generated XML/JSON.
3. Use a Moxy XMLTransformationMapping
For example:
XML binding:
<java-type name="Planet" xml-customizer="testing.HrefCustomizer">
Customizer:
public class HrefCustomizer implements DescriptorCustomizer {
#Override
public void customize(ClassDescriptor descriptor) throws Exception {
XMLTransformationMapping xtm = new XMLTransformationMapping();
xtm.addFieldTransformer("#href", new HrefWriter());
descriptor.addMapping(xtm);
}
}
Transformer:
public class HrefWriter implements FieldTransformer {
#Override
public Object buildFieldValue(Object instance, String fieldName,
Session session) {
return "href"; // constant value just for proof-of-concept
}
#Override
public void initialize(AbstractTransformationMapping mapping) {
// TODO Auto-generated method stub
}
}
I have two problems with this approach:
It was so hard to find any documentation on it that I wonder if it is in fact unsupported usage.
I can't see how the transformer is going to get a UriBuilder to work with. At minimum it would need the root URL of the rest service.
4. Slightly different Moxy xml-transform approach
If we decide we can't provide the transformer with any meaningful context at instantiation time, the customizer is adding no value and we can simplify the above to just this:
<java-type name="Planet">
<xml-root-element/>
<java-attributes>
<xml-transformation java-attribute="name">
<xml-write-transformer transformer-class="testing.HrefWriter" xml-path="#href"/>
</xml-transformation>
<xml-element java-attribute="name"/>
With the slight oddity that we are hanging the transformer off another field ("name", in this example).
5. ?????
Or, I'm completely barking up the wrong tree. Help!!
AspectJ approach
Synopsis
Use AspectJ to add a field to the model classes (called "href" in this example)
Add the Jersey #InjectLink annotation to that field
Jersey will then populate the field with the right URL as defined by the resource class
Specify the marshaling of the href field using an external mapping file.
You could also specify the marshaling of href by adding JAXB annotations to it via the same AspectJ intertype declaration mechanism.
Example code
These are the most informative bits. See http://lagod.id.au/blog/?p=494 for the full example.
The aspect
package testing;
import org.glassfish.jersey.linking.InjectLink;
import org.glassfish.jersey.linking.Binding;
public aspect HrefInjector {
private String Planet.href;
declare #field : * Planet.href : #InjectLink(
resource=Services.class,
style=InjectLink.Style.ABSOLUTE
) ;
private String Moon.href;
declare #field : * Moon.href : #InjectLink(
resource=Services.class,
method="moon",
bindings={#Binding(
name="moonid", value="${instance.name}"
)},
style=InjectLink.Style.ABSOLUTE
) ;
}
Model classes
POJOs with no REST-specific cruft. See Jersey + Moxy + JAXB - how to marshal XML without annotations.
package testing;
import java.util.ArrayList;
import java.util.List;
public class Planet {
private int id = 1;
private String name = "test";
private double radius = 3.0;
private List<Moon> moons = new ArrayList<Moon>(0);
public void addMoon(Moon moon) {
moons.add(moon);
}
}
package testing;
public class Moon {
private String name;
// No-arg constructor is a requirement of JAXB
public Moon() {
}
public Moon(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
Resource class
This is a standard JAX-RS resource class. For demo purposes, we're just returning freshly instantiated model instances.
package testing;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
#Path("/services")
#Produces({MediaType.APPLICATION_XML,MediaType.APPLICATION_JSON})
public class Services {
private Planet initPlanet() {
Planet p = new Planet();
p.addMoon(new Moon("moon1"));
p.addMoon(new Moon("moon2"));
return p;
}
#GET
public Planet planet () {
return initPlanet();
}
#GET #Path("/moons/{moonid}")
public Moon moon (#PathParam("moonid") String name) {
return new Moon(name);
}
}
Moxy mapping file
Note that you can choose for any given type whether or not you want to actually marshal the href field. In fact, by using multiple mapping files, you can include the href field in some representations and not in others.
<?xml version="1.0"?>
<xml-bindings
xmlns="http://www.eclipse.org/eclipselink/xsds/persistence/oxm"
package-name="testing"
xml-mapping-metadata-complete="true"
xml-accessor-type="NONE">
<java-types>
<java-type name="Planet">
<xml-root-element/>
<java-attributes>
<xml-attribute java-attribute="href"/>
<xml-element java-attribute="name"/>
<xml-element java-attribute="radius"/>
<xml-element java-attribute="moons" name="moon">
<xml-element-wrapper name="moons"/>
</xml-element>
</java-attributes>
</java-type>
<java-type name="Moon">
<xml-root-element/>
<java-attributes>
<xml-attribute java-attribute="href"/>
<xml-element java-attribute="name"/>
</java-attributes>
</java-type>
</java-types>
</xml-bindings>
Sample output
Ta-dah! Structural links derived automatically from the JAX-RS resource class without altering model source code. Because we're using Moxy, we also get JSON for free.
<planet href="http://localhost:8080/reststructlinks/rest/services">
<name>test</name>
<radius>3.0</radius>
<moons>
<moon href="http://localhost:8080/reststructlinks/rest/services/moons/moon1">
<name>moon1</name>
</moon>
<moon href="http://localhost:8080/reststructlinks/rest/services/moons/moon2">
<name>moon2</name>
</moon>
</moons>
</planet>
I need to manipulate owl file using the Protege-Owl API. You know, creating classes and properties isn't too difficult.But I don't know how to delete a class or property.If we treat the owl file as a graph, deleting an class means deleting an node and its direct edge.For exemple:
<owl:unionOf rdf:parseType="Collection">
<rdf:Description rdf:about="&data;DataBundle"/>
<rdf:Description rdf:about="&data;DataItem"/>
</owl:unionOf>
if I want to delete the class DataItem,
how should I do it using Protege-OWL API? Does RDFResource.delete()can achieve this? I have tried it,but I can't achieve this,maybe there is something wrong.
what will I get after I delete the DataItem?
If DataItem is the domain of an property, what will I get after I delete it?
I hope to get your answer.
Edit: the Protege OWL API is the api described here, not the OWL API described here.
#Joshua Taylor,Thank you for your answer!I'm a new user and I make a mistake for posting this problem twice.Sorry for that.I make some mistakes in my code at first and today I tried to fix it.The following codes can delete a class or property.
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.net.URI;
import edu.stanford.smi.protegex.owl.ProtegeOWL;
import edu.stanford.smi.protegex.owl.jena.JenaOWLModel;
import edu.stanford.smi.protegex.owl.model.RDFResource;
public class DeleteClass {
public static void main(String[] args) throws Exception {
// TODO Auto-generated method stub
//get model from an owl file
String filePath = "D:\\ss.owl";
FileInputStream inFile= new FileInputStream(filePath);
Reader in = new InputStreamReader(inFile,"UTF-8");
JenaOWLModel jenaOwlModel = ProtegeOWL.createJenaOWLModelFromReader(in);
//get an class from the model
RDFResource oneClass=jenaOwlModel.getRDFResource("Person");
RDFResource oneDataProperty=jenaOwlModel.getRDFResource("age");
//delete the resource
oneClass.delete();
oneDataProperty.delete();
//save the model to another owl file
URI file=URI.create("file:///D:/ssChange.owl");
System.out.println(file);
jenaOwlModel.save(file);
//System.out.println(oneClass);
}
}
I seem to be experiencing a problem when using Jackson to serialize to XML. My code is below:
TEST CONTAINER
package com.test;
import java.util.ArrayList;
import com.fasterxml.jackson.annotation.JsonProperty;
public class TestContainer {
private String testContainerID;
private String testContainerMessage;
private ArrayList<TestChild> testContainerChildren;
#JsonProperty("TestContainerID")
public String getTestContainerID() {
return testContainerID;
}
#JsonProperty("TestContainerID")
public void setTestContainerID(String testContainerID) {
this.testContainerID = testContainerID;
}
#JsonProperty("TestContainerMessage")
public String getTestContainerMessage() {
return testContainerMessage;
}
#JsonProperty("TestContainerMessage")
public void setTestContainerMessage(String testContainerMessage) {
this.testContainerMessage = testContainerMessage;
}
#JsonProperty("TestContainerChildren")
public ArrayList<TestChild> getTestContainerChildren() {
return testContainerChildren;
}
#JsonProperty("TestContainerChildren")
public void setTestContainerChildren(ArrayList<TestChild> testContainerChildren) {
this.testContainerChildren = testContainerChildren;
}
}
TESTCHILD
package com.test;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonRootName;
#JsonRootName(value="TestChild")
public class TestChild {
private String testChildID;
private String testChildMessage;
#JsonProperty("TestChildID")
public String getTestChildID() {
return testChildID;
}
#JsonProperty("TestChildID")
public void setTestChildID(String testChildID) {
this.testChildID = testChildID;
}
#JsonProperty("TestChildMessage")
public String getTestChildMessage() {
return testChildMessage;
}
#JsonProperty("TestChildMessage")
public void setTestChildMessage(String testChildMessage) {
this.testChildMessage = testChildMessage;
}
}
USE
Serialization:
XmlMapper xm = new XmlMapper();
TestContainer tc = xm.readValue(sb.toString(), TestContainer.class);
Deserialization:
System.out.println(xm.writeValueAsString(tc));
tc = xm.readValue(sb.toString(), TestContainer.class);
What I'm doing is loading an XML file from a folder on the classpath and putting the contents of the file into a StringBuffer. The problem is the generated XML for the collection of objects. When writing the XML, I want something like:
<TestContainerChildren><TestChild><...(Element Details)...></TestChild></TestContainerChildren>
but I'm getting:
<TestContainerChildren><TestContainerChildren><...(Element Details)...><TestContainerChildren></TestContainerChildren>
I'm not sure what I'm missing, here. I have no problem with the JSON part of the serialization/deserialization, only the XML. I've tried using both Jackson and JAXB annotations to turn off wrapping, I have tried using the following annotations:
#JsonRootName
#JsonProperty
#JacksonXmlElementWrapper
#JacksonElement
#XmlElementWrapper
#XmlElement
I'm pretty sure this is something stupid on my part, but any help would be most appreciated.
Ok, couple of notes. First, #JsonRootName only affects name used for the root of XML document, as name implies. So it is not used for TestChild. Second, it sounds like you want to use so-called "unwrapped" output for Lists, omitting element for property that contains List elements. This is doable with:
#JacksonXmlElementWrapper(useWrapping=false)
#JsonProperty("TestContainerChildren")
public ArrayList<TestChild> getTestContainerChildren() { ... }
since default setting is to use wrapper (this is different from JAXB, where unwrapped is the default). Or, if you want to change this globally to assume unwrapped as default, you can change the defaults via XmlModule:
JacksonXmlModule module = new JacksonXmlModule();
// to default to using "unwrapped" Lists:
module.setDefaultUseWrapper(false);
XmlMapper xmlMapper = new XmlMapper(module);
Hope this helps!
I got this working by using the following annotations above the variable declaration:
#JacksonXmlElementWrapper(localName="[insert collection name]")
#JacksonXmlProperty(localName="[insert collection element name]")
This was a simple case of RTFM, as it's documented here.