EDIT:
I messed around some time now and came to the following XML result:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<List>
<client name="Robert">
<fileNames name="anleitung.pdf"/>
<fileNames name="fernseher.jpg"/>
<fileNames name="pikantesfoto.jpg"/>
</client>
<client name="Jakob">
<fileNames name="fernseher.jpg"/>
<fileNames name="pikantesfoto.jpg"/>
<fileNames name="tagebuch.txt"/>
</client>
</List>
This isn't really a many to many relationship, but it's close, I need to remove the data redunance.
The "fileNames" should be single elements which and the clients should point on it. So if there is one file that has the same name of a file from another clients, it should appear only once.
This are my classes:
Marshaller: public class XMLMarshaller {
private Pool pool;
public XMLMarshaller(Pool pool) {
this.pool = pool;
}
public void marshal() {
JAXBContext jc;
try {
jc = JAXBContext.newInstance(Pool.class, Client.class, FileName.class);
FileChooser fileChooser = new FileChooser();
fileChooser.setTitle("Save XML-File");
fileChooser.getExtensionFilters().add(new FileChooser.ExtensionFilter("XML-Document", "*.xml"));
File path = fileChooser.showSaveDialog(new Stage());
if (path.toString().endsWith(".xml") == false) {
path = new File(path.toString() + ".xml");
}
if (path.isFile() == false)
path.createNewFile();
FileOutputStream fos = new FileOutputStream(path);
OutputStreamWriter xmlOut = new OutputStreamWriter(fos, Charset.forName("UTF8"));
Marshaller marshaller = jc.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
QName qName = new QName("List");
JAXBElement<Pool> jaxbElement = new JAXBElement<>(qName, Pool.class, pool);
marshaller.marshal(jaxbElement, xmlOut);
xmlOut.flush();
xmlOut.close();
} catch (Exception e) {e.printStackTrace();}
}
}
Pool (Contains a list of all existing "FileNames" and Clients):
public class Pool {
private List<FileName> fileNames_pool;
private List<Client> clients;
public Pool() {
this.fileNames_pool = new ArrayList<>(20);
this.clients = new ArrayList<>(20);
}
public List<FileName> getFileNameList() {
return this.fileNames_pool;
}
public List<FileName> getFileNames_pool() {
return this.fileNames_pool;
}
@XmlAnyElement(lax = true)
public List<Client> getClientList() {
return this.clients;
}
public boolean addClient(String clientName) {
this.clients.add(new Client(clientName));
return true;
}
public boolean addFileName(int clientIndex, String fileName) {
int foundIndex = 0;
boolean foundOne = false;
for (int i=0; i<fileNames_pool.size(); ++i) {
if (fileNames_pool.get(i).name == fileName) {
foundIndex = i;
foundOne = true;
break;
}
}
if (foundOne) {
clients.get(clientIndex).addFileName(fileNames_pool.get(foundIndex));
} else {
FileName temp = new FileName(fileName);
fileNames_pool.add(temp);
clients.get(clientIndex).addFileName(temp);
}
return true;
}
}
Client (there will be multiple instances/objects of it): @XmlRootElement public class Client {
static int numberOfClients = 0;
private int id;
@XmlAttribute
public String name;
public List<FileName> fileNames = new ArrayList<>();
public Client() {
}
public Client(String name) {
this.name = name;
this.id = numberOfClients++;
}
@XmlElement
public List<FileName> getFileNames() {
return this.fileNames;
}
public void addFileName(FileName fileName) {
this.fileNames.add(fileName);
}
}
FileNames (there will also be multiple instances of it):
//@XmlRootElement
public class FileName {
// public static int instanceCounter = 0;
//
// @XmlIDREF
// public int idref = 0;
@XmlAttribute
public String name;
public FileName() {
}
public FileName(String name) {
this.name = name;
// idref = instanceCounter++;
}
}
You will see that I sometimes really messed things up, but I'm totally out of ideas on what could work and what not. The Pool class is something like a Wrapper as Blaise Doughan told me to do, if I didn't get him wrong. And what I totally didn't get: Why should there be an "id" based on the string class?