Commit 940a67aa authored by Matija Obreza's avatar Matija Obreza
Browse files

Moved methods to DataService, added spring @Cache annotations

parent f2d7fa6f
......@@ -14,26 +14,31 @@
* limitations under the License.
**/
package org.crophub;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.ServerConnector;
import org.eclipse.jetty.webapp.WebAppContext;
public class JettyMain {
public static final Log _logger = LogFactory.getLog(JettyMain.class);
public static void main(String[] args) throws Exception {
Server server = new Server();
public static void main(String[] args) throws Exception {
_logger.info("Starting Jetty");
Server server = new Server();
ServerConnector connector = new ServerConnector(server);
connector.setPort(8080);
server.addConnector(connector);
ServerConnector connector = new ServerConnector(server);
connector.setPort(8080);
server.addConnector(connector);
WebAppContext root = new WebAppContext("src/main/webapp", "/");
server.setHandler(root);
WebAppContext root = new WebAppContext("src/main/webapp", "/");
server.setHandler(root);
server.start();
server.join();
}
_logger.info("Starting...");
server.start();
server.join();
}
}
......@@ -35,20 +35,31 @@ import org.crophub.rest.common.model.BusinessModel;
public class Descriptor extends BusinessModel {
private static final long serialVersionUID = 3832200593904442940L;
@Lob
private String title;
@Column(nullable = false, length = 500)
private String name;
@Column(nullable = false, length = 200)
private String code;
@Lob
private String description;
public String getName() {
return name;
public String getTitle() {
return title;
}
public void setName(final String name) {
this.name = name;
public void setTitle(String title) {
this.title = title;
}
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public String getDescription() {
return description;
}
......@@ -59,6 +70,6 @@ public class Descriptor extends BusinessModel {
@Override
public String toString() {
return MessageFormat.format("Descriptor id={0,number,#} name={1}", id, name);
return MessageFormat.format("Descriptor id={0,number,#} name={1}", id, code);
}
}
......@@ -36,13 +36,20 @@ import org.hibernate.annotations.Index;
@org.hibernate.annotations.Table(appliesTo = "sparsedata", indexes = {
@Index(columnNames = { "descriptorId", "stringId" }, name = "descriptorstring_SPARSEDATA"),
@Index(columnNames = { "sparseEntryId" }, name = "entry_SPARSEDATA"),
@Index(columnNames = { "dataSetId", "descriptorId" }, name = "datasetdescriptor_SPARSEDATA"),
@Index(columnNames = { "descriptorId" }, name = "descriptor_SPARSEDATA") })
public class SparseData extends BusinessModel {
private static final long serialVersionUID = -2142036544458439223L;
@OrderColumn
private long dataSetId;
@OrderColumn
private long sparseEntryId;
@OrderColumn
private long descriptorId;
@Column(nullable = false, length = 500)
private String value;
......@@ -50,6 +57,13 @@ public class SparseData extends BusinessModel {
@JoinColumn(name = "stringId")
private SparseString sparseString;
public long getDataSetId() {
return dataSetId;
}
public void setDataSetId(long dataSetId) {
this.dataSetId = dataSetId;
}
public long getSparseEntryId() {
return sparseEntryId;
......
......@@ -20,5 +20,5 @@ import org.crophub.rest.common.model.impl.Descriptor;
import org.springframework.data.jpa.repository.JpaRepository;
public interface DescriptorRepository extends JpaRepository<Descriptor, Long> {
Descriptor findByName(String name);
Descriptor findByCode(String code);
}
......@@ -20,12 +20,21 @@ import java.util.List;
import org.crophub.rest.common.model.impl.SparseData;
import org.crophub.rest.common.model.impl.SparseString;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
public interface SparseDataRepository extends JpaRepository<SparseData, Long> {
List<SparseData> findBySparseEntryId(long sparseEntryId);
@Query("select count(sd) from SparseData sd where sd.dataSetId=?1")
@Cacheable(value="sparsedata", key="#root.methodName+#a0")
long countByDataSetId(long dataSetId);
@Query("select distinct sd.descriptorId from SparseData sd where sd.dataSetId=?1")
@Cacheable(value="sparsedata", key="#root.methodName+#a0")
List<Long> getDescriptorIdsByDataSetId(long dataSetId);
@Query("select count(sd) from SparseData sd where sd.sparseEntryId=?1")
long countBySparseEntryId(long sparseEntryId);
......
......@@ -20,9 +20,15 @@ import java.util.List;
import org.crophub.rest.common.model.impl.DataSet;
import org.crophub.rest.common.model.impl.SparseEntry;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
public interface SparseEntryRepository extends JpaRepository<SparseEntry, Long> {
List<SparseEntry> findByDataSet(DataSet dataSet);
@Query("select count(se) from SparseEntry se where se.dataSet=?1")
@Cacheable(value="sparseentry", key="#root.methodName+#a0.id")
long countByDataSet(DataSet dataSet);
}
......@@ -20,11 +20,21 @@ package org.crophub.rest.common.service;
import java.util.List;
import org.crophub.rest.common.model.impl.DataSet;
import org.crophub.rest.common.model.impl.Descriptor;
public interface DataService {
List<DataSet> list();
DataSet getDataSet(long dataSetId);
void save(DataSet dataset);
void writeEntries(DataSet dataSet, Descriptor[] descriptors, List<String[]> data);
long countEntries(DataSet dataSet);
long countData(DataSet dataSet);
Iterable<Descriptor> getDescriptors(DataSet dataSet);
}
/**
* Copyright 2013 Global Crop Diversity Trust
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
**/
package org.crophub.rest.common.service;
import java.util.List;
import org.crophub.rest.common.model.impl.DataSet;
import org.crophub.rest.common.model.impl.Descriptor;
public interface SparseDataService {
void writeEntries(DataSet dataSet, Descriptor[] descriptors, List<String[]> data);
}
package org.crophub.rest.common.service.impl;
import java.util.ArrayList;
import java.util.List;
import org.apache.commons.lang.ArrayUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.crophub.rest.common.model.impl.DataSet;
import org.crophub.rest.common.model.impl.Descriptor;
import org.crophub.rest.common.model.impl.SparseData;
import org.crophub.rest.common.model.impl.SparseEntry;
import org.crophub.rest.common.persistence.domain.DataSetRepository;
import org.crophub.rest.common.persistence.domain.DescriptorRepository;
import org.crophub.rest.common.persistence.domain.SparseDataRepository;
import org.crophub.rest.common.persistence.domain.SparseEntryRepository;
import org.crophub.rest.common.service.DataService;
import org.crophub.rest.common.service.SparseStringService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Service
@Transactional(readOnly = true)
public class DataServiceImpl implements DataService {
public static final Log LOG = LogFactory
.getLog(DataServiceImpl.class);
@Autowired
SparseEntryRepository entryRepository;
@Autowired
SparseDataRepository dataRepository;
@Autowired
DescriptorRepository descriptorRepository;
@Autowired
SparseStringService stringService;
@Autowired
private DataSetRepository dataSetRepository;
......@@ -25,4 +51,75 @@ public class DataServiceImpl implements DataService {
public DataSet getDataSet(long dataSetId) {
return dataSetRepository.findOne(dataSetId);
}
@Override
@Transactional(readOnly=false)
public void save(DataSet dataset) {
dataSetRepository.save(dataset);
}
@Override
public long countEntries(DataSet dataSet) {
return entryRepository.countByDataSet(dataSet);
}
@Override
public long countData(DataSet dataSet) {
return dataRepository.countByDataSetId(dataSet.getId());
}
@Override
public Iterable<Descriptor> getDescriptors(DataSet dataSet) {
return descriptorRepository.findAll(dataRepository.getDescriptorIdsByDataSetId(dataSet.getId()));
}
// FIXME This code does not handle column grouping
@Override
@Transactional(readOnly = false)
@CacheEvict(value="methods", allEntries=true)
public void writeEntries(final DataSet dataSet, final Descriptor[] descriptors,
final List<String[]> datas) {
final List<SparseEntry> sparseEntries = new ArrayList<SparseEntry>(
datas.size());
final List<SparseData> sparseDatas = new ArrayList<SparseData>(
descriptors.length);
for (int j = 0; j < datas.size(); j++) {
// New entry
final SparseEntry sparseEntry = new SparseEntry();
sparseEntry.setDataSet(dataSet);
sparseEntries.add(sparseEntry);
}
// save the lot
entryRepository.save(sparseEntries);
for (int j = 0; j < datas.size(); j++) {
final String[] data = datas.get(j);
final long sparseEntryId = sparseEntries.get(j).getId();
if (data.length < descriptors.length) {
LOG.warn("Funny input: " + ArrayUtils.toString(data));
}
// All traits
int valueCount = 0;
for (int i = 0; i < descriptors.length && i < data.length; i++) {
if (data[i] != null && descriptors[i] != null) {
valueCount++;
final SparseData sparseData = new SparseData();
sparseData.setSparseEntryId(sparseEntryId);
sparseData.setDescriptorId(descriptors[i].getId());
sparseData.setValue(data[i]);
sparseDatas.add(sparseData);
}
}
if (valueCount == 0) {
entryRepository.delete(sparseEntries.remove(j));
}
}
dataRepository.save(sparseDatas);
}
}
/**
* Copyright 2013 Global Crop Diversity Trust
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
**/
package org.crophub.rest.common.service.impl;
import java.util.ArrayList;
import java.util.List;
import org.apache.commons.lang.ArrayUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.crophub.rest.common.model.impl.DataSet;
import org.crophub.rest.common.model.impl.Descriptor;
import org.crophub.rest.common.model.impl.SparseData;
import org.crophub.rest.common.model.impl.SparseEntry;
import org.crophub.rest.common.persistence.domain.SparseDataRepository;
import org.crophub.rest.common.persistence.domain.SparseEntryRepository;
import org.crophub.rest.common.service.SparseDataService;
import org.crophub.rest.common.service.SparseStringService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Service
@Transactional(readOnly = true)
public class SparseDataServiceImpl implements SparseDataService {
public static final Log LOG = LogFactory
.getLog(SparseDataServiceImpl.class);
@Autowired
SparseEntryRepository entryRepository;
@Autowired
SparseDataRepository dataRepository;
@Autowired
SparseStringService stringService;
// FIXME This code does not handle column grouping
@Override
@Transactional(readOnly = false)
public void writeEntries(final DataSet dataSet, final Descriptor[] descriptors,
final List<String[]> datas) {
final List<SparseEntry> sparseEntries = new ArrayList<SparseEntry>(
datas.size());
final List<SparseData> sparseDatas = new ArrayList<SparseData>(
descriptors.length);
for (int j = 0; j < datas.size(); j++) {
// New entry
final SparseEntry sparseEntry = new SparseEntry();
sparseEntry.setDataSet(dataSet);
sparseEntries.add(sparseEntry);
}
// save the lot
entryRepository.save(sparseEntries);
for (int j = 0; j < datas.size(); j++) {
final String[] data = datas.get(j);
final long sparseEntryId = sparseEntries.get(j).getId();
if (data.length < descriptors.length) {
LOG.warn("Funny input: " + ArrayUtils.toString(data));
}
// All traits
int valueCount = 0;
for (int i = 0; i < descriptors.length && i < data.length; i++) {
if (data[i] != null && descriptors[i] != null) {
valueCount++;
final SparseData sparseData = new SparseData();
sparseData.setSparseEntryId(sparseEntryId);
sparseData.setDescriptorId(descriptors[i].getId());
sparseData.setValue(data[i]);
sparseDatas.add(sparseData);
}
}
if (valueCount == 0) {
entryRepository.delete(sparseEntries.remove(j));
}
}
dataRepository.save(sparseDatas);
}
}
......@@ -52,6 +52,9 @@ public class DataSetController extends BaseController {
_logger.debug("Viewing data for " + dataSetId);
DataSet dataSet=dataService.getDataSet(dataSetId);
model.addAttribute("dataSet", dataSet);
model.addAttribute("entrySize", dataService.countEntries(dataSet));
model.addAttribute("dataSize", dataService.countData(dataSet));
model.addAttribute("descriptors", dataService.getDescriptors(dataSet));
return "/dataset/view";
}
......
......@@ -25,6 +25,21 @@
timeToLiveSeconds="3600"
overflowToDisk="false"/>
<!--ACL in-memory cache-->
<cache name="sparsedata"
maxElementsInMemory="10000"
eternal="false"
timeToIdleSeconds="1800"
timeToLiveSeconds="3600"
overflowToDisk="false" />
<cache name="sparseentry"
maxElementsInMemory="10000"
eternal="false"
timeToIdleSeconds="1800"
timeToLiveSeconds="3600"
overflowToDisk="false" />
<!--CACHEABLE CACHES-->
<!--ACL in-memory cache-->
......
......@@ -28,4 +28,4 @@ log4j.appender.file.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n
### set log levels - for more verbose logging change 'info' to 'debug' ###
log4j.rootLogger=info, stdout
log4j.category.org.crophub=info, file
log4j.category.org.crophub=info
......@@ -50,7 +50,26 @@
<a href="/data/view/${dataSet.id}"><c:out value="${dataSet.name}" /></a>
</h3>
<p>
<c:out value="${dataSet.uploadDate}" />
<fmt:formatNumber value="${entrySize}" /> Entries in this dataset.
<fmt:formatNumber value="${dataSize}" /> Data points in this dataset.
</p>
<p>
<c:out value="${descriptors.size()}" /> distinct Descriptors in this dataset.
</p>
<table>
<c:forEach items="${descriptors}" var="descriptor">
<tr>
<td><c:out value="${descriptor.title}" /></td>
<td><c:out value="${descriptor.code}" /></td>
<td><c:out value="${descriptor.description}" /></td>
</tr>
</c:forEach>
</table>
<p>
<c:out value="${dataSet.source}" />
</p>
<p>
<fmt:formatDate value="${dataSet.uploadDate}" />
</p>
<div>
<c:out value="${dataSet.description}" escapeXml="false" />
......
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="security" uri="http://www.springframework.org/security/tags" %>
<%@ taglib prefix="spring" uri="http://www.springframework.org/tags" %>
\ No newline at end of file
<%@ taglib prefix="spring" uri="http://www.springframework.org/tags" %>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
\ No newline at end of file
......@@ -18,4 +18,8 @@
.ui-widget-content a.btn-inverse{
color: #fff;
}
td {
vertical-align: top;
}
\ No newline at end of file
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment