Tuesday, November 6, 2018

XML Schema

Objectives


Today I'm going to introduce you in subject of creating, visualization and using XSD. XML Schema was created by W3C for creating XML structure definition. This is a kind of contract which could be used in many solutions. One of the best usages is creating data model in WSDL (Web service contract)

Below is personal data's XSD structure which contains simple and complex types. There are diverse types of restrictions:

  • simple:  minOccurs, maxOccurs
  • complex: <xsd:restriction base="xsd:string"> 

There is also example of inheritance:  <xsd:extension base="as:document">

<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
            xmlns:as="https://www.linkedin.com/in/artur-scigajlo-9144092/"
            targetNamespace="https://www.linkedin.com/in/artur-scigajlo-9144092/"
            xmlns:iso639-2="http://lcweb.loc.gov/standards/iso639-2/"
            elementFormDefault="qualified">
           
    <xsd:import namespace="http://lcweb.loc.gov/standards/iso639-2/"  schemaLocation="http://files.dnb.de/standards/xmetadiss/iso639-2.xsd"/>
               
               
   <xsd:complexType name="personalData">
        <xsd:sequence>
            <xsd:element name="workerId" type="xsd:string" minOccurs="1" maxOccurs="1"/>
            <xsd:element name="worker" type="as:worker" minOccurs="1" maxOccurs="1"/>
            <xsd:element name="partA" type="as:documentPartA" minOccurs="1" maxOccurs="unbounded"/>
            <xsd:element name="partB" type="as:documentPartB" minOccurs="0" maxOccurs="unbounded"/>
        </xsd:sequence>
    </xsd:complexType>
             
  <xsd:complexType name="worker">
        <xsd:sequence>
            <xsd:element name="lastName" type="xsd:string" minOccurs="1" maxOccurs="1"/>
            <xsd:element name="firstName" type="xsd:string" minOccurs="1" maxOccurs="1"/>
            <xsd:choice>
                <xsd:element name="personId">
                   <xsd:simpleType>
                    <xsd:restriction base="xsd:string">
                      <xsd:minLength value="10"/>
                      <xsd:maxLength value="26"/>
                    </xsd:restriction>
                  </xsd:simpleType>
                </xsd:element>
                <xsd:element name="otherTypeOfDocument">
                    <xsd:complexType>
                        <xsd:sequence>
                          <xsd:element name="type" type="xsd:string" minOccurs="1" maxOccurs="1"/>
                          <xsd:element name="number" type="xsd:string" minOccurs="1" maxOccurs="1"/>
                        </xsd:sequence>
                    </xsd:complexType>
                </xsd:element>
            </xsd:choice>
        </xsd:sequence>
    </xsd:complexType>
   
        <xsd:complexType name="document">
            <xsd:sequence>
                <xsd:element name="documentId" type="xsd:string" minOccurs="1" maxOccurs="1"/>
                <xsd:element name="title" type="as:title" minOccurs="0" maxOccurs="1"/>
                <xsd:element name="createdDate" type="xsd:date" minOccurs="1" maxOccurs="1"/>
                <xsd:element name="documentType" type="as:documentType" minOccurs="0" maxOccurs="1"/>
            </xsd:sequence>
    </xsd:complexType>
   
       <xsd:complexType name="title">
        <xsd:simpleContent>
            <xsd:extension base="xsd:string">
                <xsd:attribute name="language" type="iso639-2:RegisteredCodeType" use="optional"/>
            </xsd:extension>
        </xsd:simpleContent>
    </xsd:complexType>
   
      <xsd:complexType name="documentType">
        <xsd:sequence>
            <xsd:element name="type" minOccurs="1" maxOccurs="1">
              <xsd:simpleType>
                <xsd:restriction base="xsd:string">
                  <xsd:enumeration value="driverLicence"/>
                  <xsd:enumeration value="passport"/>
                  <xsd:enumeration value="insuranceNo"/>
                  <xsd:enumeration value="other"/>
                </xsd:restriction>
              </xsd:simpleType>
            </xsd:element>
            <xsd:element name="numer" type="xsd:string" minOccurs="1" maxOccurs="1"/>
        </xsd:sequence>
      </xsd:complexType>
   
    <xsd:complexType name="documentPartA">
        <xsd:complexContent>
            <xsd:extension base="as:document">
                <xsd:attribute name="subType" use="required">
                    <xsd:simpleType>
                        <xsd:restriction base="xsd:string">
                          <xsd:pattern value="^[ABC]\d{2}$"/>
                        </xsd:restriction>
                    </xsd:simpleType>
                </xsd:attribute>
            </xsd:extension>
        </xsd:complexContent>
    </xsd:complexType>
   
    <xsd:complexType name="documentPartB">
        <xsd:complexContent>
            <xsd:extension base="as:document">
                <xsd:attribute name="subType" use="required">
                    <xsd:simpleType>
                        <xsd:restriction base="xsd:string">
                          <xsd:pattern value="^[XYZ]\d{2}$"/>
                        </xsd:restriction>
                    </xsd:simpleType>
                </xsd:attribute>
            </xsd:extension>
        </xsd:complexContent>
    </xsd:complexType>   

