Codebase as of c53e4aed26 as an initial commit for the shrunk repo

Signed-off-by: Kai Kreuzer <kai@openhab.org>
This commit is contained in:
Kai Kreuzer
2010-02-20 19:23:32 +01:00
committed by Kai Kreuzer
commit bbf1a7fd29
302 changed files with 29726 additions and 0 deletions

View File

@@ -0,0 +1,32 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" output="target/classes" path="src/main/java">
<attributes>
<attribute name="optional" value="true"/>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-11">
<attributes>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER">
<attributes>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry excluding="**" kind="src" output="target/classes" path="src/main/resources">
<attributes>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="src" output="target/test-classes" path="src/test/java">
<attributes>
<attribute name="optional" value="true"/>
<attribute name="maven.pomderived" value="true"/>
<attribute name="test" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="output" path="target/classes"/>
</classpath>

View File

@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>org.openhab.persistence.jpa</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.m2e.core.maven2Builder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.jdt.core.javanature</nature>
<nature>org.eclipse.m2e.core.maven2Nature</nature>
</natures>
</projectDescription>

View File

@@ -0,0 +1,13 @@
This content is produced and maintained by the openHAB project.
* Project home: https://www.openhab.org
== Declared Project Licenses
This program and the accompanying materials are made available under the terms
of the Eclipse Public License 2.0 which is available at
https://www.eclipse.org/legal/epl-2.0/.
== Source Code
https://github.com/openhab/openhab-addons

View File

