From ed984f2b0148400a5a69fe3d7d798ea195090199 Mon Sep 17 00:00:00 2001
From: Tor-Einar Skog <tor-einar.skog@bioforsk.no>
Date: Mon, 9 Sep 2013 11:14:53 +0200
Subject: [PATCH] First version with weather stations

---
 .../logic/controller/LoginController.java     |   7 +-
 .../controller/PointOfInterestController.java |  95 ++++++++
 .../bioforsk/vips/logic/entity/Country.java   | 113 ++++++++++
 .../vips/logic/entity/ExternalResource.java   | 158 +++++++++++++
 .../logic/entity/ExternalResourceType.java    | 106 +++++++++
 .../vips/logic/entity/HierarchyCategory.java  | 124 ++++++++++
 .../bioforsk/vips/logic/entity/Organism.java  | 187 +++++++++++++++
 .../entity/OrganismExternalResource.java      | 114 ++++++++++
 .../entity/OrganismExternalResourcePK.java    |  82 +++++++
 .../vips/logic/entity/OrganismLocale.java     | 103 +++++++++
 .../vips/logic/entity/OrganismLocalePK.java   |  84 +++++++
 .../vips/logic/entity/PointOfInterest.java    | 213 ++++++++++++++++++
 .../logic/entity/PointOfInterestType.java     | 112 +++++++++
 .../entity/PointOfInterestWeatherStation.java | 103 +++++++++
 .../logic/entity/UserPointOfInterest.java     |  89 ++++++++
 .../logic/entity/UserPointOfInterestPK.java   |  82 +++++++
 .../vips/logic/entity/UserVipslogicRole.java  |  89 ++++++++
 .../logic/entity/UserVipslogicRolePK.java     |  82 +++++++
 .../vips/logic/entity/VipslogicRole.java      | 119 ++++++++++
 .../entity/WeatherStationDataSource.java      | 125 ++++++++++
 .../logic/session/PointOfInterestBean.java    |  57 +++++
 .../session/SessionControllerGetter.java      |  35 +++
 .../no/bioforsk/vips/logic/util/Globals.java  |   3 +
 src/main/resources/META-INF/persistence.xml   |   8 +
 .../vips/logic/i18n/vipslogictexts.properties |  11 +
 .../logic/i18n/vipslogictexts_no.properties   |  11 +
 src/main/setup/jboss-ds.xml                   |  13 ++
 src/main/webapp/WEB-INF/web.xml               |  11 +-
 src/main/webapp/templates/master.ftl          |   4 +-
 src/main/webapp/templates/poi.ftl             |  13 ++
 src/main/webapp/templates/weatherstation.ftl  |  25 ++
 .../webapp/templates/weatherstationlist.ftl   |  13 ++
 32 files changed, 2382 insertions(+), 9 deletions(-)
 create mode 100644 src/main/java/no/bioforsk/vips/logic/controller/PointOfInterestController.java
 create mode 100644 src/main/java/no/bioforsk/vips/logic/entity/Country.java
 create mode 100644 src/main/java/no/bioforsk/vips/logic/entity/ExternalResource.java
 create mode 100644 src/main/java/no/bioforsk/vips/logic/entity/ExternalResourceType.java
 create mode 100644 src/main/java/no/bioforsk/vips/logic/entity/HierarchyCategory.java
 create mode 100644 src/main/java/no/bioforsk/vips/logic/entity/Organism.java
 create mode 100644 src/main/java/no/bioforsk/vips/logic/entity/OrganismExternalResource.java
 create mode 100644 src/main/java/no/bioforsk/vips/logic/entity/OrganismExternalResourcePK.java
 create mode 100644 src/main/java/no/bioforsk/vips/logic/entity/OrganismLocale.java
 create mode 100644 src/main/java/no/bioforsk/vips/logic/entity/OrganismLocalePK.java
 create mode 100644 src/main/java/no/bioforsk/vips/logic/entity/PointOfInterest.java
 create mode 100644 src/main/java/no/bioforsk/vips/logic/entity/PointOfInterestType.java
 create mode 100644 src/main/java/no/bioforsk/vips/logic/entity/PointOfInterestWeatherStation.java
 create mode 100644 src/main/java/no/bioforsk/vips/logic/entity/UserPointOfInterest.java
 create mode 100644 src/main/java/no/bioforsk/vips/logic/entity/UserPointOfInterestPK.java
 create mode 100644 src/main/java/no/bioforsk/vips/logic/entity/UserVipslogicRole.java
 create mode 100644 src/main/java/no/bioforsk/vips/logic/entity/UserVipslogicRolePK.java
 create mode 100644 src/main/java/no/bioforsk/vips/logic/entity/VipslogicRole.java
 create mode 100644 src/main/java/no/bioforsk/vips/logic/entity/WeatherStationDataSource.java
 create mode 100644 src/main/java/no/bioforsk/vips/logic/session/PointOfInterestBean.java
 create mode 100644 src/main/java/no/bioforsk/vips/logic/session/SessionControllerGetter.java
 create mode 100644 src/main/resources/META-INF/persistence.xml
 create mode 100644 src/main/setup/jboss-ds.xml
 create mode 100644 src/main/webapp/templates/poi.ftl
 create mode 100644 src/main/webapp/templates/weatherstation.ftl
 create mode 100644 src/main/webapp/templates/weatherstationlist.ftl

diff --git a/src/main/java/no/bioforsk/vips/logic/controller/LoginController.java b/src/main/java/no/bioforsk/vips/logic/controller/LoginController.java
index b53cdf4a..8db10e92 100644
--- a/src/main/java/no/bioforsk/vips/logic/controller/LoginController.java
+++ b/src/main/java/no/bioforsk/vips/logic/controller/LoginController.java
@@ -2,11 +2,9 @@ package no.bioforsk.vips.logic.controller;
 
 import java.io.IOException;
 import java.io.PrintWriter;
-import java.net.URLEncoder;
 import java.util.HashMap;
 import java.util.Locale;
 import java.util.Map;
-import java.util.ResourceBundle;
 import javax.servlet.ServletException;
 import javax.servlet.http.HttpServlet;
 import javax.servlet.http.HttpServletRequest;
@@ -20,7 +18,7 @@ import no.bioforsk.vips.logic.util.ServletUtil;
 import org.jboss.resteasy.client.jaxrs.ResteasyWebTarget;
 
 /**
- * Logs a user in
+ * Logs a user in or out
  * @copyright 2013 <a href="http://www.bioforsk.no/">Bioforsk</a>
  * @author Tor-Einar Skog <tor-einar.skog@bioforsk.no>
  */
