JAXB: how to marshall map into <key>value</key>

JavaXmlJaxbJaxb2

Java Problem Overview


The question is about JAXB Map marshalling - there is plenty of examples on how to marhsall a Map into a structure like follows:

<map>
  <entry>
    <key> KEY </key>
    <value> VALUE </value>
  </entry>
  <entry>
    <key> KEY2 </key>
    <value> VALUE2 </value>
  </entry>
  <entry>
  ...
</map>

In fact, this is natively supported by JAXB. What I need, however, is the XML where key is the element name, and value is its content:

<map>
  <key> VALUE </key>
  <key2> VALUE2 </key2>
 ...
</map>

I didn't succeed implementing my Map adapter the way it is recommended by JAXB developers (https://jaxb.dev.java.net/guide/Mapping_your_favorite_class.html), as I need, he - dynamic attribute name :)

Is there any solution for that?

P.S. Currently I have to create a dedicated container class for each typical set of key-value pairs I want to marshall to XML - it works, but I have to create way too many of these helper containers.

Java Solutions


Solution 1 - Java

There may be a valid reason why you want to do this, but generating this kind of XML is generally best avoided. Why? Because it means that the XML elements of your map are dependent on the runtime contents of your map. And since XML is usually used as an external interface or interface layer this is not desirable. Let me explain.

The Xml Schema (xsd) defines the interface contract of your XML documents. In addition to being able to generate code from the XSD, JAXB can also generate the XML schema for you from the code. This allows you to restrict the data exchanged over the interface to the pre-agreed structures defined in the XSD.

In the default case for a Map<String, String>, the generated XSD will restrict the map element to contain multiple entry elements each of which must contain one xs:string key and one xs:string value. That's a pretty clear interface contract.

What you describe is that you want the xml map to contain elements whose name will be determined by the content of the map at runtime. Then the generated XSD can only specify that the map must contain a list of elements whose type is unknown at compile time. This is something that you should generally avoid when defining an interface contract.

To achieve a strict contract in this case, you should use an enumerated type as the key of the map instead of a String. E.g.

public enum KeyType {
 KEY, KEY2;
}

@XmlJavaTypeAdapter(MapAdapter.class)
Map<KeyType , String> mapProperty;

That way the keys which you want to become elements in XML are known at compile time so JAXB should be able to generate a schema that would restrict the elements of map to elements using one of the predefined keys KEY or KEY2.

On the other hand, if you wish to simplify the default generated structure

<map>
    <entry>
        <key>KEY</key>
        <value>VALUE</value>
    </entry>
    <entry>
        <key>KEY2</key>
        <value>VALUE2</value>
    </entry>
</map>

To something simpler like this

<map>
    <item key="KEY" value="VALUE"/>
    <item key="KEY2" value="VALUE2"/>
</map>

You can use a MapAdapter that converts the Map to an array of MapElements as follows:

class MapElements {
    @XmlAttribute
    public String key;
    @XmlAttribute
    public String value;

    private MapElements() {
    } //Required by JAXB

    public MapElements(String key, String value) {
        this.key = key;
        this.value = value;
    }
}


public class MapAdapter extends XmlAdapter<MapElements[], Map<String, String>> {
    public MapAdapter() {
    }

    public MapElements[] marshal(Map<String, String> arg0) throws Exception {
        MapElements[] mapElements = new MapElements[arg0.size()];
        int i = 0;
        for (Map.Entry<String, String> entry : arg0.entrySet())
            mapElements[i++] = new MapElements(entry.getKey(), entry.getValue());

        return mapElements;
    }

    public Map<String, String> unmarshal(MapElements[] arg0) throws Exception {
        Map<String, String> r = new TreeMap<String, String>();
        for (MapElements mapelement : arg0)
            r.put(mapelement.key, mapelement.value);
        return r;
    }
}

Solution 2 - Java

the code provided didn't work for me. I found another way to Map :

MapElements :

package com.cellfish.mediadb.rest.lucene;

import javax.xml.bind.annotation.XmlElement;