</xsd:schema>




Data model visualization

There are existing useful applications to help creating XSD. Some of them have a plugins to generate visualization diagrams. Below is our schema's diagram.





Genarating XML file base on XSD Schema


I created project in Netbeans.





I imported XSD and generated java classes automatically.







We can see the generated classes





The main class is used to generate XML file









Below is java class

/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package artur.scigajlo;

import artur.scigajlo.personalData.DocumentPartA;
import artur.scigajlo.personalData.DocumentType;
import artur.scigajlo.personalData.PersonalData;
import artur.scigajlo.personalData.Title;
import artur.scigajlo.personalData.Worker;
import artur.scigajlo.personalData.Worker.OtherTypeOfDocument;
import com.sun.org.apache.xerces.internal.jaxp.datatype.XMLGregorianCalendarImpl;
import java.io.File;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.PropertyException;

/**
 *
 * @author a.scigajlo
 */
public class PersonalDataProject {

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) throws PropertyException, JAXBException {
              PersonalData ao = new PersonalData();
        ao.setWorkerId("worker_01");
     
        Worker worker = new Worker();
        worker.setFirstName("Jon");
        worker.setLastName("Black");
     
        OtherTypeOfDocument otherDoc = new OtherTypeOfDocument();
        otherDoc.setNumber("AAA123456");
        otherDoc.setType("otherPersonId"); 
        worker.setOtherTypeOfDocument(otherDoc);     
     
        ao.setWorker(worker);
     
     
        DocumentPartA docA1 = new DocumentPartA();
        docA1.setCreatedDate(XMLGregorianCalendarImpl.createDate(2018,3,4,0));
        docA1.setDocumentId("docID-714");
     
        Title t1 = new Title();
        t1.setLanguage("pol");
        t1.setValue("hello.pdf");
        docA1.setTitle(t1);
     
        DocumentType dt1 = new DocumentType();
        dt1.setNumer("AEC12");
        dt1.setType("driverLicence");
        docA1.setDocumentType(dt1);
     
        ao.getPartA().add(docA1);
     
        DocumentPartA docA2 = new DocumentPartA();
        docA2.setCreatedDate(XMLGregorianCalendarImpl.createDate(2018,5,14,0));
        docA2.setDocumentId("annexID-318");
     
        Title t2 = new Title();
        t2.setLanguage("pol");
        t2.setValue("test.pdf");
        docA2.setTitle(t2);
     
        DocumentType dt2 = new DocumentType();
        dt2.setNumer("AEC12");
        dt2.setType("driverLicence");
        docA2.setDocumentType(dt2);
     
        ao.getPartA().add(docA2);
         
        JAXBContext jaxbContext = JAXBContext.newInstance(PersonalData.class);
        Marshaller jaxbMarshaller = jaxbContext.createMarshaller();
        jaxbMarshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
     
     
        //ZAPIS DO PLIKU
        jaxbMarshaller.marshal(ao, new File("c:\\tmp\\PersonalData.xml"));
    }
 
}