@@ -41,9 +39,6 @@ public class LoginController extends HttpServlet {
     protected void processRequest(HttpServletRequest request, HttpServletResponse response)
             throws ServletException, IOException {
         
-        System.out.println("Request Locale=" + request.getLocale().toString());
-        System.out.println("Current locale=" + ((Locale)request.getSession().getAttribute("currentLocale")).toString());
-        
         // Resetting messages
         request.getSession().removeAttribute("messageKey");
         request.getSession().removeAttribute("errorMessageKey");
diff --git a/src/main/java/no/bioforsk/vips/logic/controller/PointOfInterestController.java b/src/main/java/no/bioforsk/vips/logic/controller/PointOfInterestController.java
new file mode 100644
index 00000000..58b0a290
--- /dev/null
+++ b/src/main/java/no/bioforsk/vips/logic/controller/PointOfInterestController.java
@@ -0,0 +1,95 @@
+package no.bioforsk.vips.logic.controller;
+
+import java.io.IOException;
+import java.util.Map;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import no.bioforsk.vips.logic.session.SessionControllerGetter;
+
+/**
+ * Handles transactions for POIs
+ * @copyright 2013 <a href="http://www.bioforsk.no/">Bioforsk</a>
+ * @author Tor-Einar Skog <tor-einar.skog@bioforsk.no>
+ */
+public class PointOfInterestController extends HttpServlet {
+
+    /**
+     * Processes requests for both HTTP
+     * <code>GET</code> and
+     * <code>POST</code> methods.
+     *
+     * @param request servlet request
+     * @param response servlet response
+     * @throws ServletException if a servlet-specific error occurs
+     * @throws IOException if an I/O error occurs
+     */
+    protected void processRequest(HttpServletRequest request, HttpServletResponse response)
+            throws ServletException, IOException {
+        
+        request.getSession().removeAttribute("weatherStations");
+        request.getSession().removeAttribute("weatherStation");
+        
+        Map userInfo = (Map) request.getSession().getAttribute("user");
+        Integer userId = (Integer) userInfo.get("vipsCoreUserId");
+        
+        if(request.getServletPath().equals("/weatherStation"))
+        {
+            String pointOfInterestId = request.getParameter("pointOfInterestId");
+            if(pointOfInterestId == null)
+            {
+                request.getSession().setAttribute("weatherStations", SessionControllerGetter.getPointOfInterestBean().getWeatherstationsForUser(userId));
+                request.getRequestDispatcher("/weatherstationlist.ftl").forward(request, response);
+            }
+            else
+            {
+                request.getSession().setAttribute("weatherStation", SessionControllerGetter.getPointOfInterestBean().getPointOfInterest(Integer.valueOf(pointOfInterestId)));
+                request.getRequestDispatcher("/weatherstation.ftl").forward(request, response);
+            }
+        }
+        
+        
+    }
+
+    // <editor-fold defaultstate="collapsed" desc="HttpServlet methods. Click on the + sign on the left to edit the code.">
+    /**
+     * Handles the HTTP
+     * <code>GET</code> method.
+     *
+     * @param request servlet request
+     * @param response servlet response
+     * @throws ServletException if a servlet-specific error occurs
+     * @throws IOException if an I/O error occurs
+     */
+    @Override
+    protected void doGet(HttpServletRequest request, HttpServletResponse response)
+            throws ServletException, IOException {
+        processRequest(request, response);
+    }
+
+    /**
+     * Handles the HTTP
+     * <code>POST</code> method.
+     *
+     * @param request servlet request
+     * @param response servlet response
+     * @throws ServletException if a servlet-specific error occurs
+     * @throws IOException if an I/O error occurs
+     */
+    @Override
+    protected void doPost(HttpServletRequest request, HttpServletResponse response)
+            throws ServletException, IOException {
+        processRequest(request, response);
+    }
+
+    /**
+     * Returns a short description of the servlet.
+     *
+     * @return a String containing servlet description
+     */
+    @Override
+    public String getServletInfo() {
+        return "Short description";
+    }// </editor-fold>
+}
diff --git a/src/main/java/no/bioforsk/vips/logic/entity/Country.java b/src/main/java/no/bioforsk/vips/logic/entity/Country.java
new file mode 100644
index 00000000..4406c8b7
--- /dev/null
+++ b/src/main/java/no/bioforsk/vips/logic/entity/Country.java
@@ -0,0 +1,113 @@
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+
+package no.bioforsk.vips.logic.entity;
+
+import java.io.Serializable;
+import java.util.Set;
+import javax.persistence.Basic;
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.JoinTable;
+import javax.persistence.ManyToMany;
+import javax.persistence.NamedQueries;
+import javax.persistence.NamedQuery;
+import javax.persistence.OneToMany;
+import javax.persistence.Table;
+import javax.validation.constraints.NotNull;
+import javax.validation.constraints.Size;
+import javax.xml.bind.annotation.XmlRootElement;
+import javax.xml.bind.annotation.XmlTransient;
+import org.codehaus.jackson.annotate.JsonIgnore;
+
+/**
+ * @copyright 2013 <a href="http://www.bioforsk.no/">Bioforsk</a>
+ * @author Tor-Einar Skog <tor-einar.skog@bioforsk.no>
+ */
+@Entity
+@Table(name = "country")
+@XmlRootElement
+@NamedQueries({
+    @NamedQuery(name = "Country.findAll", query = "SELECT c FROM Country c"),
+    @NamedQuery(name = "Country.findByCountryCode", query = "SELECT c FROM Country c WHERE c.countryCode = :countryCode")})
+public class Country implements Serializable {
+    private static final long serialVersionUID = 1L;
+    @Id
+    @Basic(optional = false)
+    @NotNull
+    @Size(min = 1, max = 2)
+    @Column(name = "country_code")
+    private String countryCode;
+    @JoinTable(name = "external_resource_validity", joinColumns = {
+        @JoinColumn(name = "country_code", referencedColumnName = "country_code")}, inverseJoinColumns = {
+        @JoinColumn(name = "external_resource_id", referencedColumnName = "external_resource_id")})
+    @ManyToMany
+    private Set<ExternalResource> externalResourceSet;
+    @OneToMany(mappedBy = "countryCode")
+    private Set<PointOfInterest> pointOfInterestSet;
+
+    public Country() {
+    }
+
+    public Country(String countryCode) {
+        this.countryCode = countryCode;
+    }
+
+    public String getCountryCode() {
+        return countryCode;
+    }
+
+    public void setCountryCode(String countryCode) {
+        this.countryCode = countryCode;
+    }
+
+    @XmlTransient
+    @JsonIgnore
+    public Set<ExternalResource> getExternalResourceSet() {
+        return externalResourceSet;
+    }
+
+    public void setExternalResourceSet(Set<ExternalResource> externalResourceSet) {
+        this.externalResourceSet = externalResourceSet;
+    }
+
+    @XmlTransient
+    @JsonIgnore
+    public Set<PointOfInterest> getPointOfInterestSet() {
+        return pointOfInterestSet;
+    }
+
+    public void setPointOfInterestSet(Set<PointOfInterest> pointOfInterestSet) {
+        this.pointOfInterestSet = pointOfInterestSet;
+    }
+
+    @Override
+    public int hashCode() {
+        int hash = 0;
+        hash += (countryCode != null ? countryCode.hashCode() : 0);
+        return hash;
+    }
+
+    @Override
+    public boolean equals(Object object) {
+        // TODO: Warning - this method won't work in the case the id fields are not set
+        if (!(object instanceof Country)) {
+            return false;
+        }
+        Country other = (Country) object;
+        if ((this.countryCode == null && other.countryCode != null) || (this.countryCode != null && !this.countryCode.equals(other.countryCode))) {
+            return false;
+        }
+        return true;
+    }
+
+    @Override
+    public String toString() {
+        return "no.bioforsk.vips.logic.entity.Country[ countryCode=" + countryCode + " ]";
+    }
+
+}
diff --git a/src/main/java/no/bioforsk/vips/logic/entity/ExternalResource.java b/src/main/java/no/bioforsk/vips/logic/entity/ExternalResource.java
new file mode 100644
index 00000000..52430f03
--- /dev/null
+++ b/src/main/java/no/bioforsk/vips/logic/entity/ExternalResource.java
@@ -0,0 +1,158 @@
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+
+package no.bioforsk.vips.logic.entity;
+
+import java.io.Serializable;
+import java.util.Set;
+import javax.persistence.Basic;
+import javax.persistence.CascadeType;
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToMany;
+import javax.persistence.ManyToOne;
+import javax.persistence.NamedQueries;
+import javax.persistence.NamedQuery;
+import javax.persistence.OneToMany;
+import javax.persistence.Table;
+import javax.validation.constraints.Size;
+import javax.xml.bind.annotation.XmlRootElement;
+import javax.xml.bind.annotation.XmlTransient;
+import org.codehaus.jackson.annotate.JsonIgnore;
+
+/**
+ * @copyright 2013 <a href="http://www.bioforsk.no/">Bioforsk</a>
+ * @author Tor-Einar Skog <tor-einar.skog@bioforsk.no>
+ */
+@Entity
+@Table(name = "external_resource")
+@XmlRootElement
+@NamedQueries({
+    @NamedQuery(name = "ExternalResource.findAll", query = "SELECT e FROM ExternalResource e"),
+    @NamedQuery(name = "ExternalResource.findByExternalResourceId", query = "SELECT e FROM ExternalResource e WHERE e.externalResourceId = :externalResourceId"),
+    @NamedQuery(name = "ExternalResource.findByUri", query = "SELECT e FROM ExternalResource e WHERE e.uri = :uri"),
+    @NamedQuery(name = "ExternalResource.findByIdentifierTemplate", query = "SELECT e FROM ExternalResource e WHERE e.identifierTemplate = :identifierTemplate"),
+    @NamedQuery(name = "ExternalResource.findByName", query = "SELECT e FROM ExternalResource e WHERE e.name = :name")})
+public class ExternalResource implements Serializable {
+    private static final long serialVersionUID = 1L;
+    @Id
+    @GeneratedValue(strategy = GenerationType.IDENTITY)
+    @Basic(optional = false)
+    @Column(name = "external_resource_id")
+    private Integer externalResourceId;
+    @Size(max = 1023)
+    @Column(name = "uri")
+    private String uri;
+    @Size(max = 255)
+    @Column(name = "identifier_template")
+    private String identifierTemplate;
+    @Size(max = 255)
+    @Column(name = "name")
+    private String name;
+    @ManyToMany(mappedBy = "externalResourceSet")
+    private Set<Country> countrySet;
+    @JoinColumn(name = "external_resource_type_id", referencedColumnName = "external_resource_type_id")
+    @ManyToOne
+    private ExternalResourceType externalResourceTypeId;
+    @OneToMany(cascade = CascadeType.ALL, mappedBy = "externalResource")
+    private Set<OrganismExternalResource> organismExternalResourceSet;
+
+    public ExternalResource() {
+    }
+
+    public ExternalResource(Integer externalResourceId) {
+        this.externalResourceId = externalResourceId;
+    }
+
+    public Integer getExternalResourceId() {
+        return externalResourceId;
+    }
+
+    public void setExternalResourceId(Integer externalResourceId) {
+        this.externalResourceId = externalResourceId;
+    }
+
+    public String getUri() {
+        return uri;
+    }
+
+    public void setUri(String uri) {
+        this.uri = uri;
+    }
+
+    public String getIdentifierTemplate() {
+        return identifierTemplate;
+    }
+
+    public void setIdentifierTemplate(String identifierTemplate) {
+        this.identifierTemplate = identifierTemplate;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    @XmlTransient
+    @JsonIgnore
+    public Set<Country> getCountrySet() {
+        return countrySet;
+    }
+
+    public void setCountrySet(Set<Country> countrySet) {
+        this.countrySet = countrySet;
+    }
+
+    public ExternalResourceType getExternalResourceTypeId() {
+        return externalResourceTypeId;
+    }
+
+    public void setExternalResourceTypeId(ExternalResourceType externalResourceTypeId) {
+        this.externalResourceTypeId = externalResourceTypeId;
+    }
+
+    @XmlTransient
+    @JsonIgnore
+    public Set<OrganismExternalResource> getOrganismExternalResourceSet() {
+        return organismExternalResourceSet;
+    }
+
+    public void setOrganismExternalResourceSet(Set<OrganismExternalResource> organismExternalResourceSet) {
+        this.organismExternalResourceSet = organismExternalResourceSet;
+    }
+
+    @Override
+    public int hashCode() {
+        int hash = 0;
+        hash += (externalResourceId != null ? externalResourceId.hashCode() : 0);
+        return hash;
+    }
+
+    @Override
+    public boolean equals(Object object) {
+        // TODO: Warning - this method won't work in the case the id fields are not set
+        if (!(object instanceof ExternalResource)) {
+            return false;
+        }
+        ExternalResource other = (ExternalResource) object;
+        if ((this.externalResourceId == null && other.externalResourceId != null) || (this.externalResourceId != null && !this.externalResourceId.equals(other.externalResourceId))) {
+            return false;
+        }
+        return true;
+    }
+
+    @Override
+    public String toString() {
+        return "no.bioforsk.vips.logic.entity.ExternalResource[ externalResourceId=" + externalResourceId + " ]";
+    }
+
+}
diff --git a/src/main/java/no/bioforsk/vips/logic/entity/ExternalResourceType.java b/src/main/java/no/bioforsk/vips/logic/entity/ExternalResourceType.java
new file mode 100644
index 00000000..ff296be5
--- /dev/null
+++ b/src/main/java/no/bioforsk/vips/logic/entity/ExternalResourceType.java
@@ -0,0 +1,106 @@
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+
+package no.bioforsk.vips.logic.entity;
+
+import java.io.Serializable;
+import java.util.Set;
+import javax.persistence.Basic;
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.Id;
+import javax.persistence.NamedQueries;
+import javax.persistence.NamedQuery;
+import javax.persistence.OneToMany;
+import javax.persistence.Table;
+import javax.validation.constraints.NotNull;
+import javax.validation.constraints.Size;
+import javax.xml.bind.annotation.XmlRootElement;
+import javax.xml.bind.annotation.XmlTransient;
+import org.codehaus.jackson.annotate.JsonIgnore;
+
+/**
+ * @copyright 2013 <a href="http://www.bioforsk.no/">Bioforsk</a>
+ * @author Tor-Einar Skog <tor-einar.skog@bioforsk.no>
+ */
+@Entity
+@Table(name = "external_resource_type")
+@XmlRootElement
+@NamedQueries({
+    @NamedQuery(name = "ExternalResourceType.findAll", query = "SELECT e FROM ExternalResourceType e"),
+    @NamedQuery(name = "ExternalResourceType.findByExternalResourceTypeId", query = "SELECT e FROM ExternalResourceType e WHERE e.externalResourceTypeId = :externalResourceTypeId"),
+    @NamedQuery(name = "ExternalResourceType.findByDefaultName", query = "SELECT e FROM ExternalResourceType e WHERE e.defaultName = :defaultName")})
+public class ExternalResourceType implements Serializable {
+    private static final long serialVersionUID = 1L;
+    @Id
+    @Basic(optional = false)
+    @NotNull
+    @Column(name = "external_resource_type_id")
+    private Integer externalResourceTypeId;
+    @Size(max = 255)
+    @Column(name = "default_name")
+    private String defaultName;
+    @OneToMany(mappedBy = "externalResourceTypeId")
+    private Set<ExternalResource> externalResourceSet;
+
+    public ExternalResourceType() {
+    }
+
+    public ExternalResourceType(Integer externalResourceTypeId) {
+        this.externalResourceTypeId = externalResourceTypeId;
+    }
+
+    public Integer getExternalResourceTypeId() {
+        return externalResourceTypeId;
+    }
+
+    public void setExternalResourceTypeId(Integer externalResourceTypeId) {
+        this.externalResourceTypeId = externalResourceTypeId;
+    }
+
+    public String getDefaultName() {
+        return defaultName;
+    }
+
+    public void setDefaultName(String defaultName) {
+        this.defaultName = defaultName;
+    }
+
+    @XmlTransient
+    @JsonIgnore
+    public Set<ExternalResource> getExternalResourceSet() {
+        return externalResourceSet;
+    }
+
+    public void setExternalResourceSet(Set<ExternalResource> externalResourceSet) {
+        this.externalResourceSet = externalResourceSet;
+    }
+
+    @Override
+    public int hashCode() {
+        int hash = 0;
+        hash += (externalResourceTypeId != null ? externalResourceTypeId.hashCode() : 0);
+        return hash;
+    }
+
+    @Override
+    public boolean equals(Object object) {
+        // TODO: Warning - this method won't work in the case the id fields are not set
+        if (!(object instanceof ExternalResourceType)) {
+            return false;
+        }
+        ExternalResourceType other = (ExternalResourceType) object;
+        if ((this.externalResourceTypeId == null && other.externalResourceTypeId != null) || (this.externalResourceTypeId != null && !this.externalResourceTypeId.equals(other.externalResourceTypeId))) {
+            return false;
+        }
+        return true;
+    }
+
+    @Override
+    public String toString() {
+        return "no.bioforsk.vips.logic.entity.ExternalResourceType[ externalResourceTypeId=" + externalResourceTypeId + " ]";
+    }
+
+}
diff --git a/src/main/java/no/bioforsk/vips/logic/entity/HierarchyCategory.java b/src/main/java/no/bioforsk/vips/logic/entity/HierarchyCategory.java
new file mode 100644
index 00000000..ec1d5d8e
--- /dev/null
+++ b/src/main/java/no/bioforsk/vips/logic/entity/HierarchyCategory.java
@@ -0,0 +1,124 @@
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+
+package no.bioforsk.vips.logic.entity;
+
+import java.io.Serializable;
+import java.util.Set;
+import javax.persistence.Basic;
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.Id;
+import javax.persistence.NamedQueries;
+import javax.persistence.NamedQuery;
+import javax.persistence.OneToMany;
+import javax.persistence.Table;
+import javax.validation.constraints.NotNull;
+import javax.validation.constraints.Size;
+import javax.xml.bind.annotation.XmlRootElement;
+import javax.xml.bind.annotation.XmlTransient;
+import org.codehaus.jackson.annotate.JsonIgnore;
+
+/**
+ * @copyright 2013 <a href="http://www.bioforsk.no/">Bioforsk</a>
+ * @author Tor-Einar Skog <tor-einar.skog@bioforsk.no>
+ */
+@Entity
+@Table(name = "hierarchy_category")
+@XmlRootElement
+@NamedQueries({
+    @NamedQuery(name = "HierarchyCategory.findAll", query = "SELECT h FROM HierarchyCategory h"),
+    @NamedQuery(name = "HierarchyCategory.findByHierarchyCategoryId", query = "SELECT h FROM HierarchyCategory h WHERE h.hierarchyCategoryId = :hierarchyCategoryId"),
+    @NamedQuery(name = "HierarchyCategory.findByDefaultName", query = "SELECT h FROM HierarchyCategory h WHERE h.defaultName = :defaultName"),
+    @NamedQuery(name = "HierarchyCategory.findByLogicallyDeleted", query = "SELECT h FROM HierarchyCategory h WHERE h.logicallyDeleted = :logicallyDeleted")})
+public class HierarchyCategory implements Serializable {
+    private static final long serialVersionUID = 1L;
+    @Id
+    @Basic(optional = false)
+    @NotNull
+    @Column(name = "hierarchy_category_id")
+    private Integer hierarchyCategoryId;
+    @Size(max = 63)
+    @Column(name = "default_name")
+    private String defaultName;
+    @Basic(optional = false)
+    @NotNull
+    @Column(name = "logically_deleted")
+    private boolean logicallyDeleted;
+    @OneToMany(mappedBy = "hierarchyCategoryId")
+    private Set<Organism> organismSet;
+
+    public HierarchyCategory() {
+    }
+
+    public HierarchyCategory(Integer hierarchyCategoryId) {
+        this.hierarchyCategoryId = hierarchyCategoryId;
+    }
+
+    public HierarchyCategory(Integer hierarchyCategoryId, boolean logicallyDeleted) {
+        this.hierarchyCategoryId = hierarchyCategoryId;
+        this.logicallyDeleted = logicallyDeleted;
+    }
+
+    public Integer getHierarchyCategoryId() {
+        return hierarchyCategoryId;
+    }
+
+    public void setHierarchyCategoryId(Integer hierarchyCategoryId) {
+        this.hierarchyCategoryId = hierarchyCategoryId;
+    }
+
+    public String getDefaultName() {
+        return defaultName;
+    }
+
+    public void setDefaultName(String defaultName) {
+        this.defaultName = defaultName;
+    }
+
+    public boolean getLogicallyDeleted() {
+        return logicallyDeleted;
+    }
+
+    public void setLogicallyDeleted(boolean logicallyDeleted) {
+        this.logicallyDeleted = logicallyDeleted;
+    }
+
+    @XmlTransient
+    @JsonIgnore
+    public Set<Organism> getOrganismSet() {
+        return organismSet;
+    }
+
+    public void setOrganismSet(Set<Organism> organismSet) {
+        this.organismSet = organismSet;
+    }
+
+    @Override
+    public int hashCode() {
+        int hash = 0;
+        hash += (hierarchyCategoryId != null ? hierarchyCategoryId.hashCode() : 0);
+        return hash;
+    }
+
+    @Override
+    public boolean equals(Object object) {
+        // TODO: Warning - this method won't work in the case the id fields are not set
+        if (!(object instanceof HierarchyCategory)) {
+            return false;
+        }
+        HierarchyCategory other = (HierarchyCategory) object;
+        if ((this.hierarchyCategoryId == null && other.hierarchyCategoryId != null) || (this.hierarchyCategoryId != null && !this.hierarchyCategoryId.equals(other.hierarchyCategoryId))) {
+            return false;
+        }
+        return true;
+    }
+
+    @Override
+    public String toString() {
+        return "no.bioforsk.vips.logic.entity.HierarchyCategory[ hierarchyCategoryId=" + hierarchyCategoryId + " ]";
+    }
+
+}
diff --git a/src/main/java/no/bioforsk/vips/logic/entity/Organism.java b/src/main/java/no/bioforsk/vips/logic/entity/Organism.java
new file mode 100644
index 00000000..edd0dc7d
--- /dev/null
+++ b/src/main/java/no/bioforsk/vips/logic/entity/Organism.java
@@ -0,0 +1,187 @@
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+
+package no.bioforsk.vips.logic.entity;
+
+import java.io.Serializable;
+import java.util.Set;
+import javax.persistence.Basic;
+import javax.persistence.CascadeType;
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToOne;
+import javax.persistence.NamedQueries;
+import javax.persistence.NamedQuery;
+import javax.persistence.OneToMany;
+import javax.persistence.Table;
+import javax.validation.constraints.NotNull;
+import javax.validation.constraints.Size;
+import javax.xml.bind.annotation.XmlRootElement;
+import javax.xml.bind.annotation.XmlTransient;
+import org.codehaus.jackson.annotate.JsonIgnore;
+
+/**
+ * @copyright 2013 <a href="http://www.bioforsk.no/">Bioforsk</a>
+ * @author Tor-Einar Skog <tor-einar.skog@bioforsk.no>
+ */
+@Entity
+@Table(name = "organism")
+@XmlRootElement
+@NamedQueries({
+    @NamedQuery(name = "Organism.findAll", query = "SELECT o FROM Organism o"),
+    @NamedQuery(name = "Organism.findByOrganismId", query = "SELECT o FROM Organism o WHERE o.organismId = :organismId"),
+    @NamedQuery(name = "Organism.findByLatinName", query = "SELECT o FROM Organism o WHERE o.latinName = :latinName"),
+    @NamedQuery(name = "Organism.findByTradeName", query = "SELECT o FROM Organism o WHERE o.tradeName = :tradeName"),
+    @NamedQuery(name = "Organism.findByLogicallyDeleted", query = "SELECT o FROM Organism o WHERE o.logicallyDeleted = :logicallyDeleted")})
+public class Organism implements Serializable {
+    private static final long serialVersionUID = 1L;
+    @Id
+    @GeneratedValue(strategy = GenerationType.IDENTITY)
+    @Basic(optional = false)
+    @Column(name = "organism_id")
+    private Integer organismId;
+    @Size(max = 255)
+    @Column(name = "latin_name")
+    private String latinName;
+    @Size(max = 255)
+    @Column(name = "trade_name")
+    private String tradeName;
+    @Basic(optional = false)
+    @NotNull
+    @Column(name = "logically_deleted")
+    private boolean logicallyDeleted;
+    @OneToMany(cascade = CascadeType.ALL, mappedBy = "organism")
+    private Set<OrganismLocale> organismLocaleSet;
+    @OneToMany(cascade = CascadeType.ALL, mappedBy = "organism")
+    private Set<OrganismExternalResource> organismExternalResourceSet;
+    @OneToMany(mappedBy = "parentOrganismId")
+    private Set<Organism> organismSet;
+    @JoinColumn(name = "parent_organism_id", referencedColumnName = "organism_id")
+    @ManyToOne
+    private Organism parentOrganismId;
+    @JoinColumn(name = "hierarchy_category_id", referencedColumnName = "hierarchy_category_id")
+    @ManyToOne
+    private HierarchyCategory hierarchyCategoryId;
+
+    public Organism() {
+    }
+
+    public Organism(Integer organismId) {
+        this.organismId = organismId;
+    }
+
+    public Organism(Integer organismId, boolean logicallyDeleted) {
+        this.organismId = organismId;
+        this.logicallyDeleted = logicallyDeleted;
+    }
+
+    public Integer getOrganismId() {
+        return organismId;
+    }
+
+    public void setOrganismId(Integer organismId) {
+        this.organismId = organismId;
+    }
+
+    public String getLatinName() {
+        return latinName;
+    }
+
+    public void setLatinName(String latinName) {
+        this.latinName = latinName;
+    }
+
+    public String getTradeName() {
+        return tradeName;
+    }
+
+    public void setTradeName(String tradeName) {
+        this.tradeName = tradeName;
+    }
+
+    public boolean getLogicallyDeleted() {
+        return logicallyDeleted;
+    }
+
+    public void setLogicallyDeleted(boolean logicallyDeleted) {
+        this.logicallyDeleted = logicallyDeleted;
+    }
+
+    @XmlTransient
+    @JsonIgnore
+    public Set<OrganismLocale> getOrganismLocaleSet() {
+        return organismLocaleSet;
+    }
+
+    public void setOrganismLocaleSet(Set<OrganismLocale> organismLocaleSet) {
+        this.organismLocaleSet = organismLocaleSet;
+    }
+
+    @XmlTransient
+    @JsonIgnore
+    public Set<OrganismExternalResource> getOrganismExternalResourceSet() {
+        return organismExternalResourceSet;
+    }
+
+    public void setOrganismExternalResourceSet(Set<OrganismExternalResource> organismExternalResourceSet) {
+        this.organismExternalResourceSet = organismExternalResourceSet;
+    }
+
+    @XmlTransient
+    @JsonIgnore
+    public Set<Organism> getOrganismSet() {
+        return organismSet;
+    }
+
+    public void setOrganismSet(Set<Organism> organismSet) {
+        this.organismSet = organismSet;
+    }
+
+    public Organism getParentOrganismId() {
+        return parentOrganismId;
+    }
+
+    public void setParentOrganismId(Organism parentOrganismId) {
+        this.parentOrganismId = parentOrganismId;
+    }
+
+    public HierarchyCategory getHierarchyCategoryId() {
+        return hierarchyCategoryId;
+    }
+
+    public void setHierarchyCategoryId(HierarchyCategory hierarchyCategoryId) {
+        this.hierarchyCategoryId = hierarchyCategoryId;
+    }
+
+    @Override
+    public int hashCode() {
+        int hash = 0;
+        hash += (organismId != null ? organismId.hashCode() : 0);
+        return hash;
+    }
+
+    @Override
+    public boolean equals(Object object) {
+        // TODO: Warning - this method won't work in the case the id fields are not set
+        if (!(object instanceof Organism)) {
+            return false;
+        }
+        Organism other = (Organism) object;
+        if ((this.organismId == null && other.organismId != null) || (this.organismId != null && !this.organismId.equals(other.organismId))) {
+            return false;
+        }
+        return true;
+    }
+
+    @Override
+    public String toString() {
+        return "no.bioforsk.vips.logic.entity.Organism[ organismId=" + organismId + " ]";
+    }
+
+}
diff --git a/src/main/java/no/bioforsk/vips/logic/entity/OrganismExternalResource.java b/src/main/java/no/bioforsk/vips/logic/entity/OrganismExternalResource.java
new file mode 100644
index 00000000..6b385865
--- /dev/null
+++ b/src/main/java/no/bioforsk/vips/logic/entity/OrganismExternalResource.java
@@ -0,0 +1,114 @@
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+
+package no.bioforsk.vips.logic.entity;
+
+import java.io.Serializable;
+import javax.persistence.Column;
+import javax.persistence.EmbeddedId;
+import javax.persistence.Entity;
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToOne;
+import javax.persistence.NamedQueries;
+import javax.persistence.NamedQuery;
+import javax.persistence.Table;
+import javax.validation.constraints.Size;
+import javax.xml.bind.annotation.XmlRootElement;
+
+/**
+ * @copyright 2013 <a href="http://www.bioforsk.no/">Bioforsk</a>
+ * @author Tor-Einar Skog <tor-einar.skog@bioforsk.no>
+ */
+@Entity
+@Table(name = "organism_external_resource")
+@XmlRootElement
+@NamedQueries({
+    @NamedQuery(name = "OrganismExternalResource.findAll", query = "SELECT o FROM OrganismExternalResource o"),
+    @NamedQuery(name = "OrganismExternalResource.findByOrganismId", query = "SELECT o FROM OrganismExternalResource o WHERE o.organismExternalResourcePK.organismId = :organismId"),
+    @NamedQuery(name = "OrganismExternalResource.findByExternalResourceId", query = "SELECT o FROM OrganismExternalResource o WHERE o.organismExternalResourcePK.externalResourceId = :externalResourceId"),
+    @NamedQuery(name = "OrganismExternalResource.findByResourceIdentifier", query = "SELECT o FROM OrganismExternalResource o WHERE o.resourceIdentifier = :resourceIdentifier")})
+public class OrganismExternalResource implements Serializable {
+    private static final long serialVersionUID = 1L;
+    @EmbeddedId
+    protected OrganismExternalResourcePK organismExternalResourcePK;
+    @Size(max = 255)
+    @Column(name = "resource_identifier")
+    private String resourceIdentifier;
+    @JoinColumn(name = "organism_id", referencedColumnName = "organism_id", insertable = false, updatable = false)
+    @ManyToOne(optional = false)
+    private Organism organism;
+    @JoinColumn(name = "external_resource_id", referencedColumnName = "external_resource_id", insertable = false, updatable = false)
+    @ManyToOne(optional = false)
+    private ExternalResource externalResource;
+
+    public OrganismExternalResource() {
+    }
+
+    public OrganismExternalResource(OrganismExternalResourcePK organismExternalResourcePK) {
+        this.organismExternalResourcePK = organismExternalResourcePK;
+    }
+
+    public OrganismExternalResource(int organismId, int externalResourceId) {
+        this.organismExternalResourcePK = new OrganismExternalResourcePK(organismId, externalResourceId);
+    }
+
+    public OrganismExternalResourcePK getOrganismExternalResourcePK() {
+        return organismExternalResourcePK;
+    }
+
+    public void setOrganismExternalResourcePK(OrganismExternalResourcePK organismExternalResourcePK) {
+        this.organismExternalResourcePK = organismExternalResourcePK;
+    }
+
+    public String getResourceIdentifier() {
+        return resourceIdentifier;
+    }
+
+    public void setResourceIdentifier(String resourceIdentifier) {
+        this.resourceIdentifier = resourceIdentifier;
+    }
+
+    public Organism getOrganism() {
+        return organism;
+    }
+
+    public void setOrganism(Organism organism) {
+        this.organism = organism;
+    }
+
+    public ExternalResource getExternalResource() {
+        return externalResource;
+    }
+
+    public void setExternalResource(ExternalResource externalResource) {
+        this.externalResource = externalResource;
+    }
+
+    @Override
+    public int hashCode() {
+        int hash = 0;
+        hash += (organismExternalResourcePK != null ? organismExternalResourcePK.hashCode() : 0);
+        return hash;
+    }
+
+    @Override
+    public boolean equals(Object object) {
+        // TODO: Warning - this method won't work in the case the id fields are not set
+        if (!(object instanceof OrganismExternalResource)) {
+            return false;
+        }
+        OrganismExternalResource other = (OrganismExternalResource) object;
+        if ((this.organismExternalResourcePK == null && other.organismExternalResourcePK != null) || (this.organismExternalResourcePK != null && !this.organismExternalResourcePK.equals(other.organismExternalResourcePK))) {
+            return false;
+        }
+        return true;
+    }
+
+    @Override
+    public String toString() {
+        return "no.bioforsk.vips.logic.entity.OrganismExternalResource[ organismExternalResourcePK=" + organismExternalResourcePK + " ]";
+    }
+
+}
diff --git a/src/main/java/no/bioforsk/vips/logic/entity/OrganismExternalResourcePK.java b/src/main/java/no/bioforsk/vips/logic/entity/OrganismExternalResourcePK.java
new file mode 100644
index 00000000..b9b3f148
--- /dev/null
+++ b/src/main/java/no/bioforsk/vips/logic/entity/OrganismExternalResourcePK.java
@@ -0,0 +1,82 @@
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+
+package no.bioforsk.vips.logic.entity;
+
+import java.io.Serializable;
+import javax.persistence.Basic;
+import javax.persistence.Column;
+import javax.persistence.Embeddable;
+import javax.validation.constraints.NotNull;
+
+/**
+ * @copyright 2013 <a href="http://www.bioforsk.no/">Bioforsk</a>
+ * @author Tor-Einar Skog <tor-einar.skog@bioforsk.no>
+ */
+@Embeddable
+public class OrganismExternalResourcePK implements Serializable {
+    @Basic(optional = false)
+    @NotNull
+    @Column(name = "organism_id")
+    private int organismId;
+    @Basic(optional = false)
+    @NotNull
+    @Column(name = "external_resource_id")
+    private int externalResourceId;
+
+    public OrganismExternalResourcePK() {
+    }
+
+    public OrganismExternalResourcePK(int organismId, int externalResourceId) {
+        this.organismId = organismId;
+        this.externalResourceId = externalResourceId;
+    }
+
+    public int getOrganismId() {
+        return organismId;
+    }
+
+    public void setOrganismId(int organismId) {
+        this.organismId = organismId;
+    }
+
+    public int getExternalResourceId() {
+        return externalResourceId;
+    }
+
+    public void setExternalResourceId(int externalResourceId) {
+        this.externalResourceId = externalResourceId;
+    }
+
+    @Override
+    public int hashCode() {
+        int hash = 0;
+        hash += (int) organismId;
+        hash += (int) externalResourceId;
+        return hash;
+    }
+
+    @Override
+    public boolean equals(Object object) {
+        // TODO: Warning - this method won't work in the case the id fields are not set
+        if (!(object instanceof OrganismExternalResourcePK)) {
+            return false;
+        }
+        OrganismExternalResourcePK other = (OrganismExternalResourcePK) object;
+        if (this.organismId != other.organismId) {
+            return false;
+        }
+        if (this.externalResourceId != other.externalResourceId) {
+            return false;
+        }
+        return true;
+    }
+
+    @Override
+    public String toString() {
+        return "no.bioforsk.vips.logic.entity.OrganismExternalResourcePK[ organismId=" + organismId + ", externalResourceId=" + externalResourceId + " ]";
+    }
+
+}
diff --git a/src/main/java/no/bioforsk/vips/logic/entity/OrganismLocale.java b/src/main/java/no/bioforsk/vips/logic/entity/OrganismLocale.java
new file mode 100644
index 00000000..2ba06c28
--- /dev/null
+++ b/src/main/java/no/bioforsk/vips/logic/entity/OrganismLocale.java
@@ -0,0 +1,103 @@
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+
+package no.bioforsk.vips.logic.entity;
+
+import java.io.Serializable;
+import javax.persistence.Column;
+import javax.persistence.EmbeddedId;
+import javax.persistence.Entity;
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToOne;
+import javax.persistence.NamedQueries;
+import javax.persistence.NamedQuery;
+import javax.persistence.Table;
+import javax.validation.constraints.Size;
+import javax.xml.bind.annotation.XmlRootElement;
+
+/**
+ * @copyright 2013 <a href="http://www.bioforsk.no/">Bioforsk</a>
+ * @author Tor-Einar Skog <tor-einar.skog@bioforsk.no>
+ */
+@Entity
+@Table(name = "organism_locale")
+@XmlRootElement
+@NamedQueries({
+    @NamedQuery(name = "OrganismLocale.findAll", query = "SELECT o FROM OrganismLocale o"),
+    @NamedQuery(name = "OrganismLocale.findByOrganismId", query = "SELECT o FROM OrganismLocale o WHERE o.organismLocalePK.organismId = :organismId"),
+    @NamedQuery(name = "OrganismLocale.findByLocale", query = "SELECT o FROM OrganismLocale o WHERE o.organismLocalePK.locale = :locale"),
+    @NamedQuery(name = "OrganismLocale.findByLocalName", query = "SELECT o FROM OrganismLocale o WHERE o.localName = :localName")})
+public class OrganismLocale implements Serializable {
+    private static final long serialVersionUID = 1L;
+    @EmbeddedId
+    protected OrganismLocalePK organismLocalePK;
+    @Size(max = 255)
+    @Column(name = "local_name")
+    private String localName;
+    @JoinColumn(name = "organism_id", referencedColumnName = "organism_id", insertable = false, updatable = false)
+    @ManyToOne(optional = false)
+    private Organism organism;
+
+    public OrganismLocale() {
+    }
+
+    public OrganismLocale(OrganismLocalePK organismLocalePK) {
+        this.organismLocalePK = organismLocalePK;
+    }
+
+    public OrganismLocale(int organismId, String locale) {
+        this.organismLocalePK = new OrganismLocalePK(organismId, locale);
+    }
+
+    public OrganismLocalePK getOrganismLocalePK() {
+        return organismLocalePK;
+    }
+
+    public void setOrganismLocalePK(OrganismLocalePK organismLocalePK) {
+        this.organismLocalePK = organismLocalePK;
+    }
+
+    public String getLocalName() {
+        return localName;
+    }
+
+    public void setLocalName(String localName) {
+        this.localName = localName;
+    }
+
+    public Organism getOrganism() {
+        return organism;
+    }
+
+    public void setOrganism(Organism organism) {
+        this.organism = organism;
+    }
+
+    @Override
+    public int hashCode() {
+        int hash = 0;
+        hash += (organismLocalePK != null ? organismLocalePK.hashCode() : 0);
+        return hash;
+    }
+
+    @Override
+    public boolean equals(Object object) {
+        // TODO: Warning - this method won't work in the case the id fields are not set
+        if (!(object instanceof OrganismLocale)) {
+            return false;
+        }
+        OrganismLocale other = (OrganismLocale) object;
+        if ((this.organismLocalePK == null && other.organismLocalePK != null) || (this.organismLocalePK != null && !this.organismLocalePK.equals(other.organismLocalePK))) {
+            return false;
+        }
+        return true;
+    }
+
+    @Override
+    public String toString() {
+        return "no.bioforsk.vips.logic.entity.OrganismLocale[ organismLocalePK=" + organismLocalePK + " ]";
+    }
+
+}
diff --git a/src/main/java/no/bioforsk/vips/logic/entity/OrganismLocalePK.java b/src/main/java/no/bioforsk/vips/logic/entity/OrganismLocalePK.java
new file mode 100644
index 00000000..bd89b4d8
--- /dev/null
+++ b/src/main/java/no/bioforsk/vips/logic/entity/OrganismLocalePK.java
@@ -0,0 +1,84 @@
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+
+package no.bioforsk.vips.logic.entity;
+
+import java.io.Serializable;
+import javax.persistence.Basic;
+import javax.persistence.Column;
+import javax.persistence.Embeddable;
+import javax.validation.constraints.NotNull;
+import javax.validation.constraints.Size;
+
+/**
+ * @copyright 2013 <a href="http://www.bioforsk.no/">Bioforsk</a>
+ * @author Tor-Einar Skog <tor-einar.skog@bioforsk.no>
+ */
+@Embeddable
+public class OrganismLocalePK implements Serializable {
+    @Basic(optional = false)
+    @NotNull
+    @Column(name = "organism_id")
+    private int organismId;
+    @Basic(optional = false)
+    @NotNull
+    @Size(min = 1, max = 10)
+    @Column(name = "locale")
+    private String locale;
+
+    public OrganismLocalePK() {
+    }
+
+    public OrganismLocalePK(int organismId, String locale) {
+        this.organismId = organismId;
+        this.locale = locale;
+    }
+
+    public int getOrganismId() {
+        return organismId;
+    }
+
+    public void setOrganismId(int organismId) {
+        this.organismId = organismId;
+    }
+
+    public String getLocale() {
+        return locale;
+    }
+
+    public void setLocale(String locale) {
+        this.locale = locale;
+    }
+
+    @Override
+    public int hashCode() {
+        int hash = 0;
+        hash += (int) organismId;
+        hash += (locale != null ? locale.hashCode() : 0);
+        return hash;
+    }
+
+    @Override
+    public boolean equals(Object object) {
+        // TODO: Warning - this method won't work in the case the id fields are not set
+        if (!(object instanceof OrganismLocalePK)) {
+            return false;
+        }
+        OrganismLocalePK other = (OrganismLocalePK) object;
+        if (this.organismId != other.organismId) {
+            return false;
+        }
+        if ((this.locale == null && other.locale != null) || (this.locale != null && !this.locale.equals(other.locale))) {
+            return false;
+        }
+        return true;
+    }
+
+    @Override
+    public String toString() {
+        return "no.bioforsk.vips.logic.entity.OrganismLocalePK[ organismId=" + organismId + ", locale=" + locale + " ]";
+    }
+
+}
diff --git a/src/main/java/no/bioforsk/vips/logic/entity/PointOfInterest.java b/src/main/java/no/bioforsk/vips/logic/entity/PointOfInterest.java
new file mode 100644
index 00000000..1f511a9e
--- /dev/null
+++ b/src/main/java/no/bioforsk/vips/logic/entity/PointOfInterest.java
@@ -0,0 +1,213 @@
+package no.bioforsk.vips.logic.entity;
+
+import java.io.Serializable;
+import java.util.Set;
+import javax.persistence.Basic;
+import javax.persistence.CascadeType;
+import javax.persistence.Column;
+import javax.persistence.DiscriminatorColumn;
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.Inheritance;
+import javax.persistence.InheritanceType;
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToOne;
+import javax.persistence.NamedQueries;
+import javax.persistence.NamedQuery;
+import javax.persistence.OneToMany;
+import javax.persistence.OneToOne;
+import javax.persistence.Table;
+import javax.validation.constraints.Size;
+import javax.xml.bind.annotation.XmlRootElement;
+import javax.xml.bind.annotation.XmlTransient;
+import org.codehaus.jackson.annotate.JsonIgnore;
+
+/**
+ * @copyright 2013 <a href="http://www.bioforsk.no/">Bioforsk</a>
+ * @author Tor-Einar Skog <tor-einar.skog@bioforsk.no>
+ */
+@Entity
+@Table(name = "point_of_interest")
+@Inheritance(strategy=InheritanceType.JOINED)
+@DiscriminatorColumn(name="point_of_interest_type_id")
+@XmlRootElement
+@NamedQueries({
+    @NamedQuery(name = "PointOfInterest.findAll", query = "SELECT p FROM PointOfInterest p"),
+    @NamedQuery(name = "PointOfInterest.findByPointOfInterestId", query = "SELECT p FROM PointOfInterest p WHERE p.pointOfInterestId = :pointOfInterestId"),
+    @NamedQuery(name = "PointOfInterest.findByPointOfInterestTypeId", query = "SELECT p FROM PointOfInterest p WHERE p.pointOfInterestType = :pointOfInterestType"),
+    @NamedQuery(name = "PointOfInterest.findByName", query = "SELECT p FROM PointOfInterest p WHERE p.name = :name"),
+    @NamedQuery(name = "PointOfInterest.findByLongitude", query = "SELECT p FROM PointOfInterest p WHERE p.longitude = :longitude"),
+    @NamedQuery(name = "PointOfInterest.findByLatitude", query = "SELECT p FROM PointOfInterest p WHERE p.latitude = :latitude"),
+    @NamedQuery(name = "PointOfInterest.findByAltitude", query = "SELECT p FROM PointOfInterest p WHERE p.altitude = :altitude")
+})
+public class PointOfInterest implements Serializable, Comparable {
+    /*@OneToOne(cascade = CascadeType.ALL, mappedBy = "pointOfInterest")
+    private PointOfInterestWeatherStation pointOfInterestWeatherStation;
+    @OneToMany(cascade = CascadeType.ALL, mappedBy = "pointOfInterest")
+    private Set<PointOfInterestWeatherStation> pointOfInterestWeatherStationSet;*/
+    private static final long serialVersionUID = 1L;
+    @Id
+    @GeneratedValue(strategy = GenerationType.IDENTITY)
+    @Basic(optional = false)
+    @Column(name = "point_of_interest_id")
+    private Integer pointOfInterestId;
+    @Size(max = 255)
+    @Column(name = "name")
+    private String name;
+    // @Max(value=?)  @Min(value=?)//if you know range of your decimal fields consider using these annotations to enforce field validation
+    @Column(name = "longitude")
+    private Double longitude;
+    @Column(name = "latitude")
+    private Double latitude;
+    @Column(name = "altitude")
+    private Double altitude;
+    @OneToMany(cascade = CascadeType.ALL, mappedBy = "pointOfInterest")
+    private Set<UserPointOfInterest> userPointOfInterestSet;
+    @JoinColumn(name = "country_code", referencedColumnName = "country_code")
+    @ManyToOne
+    private Country countryCode;
+    @JoinColumn(name="point_of_interest_type_id", referencedColumnName="point_of_interest_type_id")
+    @ManyToOne
+    private PointOfInterestType pointOfInterestType;
+    
+    public PointOfInterest() {
+    }
+
+    public PointOfInterest(Integer pointOfInterestId) {
+        this.pointOfInterestId = pointOfInterestId;
+    }
+
+    public Integer getPointOfInterestId() {
+        return pointOfInterestId;
+    }
+
+    public void setPointOfInterestId(Integer pointOfInterestId) {
+        this.pointOfInterestId = pointOfInterestId;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public Double getLongitude() {
+        return longitude;
+    }
+
+    public void setLongitude(Double longitude) {
+        this.longitude = longitude;
+    }
+
+    public Double getLatitude() {
+        return latitude;
+    }
+
+    public void setLatitude(Double latitude) {
+        this.latitude = latitude;
+    }
+
+    public Double getAltitude() {
+        return altitude;
+    }
+
+    public void setAltitude(Double altitude) {
+        this.altitude = altitude;
+    }
+
+    @XmlTransient
+    @JsonIgnore
+    public Set<UserPointOfInterest> getUserPointOfInterestSet() {
+        return userPointOfInterestSet;
+    }
+
+    public void setUserPointOfInterestSet(Set<UserPointOfInterest> userPointOfInterestSet) {
+        this.userPointOfInterestSet = userPointOfInterestSet;
+    }
+
+    public Country getCountryCode() {
+        return countryCode;
+    }
+
+    public void setCountryCode(Country countryCode) {
+        this.countryCode = countryCode;
+    }
+
+    @Override
+    public int hashCode() {
+        int hash = 0;
+        hash += (pointOfInterestId != null ? pointOfInterestId.hashCode() : 0);
+        return hash;
+    }
+
+    @Override
+    public boolean equals(Object object) {
+        // TODO: Warning - this method won't work in the case the id fields are not set
+        if (!(object instanceof PointOfInterest)) {
+            return false;
+        }
+        PointOfInterest other = (PointOfInterest) object;
+        if ((this.pointOfInterestId == null && other.pointOfInterestId != null) || (this.pointOfInterestId != null && !this.pointOfInterestId.equals(other.pointOfInterestId))) {
+            return false;
+        }
+        return true;
+    }
+
+    @Override
+    public String toString() {
+        return "no.bioforsk.vips.logic.entity.PointOfInterest[ pointOfInterestId=" + pointOfInterestId + " ]";
+    }
+
+    /**
+     * @return the pointOfInterestType
+     */
+    public PointOfInterestType getPointOfInterestType() {
+        return pointOfInterestType;
+    }
+
+    /**
+     * @param pointOfInterestType the pointOfInterestType to set
+     */
+    public void setPointOfInterestType(PointOfInterestType pointOfInterestType) {
+        this.pointOfInterestType = pointOfInterestType;
+    }
+
+    @Override
+    public int compareTo(Object t) {
+        return this.compareTo((PointOfInterest) t);
+    }
+    
+    /**
+     * We sort alphabetically by name
+     * @param other
+     * @return 
+     */
+    public int compareTo(PointOfInterest other)
+    {
+        return this.getName().compareToIgnoreCase(other.getName());
+    }
+
+    /*
+    @XmlTransient
+    @JsonIgnore
+    public Set<PointOfInterestWeatherStation> getPointOfInterestWeatherStationSet() {
+        return pointOfInterestWeatherStationSet;
+    }
+
+    public void setPointOfInterestWeatherStationSet(Set<PointOfInterestWeatherStation> pointOfInterestWeatherStationSet) {
+        this.pointOfInterestWeatherStationSet = pointOfInterestWeatherStationSet;
+    }
+
+    public PointOfInterestWeatherStation getPointOfInterestWeatherStation() {
+        return pointOfInterestWeatherStation;
+    }
+
+    public void setPointOfInterestWeatherStation(PointOfInterestWeatherStation pointOfInterestWeatherStation) {
+        this.pointOfInterestWeatherStation = pointOfInterestWeatherStation;
+    }
+*/
+}
diff --git a/src/main/java/no/bioforsk/vips/logic/entity/PointOfInterestType.java b/src/main/java/no/bioforsk/vips/logic/entity/PointOfInterestType.java
new file mode 100644
index 00000000..bd0821b4
--- /dev/null
+++ b/src/main/java/no/bioforsk/vips/logic/entity/PointOfInterestType.java
@@ -0,0 +1,112 @@
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+
+package no.bioforsk.vips.logic.entity;
+
+import java.io.Serializable;
+import java.util.Set;
+import javax.persistence.Basic;
+import javax.persistence.Column;
+import javax.persistence.DiscriminatorColumn;
+import javax.persistence.Entity;
+import javax.persistence.Id;
+import javax.persistence.Inheritance;
+import javax.persistence.InheritanceType;
+import javax.persistence.NamedQueries;
+import javax.persistence.NamedQuery;
+import javax.persistence.OneToMany;
+import javax.persistence.Table;
+import javax.validation.constraints.NotNull;
+import javax.validation.constraints.Size;
+import javax.xml.bind.annotation.XmlRootElement;
+import javax.xml.bind.annotation.XmlTransient;
+import org.codehaus.jackson.annotate.JsonIgnore;
+
+/**
+ * @copyright 2013 <a href="http://www.bioforsk.no/">Bioforsk</a>
+ * @author Tor-Einar Skog <tor-einar.skog@bioforsk.no>
+ */
+@Entity
+@Inheritance(strategy=InheritanceType.JOINED)
+@DiscriminatorColumn(name="point_of_interest_type_id")
+@Table(name = "point_of_interest_type")
+@XmlRootElement
+@NamedQueries({
+    @NamedQuery(name = "PointOfInterestType.findAll", query = "SELECT p FROM PointOfInterestType p"),
+    @NamedQuery(name = "PointOfInterestType.findByPointOfInterestTypeId", query = "SELECT p FROM PointOfInterestType p WHERE p.pointOfInterestTypeId = :pointOfInterestTypeId"),
+    @NamedQuery(name = "PointOfInterestType.findByDefaultName", query = "SELECT p FROM PointOfInterestType p WHERE p.defaultName = :defaultName")})
+public class PointOfInterestType implements Serializable {
+    /*@OneToMany(mappedBy = "pointOfInterestTypeId")
+    private Set<PointOfInterest> pointOfInterestSet;*/
+    private static final long serialVersionUID = 1L;
+    @Id
+    @Basic(optional = false)
+    @NotNull
+    @Column(name = "point_of_interest_type_id")
+    private Integer pointOfInterestTypeId;
+    @Size(max = 255)
+    @Column(name = "default_name")
+    private String defaultName;
+
+    public PointOfInterestType() {
+    }
+
+    public PointOfInterestType(Integer pointOfInterestTypeId) {
+        this.pointOfInterestTypeId = pointOfInterestTypeId;
+    }
+
+    public Integer getPointOfInterestTypeId() {
+        return pointOfInterestTypeId;
+    }
+
+    public void setPointOfInterestTypeId(Integer pointOfInterestTypeId) {
+        this.pointOfInterestTypeId = pointOfInterestTypeId;
+    }
+
+    public String getDefaultName() {
+        return defaultName;
+    }
+
+    public void setDefaultName(String defaultName) {
+        this.defaultName = defaultName;
+    }
+
+    @Override
+    public int hashCode() {
+        int hash = 0;
+        hash += (pointOfInterestTypeId != null ? pointOfInterestTypeId.hashCode() : 0);
+        return hash;
+    }
+
+    @Override
+    public boolean equals(Object object) {
+        // TODO: Warning - this method won't work in the case the id fields are not set
+        if (!(object instanceof PointOfInterestType)) {
+            return false;
+        }
+        PointOfInterestType other = (PointOfInterestType) object;
+        if ((this.pointOfInterestTypeId == null && other.pointOfInterestTypeId != null) || (this.pointOfInterestTypeId != null && !this.pointOfInterestTypeId.equals(other.pointOfInterestTypeId))) {
+            return false;
+        }
+        return true;
+    }
+
+    @Override
+    public String toString() {
+        return "no.bioforsk.vips.logic.entity.PointOfInterestType[ pointOfInterestTypeId=" + pointOfInterestTypeId + " ]";
+    }
+
+    /*
+    @XmlTransient
+    @JsonIgnore
+    public Set<PointOfInterest> getPointOfInterestSet() {
+        return pointOfInterestSet;
+    }
+
+    public void setPointOfInterestSet(Set<PointOfInterest> pointOfInterestSet) {
+        this.pointOfInterestSet = pointOfInterestSet;
+    }*/
+
+}
diff --git a/src/main/java/no/bioforsk/vips/logic/entity/PointOfInterestWeatherStation.java b/src/main/java/no/bioforsk/vips/logic/entity/PointOfInterestWeatherStation.java
new file mode 100644
index 00000000..8e468733
--- /dev/null
+++ b/src/main/java/no/bioforsk/vips/logic/entity/PointOfInterestWeatherStation.java
@@ -0,0 +1,103 @@
+package no.bioforsk.vips.logic.entity;
+
+import java.io.Serializable;
+import javax.persistence.Column;
+import javax.persistence.DiscriminatorValue;
+import javax.persistence.Entity;
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToOne;
+import javax.persistence.NamedQueries;
+import javax.persistence.NamedQuery;
+import javax.persistence.OneToOne;
+import javax.persistence.Table;
+import javax.validation.constraints.Size;
+import javax.xml.bind.annotation.XmlRootElement;
+import no.bioforsk.vips.logic.util.Globals;
+
+/**
+ * Extension of {@see PointOfInterest}, with additional info for weather stations
+ * @copyright 2013 <a href="http://www.bioforsk.no/">Bioforsk</a>
+ * @author Tor-Einar Skog <tor-einar.skog@bioforsk.no>
+ */
+@Entity
+@DiscriminatorValue("1")
+@Table(name = "point_of_interest_weather_station")
+@XmlRootElement
+@NamedQueries({
+    @NamedQuery(name = "PointOfInterestWeatherStation.findAll", query = "SELECT p FROM PointOfInterestWeatherStation p"),
+    @NamedQuery(name = "PointOfInterestWeatherStation.findByPointOfInterestId", query = "SELECT p FROM PointOfInterest p WHERE p.pointOfInterestId = :pointOfInterestId AND p.pointOfInterestType.pointOfInterestTypeId=1"),
+    @NamedQuery(name = "PointOfInterestWeatherStation.findByUserId", query = "SELECT p FROM PointOfInterest p WHERE p.pointOfInterestType.pointOfInterestTypeId=1 AND p.pointOfInterestId IN(SELECT up.pointOfInterest.pointOfInterestId FROM UserPointOfInterest up WHERE up.userPointOfInterestPK.userId = :userId)")
+})
+public class PointOfInterestWeatherStation extends PointOfInterest implements Serializable {
+    @Size(max = 255)
+    @Column(name = "weather_station_remote_id")
+    private String weatherStationRemoteId;
+    @JoinColumn(name = "weather_station_data_source_id", referencedColumnName = "weather_station_data_source_id")
+    @ManyToOne
+    private WeatherStationDataSource weatherStationDataSourceId;
+    @JoinColumn(name = "point_of_interest_id", referencedColumnName = "point_of_interest_id", insertable = false, updatable = false)
+    @OneToOne(optional = false)
+    private PointOfInterest pointOfInterest;
+
+    public PointOfInterestWeatherStation() {
+    }
+
+
+    public String getWeatherStationRemoteId() {
+        return weatherStationRemoteId;
+    }
+
+    public void setWeatherStationRemoteId(String weatherStationRemoteId) {
+        this.weatherStationRemoteId = weatherStationRemoteId;
+    }
+
+    public WeatherStationDataSource getWeatherStationDataSourceId() {
+        return weatherStationDataSourceId;
+    }
+
+    public void setWeatherStationDataSourceId(WeatherStationDataSource weatherStationDataSourceId) {
+        this.weatherStationDataSourceId = weatherStationDataSourceId;
+    }
+
+    public PointOfInterest getPointOfInterest() {
+        return pointOfInterest;
+    }
+
+    public void setPointOfInterest(PointOfInterest pointOfInterest) {
+        this.pointOfInterest = pointOfInterest;
+    }
+    
+    @Override
+    public Integer getPointOfInterestId()
+    {
+        return super.getPointOfInterestId();
+    }
+
+    @Override
+    public int hashCode() {
+        int hash = 0;
+        hash += (this.getPointOfInterestId() != null ? this.getPointOfInterestId().hashCode() : 0);
+        return hash;
+    }
+
+    
+    
+    @Override
+    public boolean equals(Object object) {
+        // TODO: Warning - this method won't work in the case the id fields are not set
+        if (!(object instanceof PointOfInterestWeatherStation)) {
+            return false;
+        }
+        PointOfInterestWeatherStation other = (PointOfInterestWeatherStation) object;
+        if ((this.getPointOfInterestId() == null && other.getPointOfInterestId() != null) || (this.getPointOfInterestId() != null && !this.getPointOfInterestId().equals(other.getPointOfInterestId()))) {
+            return false;
+        }
+        return true;
+    }
+
+    @Override
+    public String toString() {
+        return "no.bioforsk.vips.logic.entity.PointOfInterestWeatherStation[ pointOfInterestId=" + this.getPointOfInterestId() + " ]";
+    }
+
+}
diff --git a/src/main/java/no/bioforsk/vips/logic/entity/UserPointOfInterest.java b/src/main/java/no/bioforsk/vips/logic/entity/UserPointOfInterest.java
new file mode 100644
index 00000000..61e0226c
--- /dev/null
+++ b/src/main/java/no/bioforsk/vips/logic/entity/UserPointOfInterest.java
@@ -0,0 +1,89 @@
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+
+package no.bioforsk.vips.logic.entity;
+
+import java.io.Serializable;
+import javax.persistence.EmbeddedId;
+import javax.persistence.Entity;
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToOne;
+import javax.persistence.NamedQueries;
+import javax.persistence.NamedQuery;
+import javax.persistence.Table;
+import javax.xml.bind.annotation.XmlRootElement;
+
+/**
+ * @copyright 2013 <a href="http://www.bioforsk.no/">Bioforsk</a>
+ * @author Tor-Einar Skog <tor-einar.skog@bioforsk.no>
+ */
+@Entity
+@Table(name = "user_point_of_interest")
+@XmlRootElement
+@NamedQueries({
+    @NamedQuery(name = "UserPointOfInterest.findAll", query = "SELECT u FROM UserPointOfInterest u"),
+    @NamedQuery(name = "UserPointOfInterest.findByPointOfInterestId", query = "SELECT u FROM UserPointOfInterest u WHERE u.userPointOfInterestPK.pointOfInterestId = :pointOfInterestId"),
+    @NamedQuery(name = "UserPointOfInterest.findByUserId", query = "SELECT u FROM UserPointOfInterest u WHERE u.userPointOfInterestPK.userId = :userId")})
+public class UserPointOfInterest implements Serializable {
+    private static final long serialVersionUID = 1L;
+    @EmbeddedId
+    protected UserPointOfInterestPK userPointOfInterestPK;
+    @JoinColumn(name = "point_of_interest_id", referencedColumnName = "point_of_interest_id", insertable = false, updatable = false)
+    @ManyToOne(optional = false)
+    private PointOfInterest pointOfInterest;
+
+    public UserPointOfInterest() {
+    }
+
+    public UserPointOfInterest(UserPointOfInterestPK userPointOfInterestPK) {
+        this.userPointOfInterestPK = userPointOfInterestPK;
+    }
+
+    public UserPointOfInterest(int pointOfInterestId, int userId) {
+        this.userPointOfInterestPK = new UserPointOfInterestPK(pointOfInterestId, userId);
+    }
+
+    public UserPointOfInterestPK getUserPointOfInterestPK() {
+        return userPointOfInterestPK;
+    }
+
+    public void setUserPointOfInterestPK(UserPointOfInterestPK userPointOfInterestPK) {
+        this.userPointOfInterestPK = userPointOfInterestPK;
+    }
+
+    public PointOfInterest getPointOfInterest() {
+        return pointOfInterest;
+    }
+
+    public void setPointOfInterest(PointOfInterest pointOfInterest) {
+        this.pointOfInterest = pointOfInterest;
+    }
+
+    @Override
+    public int hashCode() {
+        int hash = 0;
+        hash += (userPointOfInterestPK != null ? userPointOfInterestPK.hashCode() : 0);
+        return hash;
+    }
+
+    @Override
+    public boolean equals(Object object) {
+        // TODO: Warning - this method won't work in the case the id fields are not set
+        if (!(object instanceof UserPointOfInterest)) {
+            return false;
+        }
+        UserPointOfInterest other = (UserPointOfInterest) object;
+        if ((this.userPointOfInterestPK == null && other.userPointOfInterestPK != null) || (this.userPointOfInterestPK != null && !this.userPointOfInterestPK.equals(other.userPointOfInterestPK))) {
+            return false;
+        }
+        return true;
+    }
+
+    @Override
+    public String toString() {
+        return "no.bioforsk.vips.logic.entity.UserPointOfInterest[ userPointOfInterestPK=" + userPointOfInterestPK + " ]";
+    }
+
+}
diff --git a/src/main/java/no/bioforsk/vips/logic/entity/UserPointOfInterestPK.java b/src/main/java/no/bioforsk/vips/logic/entity/UserPointOfInterestPK.java
new file mode 100644
index 00000000..7333a659
--- /dev/null
+++ b/src/main/java/no/bioforsk/vips/logic/entity/UserPointOfInterestPK.java
@@ -0,0 +1,82 @@
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+
+package no.bioforsk.vips.logic.entity;
+
+import java.io.Serializable;
+import javax.persistence.Basic;
+import javax.persistence.Column;
+import javax.persistence.Embeddable;
+import javax.validation.constraints.NotNull;
+
+/**
+ * @copyright 2013 <a href="http://www.bioforsk.no/">Bioforsk</a>
+ * @author Tor-Einar Skog <tor-einar.skog@bioforsk.no>
+ */
+@Embeddable
+public class UserPointOfInterestPK implements Serializable {
+    @Basic(optional = false)
+    @NotNull
+    @Column(name = "point_of_interest_id")
+    private int pointOfInterestId;
+    @Basic(optional = false)
+    @NotNull
+    @Column(name = "user_id")
+    private int userId;
+
+    public UserPointOfInterestPK() {
+    }
+
+    public UserPointOfInterestPK(int pointOfInterestId, int userId) {
+        this.pointOfInterestId = pointOfInterestId;
+        this.userId = userId;
+    }
+
+    public int getPointOfInterestId() {
+        return pointOfInterestId;
+    }
+
+    public void setPointOfInterestId(int pointOfInterestId) {
+        this.pointOfInterestId = pointOfInterestId;
+    }
+
+    public int getUserId() {
+        return userId;
+    }
+
+    public void setUserId(int userId) {
+        this.userId = userId;
+    }
+
+    @Override
+    public int hashCode() {
+        int hash = 0;
+        hash += (int) pointOfInterestId;
+        hash += (int) userId;
+        return hash;
+    }
+
+    @Override
+    public boolean equals(Object object) {
+        // TODO: Warning - this method won't work in the case the id fields are not set
+        if (!(object instanceof UserPointOfInterestPK)) {
+            return false;
+        }
+        UserPointOfInterestPK other = (UserPointOfInterestPK) object;
+        if (this.pointOfInterestId != other.pointOfInterestId) {
+            return false;
+        }
+        if (this.userId != other.userId) {
+            return false;
+        }
+        return true;
+    }
+
+    @Override
+    public String toString() {
+        return "no.bioforsk.vips.logic.entity.UserPointOfInterestPK[ pointOfInterestId=" + pointOfInterestId + ", userId=" + userId + " ]";
+    }
+
+}
diff --git a/src/main/java/no/bioforsk/vips/logic/entity/UserVipslogicRole.java b/src/main/java/no/bioforsk/vips/logic/entity/UserVipslogicRole.java
new file mode 100644
index 00000000..7e2001b7
--- /dev/null
+++ b/src/main/java/no/bioforsk/vips/logic/entity/UserVipslogicRole.java
@@ -0,0 +1,89 @@
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+
+package no.bioforsk.vips.logic.entity;
+
+import java.io.Serializable;
+import javax.persistence.EmbeddedId;
+import javax.persistence.Entity;
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToOne;
+import javax.persistence.NamedQueries;
+import javax.persistence.NamedQuery;
+import javax.persistence.Table;
+import javax.xml.bind.annotation.XmlRootElement;
+
+/**
+ * @copyright 2013 <a href="http://www.bioforsk.no/">Bioforsk</a>
+ * @author Tor-Einar Skog <tor-einar.skog@bioforsk.no>
+ */
+@Entity
+@Table(name = "user_vipslogic_role")
+@XmlRootElement
+@NamedQueries({
+    @NamedQuery(name = "UserVipslogicRole.findAll", query = "SELECT u FROM UserVipslogicRole u"),
+    @NamedQuery(name = "UserVipslogicRole.findByVipslogicRoleId", query = "SELECT u FROM UserVipslogicRole u WHERE u.userVipslogicRolePK.vipslogicRoleId = :vipslogicRoleId"),
+    @NamedQuery(name = "UserVipslogicRole.findByUserId", query = "SELECT u FROM UserVipslogicRole u WHERE u.userVipslogicRolePK.userId = :userId")})
+public class UserVipslogicRole implements Serializable {
+    private static final long serialVersionUID = 1L;
+    @EmbeddedId
+    protected UserVipslogicRolePK userVipslogicRolePK;
+    @JoinColumn(name = "vipslogic_role_id", referencedColumnName = "vipslogic_role_id", insertable = false, updatable = false)
+    @ManyToOne(optional = false)
+    private VipslogicRole vipslogicRole;
+
+    public UserVipslogicRole() {
+    }
+
+    public UserVipslogicRole(UserVipslogicRolePK userVipslogicRolePK) {
+        this.userVipslogicRolePK = userVipslogicRolePK;
+    }
+
+    public UserVipslogicRole(int vipslogicRoleId, int userId) {
+        this.userVipslogicRolePK = new UserVipslogicRolePK(vipslogicRoleId, userId);
+    }
+
+    public UserVipslogicRolePK getUserVipslogicRolePK() {
+        return userVipslogicRolePK;
+    }
+
+    public void setUserVipslogicRolePK(UserVipslogicRolePK userVipslogicRolePK) {
+        this.userVipslogicRolePK = userVipslogicRolePK;
+    }
+
+    public VipslogicRole getVipslogicRole() {
+        return vipslogicRole;
+    }
+
+    public void setVipslogicRole(VipslogicRole vipslogicRole) {
+        this.vipslogicRole = vipslogicRole;
+    }
+
+    @Override
+    public int hashCode() {
+        int hash = 0;
+        hash += (userVipslogicRolePK != null ? userVipslogicRolePK.hashCode() : 0);
+        return hash;
+    }
+
+    @Override
+    public boolean equals(Object object) {
+        // TODO: Warning - this method won't work in the case the id fields are not set
+        if (!(object instanceof UserVipslogicRole)) {
+            return false;
+        }
+        UserVipslogicRole other = (UserVipslogicRole) object;
+        if ((this.userVipslogicRolePK == null && other.userVipslogicRolePK != null) || (this.userVipslogicRolePK != null && !this.userVipslogicRolePK.equals(other.userVipslogicRolePK))) {
+            return false;
+        }
+        return true;
+    }
+
+    @Override
+    public String toString() {
+        return "no.bioforsk.vips.logic.entity.UserVipslogicRole[ userVipslogicRolePK=" + userVipslogicRolePK + " ]";
+    }
+
+}
diff --git a/src/main/java/no/bioforsk/vips/logic/entity/UserVipslogicRolePK.java b/src/main/java/no/bioforsk/vips/logic/entity/UserVipslogicRolePK.java
new file mode 100644
index 00000000..1a506a30
--- /dev/null
+++ b/src/main/java/no/bioforsk/vips/logic/entity/UserVipslogicRolePK.java
@@ -0,0 +1,82 @@
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+
+package no.bioforsk.vips.logic.entity;
+
+import java.io.Serializable;
+import javax.persistence.Basic;
+import javax.persistence.Column;
+import javax.persistence.Embeddable;
+import javax.validation.constraints.NotNull;
+
+/**
+ * @copyright 2013 <a href="http://www.bioforsk.no/">Bioforsk</a>
+ * @author Tor-Einar Skog <tor-einar.skog@bioforsk.no>
+ */
+@Embeddable
+public class UserVipslogicRolePK implements Serializable {
+    @Basic(optional = false)
+    @NotNull
+    @Column(name = "vipslogic_role_id")
+    private int vipslogicRoleId;
+    @Basic(optional = false)
+    @NotNull
+    @Column(name = "user_id")
+    private int userId;
+
+    public UserVipslogicRolePK() {
+    }
+
+    public UserVipslogicRolePK(int vipslogicRoleId, int userId) {
+        this.vipslogicRoleId = vipslogicRoleId;
+        this.userId = userId;
+    }
+
+    public int getVipslogicRoleId() {
+        return vipslogicRoleId;
+    }
+
+    public void setVipslogicRoleId(int vipslogicRoleId) {
+        this.vipslogicRoleId = vipslogicRoleId;
+    }
+
+    public int getUserId() {
+        return userId;
+    }
+
+    public void setUserId(int userId) {
+        this.userId = userId;
+    }
+
+    @Override
+    public int hashCode() {
+        int hash = 0;
+        hash += (int) vipslogicRoleId;
+        hash += (int) userId;
+        return hash;
+    }
+
+    @Override
+    public boolean equals(Object object) {
+        // TODO: Warning - this method won't work in the case the id fields are not set
+        if (!(object instanceof UserVipslogicRolePK)) {
+            return false;
+        }
+        UserVipslogicRolePK other = (UserVipslogicRolePK) object;
+        if (this.vipslogicRoleId != other.vipslogicRoleId) {
+            return false;
+        }
+        if (this.userId != other.userId) {
+            return false;
+        }
+        return true;
+    }
+
+    @Override
+    public String toString() {
+        return "no.bioforsk.vips.logic.entity.UserVipslogicRolePK[ vipslogicRoleId=" + vipslogicRoleId + ", userId=" + userId + " ]";
+    }
+
+}
diff --git a/src/main/java/no/bioforsk/vips/logic/entity/VipslogicRole.java b/src/main/java/no/bioforsk/vips/logic/entity/VipslogicRole.java
new file mode 100644
index 00000000..9a6dc420
--- /dev/null
+++ b/src/main/java/no/bioforsk/vips/logic/entity/VipslogicRole.java
@@ -0,0 +1,119 @@
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+
+package no.bioforsk.vips.logic.entity;
+
+import java.io.Serializable;
+import java.util.Set;
+import javax.persistence.Basic;
+import javax.persistence.CascadeType;
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.Id;
+import javax.persistence.NamedQueries;
+import javax.persistence.NamedQuery;
+import javax.persistence.OneToMany;
+import javax.persistence.Table;
+import javax.validation.constraints.NotNull;
+import javax.validation.constraints.Size;
+import javax.xml.bind.annotation.XmlRootElement;
+import javax.xml.bind.annotation.XmlTransient;
+import org.codehaus.jackson.annotate.JsonIgnore;
+
+/**
+ * @copyright 2013 <a href="http://www.bioforsk.no/">Bioforsk</a>
+ * @author Tor-Einar Skog <tor-einar.skog@bioforsk.no>
+ */
+@Entity
+@Table(name = "vipslogic_role")
+@XmlRootElement
+@NamedQueries({
+    @NamedQuery(name = "VipslogicRole.findAll", query = "SELECT v FROM VipslogicRole v"),
+    @NamedQuery(name = "VipslogicRole.findByVipslogicRoleId", query = "SELECT v FROM VipslogicRole v WHERE v.vipslogicRoleId = :vipslogicRoleId"),
+    @NamedQuery(name = "VipslogicRole.findByDefaultTitle", query = "SELECT v FROM VipslogicRole v WHERE v.defaultTitle = :defaultTitle"),
+    @NamedQuery(name = "VipslogicRole.findByDefaultDescription", query = "SELECT v FROM VipslogicRole v WHERE v.defaultDescription = :defaultDescription")})
+public class VipslogicRole implements Serializable {
+    private static final long serialVersionUID = 1L;
+    @Id
+    @Basic(optional = false)
+    @NotNull
+    @Column(name = "vipslogic_role_id")
+    private Integer vipslogicRoleId;
+    @Size(max = 255)
+    @Column(name = "default_title")
+    private String defaultTitle;
+    @Size(max = 2147483647)
+    @Column(name = "default_description")
+    private String defaultDescription;
+    @OneToMany(cascade = CascadeType.ALL, mappedBy = "vipslogicRole")
+    private Set<UserVipslogicRole> userVipslogicRoleSet;
+
+    public VipslogicRole() {
+    }
+
+    public VipslogicRole(Integer vipslogicRoleId) {
+        this.vipslogicRoleId = vipslogicRoleId;
+    }
+
+    public Integer getVipslogicRoleId() {
+        return vipslogicRoleId;
+    }
+
+    public void setVipslogicRoleId(Integer vipslogicRoleId) {
+        this.vipslogicRoleId = vipslogicRoleId;
+    }
+
+    public String getDefaultTitle() {
+        return defaultTitle;
+    }
+
+    public void setDefaultTitle(String defaultTitle) {
+        this.defaultTitle = defaultTitle;
+    }
+
+    public String getDefaultDescription() {
+        return defaultDescription;
+    }
+
+    public void setDefaultDescription(String defaultDescription) {
+        this.defaultDescription = defaultDescription;
+    }
+
+    @XmlTransient
+    @JsonIgnore
+    public Set<UserVipslogicRole> getUserVipslogicRoleSet() {
+        return userVipslogicRoleSet;
+    }
+
+    public void setUserVipslogicRoleSet(Set<UserVipslogicRole> userVipslogicRoleSet) {
+        this.userVipslogicRoleSet = userVipslogicRoleSet;
+    }
+
+    @Override
+    public int hashCode() {
+        int hash = 0;
+        hash += (vipslogicRoleId != null ? vipslogicRoleId.hashCode() : 0);
+        return hash;
+    }
+
+    @Override
+    public boolean equals(Object object) {
+        // TODO: Warning - this method won't work in the case the id fields are not set
+        if (!(object instanceof VipslogicRole)) {
+            return false;
+        }
+        VipslogicRole other = (VipslogicRole) object;
+        if ((this.vipslogicRoleId == null && other.vipslogicRoleId != null) || (this.vipslogicRoleId != null && !this.vipslogicRoleId.equals(other.vipslogicRoleId))) {
+            return false;
+        }
+        return true;
+    }
+
+    @Override
+    public String toString() {
+        return "no.bioforsk.vips.logic.entity.VipslogicRole[ vipslogicRoleId=" + vipslogicRoleId + " ]";
+    }
+
+}
diff --git a/src/main/java/no/bioforsk/vips/logic/entity/WeatherStationDataSource.java b/src/main/java/no/bioforsk/vips/logic/entity/WeatherStationDataSource.java
new file mode 100644
index 00000000..9e815f3c
--- /dev/null
+++ b/src/main/java/no/bioforsk/vips/logic/entity/WeatherStationDataSource.java
@@ -0,0 +1,125 @@
+package no.bioforsk.vips.logic.entity;
+
+import java.io.Serializable;
+import javax.persistence.Basic;
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.NamedQueries;
+import javax.persistence.NamedQuery;
+import javax.persistence.Table;
+import javax.validation.constraints.Size;
+import javax.xml.bind.annotation.XmlRootElement;
+
+/**
+ * @copyright 2013 <a href="http://www.bioforsk.no/">Bioforsk</a>
+ * @author Tor-Einar Skog <tor-einar.skog@bioforsk.no>
+ */
+@Entity
+@Table(name = "weather_station_data_source")
+@XmlRootElement
+@NamedQueries({
+    @NamedQuery(name = "WeatherStationDataSource.findAll", query = "SELECT w FROM WeatherStationDataSource w"),
+    @NamedQuery(name = "WeatherStationDataSource.findByWeatherStationDataSourceId", query = "SELECT w FROM WeatherStationDataSource w WHERE w.weatherStationDataSourceId = :weatherStationDataSourceId"),
+    @NamedQuery(name = "WeatherStationDataSource.findByName", query = "SELECT w FROM WeatherStationDataSource w WHERE w.name = :name"),
+    @NamedQuery(name = "WeatherStationDataSource.findByDefaultDescription", query = "SELECT w FROM WeatherStationDataSource w WHERE w.defaultDescription = :defaultDescription"),
+    @NamedQuery(name = "WeatherStationDataSource.findByUri", query = "SELECT w FROM WeatherStationDataSource w WHERE w.uri = :uri"),
+    @NamedQuery(name = "WeatherStationDataSource.findByDatafetchUriExpression", query = "SELECT w FROM WeatherStationDataSource w WHERE w.datafetchUriExpression = :datafetchUriExpression")})
+public class WeatherStationDataSource implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+    @Id
+    @GeneratedValue(strategy = GenerationType.IDENTITY)
+    @Basic(optional = false)
+    @Column(name = "weather_station_data_source_id")
+    private Integer weatherStationDataSourceId;
+    @Size(max = 255)
+    @Column(name = "name")
+    private String name;
+    @Size(max = 2147483647)
+    @Column(name = "default_description")
+    private String defaultDescription;
+    @Size(max = 1024)
+    @Column(name = "uri")
+    private String uri;
+    @Size(max = 1024)
+    @Column(name = "datafetch_uri_expression")
+    private String datafetchUriExpression;
+
+    public WeatherStationDataSource() {
+    }
+
+    public WeatherStationDataSource(Integer weatherStationDataSourceId) {
+        this.weatherStationDataSourceId = weatherStationDataSourceId;
+    }
+
+    public Integer getWeatherStationDataSourceId() {
+        return weatherStationDataSourceId;
+    }
+
+    public void setWeatherStationDataSourceId(Integer weatherStationDataSourceId) {
+        this.weatherStationDataSourceId = weatherStationDataSourceId;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public String getDefaultDescription() {
+        return defaultDescription;
+    }
+
+    public void setDefaultDescription(String defaultDescription) {
+        this.defaultDescription = defaultDescription;
+    }
+
+    public String getUri() {
+        return uri;
+    }
+
+    public void setUri(String uri) {
+        this.uri = uri;
+    }
+
+    public String getDatafetchUriExpression() {
+        return datafetchUriExpression;
+    }
+
+    public void setDatafetchUriExpression(String datafetchUriExpression) {
+        this.datafetchUriExpression = datafetchUriExpression;
+    }
+
+    @Override
+    public int hashCode() {
+        int hash = 0;
+        hash += (weatherStationDataSourceId != null ? weatherStationDataSourceId.hashCode() : 0);
+        return hash;
+    }
+
+    @Override
+    public boolean equals(Object object) {
+        // TODO: Warning - this method won't work in the case the id fields are not set
+        if (!(object instanceof WeatherStationDataSource)) {
+            return false;
+        }
+        WeatherStationDataSource other = (WeatherStationDataSource) object;
+        if ((this.weatherStationDataSourceId == null && other.weatherStationDataSourceId != null) || (this.weatherStationDataSourceId != null && !this.weatherStationDataSourceId.equals(other.weatherStationDataSourceId))) {
+            return false;
+        }
+        return true;
+    }
+
+    @Override
+    public String toString() {
+        return "no.bioforsk.vips.logic.entity.WeatherStationDataSource[ weatherStationDataSourceId=" + weatherStationDataSourceId + " ]";
+    }
+
+    
+
+}
diff --git a/src/main/java/no/bioforsk/vips/logic/session/PointOfInterestBean.java b/src/main/java/no/bioforsk/vips/logic/session/PointOfInterestBean.java
new file mode 100644
index 00000000..42ead876
--- /dev/null
+++ b/src/main/java/no/bioforsk/vips/logic/session/PointOfInterestBean.java
@@ -0,0 +1,57 @@
+package no.bioforsk.vips.logic.session;
+
+import java.util.List;
+import javax.ejb.LocalBean;
+import javax.ejb.Stateless;
+import javax.persistence.EntityManager;
+import javax.persistence.PersistenceContext;
+import javax.persistence.Query;
+import no.bioforsk.vips.logic.entity.PointOfInterest;
+import no.bioforsk.vips.logic.entity.PointOfInterestWeatherStation;
+import no.bioforsk.vips.logic.util.Globals;
+
+
+/**
+ * Handles transactions for POIs
+ * @copyright 2013 <a href="http://www.bioforsk.no/">Bioforsk</a>
+ * @author Tor-Einar Skog <tor-einar.skog@bioforsk.no>
+ */
+@LocalBean
+@Stateless
+public class PointOfInterestBean {
+    @PersistenceContext(unitName="VIPSLogic-PU")
+    EntityManager em;
+    
+    public List<PointOfInterest> getWeatherstations(String countryCode)
+    {
+        Query q = em.createNamedQuery("PointOfInterest.findByPointOfInterestTypeAndCountryCode");
+        q.setParameter("pointOfInterestTypeId", Globals.POI_TYPE_WEATHERSTATION);
+        q.setParameter("countryCode", countryCode);
+        return q.getResultList();
+    }
+    
+    /**
+     * 
+     * @param userId
+     * @return all weather stations related to the user
+     */
+    public List<PointOfInterestWeatherStation> getWeatherstationsForUser(Integer userId)
+    {
+        Query q = em.createNamedQuery("PointOfInterestWeatherStation.findByUserId");
+        q.setParameter("userId", userId);
+        return q.getResultList();
+    }
+    
+    /**
+     * 
+     * @param pointOfInterestId
+     * @return the specified point of interest. May be one of the subclasses, e.g. PointOfInterestWeatherstation
+     */
+    public PointOfInterest getPointOfInterest(Integer pointOfInterestId)
+    {
+        Query q = em.createNamedQuery("PointOfInterest.findByPointOfInterestId");
+        q.setParameter("pointOfInterestId", pointOfInterestId);
+        return (PointOfInterest) q.getSingleResult();
+        
+    }
+}
diff --git a/src/main/java/no/bioforsk/vips/logic/session/SessionControllerGetter.java b/src/main/java/no/bioforsk/vips/logic/session/SessionControllerGetter.java
new file mode 100644
index 00000000..23c9a5a0
--- /dev/null
+++ b/src/main/java/no/bioforsk/vips/logic/session/SessionControllerGetter.java
@@ -0,0 +1,35 @@
+package no.bioforsk.vips.logic.session;
+
+import javax.naming.InitialContext;
+import javax.naming.NamingException;
+
+/**
+ * @copyright 2013 <a href="http://www.bioforsk.no/">Bioforsk</a>
+ * @author Tor-Einar Skog <tor-einar.skog@bioforsk.no>
+ */
+public class SessionControllerGetter {
+    
+    private static final String JNDI_PATH = "java:global/VIPSLogic-1.0-SNAPSHOT/";
+
+    public static PointOfInterestBean getPointOfInterestBean()
+    {
+        try
+        {
+            InitialContext ic = new InitialContext();
+            PointOfInterestBean retVal = (PointOfInterestBean) ic.lookup(SessionControllerGetter.getJndiPath(PointOfInterestBean.class));
+
+            return retVal;
+        }catch(NamingException ne)
+        {
+            System.out.println("Could not find " + PointOfInterestBean.class.getSimpleName());
+            return null;
+        }
+    }
+    
+    private static String getJndiPath(Class obj)
+    {
+        String retVal = SessionControllerGetter.JNDI_PATH + obj.getSimpleName();
+        //System.out.println("JNDI-path=" + retVal);
+        return retVal;
+    }
+}
diff --git a/src/main/java/no/bioforsk/vips/logic/util/Globals.java b/src/main/java/no/bioforsk/vips/logic/util/Globals.java
index d6fe469f..d115ac64 100644
--- a/src/main/java/no/bioforsk/vips/logic/util/Globals.java
+++ b/src/main/java/no/bioforsk/vips/logic/util/Globals.java
@@ -19,4 +19,7 @@ public class Globals {
         "/404"
     };
     
+    // Point of interest type IDs
+    public static final Integer POI_TYPE_WEATHERSTATION=1;
+    
 }
diff --git a/src/main/resources/META-INF/persistence.xml b/src/main/resources/META-INF/persistence.xml
new file mode 100644
index 00000000..0b9cbcf5
--- /dev/null
+++ b/src/main/resources/META-INF/persistence.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<persistence version="2.0" xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
+  <persistence-unit name="VIPSLogic-PU" transaction-type="JTA">
+    <jta-data-source>java:/jboss/datasources/vipslogic</jta-data-source>
+    <exclude-unlisted-classes>false</exclude-unlisted-classes>
+    <properties/>
+  </persistence-unit>
+</persistence>
diff --git a/src/main/resources/no/bioforsk/vips/logic/i18n/vipslogictexts.properties b/src/main/resources/no/bioforsk/vips/logic/i18n/vipslogictexts.properties
index f486aac7..260a833f 100644
--- a/src/main/resources/no/bioforsk/vips/logic/i18n/vipslogictexts.properties
+++ b/src/main/resources/no/bioforsk/vips/logic/i18n/vipslogictexts.properties
@@ -10,3 +10,14 @@ username=User name
 password=Password
 loggedinas=Logged in as
 logout=Log out
+weatherStations=Weather stations
+position=Position
+dataSource=Data source
+name=Name
+dataSourceMissing=Data source is missing
+weatherStationRemoteIdMissing=Remote Id for weather station is missing
+weatherStationRemoteId=Remote Id for weather station
+latitude=Latitude
+longitude=Longitude
+missing=Missing
+altitude=Altitude
diff --git a/src/main/resources/no/bioforsk/vips/logic/i18n/vipslogictexts_no.properties b/src/main/resources/no/bioforsk/vips/logic/i18n/vipslogictexts_no.properties
index f663545b..4c91b4cd 100644
--- a/src/main/resources/no/bioforsk/vips/logic/i18n/vipslogictexts_no.properties
+++ b/src/main/resources/no/bioforsk/vips/logic/i18n/vipslogictexts_no.properties
@@ -10,3 +10,14 @@ username=Brukernavn
 password=Passord
 loggedinas=Innlogget som
 logout=Logg ut
+weatherStations=M\u00e5lestasjoner
+position=Posisjon
+dataSource=Datakilde
+name=Navn
+dataSourceMissing=Datakilde mangler
+weatherStationRemoteIdMissing=Fjern-Id for m\u00e5lestasjon mangler
+weatherStationRemoteId=Fjern-Id for m\u00e5lestasjon
+latitude=Breddegrad
+longitude=Lengdegrad
+missing=Mangler
+altitude=H\u00f8yde over havet
diff --git a/src/main/setup/jboss-ds.xml b/src/main/setup/jboss-ds.xml
new file mode 100644
index 00000000..09938db7
--- /dev/null
+++ b/src/main/setup/jboss-ds.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<datasources>
+  <local-tx-datasource>
+    <jndi-name>VIPSLogic</jndi-name>
+    <connection-url>jdbc:postgresql://localhost:5432/vipslogic</connection-url>
+    <driver-class>org.postgresql.Driver</driver-class>
+    <user-name>vipslogic</user-name>
+    <password>VIPS123</password>
+    <min-pool-size>5</min-pool-size>
+    <max-pool-size>20</max-pool-size>
+    <idle-timeout-minutes>5</idle-timeout-minutes>
+  </local-tx-datasource>
+</datasources>
diff --git a/src/main/webapp/WEB-INF/web.xml b/src/main/webapp/WEB-INF/web.xml
index fc739cc1..27c4d6e8 100644
--- a/src/main/webapp/WEB-INF/web.xml
+++ b/src/main/webapp/WEB-INF/web.xml
@@ -1,11 +1,20 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
     <display-name>VIPSLogic</display-name>
+    <servlet>
+        <servlet-name>PointOfInterestController</servlet-name>
+        <servlet-class>no.bioforsk.vips.logic.controller.PointOfInterestController</servlet-class>
+    </servlet>
     <servlet-mapping>
         <servlet-name>LoginController</servlet-name>
         <url-pattern>/login</url-pattern>
         <url-pattern>/logout</url-pattern>
     </servlet-mapping>
+    <servlet-mapping>
+        <servlet-name>PointOfInterestController</servlet-name>
+        <url-pattern>/poi</url-pattern>
+        <url-pattern>/weatherStation</url-pattern>
+    </servlet-mapping>
     <welcome-file-list>
         <welcome-file>index.html</welcome-file>
     </welcome-file-list>
@@ -100,7 +109,7 @@
             <param-value>no</param-value>
         </init-param>
         <load-on-startup>1</load-on-startup>
-        </servlet>
+    </servlet>
     <servlet-mapping>
         <servlet-name>freemarker</servlet-name>
         <url-pattern>*.ftl</url-pattern>
diff --git a/src/main/webapp/templates/master.ftl b/src/main/webapp/templates/master.ftl
index ceefeaf8..740e2f9b 100644
--- a/src/main/webapp/templates/master.ftl
+++ b/src/main/webapp/templates/master.ftl
@@ -40,7 +40,7 @@
 	    <form class="navbar-form navbar-right"  action="/logout" method="POST" role="logout">
 	      <div class="form-group">
 	      	<input type="hidden" name="logout" value="true"/>
-		${i18nBundle.loggedinas} ${user.firstName} ${user.lastName}
+		${i18nBundle.loggedinas} ${user.firstName} ${user.lastName} (${user.organizationId.organizationName})
 	      </div>
 	      <button type="submit" class="btn btn-default">${i18nBundle.logout}</button>
 	    </form>
@@ -52,7 +52,7 @@
 			<h2>En sidemeny?</h2>
 			<p>Lorem ipsum dolor sit amet, consectetuer adipiscing elit...</p>
 			<ul>
-				<li><a href="#">Link 1</a></li>
+				<li><a href="/weatherStation">${i18nBundle.weatherStations}</a></li>
 				<li><a href="#">Link 2</a></li>
 			</ul>
 		</div>
diff --git a/src/main/webapp/templates/poi.ftl b/src/main/webapp/templates/poi.ftl
new file mode 100644
index 00000000..a0a4e08c
--- /dev/null
+++ b/src/main/webapp/templates/poi.ftl
@@ -0,0 +1,13 @@
+<#include "master.ftl">
+<#macro page_head>
+        <title>POI</title>
+</#macro>
+<#macro page_contents>
+        <h1>POI</h1>
+	<ul>
+	<#list weatherstations?sort_by("name") as weatherstation>
+	    <li>${weatherstation.name}<#if weatherstation.weatherStationDataSourceId??>, ${weatherstation.weatherStationDataSourceId.uri!}<#else></#if></li>
+	</#list>
+        </ul>
+</#macro>
+<@page_html/>
diff --git a/src/main/webapp/templates/weatherstation.ftl b/src/main/webapp/templates/weatherstation.ftl
new file mode 100644
index 00000000..d898be36
--- /dev/null
+++ b/src/main/webapp/templates/weatherstation.ftl
@@ -0,0 +1,25 @@
+<#include "master.ftl">
+<#macro page_head>
+        <title>${weatherStation.name}</title>
+</#macro>
+<#macro page_contents>
+        <h1>${weatherStation.name}</h1>
+        <h2>${i18nBundle.position}</h2>
+	<ul>
+		<li>${i18nBundle.latitude}: ${weatherStation.latitude!i18nBundle.missing}</li>
+		<li>${i18nBundle.longitude}: ${weatherStation.longitude!i18nBundle.missing}</li>
+		<li>${i18nBundle.altitude}: ${weatherStation.altitude!i18nBundle.missing}</li>
+	</ul>
+	<h2>${i18nBundle.dataSource}</h2>
+	<#if weatherStation.weatherStationDataSourceId??>
+	<ul>
+		<li>${i18nBundle.name}: ${weatherStation.weatherStationDataSourceId.name}</li>
+		<li>URI: <a href="${weatherStation.weatherStationDataSourceId.uri}" target="new">${weatherStation.weatherStationDataSourceId.uri}</a></li>
+		<li>${i18nBundle.weatherStationRemoteId}: ${weatherStation.weatherStationRemoteId!i18nBundle.weatherStationRemoteIdMissing}</li>
+	</ul>
+	<#else>
+	<p>${i18nBundle.dataSourceMissing}</p>
+	</#if>
+	
+</#macro>
+<@page_html/>
diff --git a/src/main/webapp/templates/weatherstationlist.ftl b/src/main/webapp/templates/weatherstationlist.ftl
new file mode 100644
index 00000000..5ea6a11a
--- /dev/null
+++ b/src/main/webapp/templates/weatherstationlist.ftl
@@ -0,0 +1,13 @@
+<#include "master.ftl">
+<#macro page_head>
+        <title>${i18nBundle.weatherStations}</title>
+</#macro>
+<#macro page_contents>
+        <h1>${i18nBundle.weatherStations}</h1>
+	<ul>
+	<#list weatherStations?sort_by("name") as weatherStation>
+	    <li><a href="weatherStation?pointOfInterestId=${weatherStation.pointOfInterestId}">${weatherStation.name}</a><#if weatherStation.weatherStationDataSourceId??>, ${weatherStation.weatherStationDataSourceId.uri!}<#else></#if></li>
+	</#list>
+        </ul>
+</#macro>
+<@page_html/>
-- 
GitLab