class MapElements
{
  @XmlElement public String  key;
  @XmlElement public Integer value;
 
  private MapElements() {} //Required by JAXB
 
  public MapElements(String key, Integer value)
  {
    this.key   = key;
    this.value = value;
  }
}

MapAdapter :

import java.util.HashMap;
import java.util.Map;

import javax.xml.bind.annotation.adapters.XmlAdapter;

class MapAdapter extends XmlAdapter<MapElements[], Map<String, Integer>> {
	public MapElements[] marshal(Map<String, Integer> arg0) throws Exception {
		MapElements[] mapElements = new MapElements[arg0.size()];
		int i = 0;
		for (Map.Entry<String, Integer> entry : arg0.entrySet())
			mapElements[i++] = new MapElements(entry.getKey(), entry.getValue());

		return mapElements;
	}

	public Map<String, Integer> unmarshal(MapElements[] arg0) throws Exception {
		Map<String, Integer> r = new HashMap<String, Integer>();
		for (MapElements mapelement : arg0)
			r.put(mapelement.key, mapelement.value);
		return r;
	}
}

The rootElement :

import java.util.HashMap;
import java.util.Map;

import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;

@XmlRootElement
public class Root {

    private Map<String, Integer> mapProperty;

    public Root() {
        mapProperty = new HashMap<String, Integer>();
    }

    @XmlJavaTypeAdapter(MapAdapter.class)
    public Map<String, Integer> getMapProperty() {
        return mapProperty;
    }

    public void setMapProperty(Map<String, Integer> map) {
        this.mapProperty = map;
    }

}

I found the code in this website : http://www.developpez.net/forums/d972324/java/general-java/xml/hashmap-jaxb/

Solution 3 - Java

I'm still working on a better solution but using MOXy JAXB, I've been able to handle the following XML:

<?xml version="1.0" encoding="UTF-8"?>
<root>
   <mapProperty>
      <map>
         <key>value</key>
         <key2>value2</key2>
      </map>
   </mapProperty>
</root>

You need to use an @XmlJavaTypeAdapter on your Map property:

import java.util.HashMap;
import java.util.Map;

import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;

@XmlRootElement
public class Root {

    private Map<String, String> mapProperty;

    public Root() {
        mapProperty = new HashMap<String, String>();
    }

    @XmlJavaTypeAdapter(MapAdapter.class)
    public Map<String, String> getMapProperty() {
        return mapProperty;
    }

    public void setMapProperty(Map<String, String> map) {
        this.mapProperty = map;
    }

}

The implementation of the XmlAdapter is as follows:

import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;

import javax.xml.bind.annotation.adapters.XmlAdapter;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

public class MapAdapter extends XmlAdapter<AdaptedMap, Map<String, String>> {

    @Override
    public AdaptedMap marshal(Map<String, String> map) throws Exception {
        DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
        DocumentBuilder db = dbf.newDocumentBuilder();
        Document document = db.newDocument();
        Element rootElement = document.createElement("map");
        document.appendChild(rootElement);

        for(Entry<String,String> entry : map.entrySet()) {
            Element mapElement = document.createElement(entry.getKey());
            mapElement.setTextContent(entry.getValue());
            rootElement.appendChild(mapElement);
        }

        AdaptedMap adaptedMap = new AdaptedMap();
        adaptedMap.setValue(document);
        return adaptedMap;
    }

    @Override
    public Map<String, String> unmarshal(AdaptedMap adaptedMap) throws Exception {
        Map<String, String> map = new HashMap<String, String>();
        Element rootElement = (Element) adaptedMap.getValue();
        NodeList childNodes = rootElement.getChildNodes();
        for(int x=0,size=childNodes.getLength(); x<size; x++) {
            Node childNode = childNodes.item(x);
            if(childNode.getNodeType() == Node.ELEMENT_NODE) {
                map.put(childNode.getLocalName(), childNode.getTextContent());
            }
        }
        return map;
    }

}

The AdpatedMap class is where all the magic happens, we will use a DOM to represent the content. We will trick JAXB intro dealing with a DOM through the combination of @XmlAnyElement and a property of type Object:

import javax.xml.bind.annotation.XmlAnyElement;

public class AdaptedMap {

    private Object value;

    @XmlAnyElement
    public Object getValue() {
        return value;
    }

    public void setValue(Object value) {
        this.value = value;
    }

}

This solution requires the MOXy JAXB implementation. You can configure the JAXB runtime to use the MOXy implementation by adding a file named jaxb.properties in with your model classes with the following entry:

javax.xml.bind.context.factory=org.eclipse.persistence.jaxb.JAXBContextFactory

The following demo code can be used to verify the code:

import java.io.File;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;

public class Demo {

    public static void main(String[] args) throws Exception {
        JAXBContext jc = JAXBContext.newInstance(Root.class);

        Unmarshaller unmarshaller = jc.createUnmarshaller();
        Root root = (Root) unmarshaller.unmarshal(new File("src/forum74/input.xml"));
        
        Marshaller marshaller = jc.createMarshaller();
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
        marshaller.marshal(root, System.out);
    }
}

Solution 4 - Java

I didn't see anything that really answered this very well. I found something that worked pretty well here:

https://stackoverflow.com/questions/21382202/use-jaxb-xmlanyelement-type-of-style-to-return-dynamic-element-names

I modified it a bit to support hashmap trees. You could add other collections.

public class MapAdapter extends XmlAdapter<MapWrapper, Map<String, Object>> {
    @Override
    public MapWrapper marshal(Map<String, Object> m) throws Exception {
        MapWrapper wrapper = new MapWrapper();
        List elements = new ArrayList();
        for (Map.Entry<String, Object> property : m.entrySet()) {

            if (property.getValue() instanceof Map)
                elements.add(new JAXBElement<MapWrapper>(new QName(getCleanLabel(property.getKey())),
                        MapWrapper.class, marshal((Map) property.getValue())));
            else
                elements.add(new JAXBElement<String>(new QName(getCleanLabel(property.getKey())),
                        String.class, property.getValue().toString()));
        }
        wrapper.elements = elements;
        return wrapper;
    }

@Override
public Map<String, Object> unmarshal(MapWrapper v) throws Exception {
    HashMap<String, Object> returnval = new HashMap();
    for (Object o : v.elements) {
        Element e = (Element) o;
        if (e.getChildNodes().getLength() > 1) {
            MapWrapper mw = new MapWrapper();
            mw.elements = new ArrayList();
            for (int count = 0; count < e.getChildNodes().getLength(); count++) {
                if (e.getChildNodes().item(count) instanceof Element) {
                    mw.elements.add(e.getChildNodes().item(count));
                }
            }
            returnval.put(e.getTagName(), unmarshal(mw));
        } else {
            returnval.put(e.getTagName(), e.getTextContent());
        }
    }
    return returnval;
}


    // Return a XML-safe attribute.  Might want to add camel case support
    private String getCleanLabel(String attributeLabel) {
        attributeLabel = attributeLabel.replaceAll("[()]", "").replaceAll("[^\\w\\s]", "_").replaceAll(" ", "_");
        return attributeLabel;
    }
}
class MapWrapper {
    @XmlAnyElement
    List elements;
}

Then to implement it:

static class myxml {
    String name = "Full Name";
    String address = "1234 Main St";
    // I assign values to the map elsewhere, but it's just a simple
    // hashmap with a hashmap child as an example.
    @XmlJavaTypeAdapter(MapAdapter.class)
    public Map<String, Object> childMap;
}

Feeding this through a simple Marshaller gives output that looks like this:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<myxml>
    <name>Full Name</name>
    <address>1234 Main St</address>
    <childMap>
        <key2>value2</key2>
        <key1>value1</key1>
        <childTree>
            <childkey1>childvalue1</childkey1>
        </childTree>
    </childMap>
</myxml>

Solution 5 - Java

I have solution without adapter. Transient map converted to xml-elements and vise versa:

@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement(name = "SchemaBasedProperties")
public class SchemaBasedProperties
{
  @XmlTransient
  Map<String, Map<String, String>> properties;