Finally we get XML file




Thursday, August 16, 2018

LinkedList custom implementation in Java

Objectives


Today i'm going to introduce you in my custom LinkedList implementation.Below is prepared diagram which shows internal class's structure. Every Node handles reference to next Node. The last Node has an empty reference. There are two fields which hold reference to first and last Nodes.




Below is internal Node's structure which holds items and references.


private class Node<T extends Object>{
        Node<T> next;
        T object;
     
        public Node(T object){
            this.next = null;
            this.object = object;
        }
     
        public Node(T object, Node<T> next){
            next.setNext(this);
            this.next = null;
            this.object = object;
        }

        public Node<T> getNext() {
            return next;
        }

        public void setNext(Node<T> next) {
            this.next = next;
        }

        public T getObject() {
            return object;
        }

        public void setObject(T object) {
            this.object = object;
        }     
     
    }

Thursday, July 19, 2018

HashMap custom implementation

Objectives


HashMap is array of buckets to store linkedList's simple structure. Each linkedList consists of agregated in key-value ernty objects with additional references to next entry object. Very important is to create method to point correct Bucket.

Below is diagram which shows inserting entries to HashMap process.




Entry structure


Below is entry structure which implements Map.Entry interface.


    static class Entry<K,V> implements Map.Entry<K,V> {
        private K key;
        private V value;
        private Entry<K,V> next;
        public Entry(K key, V value){
            this.key = key;
            this.value = value;       
        }
        public Entry(K key, V value, Entry<K,V> next){
            this.key = key;
            this.value = value;
            this.next = next;
        }
        @Override
        public K getKey() {
            return key;
        }
        @Override
        public V getValue() {
            return value;
        }
        @Override
        public V setValue(V v) {
            this.value = v;
            return this.value;
        }
        public Entry<K, V> getNext() {
            return next;
        }
        public void setNext(Entry<K, V> next) {
            this.next = next;
        }         
    }


Bucket

Very important aspect is to create appropriate method to calculate bucket. The method has only one incoming parameter - the calculated hashCode base on key.

public static int calculateIndex(int hash) {
        return hash & (capacity-1);
    }

Main Class

Below is full source code.  
package artsci.pl;

import java.util.Map;

/**
 *
 * @author Artur
 */
public class MyHashMap <K, V> {
    private Entry<K,V>[] table;
    private final static int capacity = 16;

    public MyHashMap(){
       table = new Entry[capacity];
    }


    public void put(K key, V value){
       if(key==null)
           return;
   
       int hash=key.hashCode();
       int index = calculateIndex(hash);
   
       if(table[index] == null){
           table[index] = new Entry(key, value);
       }else{
           boolean isNodeExists = true;
           Entry currentNode = table[index];
       
           while (currentNode != null && isNodeExists) {
                if(currentNode.getKey().hashCode() == hash && key.equals(currentNode.getKey())){
                    currentNode.setValue(value);
                    break;
                }           
           
                if(currentNode.getNext() != null){
                    currentNode = currentNode.getNext();
                }else{
                    isNodeExists = false;
                    table[index] = new Entry(key, value, table[index]);
                }
            }       
       }
    }

   

    public V get(K key){
       if(key==null)
           return null;
   
       int hash=key.hashCode();
       int index = calculateIndex(hash);
       boolean isNodeExists = true;
       V out = null;
   
       if(table[index] != null){
           Entry currentNode = table[index];
   
           while (currentNode != null && isNodeExists) {
                if(currentNode.getKey().hashCode() == hash && key.equals(currentNode.getKey())){
                    out = (V)currentNode.getValue();
                }           
           
                if(currentNode.getNext() != null){
                    currentNode = currentNode.getNext();
                }else{
                    isNodeExists = false;
                }
            }   
       }
       return out;
    }

