parsing subnodes with Jersey - java

We are connecting to a third party using Jersey. We then want to extract the returned xml into our class. This is actually working fine except for one node in the xml that is in a subnode.
Here is the xml returned:
<response>
...
<langISO>en</langISO>
<acquirerAmount>1000</acquirerAmount>
<acquirerCurrency>GBP</acquirerCurrency>
<subXml>
<authCode>122958</authCode>
</subXml>
</response>
Note that the authCode node is in a subnode (called subXml).
OurResponse myriadResponse = response.getEntity(OurResponse.class);
Here is our class, but it is not parsing out the authCode
package com.xxx;
import javax.ws.rs.Consumes;
import javax.ws.rs.Path;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
#XmlRootElement
#Consumes("application/xml")
public class OurResponse {
private String authCode;
#XmlElement(name = "subXml/authCode")
public String getAuthCode() {
return authCode;
}
#XmlElement(name = "subXml/authCode")
public void setAuthCode(String authCode) {
this.authCode = authCode;
}
}

You have a couple different options:
Option 1 - MOXy JAXB & #XmlPath
You could use the MOXy JAXB implementation and the #XmlPath extension to achieve the desired result:
import javax.xml.bind.annotation.XmlRootElement;
import org.eclipse.persistence.oxm.annotations.XmlPath;
#XmlRootElement(name="response")
public class OurResponse {
private String authCode;
#XmlPath("subXml/authCode/text()")
public String getAuthCode() {
return authCode;
}
public void setAuthCode(String authCode) {
this.authCode = authCode;
}
}
For more information see:
http://bdoughan.blogspot.com/2010/09/xpath-based-mapping-geocode-example.html
Option 2 - Any JAXB Impl and #XmlJavaTypeAdapter
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
#XmlRootElement(name="response")
public class OurResponse {
private String authCode;
#XmlJavaTypeAdapter(AuthCodeAdapter.class)
#XmlElement(name="subXml")
public String getAuthCode() {
return authCode;
}
public void setAuthCode(String authCode) {
this.authCode = authCode;
}
}
with
import javax.xml.bind.annotation.adapters.XmlAdapter;
public class AuthCodeAdapter extends XmlAdapter<SubXml, String> {
#Override
public String unmarshal(SubXml v) throws Exception {
return v.getAuthCode();
}
#Override
public SubXml marshal(String v) throws Exception {
SubXml subXml = new SubXml();
subXml.setAuthCode(v);
return subXml;
}
}
and
public class SubXml {
private String authCode;
public String getAuthCode() {
return authCode;
}
public void setAuthCode(String authCode) {
this.authCode = authCode;
}
}
For more information see:
http://bdoughan.blogspot.com/2010/07/xmladapter-jaxbs-secret-weapon.html

I don't think you can annotate with XmlElement like that. You might need to create a seperate SubXml class;
import javax.xml.bind.annotation.XmlRootElement;
#XmlRootElement(name="response")
public class OurResponse
{
private String lang;
private String amt;
private String curr;
private SubXml subXml;
public OurResponse()
{
}
//Getters and setters
}
and
public class SubXml
{
private String authcode;
public SubXml()
{
}
public String getAuthcode()
{
return authcode;
}
public void setAuthcode(String authcode)
{
this.authcode = authcode;
}
}
Note that the only annotation you need is #XmlRootElement on the OurResponse class and you need to set the name; name="response".

Related

Error in fetching table through JpaRepository