  @XmlAnyElement(lax = true)
  List<Object> xmlmap;

  public Map<String, Map<String, String>> getProperties()
  {
	if (properties == null)
	  properties = new LinkedHashMap<String, Map<String, String>>(); // I want same order

	return properties;
  }

  boolean beforeMarshal(Marshaller m)
  {
	try
	{
	  if (properties != null && !properties.isEmpty())
	  {
		if (xmlmap == null)
		  xmlmap = new ArrayList<Object>();
		else
		  xmlmap.clear();

		javax.xml.parsers.DocumentBuilderFactory dbf = javax.xml.parsers.DocumentBuilderFactory.newInstance();
		javax.xml.parsers.DocumentBuilder db = dbf.newDocumentBuilder();
		org.w3c.dom.Document doc = db.newDocument();
		org.w3c.dom.Element element;

		Map<String, String> attrs;

		for (Map.Entry<String, Map<String, String>> it: properties.entrySet())
		{
		  element = doc.createElement(it.getKey());
		  attrs = it.getValue();

		  if (attrs != null)
			for (Map.Entry<String, String> at: attrs.entrySet())
			  element.setAttribute(at.getKey(), at.getValue());

		  xmlmap.add(element);
		}
	  }
	  else
		xmlmap = null;
	}
	catch (Exception e)
	{
	  e.printStackTrace();
	  return false;
	}

	return true;
  }

  void afterUnmarshal(Unmarshaller u, Object p)
  {
	org.w3c.dom.Node node;
	org.w3c.dom.NamedNodeMap nodeMap;

	String name;
	Map<String, String> attrs;

	getProperties().clear();

	if (xmlmap != null)
	  for (Object xmlNode: xmlmap)
		if (xmlNode instanceof org.w3c.dom.Node)
		{
		  node = (org.w3c.dom.Node) xmlNode;
		  nodeMap = node.getAttributes();

		  name = node.getLocalName();
		  attrs = new HashMap<String, String>();

		  for (int i = 0, l = nodeMap.getLength(); i < l; i++)
		  {
			node = nodeMap.item(i);
			attrs.put(node.getNodeName(), node.getNodeValue());
		  }

		  getProperties().put(name, attrs);
		}

	xmlmap = null;
  }

  public static void main(String[] args)
	throws Exception
  {
	SchemaBasedProperties props = new SchemaBasedProperties();
	Map<String, String> attrs;

	attrs = new HashMap<String, String>();
	attrs.put("ResId", "A_LABEL");
	props.getProperties().put("LABEL", attrs);

	attrs = new HashMap<String, String>();
	attrs.put("ResId", "A_TOOLTIP");
	props.getProperties().put("TOOLTIP", attrs);

	attrs = new HashMap<String, String>();
	attrs.put("Value", "hide");
	props.getProperties().put("DISPLAYHINT", attrs);

	javax.xml.bind.JAXBContext jc = javax.xml.bind.JAXBContext.newInstance(SchemaBasedProperties.class);

	Marshaller marshaller = jc.createMarshaller();
	marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
	marshaller.marshal(props, new java.io.File("test.xml"));

	Unmarshaller unmarshaller = jc.createUnmarshaller();
	props = (SchemaBasedProperties) unmarshaller.unmarshal(new java.io.File("test.xml"));

	System.out.println(props.getProperties());
  }
}

My output as espected:

<SchemaBasedProperties>
	<LABEL ResId="A_LABEL"/>
	<TOOLTIP ResId="A_TOOLTIP"/>
	<DISPLAYHINT Value="hide"/>
</SchemaBasedProperties>

{LABEL={ResId=A_LABEL}, TOOLTIP={ResId=A_TOOLTIP}, DISPLAYHINT={Value=hide}}

You can use element name/value pair. I need attributes... Have fun!

Solution 6 - Java