@@ -0,0 +1,44 @@
# Java Persistence API (JPA) Persistence
This service allows you to persist state updates using a SQL or NoSQL database through the [Java Persistence API](https://en.wikipedia.org/wiki/Java_Persistence_API).
The service uses an abstraction layer that theoretically allows it to support many available SQL or NoSQL databases.
It will create one table named `historic_item` where all item states are stored.
The item state is stored in a string representation.
The service currently supports MySQL, Apache Derby and PostgreSQL databases.
Only the embedded Apache Derby database driver is included.
Other drivers must be installed manually.
(See below for more information on that.)
## Configuration
This service can be configured in the file `services/jpa.cfg`.
| Property | Default | Required | Description |
| -------- | ------- | :-------: | ------------------------------------------------------------ |
| url | | Yes | JDBC connection URL. Examples:<br/><br/>`jdbc:postgresql://hab.local:5432/openhab`<br/>`jdbc:derby://hab.local:1527/openhab;create=true`<br/>`jdbc:mysql://localhost:3306/openhab` |
| driver | | Yes | database driver. Examples:<br/><br/>`org.postgresql.Driver`<br/>`org.apache.derby.jdbc.ClientDriver`<br/>`com.mysql.jdbc.Driver`<br/></br>Only the Apache Derby driver is included with the service. Drivers for other databases must be installed manually. This is a trivial process. Normally JDBC database drivers are packaged as OSGi bundles and can just be dropped into the `addons` folder. This has the advantage that users can update their drivers as needed. The following database drivers are known to work:<br/><br/>`postgresql-9.4-1203-jdbc41.jar`<br/>`postgresql-9.4-1206-jdbc41.jar` |
| user | | if needed | database user name for connection |
| password | | if needed | database user password for connection |
## Adding support for other JPA supported databases
All item- and event-related configuration is done in the file `persistence/jpa.persist`.
If a database driver is not an OSGi bundle, the technique below can be used to extend the openHAB classpath.
Other database drivers can be added by expanding the openHAB classpath.
Use the following classpath setup in start.sh / start_debug.sh of openHAB:
```
cp=$(echo lib/*.jar | tr ' ' ':'):$(find $eclipsehome -name "org.eclipse.equinox.launcher_*.jar" | sort | tail -1);
```
This will add all .jar files in a folder "lib" in the root of openhab.
All databases that are supported by JPA can be added.
Define `driver` and `url` according to the database definitions.

View File

@@ -0,0 +1,70 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.openhab.addons.bundles</groupId>
<artifactId>org.openhab.addons.reactor.bundles</artifactId>
<version>3.0.0-SNAPSHOT</version>
</parent>
<artifactId>org.openhab.persistence.jpa</artifactId>
<name>openHAB Add-ons :: Bundles :: Persistence Service :: JPA</name>
<properties>
<bnd.importpackage>!com.ibm.*,!com.sun.*,!oracle.*,!org.apache.bval.*,!org.apache.geronimo.*,!org.apache.avalon.*,!org.apache.log,!org.apache.tools.*,!org.apache.xerces.*,!org.jboss.*,!org.postgresql.*,!org.slf4j.impl,!weblogic.*,!javax.rmi</bnd.importpackage>
</properties>
<dependencies>
<!-- https://mvnrepository.com/artifact/org.apache.openjpa/openjpa-all -->
<dependency>
<groupId>org.apache.openjpa</groupId>
<artifactId>openjpa-all</artifactId>
<version>2.4.0</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.derby/derby -->
<dependency>
<groupId>org.apache.derby</groupId>
<artifactId>derby</artifactId>
<version>10.11.1.1</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.openjpa</groupId>
<artifactId>openjpa-maven-plugin</artifactId>
<version>3.1.0</version>
<configuration>
<excludes>org/apache/bval/**</excludes>
<includes>**/model/*.class</includes>
<addDefaultConstructor>true</addDefaultConstructor>
<enforcePropertyRestrictions>true</enforcePropertyRestrictions>
</configuration>
<dependencies>
<dependency>
<groupId>org.apache.openjpa</groupId>
<artifactId>openjpa</artifactId>
<!-- set the version to be the same as the level in your runtime -->
<version>3.1.0</version>
</dependency>
</dependencies>
<executions>
<execution>
<id>enhancer</id>
<goals>
<goal>enhance</goal>
</goals>
<phase>process-classes</phase>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

View File

@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<features name="org.openhab.persistence.jpa-${project.version}" xmlns="http://karaf.apache.org/xmlns/features/v1.4.0">
<repository>mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features</repository>
<feature name="openhab-persistence-jpa" description="JPA Persistence" version="${project.version}">
<feature>openhab-runtime-base</feature>
<bundle start-level="80">mvn:org.openhab.addons.bundles/org.openhab.persistence.jpa/${project.version}</bundle>
<configfile finalname="${openhab.conf}/services/jpa.cfg" override="false">mvn:${project.groupId}/openhab-addons-external3/${project.version}/cfg/jpa</configfile>
</feature>
</features>

View File

@@ -0,0 +1,83 @@
/**
* Copyright (c) 2010-2020 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.openhab.persistence.jpa.internal;
import java.util.Map;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* The configuration required for Jpa binding.
*
* @author Manfred Bergmann - Initial contribution
* @author Kai Kreuzer - migrated to 3.x
*
*/
public class JpaConfiguration {
private final Logger logger = LoggerFactory.getLogger(JpaConfiguration.class);
private static final String CFG_CONNECTION_URL = "url";
private static final String CFG_DRIVER_CLASS = "driver";
private static final String CFG_USERNAME = "user";
private static final String CFG_PASSWORD = "password";
private static final String CFG_SYNCMAPPING = "syncmappings";
public static boolean isInitialized = false;
public final String dbConnectionUrl;
public final String dbDriverClass;
public final String dbUserName;
public final String dbPassword;
public final String dbSyncMapping;
public JpaConfiguration(final Map<String, Object> properties) {
logger.debug("Update config...");
String param = (String) properties.get(CFG_CONNECTION_URL);
logger.debug("url: {}", param);
if (param == null) {
logger.warn("Connection url is required in jpa.cfg!");
} else if (param.isBlank()) {
logger.warn("Empty connection url in jpa.cfg!");
}
dbConnectionUrl = param;
param = (String) properties.get(CFG_DRIVER_CLASS);
logger.debug("driver: {}", param);
if (param == null) {
logger.warn("Driver class is required in jpa.cfg!");
} else if (param.isBlank()) {
logger.warn("Empty driver class in jpa.cfg!");
}
dbDriverClass = param;
if (properties.get(CFG_USERNAME) == null) {
logger.info("{} was not specified!", CFG_USERNAME);
}
dbUserName = (String) properties.get(CFG_USERNAME);
if (properties.get(CFG_PASSWORD) == null) {
logger.info("{} was not specified!", CFG_PASSWORD);
}
dbPassword = (String) properties.get(CFG_PASSWORD);
if (properties.get(CFG_SYNCMAPPING) == null) {
logger.debug("{} was not specified!", CFG_SYNCMAPPING);
}
dbSyncMapping = (String) properties.get(CFG_SYNCMAPPING);
isInitialized = true;
logger.debug("Update config... done");
}
}

View File

@@ -0,0 +1,137 @@
/**
* Copyright (c) 2010-2020 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.openhab.persistence.jpa.internal;
import java.text.DateFormat;
import java.time.Instant;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.util.ArrayList;
import java.util.List;
import org.openhab.core.items.Item;
import org.openhab.core.library.items.ContactItem;
import org.openhab.core.library.items.DateTimeItem;
import org.openhab.core.library.items.DimmerItem;
import org.openhab.core.library.items.LocationItem;
import org.openhab.core.library.items.NumberItem;
import org.openhab.core.library.items.RollershutterItem;
import org.openhab.core.library.items.SwitchItem;
import org.openhab.core.library.types.DateTimeType;
import org.openhab.core.library.types.DecimalType;
import org.openhab.core.library.types.OnOffType;
import org.openhab.core.library.types.OpenClosedType;
import org.openhab.core.library.types.PercentType;
import org.openhab.core.library.types.PointType;
import org.openhab.core.library.types.StringListType;
import org.openhab.core.library.types.StringType;
import org.openhab.core.persistence.HistoricItem;
import org.openhab.core.types.State;
import org.openhab.persistence.jpa.internal.model.JpaPersistentItem;
/**
* The historic item as returned when querying the service.
*
* @author Manfred Bergmann - Initial contribution
*
*/
public class JpaHistoricItem implements HistoricItem {
private final String name;
private final State state;
private final ZonedDateTime timestamp;
public JpaHistoricItem(String name, State state, ZonedDateTime timestamp) {
this.name = name;
this.state = state;
this.timestamp = timestamp;
}
@Override
public String getName() {
return name;
}
@Override
public ZonedDateTime getTimestamp() {
return timestamp;
}
@Override
public State getState() {
return state;
}
@Override
public String toString() {
return DateFormat.getDateTimeInstance().format(timestamp) + ": " + name + " -> " + state.toString();
}
/**
* This method maps a jpa result item to this historic item.
*
* @param jpaQueryResult the result which jpa items
* @param item used for query information, like the state (State)
* @return list of historic items
*/
public static List<HistoricItem> fromResultList(List<JpaPersistentItem> jpaQueryResult, Item item) {
List<HistoricItem> ret = new ArrayList<>();
for (JpaPersistentItem i : jpaQueryResult) {
HistoricItem hi = fromPersistedItem(i, item);
ret.add(hi);
}
return ret;
}
/**
* Converts the string value of the persisted item to the state of a HistoricItem.
*
* @param pItem the persisted JpaPersistentItem
* @param item the source reference Item
* @return historic item
*/
public static HistoricItem fromPersistedItem(JpaPersistentItem pItem, Item item) {
State state;
if (item instanceof NumberItem) {
state = new DecimalType(Double.valueOf(pItem.getValue()));
} else if (item instanceof DimmerItem) {
state = new PercentType(Integer.valueOf(pItem.getValue()));
} else if (item instanceof SwitchItem) {
state = OnOffType.valueOf(pItem.getValue());
} else if (item instanceof ContactItem) {
state = OpenClosedType.valueOf(pItem.getValue());
} else if (item instanceof RollershutterItem) {
state = PercentType.valueOf(pItem.getValue());
} else if (item instanceof DateTimeItem) {
state = new DateTimeType(ZonedDateTime.ofInstant(Instant.ofEpochMilli(Long.valueOf(pItem.getValue())),
ZoneId.systemDefault()));
} else if (item instanceof LocationItem) {
PointType pType = null;
String[] comps = pItem.getValue().split(";");
if (comps.length >= 2) {
pType = new PointType(new DecimalType(comps[0]), new DecimalType(comps[1]));
if (comps.length == 3) {
pType.setAltitude(new DecimalType(comps[2]));
}
}
state = pType;
} else if (item instanceof StringListType) {
state = new StringListType(pItem.getValue());
} else {
state = new StringType(pItem.getValue());
}
return new JpaHistoricItem(item.getName(), state, pItem.getTimestamp());
}
}

View File

@@ -0,0 +1,322 @@
/**
* Copyright (c) 2010-2020 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.openhab.persistence.jpa.internal;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import javax.persistence.Query;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.openhab.core.items.Item;
import org.openhab.core.items.ItemNotFoundException;
import org.openhab.core.items.ItemRegistry;
import org.openhab.core.persistence.FilterCriteria;
import org.openhab.core.persistence.FilterCriteria.Ordering;
import org.openhab.core.persistence.HistoricItem;
import org.openhab.core.persistence.PersistenceItemInfo;
import org.openhab.core.persistence.PersistenceService;
import org.openhab.core.persistence.QueryablePersistenceService;
import org.openhab.core.persistence.strategy.PersistenceStrategy;
import org.openhab.core.types.UnDefType;
import org.openhab.persistence.jpa.internal.model.JpaPersistentItem;
import org.osgi.framework.BundleContext;
import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.ConfigurationPolicy;
import org.osgi.service.component.annotations.Deactivate;
import org.osgi.service.component.annotations.Reference;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* JPA based implementation of QueryablePersistenceService.
*
* @author Manfred Bergmann - Initial contribution
*/
@NonNullByDefault
@Component(service = { PersistenceService.class,
QueryablePersistenceService.class }, configurationPid = "org.openhab.jpa", configurationPolicy = ConfigurationPolicy.REQUIRE)
public class JpaPersistenceService implements QueryablePersistenceService {
private final Logger logger = LoggerFactory.getLogger(JpaPersistenceService.class);
private final ItemRegistry itemRegistry;
private @Nullable EntityManagerFactory emf = null;
private @NonNullByDefault({}) JpaConfiguration config;
@Activate
public JpaPersistenceService(final @Reference ItemRegistry itemRegistry) {
this.itemRegistry = itemRegistry;
}
/**
* lazy loading because update() is called after activate()
*
* @return EntityManagerFactory
*/
protected @Nullable EntityManagerFactory getEntityManagerFactory() {
if (emf == null) {
emf = newEntityManagerFactory();
}
return emf;
}
@Activate
public void activate(BundleContext context, Map<String, Object> properties) {
logger.debug("Activating jpa persistence service");
config = new JpaConfiguration(properties);
}
/**
* Closes the EntityPersistenceFactory
*/
@Deactivate
public void deactivate() {
logger.debug("Deactivating jpa persistence service");
closeEntityManagerFactory();
}
@Override
public String getId() {
return "jpa";
}
@Override
public String getLabel(@Nullable Locale locale) {
return "JPA";
}
@Override
public void store(Item item) {
store(item, null);
}
@Override
public void store(Item item, @Nullable String alias) {
logger.debug("Storing item: {}", item.getName());
if (item.getState() instanceof UnDefType) {
logger.debug("This item is of undefined type. Cannot persist it!");
return;
}
if (!JpaConfiguration.isInitialized) {
logger.debug("Trying to create EntityManagerFactory but we don't have configuration yet!");
return;
}
// determine item name to be stored
String name = (alias != null) ? alias : item.getName();
JpaPersistentItem pItem = new JpaPersistentItem();
try {
String newValue = StateHelper.toString(item.getState());
pItem.setValue(newValue);
logger.debug("Stored new value: {}", newValue);
} catch (Exception e1) {
logger.error("Error on converting state value to string: {}", e1.getMessage());
return;
}
pItem.setName(name);
pItem.setRealName(item.getName());
pItem.setTimestamp(new Date());
EntityManager em = getEntityManagerFactory().createEntityManager();
try {
logger.debug("Persisting item...");
// In RESOURCE_LOCAL calls to EntityManager require a begin/commit
em.getTransaction().begin();
em.persist(pItem);
em.getTransaction().commit();
logger.debug("Persisting item...done");
} catch (Exception e) {
logger.error("Error on persisting item! Rolling back!", e);
em.getTransaction().rollback();
} finally {
em.close();
}
logger.debug("Storing item...done");
}
@Override
public Set<PersistenceItemInfo> getItemInfo() {
return Collections.emptySet();
}
@Override
public Iterable<HistoricItem> query(FilterCriteria filter) {
logger.debug("Querying for historic item: {}", filter.getItemName());
if (!JpaConfiguration.isInitialized) {
logger.warn("Trying to create EntityManagerFactory but we don't have configuration yet!");
return Collections.emptyList();
}
String itemName = filter.getItemName();
Item item = getItemFromRegistry(itemName);
String sortOrder;
if (filter.getOrdering() == Ordering.ASCENDING) {
sortOrder = "ASC";
} else {
sortOrder = "DESC";
}
boolean hasBeginDate = false;
boolean hasEndDate = false;
String queryString = "SELECT n FROM " + JpaPersistentItem.class.getSimpleName()
+ " n WHERE n.realName = :itemName";
if (filter.getBeginDate() != null) {
queryString += " AND n.timestamp >= :beginDate";
hasBeginDate = true;
}
if (filter.getEndDate() != null) {
queryString += " AND n.timestamp <= :endDate";
hasEndDate = true;
}
queryString += " ORDER BY n.timestamp " + sortOrder;
logger.debug("The query: {}", queryString);
EntityManager em = getEntityManagerFactory().createEntityManager();
try {
// In RESOURCE_LOCAL calls to EntityManager require a begin/commit
em.getTransaction().begin();
logger.debug("Creating query...");
Query query = em.createQuery(queryString);
query.setParameter("itemName", item.getName());
if (hasBeginDate) {
query.setParameter("beginDate", Date.from(filter.getBeginDate().toInstant()));
}
if (hasEndDate) {
query.setParameter("endDate", Date.from(filter.getEndDate().toInstant()));
}
query.setFirstResult(filter.getPageNumber() * filter.getPageSize());
query.setMaxResults(filter.getPageSize());
logger.debug("Creating query...done");
logger.debug("Retrieving result list...");
@SuppressWarnings("unchecked")
List<JpaPersistentItem> result = query.getResultList();
logger.debug("Retrieving result list...done");
List<HistoricItem> historicList = JpaHistoricItem.fromResultList(result, item);
logger.debug("{}", String.format("Convert to HistoricItem: %d", historicList.size()));
em.getTransaction().commit();
return historicList;
} catch (Exception e) {
logger.error("Error on querying database!", e);
em.getTransaction().rollback();
} finally {
em.close();
}
return Collections.emptyList();
}
/**
* Creates a new EntityManagerFactory with properties read from openhab.cfg via JpaConfiguration.
*
* @return initialized EntityManagerFactory
*/
protected EntityManagerFactory newEntityManagerFactory() {
logger.trace("Creating EntityManagerFactory...");
Map<String, String> properties = new HashMap<>();
properties.put("javax.persistence.jdbc.url", config.dbConnectionUrl);
properties.put("javax.persistence.jdbc.driver", config.dbDriverClass);
if (config.dbUserName != null) {
properties.put("javax.persistence.jdbc.user", config.dbUserName);
}
if (config.dbPassword != null) {
properties.put("javax.persistence.jdbc.password", config.dbPassword);
}
if (config.dbUserName != null && config.dbPassword == null) {
logger.warn("JPA persistence - it is recommended to use a password to protect data store");
}
if (config.dbSyncMapping != null && !config.dbSyncMapping.isBlank()) {
logger.warn("You are settings openjpa.jdbc.SynchronizeMappings, I hope you know what you're doing!");
properties.put("openjpa.jdbc.SynchronizeMappings", config.dbSyncMapping);
}
EntityManagerFactory fac = Persistence.createEntityManagerFactory(getPersistenceUnitName(), properties);
logger.debug("Creating EntityManagerFactory...done");
return fac;
}
/**
* Closes EntityManagerFactory
*/
protected void closeEntityManagerFactory() {
if (emf != null) {
emf.close();
emf = null;
}
logger.debug("Closing down entity objects...done");
}
/**
* Checks if EntityManagerFactory is open
*
* @return true when open, false otherwise
*/
protected boolean isEntityManagerFactoryOpen() {
return emf != null && emf.isOpen();
}
/**
* Return the persistence unit as in persistence.xml file.
*
* @return the persistence unit name
*/
protected String getPersistenceUnitName() {
return "default";
}
/**
* Retrieves the item for the given name from the item registry
*
* @param itemName
* @return item
*/
private @Nullable Item getItemFromRegistry(String itemName) {
try {
return itemRegistry.getItem(itemName);
} catch (ItemNotFoundException e1) {
logger.error("Unable to get item type for {}", itemName);
}
return null;
}
@Override
public List<PersistenceStrategy> getDefaultStrategies() {
return Collections.emptyList();
}
}

View File

@@ -0,0 +1,52 @@
/**
* Copyright (c) 2010-2020 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.openhab.persistence.jpa.internal;
import java.util.Locale;
import org.openhab.core.library.types.DateTimeType;
import org.openhab.core.library.types.DecimalType;
import org.openhab.core.library.types.PointType;
import org.openhab.core.types.State;
/**
* Helper class for dealing with State
*
* @author Manfred Bergmann - Initial contribution
*
*/
public class StateHelper {
/**
* Converts the given State to a string that can be persisted in db
*
* @param state the state of the item to be persisted
* @return state converted as string
* @throws Exception
*/
public static String toString(State state) throws Exception {
if (state instanceof DateTimeType) {
return String.valueOf(((DateTimeType) state).getZonedDateTime().toInstant().toEpochMilli());
}
if (state instanceof DecimalType) {
return String.valueOf(((DecimalType) state).doubleValue());
}
if (state instanceof PointType) {
PointType pType = (PointType) state;
return String.format(Locale.ENGLISH, "%f;%f;%f", pType.getLatitude().doubleValue(),
pType.getLongitude().doubleValue(), pType.getAltitude().doubleValue());
}
return state.toString();
}
}

View File

@@ -0,0 +1,106 @@
/**
* Copyright (c) 2010-2020 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.openhab.persistence.jpa.internal.model;
import java.text.DateFormat;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.util.Date;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import org.openhab.core.persistence.HistoricItem;
import org.openhab.core.types.State;
import org.openhab.core.types.UnDefType;
/**
* This is the DAO object used for storing and retrieving to and from database.
*
* @author Manfred Bergmann - Initial contribution
*
*/
@Entity
@Table(name = "HISTORIC_ITEM")
public class JpaPersistentItem implements HistoricItem {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String name = "";
private String realName = "";
@Temporal(TemporalType.TIMESTAMP)
private Date timestamp = new Date();
@Column(length = 32672) // 32k, max varchar for apache derby
private String value = "";
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
@Override
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getRealName() {
return realName;
}
public void setRealName(String realName) {
this.realName = realName;
}
@Override
public ZonedDateTime getTimestamp() {
return ZonedDateTime.ofInstant(timestamp.toInstant(), ZoneId.systemDefault());
}
public void setTimestamp(Date timestamp) {
this.timestamp = timestamp;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
@Override
public State getState() {
return UnDefType.NULL;
}
@Override
public String toString() {
return DateFormat.getDateTimeInstance().format(getTimestamp()) + ": " + getName() + " -> " + value;
}
}

View File

@@ -0,0 +1,34 @@
<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence" version="1.0">
<persistence-unit name="default" transaction-type="RESOURCE_LOCAL">
<provider>org.apache.openjpa.persistence.PersistenceProviderImpl</provider>
<non-jta-data-source/>
<class>org.openhab.persistence.jpa.internal.model.JpaPersistentItem</class>
<exclude-unlisted-classes>true</exclude-unlisted-classes>
<properties>
<property name="javax.persistence.jdbc.url" value="jdbc:postgresql:"/>
<property name="javax.persistence.jdbc.driver" value="org.postgresql.Driver"/>
<property name="javax.persistence.jdbc.user" value=""/>
<property name="javax.persistence.jdbc.password" value=""/>
<property name="openjpa.jdbc.SynchronizeMappings" value="buildSchema(schemaAction='add')"/>
<property name="openjpa.Log" value="DefaultLevel=WARN, Tool=INFO"/>
</properties>
</persistence-unit>
<persistence-unit name="default_test" transaction-type="RESOURCE_LOCAL">
<provider>org.apache.openjpa.persistence.PersistenceProviderImpl</provider>
<non-jta-data-source/>
<class>org.openhab.persistence.jpa.internal.model.JpaPersistentItem</class>
<exclude-unlisted-classes>true</exclude-unlisted-classes>
<properties>
<property name="javax.persistence.jdbc.url" value="jdbc:derby:data;create=true"/>
<property name="javax.persistence.jdbc.driver" value="org.apache.derby.jdbc.EmbeddedDriver"/>
<property name="javax.persistence.jdbc.user" value="APP"/>
<property name="javax.persistence.jdbc.password" value="APP"/>
<property name="openjpa.jdbc.SynchronizeMappings" value="buildSchema(SchemaAction='drop,add')"/>
<property name="openjpa.Log" value="DefaultLevel=TRACE, Tool=INFO"/>
</properties>
</persistence-unit>
</persistence>