I am trying to fetch data from a table in MySQL using JpaRepository.
I am geeting an error by running code like -
Error creating bean with name 'chassiscontroller': Unsatisfied dependency expressed through field 'service': Error creating bean with name 'chassisserviceimpl': Unsatisfied dependency expressed through field 'dao': Error creating bean with name 'chassisdao' defined in com.ChassisInfo.chassis.dao.chassisdao defined in #EnableJpaRepositories declared on JpaRepositoriesRegistrar.EnableJpaRepositoriesConfiguration: Not a managed type: class com.ChassisInfo.model.chassismodel.
Controller
package com.ChassisInfo.chassis.controller;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import com.ChassisInfo.chassis.model.ChassisModel;
import com.ChassisInfo.chassis.service.ChassisService;
#RestController
public class ChassisController {
#Autowired
private ChassisService service;
#GetMapping("/chnum")
public List<ChassisModel> getchassisnumberinfo(){
return service.getAll();
}
}
Service-
package com.ChassisInfo.chassis.service;
import java.util.List;
import com.ChassisInfo.chassis.model.ChassisModel;
public interface ChassisService{
List<ChassisModel> getAll();
}
ServiceImpl-
package com.ChassisInfo.chassis.service;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.ChassisInfo.chassis.dao.ChassisDao;
import com.ChassisInfo.chassis.model.ChassisModel;
#Service
#lombok.AllArgsConstructor
#lombok.NoArgsConstructor
public class ChassisServiceimpl implements ChassisService {
#Autowired
private ChassisDao dao;
#Override
public List<ChassisModel> getAll() {
// TODO Auto-generated method stub
return dao.findAll();
}
Dao-
package com.ChassisInfo.chassis.dao;
import java.util.List;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.stereotype.Repository;
import com.ChassisInfo.chassis.model.ChassisModel;
#Repository
#EnableJpaRepositories
public interface ChassisDao extends JpaRepository<ChassisModel,String> {
#Query(value = "Select * from chassis_master" ,nativeQuery = true)
List<ChassisModel> findAll();
}
Model-
package com.ChassisInfo.model;
public class chassismodel {
private String vin;
private String active;
private String chassisNumber;
private String chassisSeries;
private String statusChangedTime;
private String tag;
private String truckid;
private String id;
private String chassis_number;
private String chassis_series;
private String status_changed_time;
private String truck_id;
public String getVin() {
return vin;
}
public void setVin(String vin) {
this.vin = vin;
}
public String getActive() {
return active;
}
public void setActive(String active) {
this.active = active;
}
public String getChassisSeries() {
return chassisSeries;
}
public void setChassisSeries(String chassisSeries) {
this.chassisSeries = chassisSeries;
}
public String getStatusChangedTime() {
return statusChangedTime;
}
public void setStatusChangedTime(String statusChangedTime) {
this.statusChangedTime = statusChangedTime;
}
public String getTag() {
return tag;
}
public void setTag(String tag) {
this.tag = tag;
}
public String getTruckid() {
return truckid;
}
public void setTruckid(String truckid) {
this.truckid = truckid;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getChassis_number() {
return chassis_number;
}
public void setChassis_number(String chassis_number) {
this.chassis_number = chassis_number;
}
public String getChassis_series() {
return chassis_series;
}
public void setChassis_series(String chassis_series) {
this.chassis_series = chassis_series;
}
public String getStatus_changed_time() {
return status_changed_time;
}
public void setStatus_changed_time(String status_changed_time) {
this.status_changed_time = status_changed_time;
}
public String getTruck_id() {
return truck_id;
}
public void setTruck_id(String truck_id) {
this.truck_id = truck_id;
}
public String getChassisNumber() {
return chassisNumber;
}
public void setChassisNumber(String chassisNumber) {
this.chassisNumber = chassisNumber;
}
}
ChassisApplication-
package com.ChassisInfo.chassis;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import com.ChassisInfo.chassis.controller.ChassisController;
#SpringBootApplication
#EnableJpaRepositories
public class ChassisApplication {
public static void main(String[] args) {
ApplicationContext context = SpringApplication.run(ChassisApplication.class, args);
ChassisController chassisController = context.getBean(ChassisController.class);
chassisController.getchassisnumberinfo();
}
}
Try to use #RequiredArgsConstructor (lombok) in chassisserviceimpl, since dao field is not accessible for autowiring. Also add final for the field:
private final chassisdao dao;
This is probably because you are missing the #EnableJpaRepositories(basePackages = "your.package.name") in you #SpringBootApplication
This is the Annotation to enable JPA repositories. Will scan the package of the annotated configuration class for Spring Data repositories by default.

unmarshaling always shows 0 and null

I think the best way is to copy my code so you can understand it.
Here are my POJO classes:
import javax.xml.bind.annotation.XmlAttribute;
public class Product {
private String name;
public Product() {
}
public Product(String name) {
this.name = name;
}
#XmlAttribute(name = "productName")
public String getProduct() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
import java.util.ArrayList;
import java.util.List;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
#XmlRootElement(name="ShoppingCart")
public class Cart {
private List<Product> productList = new ArrayList<>();
private long CartIdentifier;
public Cart() {
}
public Cart(long id) {
this.CartIdentifier=id;
}
#XmlAttribute(name="CartIdentifier")
public long getId() {
return CartIdentifier;
}
public void setType(long id) {
this.CartIdentifier=id;
}
public Cart(List<Product> list) {
this.productList = list;
}
public void addElement(Product element) {
this.productList.add(element);
}
#XmlElement(name = "CurrentProducts")
public List<Product> getCart() {
return this.productList;
}
public void setCart(List<Product> cart) {
this.productList = cart;
}
}
import java.util.ArrayList;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
#XmlRootElement(name = "CashRegister")
public class Register {
#XmlElement(name = "ShoppingCart")
private ArrayList<Cart> listCart;
long CartIdentifier;
public Register() {
}
public Register(long id) {
this.CartIdentifier=id;
}
public long getId() {
return CartIdentifier;
}
public void addElementforBonus(Cart element) {
listCart.add(element);
}
public void setType(long id) {
this. CartIdentifier=id;
}
public void setList(ArrayList<Cart> list) {
this.listCart = list;
}
public ArrayList<Cart> getCartList() {
return listCart;
}
}
So those are my POJO classes and in main they create perfect XML, but when it comes to converting from XML to normal output something goes wrong. Can someone tell me where am I making mistake and why is my output than alway 0 and null?
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
public class Main {
public static void main(String[] args) throws JAXBException, IOException {
ArrayList<Cart> list = new ArrayList<Cart>();
Register store = new Register(1);
store.setType(1);
store.setList(list);
Product first = new Product("Burger");
Product second = new Product("Banana");
Cart cart1 = new Cart(1);
cart1.setType(1);
cart1.addElement(first);
cart1.addElement(second);
store.getCartList().add(cart1);
// create JAXB context and instantiate marshaller
JAXBContext context = JAXBContext.newInstance(Register.class);
Marshaller m = context.createMarshaller();
m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
// Write to System.out
m.marshal(store, System.out);
m.marshal(store, new File("mrs.xml"));
System.out.println("Output from our XML File: ");
Unmarshaller um = context.createUnmarshaller();
Register reg = (Register) um.unmarshal(new FileReader("mrs.xml"));
ArrayList<Cart> list1 = reg.getCartList();
for(Cart x:reg.getCartList()) {
System.out.println(x.getId());
}
for (Cart cart : list1) {
System.out.println("Cart: " + cart.getId());
for(Product product : cart.getCart()) {
System.out.println("Product: " + product.getProduct());
}
}
}
}
So here is my output:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<CashRegister>
<ShoppingCart CartIdentifier="1">
<CurrentProducts productName="Burger"/>
<CurrentProducts productName="Banana"/>
</ShoppingCart>
</CashRegister>
Output from our XML File:
0
Cart: 0
Product: null
Product: null
There is one cart with two products but not with 0 and null.
No, my question isn't duplicate. I don't want to have that as Element or show the name of that element in my xml. My xml looks perfect but i can't unmarshal it
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<CashRegister>
<ShoppingCart CartIdentifier="1">
<CurrentProducts productName="Burger"/>
<CurrentProducts productName="Banana"/>
</ShoppingCart>
</CashRegister>
Output from our XML File:
Exception in thread "main" java.lang.ClassCastException: bonusxml.Register cannot be cast to bonusxml.Register1
at bonusxml.Main.main(Main.java:45)
If you are hell bent on preserving your XML structure, you will have to pay a price for that. Below, are classes that can get you de-serializing the XML you have created. But, you will end up using two different set of classes for serializing and de-serializing.
Cart.java
#XmlRootElement(name="ShoppingCart")
public class Cart1 {
#XmlElement(name = "CurrentProducts")
private List<Product1> productList = new ArrayList<>();
#XmlAttribute(name="CartIdentifier")
private long CartIdentifier;
public Cart1() {}
public Cart1(long id) {
this.CartIdentifier=id;
}
// setters & getters
}
Product.java
public class Product1 {
#XmlAttribute(name = "productName")
private String name;
public Product1() {
}
public Product1(String name) {
this.name = name;
}
// setters & getters
}
Register.java
#XmlRootElement(name = "CashRegister")
public class Register1 {
#XmlElement(name = "ShoppingCart")
private ArrayList<Cart1> listCart;
long CartIdentifier;
public Register1() {
}
public Register1(long id) {
this.CartIdentifier=id;
}
//setters & getters
}

How to create POJO for duplicate property name in JSON for Android Retrofit library

I have the following JSON to create POJO and that the POJOs will be used in Android Retrofit library but how to create POJO classes with duplicate JSON property name?
My sample JSON:
{
"result": {
"detail": {
"name": "sample"
}
},
"info": {
"detail": {
"user_information": "user"
}
}
}
Here JSON object detail is duplicated in info and result JSON objects, if I create detail.java for result and detail_.java for info then get null pointer exception from Retrofit library (I hope, get the exception for property name mismatch with pojo classes).
Create pojo like this using inner classes.
public class JsonResponse{
public Result result;
public Info info;
//Getters and Setters
public class Result{
public NameDetails detail;
//Getters and Setters
public class NameDetails{
public String name;
//Getters and Setters
}
}
public class Info{
public UserInfoDetails detail;
//Getters and Setters
public class UserInfoDetails {
public String user_information;
//Getters and Setters
}
}
}
You can use this site to convert json into pojo classes. Secondary you can declare Detail class inside Result class and Info class as a inner class. Example :- View.OnClickListener and DialogInterface.OnClickListener. In this example, OnClickListener interface name is same so we need to write outer class name to distinguish.
For your case, this is json converted by site:-
-----------------------------------com.example.Detail.java-----------------------------------
package com.example;
import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;
public class Detail {
#SerializedName("name")
#Expose
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
-----------------------------------com.example.Detail_.java-----------------------------------
package com.example;
import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;
public class Detail_ {
#SerializedName("user_information")
#Expose
private String userInformation;
public String getUserInformation() {
return userInformation;
}
public void setUserInformation(String userInformation) {
this.userInformation = userInformation;
}
}
-----------------------------------com.example.Example.java-----------------------------------
package com.example;
import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;
public class Example {
#SerializedName("result")
#Expose
private Result result;
#SerializedName("info")
#Expose
private Info info;
public Result getResult() {
return result;
}
public void setResult(Result result) {
this.result = result;
}
public Info getInfo() {
return info;
}
public void setInfo(Info info) {
this.info = info;
}
}
-----------------------------------com.example.Info.java-----------------------------------
package com.example;
import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;
public class Info {
#SerializedName("detail")
#Expose
private Detail_ detail;
public Detail_ getDetail() {
return detail;
}
public void setDetail(Detail_ detail) {
this.detail = detail;
}
}
-----------------------------------com.example.Result.java-----------------------------------
package com.example;
import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;
public class Result {
#SerializedName("detail")
#Expose
private Detail detail;
public Detail getDetail() {
return detail;
}
public void setDetail(Detail detail) {
this.detail = detail;
}
}

Cassandra entities must have the #Table, #Persistent or #PrimaryKeyClass Annotation

I am working on spring boot application and trying to connect with Data Stax Cassandra. Below is the I have written.
package com.sampleProj.dto;
import java.io.Serializable;
import java.sql.Blob;
import java.sql.Timestamp;
import org.springframework.data.cassandra.mapping.Column;
import org.springframework.data.cassandra.mapping.PrimaryKey;
import org.springframework.data.cassandra.mapping.Table;
#Table
public class Inbound implements Serializable{
#PrimaryKey
private int transactionalId;
#Column
private Timestamp received;
#Column
private String source;
#Column
private String service;
#Column
private Blob message;
public Inbound(int transactionalId, Timestamp received, String source, String service, Blob message) {
super();
this.transactionalId = transactionalId;
this.received = received;
this.source = source;
this.service = service;
this.message = message;
}
public Inbound() {
// TODO Auto-generated constructor stub
}
public int getTransactionalId() {
return transactionalId;
}
public void setTransactionalId(int transactionalId) {
this.transactionalId = transactionalId;
}
public Timestamp getReceived() {
return received;
}
public void setReceived(Timestamp received) {
this.received = received;
}
public String getSource() {
return source;
}
public void setSource(String source) {
this.source = source;
}
public String getService() {
return service;
}
public void setService(String service) {
this.service = service;
}
public Blob getMessage() {
return message;
}
public void setMessage(Blob message) {
this.message = message;
}
}
DAO:
package com.sampleProj.dao;
import org.springframework.data.cassandra.repository.CassandraRepository;
import com.sampleProj.dto.Inbound;
public interface TripDAO extends CassandraRepository<Inbound>{
}
Configuration:
package com.sampleProj;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;
#SpringBootApplication
public class SampleProConfiguration {
public static void main(String[] args) {
ApplicationContext ctx = SpringApplication.run(SampleProConfiguration .class, args);
}
}
CassandraConfiguration:
package com.sampleProj;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.cassandra.config.CassandraClusterFactoryBean;
import org.springframework.data.cassandra.config.java.AbstractCassandraConfiguration;
import org.springframework.data.cassandra.convert.MappingCassandraConverter;
import org.springframework.data.cassandra.core.CassandraOperations;
import org.springframework.data.cassandra.core.CassandraTemplate;
import org.springframework.data.cassandra.mapping.BasicCassandraMappingContext;
import org.springframework.data.cassandra.mapping.CassandraMappingContext;
import org.springframework.data.cassandra.repository.config.EnableCassandraRepositories;
#Configuration
#EnableCassandraRepositories
public class CassandraConfiguration extends AbstractCassandraConfiguration{
#Bean
#Override
public CassandraClusterFactoryBean cluster() {
CassandraClusterFactoryBean cluster = new CassandraClusterFactoryBean();
cluster.setContactPoints("localhost");
cluster.setPort(9042);
return cluster;
}
#Override
protected String getKeyspaceName() {
return "mykeyspace";
}
#Bean
#Override
public CassandraMappingContext cassandraMapping() throws ClassNotFoundException {
return new BasicCassandraMappingContext();
}
}
Dependencies:
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-cassandra</artifactId>
</dependency>
But I am getting the exception as Cassandra entities must have the #Table, #Persistent or #PrimaryKeyClass Annotation. Please help me in resolving the issue. Thanks in advance.
Not the case in this example, but for future readers.. I received the same error when annotating my pojo/table class with:
#javax.persistence.Table
rather than:
#org.springframework.data.cassandra.mapping.Table
Your Inbound class does not know which table to refer in cassandra. Provide table name after #Table annotation like:
#Table(value="table_name_here").

Java Unmarshal list of objects with a class wrapper with JAXB

From an XQuery performed by BaseX server I get a result like that:
<ProtocolloList>
<protocollo>
<numero>1</numero>
<data>2014-06-23</data>
<oggetto/>
<destinatario/>
<operatore/>
</protocollo>
...
</ProtocolloList>
And I need to convert this result in a List of Protocollo objects with JAXB so that I can show them with JList. Thus, following one of the discussions here I've declared the following classes:
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
#XmlRootElement(name = "protocollo")
public class Protocollo {
private int numero;
private String data;
private String oggetto;
private String destinatario;
private String operatore;
public Protocollo(String d, String o, String des, String op) {
this.data = d;
this.oggetto = o;
this.destinatario = des;
this.operatore = op;
}
public Protocollo() {
}
#XmlElement
public int getNumero() {
return numero;
}
public void setNumero(int numero) {
this.numero = numero;
}
#XmlElement
public String getData() {
return data;
}
public void setData(String data) {
this.data = data;
}
#XmlElement
public String getOggetto() {
return oggetto;
}
public void setOggetto(String oggetto) {
this.oggetto = oggetto;
}
#XmlElement
public String getDestinatario() {
return destinatario;
}
public void setDestinatario(String destinatario) {
this.destinatario = destinatario;
}
#XmlElement
public String getOperatore() {
return operatore;
}
public void setOperatore(String operatore) {
this.operatore = operatore;
}
}
and
import java.util.ArrayList;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlElementWrapper;
import javax.xml.bind.annotation.XmlRootElement;
#XmlRootElement(name = "ProtocolloList")
public class ProtocolloList {
#XmlElementWrapper(name = "ProtocolloList")
#XmlElement(name = "protocollo")
private ArrayList<Protocollo> ProtocolloList;
public ArrayList<Protocollo> getProtocolloList() {
return ProtocolloList;
}
public void setProtocolloList(ArrayList<Protocollo> protocolloList) {
ProtocolloList = protocolloList;
}
}
and finally I execute the converion like that:
JAXBContext jaxbContext = JAXBContext.newInstance(Protocollo.class);
Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
StringReader reader = new StringReader(this.resultXML);
protocolli = (ProtocolloList) unmarshaller.unmarshal(reader);
And I keep on getting this exception:
unexpected element (uri:"", local:"ProtocolloList"). Expected elements are <{}protocollo>
I suppose I'm making some mistakes with annotations.
Can you help?
For your use case you do not need the #XmlElementWrapper annotation. This is because the ProtocolList element corresponds to your #XmlRootElement annotation. Then you need the #XmlElement annotation on the property to grab each of the list items.
#XmlRootElement(name = "ProtocolloList")
public class ProtocolloList {
private ArrayList<Protocollo> ProtocolloList;
#XmlElement(name = "protocollo")
public ArrayList<Protocollo> getProtocolloList() {
return ProtocolloList;
}
}
Note:
By default you should annotate the property. If you want to annotate the fields you should put #XmlAccessorType(XmlAccessType.FIELD) on your class.
UPDATE
You need to make sure your JAXBContext is aware of the root class. You can change your JAXBContext creation code to be the following:
JAXBContext jaxbContext = JAXBContext.newInstance(ProtocolloList.class);

Categories

Resources