(Sorry, can't add comments)

In Blaise's answer above, if you change:

@XmlJavaTypeAdapter(MapAdapter.class)
public Map<String, String> getMapProperty() {
    return mapProperty;
}

to:

@XmlJavaTypeAdapter(MapAdapter.class)
@XmlPath(".") // <<-- add this
public Map<String, String> getMapProperty() {
    return mapProperty;
}

then this should get rid of the <mapProperty> tag, and so give you:

<?xml version="1.0" encoding="UTF-8"?>
<root>
    <map>
        <key>value</key>
        <key2>value2</key2>
    </map>
</root>

ALTERNATIVELY:

You can also change it to:

@XmlJavaTypeAdapter(MapAdapter.class)
@XmlAnyElement // <<-- add this
public Map<String, String> getMapProperty() {
    return mapProperty;
}

and then you can get rid of AdaptedMap altogether, and just change MapAdapter to marshall to a Document object directly. I've only tested this with marshalling, so there may be unmarshalling issues.

I'll try and find the time to knock up a full example of this, and edit this post accordingly.

Solution 7 - Java

Seems like this question is kind of duplicate with another one, where I've collect some marshal/unmarshal solutions into one post. You may check it here: Dynamic tag names with JAXB.

In short:

  1. A container class for @xmlAnyElement should be created
  2. An XmlAdapter can be used in pair with @XmlJavaTypeAdapter to convert between the container class and Map<>;

Solution 8 - Java

When using xml-apis-1.0, you can serialize and deserialize this:

<?xml version="1.0" encoding="UTF-8"?>
<root>
	<map>
		<key>value</key>
		<key2>value2</key2>
	</map>
</root>

Using this code:

import java.io.File;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
import javax.xml.bind.annotation.XmlAnyElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;

@XmlRootElement
class Root {

	public XmlRawData map;

}

public class Demo {

    public static void main(String[] args) throws Exception {
        JAXBContext jc = JAXBContext.newInstance(Root.class);

        Unmarshaller unmarshaller = jc.createUnmarshaller();
        Root root = (Root) unmarshaller.unmarshal(new File("src/input.xml"));
        
        System.out.println(root.map.getAsMap());
        
        Marshaller marshaller = jc.createMarshaller();
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
        marshaller.marshal(root, System.out);
    }
}

class XmlRawData {

	@XmlAnyElement
	public List<Element> elements;

	public void setFromMap(Map<String, String> values) {

		Document document;
		try {
			document = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();
		} catch (ParserConfigurationException e) {
			throw new RuntimeException(e);
		}

		for (Entry<String, String> entry : values.entrySet()) {
            Element mapElement = document.createElement(entry.getKey());
            mapElement.appendChild(document.createTextNode(entry.getValue()));
            elements.add(mapElement);
		}
	}
	
	public Map<String, String> getAsMap() {
		Map<String, String> map = new HashMap<String, String>();

		for (Element element : elements) {
			if (element.getNodeType() == Node.ELEMENT_NODE) {
				map.put(element.getLocalName(), element.getFirstChild().getNodeValue());
			}
		}

		return map;
	}
}

Solution 9 - Java

Jackson has an XmlMapper which will support this out of the box, no need to write any code at all.

Here's a nice tutorial https://www.baeldung.com/jackson-xml-serialization-and-deserialization

Maven dependency:

<dependency>
    <groupId>com.fasterxml.jackson.dataformat</groupId>
    <artifactId>jackson-dataformat-xml</artifactId>
    <version>2.9.8</version>
</dependency>

For writing a Map to xml:

Map<String, String> map = new HashMap<>();
map.put("SomeKey", "someValue");

XmlMapper mapper = new XmlMapper();
String xml = mapper.writeValueAsString(map);

Will give you

<HashMap><SomeKey>someValue</SomeKey></HashMap>

I was able to customise the root element by creating a HashMap subclass

@JacksonXmlRootElement(localName = "MyRootElement")
public class XmlHashMap<K, V> extends HashMap<K, V>
{

}

So now

Map<String, String> map = new XmlHashMap<>();
map.put("SomeKey", "someValue");

XmlMapper mapper = new XmlMapper();
String xml = mapper.writeValueAsString(map);

Will give you

<MyRootElement><SomeKey>someValue</SomeKey></MyRootElement>

Solution 10 - Java

Most people have mentioned about only marshalling here is both marshalling and unmarshalling with Map<String,Object>

import jakarta.xml.bind.JAXBElement;
import jakarta.xml.bind.annotation.XmlAnyElement;
import jakarta.xml.bind.annotation.adapters.XmlAdapter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import javax.xml.namespace.QName;
import lombok.Getter;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;


public class MoxyMapAdapter extends XmlAdapter<MapWrapper, Map<String, Object>> {

  @Override
  public Map<String, Object> unmarshal(MapWrapper value) {
    
    final Map<String, Object> extensions = new HashMap<>();
    //Loop across all elements within value
    for (Object obj : value.getElements()) {
      Element element = (Element) obj;

      final NodeList children = element.getChildNodes();

      if (children.getLength() == 1) {
        extensions.put(element.getNodeName(), element.getTextContent());
      } else {
        List<Object> child = new ArrayList<>();
        for (int i = 0; i < children.getLength(); i++) {
          final Node n = children.item(i);
          if (n.getNodeType() == Node.ELEMENT_NODE) {
            MapWrapper wrapper = new MapWrapper();
            List childElements = new ArrayList();
            childElements.add(n);
            wrapper.elements = childElements;
            child.add(unmarshal(wrapper));
          }
        }
        extensions.put(element.getNodeName(), child);
      }
    }
    return extensions;
  }


  @Override
  public MapWrapper marshal(Map<String, Object> extensions) throws Exception {
    if (extensions == null) {
      return null;
    }

    MapWrapper wrapper = new MapWrapper();

    List elements = new ArrayList();

    //Loop through the Extensions MAP
    for (Map.Entry<String, Object> property : extensions.entrySet()) {

        //If the Value type is MAP then recurse through the loop
        if (property.getValue() instanceof Map) {
          elements
              .add(new JAXBElement<MapWrapper>(new QName(namespaceURI, localPart, prefix), MapWrapper.class, marshal((Map) property.getValue())));
        } else if (property.getValue() instanceof String) {
          // If the Value type is String then directly create JAXBElement
          elements.add(new JAXBElement<String>(new QName(namespaceURI, localPart, prefix), String.class, property.getValue().toString()));
        } else if (property.getValue() instanceof ArrayList) {
          //If the Value type is ArrayList then it contains Duplicate key values so Loop through it
          for (Object dupItems : (ArrayList<String>) property.getValue()) {
            if (dupItems instanceof Map) {
              elements.add(new JAXBElement<MapWrapper>(new QName(namespaceURI, localPart, prefix), MapWrapper.class, marshal((Map) dupItems)));
            } else {
              elements.add(new JAXBElement<String>(new QName(namespaceURI, localPart, prefix), String.class, dupItems.toString()));
            }
          }
        }
    }
    wrapper.elements = elements;
    return wrapper;
  }
}


class MapWrapper {

  @Getter
  @XmlAnyElement
  List elements;
}

Solution 11 - Java

I found easiest solution.

@XmlElement(name="attribute")
	public String[] getAttributes(){
		return attributes.keySet().toArray(new String[1]);
	}
}

Now it will generate in you xml output like this:

<attribute>key1<attribute>
...
<attribute>keyN<attribute>

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionTimurView Question on Stackoverflow
Solution 1 - JavaJustin RoweView Answer on Stackoverflow
Solution 2 - JavaGrégoryView Answer on Stackoverflow
Solution 3 - JavabdoughanView Answer on Stackoverflow
Solution 4 - JavaJavaJeffView Answer on Stackoverflow
Solution 5 - JavaluniconView Answer on Stackoverflow
Solution 6 - JavalukensView Answer on Stackoverflow
Solution 7 - Javamec_test_1View Answer on Stackoverflow
Solution 8 - JavaslartidanView Answer on Stackoverflow
Solution 9 - JavaMartin CassidyView Answer on Stackoverflow
Solution 10 - JavaBATMAN_2008View Answer on Stackoverflow
Solution 11 - Javabonzai1990View Answer on Stackoverflow