    public static int calculateIndex(int hash) {
        return hash & (capacity-1);
    }

    public String toString(){
        String out = "";           
        for(Entry currentNode : table){
            boolean isNodeExists = true;       
       
            while (currentNode != null && isNodeExists) {
                out += "["+currentNode.getKey()+";"+currentNode.getValue()+"]";
                if(currentNode.getNext() != null){
                    currentNode = currentNode.getNext();
                }else{
                    isNodeExists = false;
                }
            }   
        }   
        return out;
    }

    public int size(){
        int out = 0;       
        for(Entry currentNode : table){
            boolean isNodeExists = true;       
       
            while (currentNode != null && isNodeExists) {
                out++;           
                if(currentNode.getNext() != null){
                    currentNode = currentNode.getNext();
                }else{
                    isNodeExists = false;
                }
            }         
        }           
        return out;
    }


    static class Entry<K,V> implements Map.Entry<K,V> {
        private K key;
        private V value;
        private Entry<K,V> next;

        public Entry(K key, V value){
            this.key = key;
            this.value = value;         
        }

        public Entry(K key, V value, Entry<K,V> next){
            this.key = key;
            this.value = value;
            this.next = next;
        }

        @Override
        public K getKey() {
            return key;
        }

        @Override
        public V getValue() {
            return value;
        }

        @Override
        public V setValue(V v) {
            this.value = v;
            return this.value;
        }

        public Entry<K, V> getNext() {
            return next;
        }

        public void setNext(Entry<K, V> next) {
            this.next = next;
        }   
   
    }
}

Test Class

package artsci.pl;

import org.junit.Test;
import static org.junit.Assert.*;

/**
 *
 * @author Artur
 */
public class MyHashMapTest {

    public MyHashMapTest() {
    }

    @Test
    public void testMethod() {
        MyHashMap <String, String> map = new MyHashMap <String, String>();
   
        for(int i = 0; i< 30; i++){   
            String key = "KEY_"+i;
            map.put(key, "VALUE_".concat(String.valueOf(i)));
            System.out.println("Key: "+key+" is in bucket: "+MyHashMap.calculateIndex(key.hashCode()) );       
        }           
   
        System.out.println("Size: "+map.size());   
        assertTrue(map.size() == 30);
   
    }

}


And the result is below:

Testsuite: artsci.pl.MyHashMapTest
Key: KEY_0 is in bucket: 0
Key: KEY_1 is in bucket: 1
Key: KEY_2 is in bucket: 2
Key: KEY_3 is in bucket: 3
Key: KEY_4 is in bucket: 4
Key: KEY_5 is in bucket: 5
Key: KEY_6 is in bucket: 6
Key: KEY_7 is in bucket: 7
Key: KEY_8 is in bucket: 8
Key: KEY_9 is in bucket: 9
Key: KEY_10 is in bucket: 15
Key: KEY_11 is in bucket: 0
Key: KEY_12 is in bucket: 1
Key: KEY_13 is in bucket: 2
Key: KEY_14 is in bucket: 3
Key: KEY_15 is in bucket: 4
Key: KEY_16 is in bucket: 5
Key: KEY_17 is in bucket: 6
Key: KEY_18 is in bucket: 7
Key: KEY_19 is in bucket: 8
Key: KEY_20 is in bucket: 14
Key: KEY_21 is in bucket: 15
Key: KEY_22 is in bucket: 0
Key: KEY_23 is in bucket: 1
Key: KEY_24 is in bucket: 2
Key: KEY_25 is in bucket: 3
Key: KEY_26 is in bucket: 4
Key: KEY_27 is in bucket: 5
Key: KEY_28 is in bucket: 6
Key: KEY_29 is in bucket: 7
Size: 30
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0,071 sec