Skip to content

Commit ca34de2

Browse files
committed
Initial commit of publisher points table
Many things outstanding, this is just a proof of concept for H2
1 parent fb1dead commit ca34de2

File tree

14 files changed

+675
-8
lines changed

14 files changed

+675
-8
lines changed

Core/classes/i18n.properties

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -323,6 +323,8 @@ common.logic.not=Not
323323

324324
common.invalidRql=Invalid RQL
325325

326+
database.missingModelMapping=No model mapping for {0} to {1}
327+
326328
share.sharing=Sharing
327329
share.userName=Username
328330
share.accessType=Access type

Core/db/createTables-H2.sql

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -315,6 +315,24 @@ CREATE TABLE publishers (
315315
);
316316
ALTER TABLE publishers ADD CONSTRAINT publishersUn1 UNIQUE (xid);
317317

318+
CREATE TABLE publishedPoints (
319+
id int NOT NULL auto_increment,
320+
xid varchar(100) NOT NULL,
321+
name varchar(255),
322+
enabled char(1),
323+
publisherId int NOT NULL,
324+
dataPointId int NOT NULL,
325+
data longtext NOT NULL,
326+
PRIMARY KEY (id)
327+
);
328+
ALTER TABLE publishedPoints ADD CONSTRAINT publisherPointsUn1 UNIQUE (xid);
329+
ALTER TABLE publishedPoints ADD CONSTRAINT publisherPointsFk1 FOREIGN KEY (publisherId) REFERENCES publishers(id);
330+
ALTER TABLE publishedPoints ADD CONSTRAINT publisherPointsFk2 FOREIGN KEY (dataPointId) REFERENCES dataPoints(id);
331+
332+
CREATE INDEX publishedPointNameIndex on publishedPoints (name ASC);
333+
CREATE INDEX publishedPointEnabledIndex on publishedPoints (enabled ASC);
334+
CREATE INDEX publishedPointXidNameIndex on publishedPoints (xid ASC, name ASC);
335+
318336
--
319337
--
320338
-- JsonData
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
/**
2+
* Copyright (C) 2019 Infinite Automation Software. All rights reserved.
3+
*/
4+
package com.infiniteautomation.mango.spring.db;
5+
6+
import org.springframework.stereotype.Component;
7+
8+
import com.serotonin.m2m2.vo.publish.mock.MockPublishedPointDatabaseV1Model;
9+
import com.serotonin.m2m2.vo.publish.mock.MockPublishedPointVO;
10+
11+
/**
12+
* @author Terry Packer
13+
*
14+
*/
15+
@Component
16+
public class MockPublishedPointDatabaseModelV1Mapping implements DatabaseModelJacksonMapping<MockPublishedPointVO, MockPublishedPointDatabaseV1Model> {
17+
18+
@Override
19+
public Class<? extends MockPublishedPointVO> fromClass() {
20+
return MockPublishedPointVO.class;
21+
}
22+
23+
@Override
24+
public Class<? extends MockPublishedPointDatabaseV1Model> toClass() {
25+
return MockPublishedPointDatabaseV1Model.class;
26+
}
27+
28+
@Override
29+
public MockPublishedPointDatabaseV1Model map(Object from, DatabaseModelMapper mapper) {
30+
return new MockPublishedPointDatabaseV1Model((MockPublishedPointVO)from);
31+
}
32+
33+
@Override
34+
public String getVersion() {
35+
return MockPublishedPointDatabaseV1Model.class.getName();
36+
}
37+
38+
}
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
/**
2+
* Copyright (C) 2019 Infinite Automation Software. All rights reserved.
3+
*/
4+
package com.serotonin.m2m2.vo.publish;
5+
6+
import java.util.ArrayList;
7+
import java.util.List;
8+
9+
import org.junit.Assert;
10+
import org.junit.BeforeClass;
11+
import org.junit.Test;
12+
13+
import com.serotonin.m2m2.DataTypes;
14+
import com.serotonin.m2m2.MangoTestBase;
15+
import com.serotonin.m2m2.db.dao.DataPointDao;
16+
import com.serotonin.m2m2.db.dao.DataSourceDao;
17+
import com.serotonin.m2m2.db.dao.PublishedPointDao;
18+
import com.serotonin.m2m2.db.dao.PublisherDao;
19+
import com.serotonin.m2m2.module.ModuleElementDefinition;
20+
import com.serotonin.m2m2.vo.DataPointVO;
21+
import com.serotonin.m2m2.vo.dataPoint.MockPointLocatorVO;
22+
import com.serotonin.m2m2.vo.dataSource.mock.MockDataSourceVO;
23+
import com.serotonin.m2m2.vo.publish.mock.MockPublishedPointVO;
24+
import com.serotonin.m2m2.vo.publish.mock.MockPublisherDefinition;
25+
import com.serotonin.m2m2.vo.publish.mock.MockPublisherVO;
26+
27+
/**
28+
* @author Terry Packer
29+
*
30+
*/
31+
public class PublishedPointTest extends MangoTestBase {
32+
33+
@BeforeClass
34+
public static void addDefinitions() {
35+
List<ModuleElementDefinition> definitions = new ArrayList<>();
36+
definitions.add(new MockPublisherDefinition());
37+
addModule("mockPublisher", definitions);
38+
}
39+
40+
@Test
41+
public void testPublisherAuditTrail() {
42+
MockPublisherVO pub = new MockPublisherVO();
43+
pub.setDefinition(new MockPublisherDefinition());
44+
pub.setXid("PUB_TEST1");
45+
pub.setEnabled(false);
46+
PublisherDao.getInstance().savePublisher(pub);
47+
48+
MockDataSourceVO ds = new MockDataSourceVO();
49+
ds.setXid("DS_TEST1");
50+
ds.setName("TEST");
51+
DataSourceDao.getInstance().save(ds);
52+
53+
//Save a point
54+
DataPointVO dp = new DataPointVO();
55+
dp.setXid("DP_1");
56+
dp.setName("Data point name");
57+
dp.setPointLocator(new MockPointLocatorVO(DataTypes.NUMERIC, true));
58+
dp.setDataSourceId(ds.getId());
59+
DataPointDao.getInstance().save(dp);
60+
61+
//Save publisher point
62+
MockPublishedPointVO pp = new MockPublishedPointVO();
63+
pp.setXid(PublishedPointDao.getInstance().generateUniqueXid());
64+
pp.setName("Test published point");
65+
pp.setPublisherId(pub.getId());
66+
pp.setDataPointId(dp.getId());
67+
pp.setMockSetting("mock setting");
68+
pp.ensureValid();
69+
PublishedPointDao.getInstance().save(pp);
70+
71+
//Verify the point was created correctly
72+
MockPublishedPointVO mpp = (MockPublishedPointVO)PublishedPointDao.getInstance().get(pp.getId());
73+
Assert.assertEquals(pp.getId(), mpp.getId());
74+
Assert.assertEquals(pp.getXid(), mpp.getXid());
75+
Assert.assertEquals(pp.getName(), mpp.getName());
76+
Assert.assertEquals(pp.isEnabled(), mpp.isEnabled());
77+
Assert.assertEquals(pp.getPublisherId(), mpp.getPublisherId());
78+
Assert.assertEquals(pp.getDataPointId(), mpp.getDataPointId());
79+
Assert.assertEquals(pp.getMockSetting(), mpp.getMockSetting());
80+
81+
//TODO Verify Audit Events
82+
}
83+
}
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
/**
2+
* Copyright (C) 2019 Infinite Automation Software. All rights reserved.
3+
*/
4+
package com.serotonin.m2m2.vo.publish.mock;
5+
6+
import org.springframework.stereotype.Component;
7+
8+
import com.serotonin.m2m2.db.dao.PublishedPointDao.PublishedPointSettingsDatabaseModel;
9+
import com.serotonin.m2m2.vo.publish.PublishedPointVO;
10+
11+
/**
12+
* @author Terry Packer
13+
*
14+
*/
15+
@Component
16+
public class MockPublishedPointDatabaseV1Model extends PublishedPointSettingsDatabaseModel {
17+
18+
private String setting;
19+
20+
public MockPublishedPointDatabaseV1Model() {
21+
22+
}
23+
24+
public MockPublishedPointDatabaseV1Model(MockPublishedPointVO vo) {
25+
this.setting = vo.getMockSetting();
26+
}
27+
28+
public String getSetting() {
29+
return setting;
30+
}
31+
32+
public void setSetting(String setting) {
33+
this.setting = setting;
34+
}
35+
36+
@Override
37+
public PublishedPointVO toVO() {
38+
MockPublishedPointVO vo = new MockPublishedPointVO();
39+
vo.setMockSetting(setting);
40+
return vo;
41+
}
42+
43+
@Override
44+
public String getVersion() {
45+
return this.getClass().getName();
46+
}
47+
}

Core/src-test/com/serotonin/m2m2/vo/publish/mock/MockPublishedPointVO.java

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,18 @@
1111
*
1212
* @author Terry Packer
1313
*/
14-
public class MockPublishedPointVO extends PublishedPointVO{
14+
public class MockPublishedPointVO extends PublishedPointVO {
15+
16+
private String mockSetting;
17+
18+
public String getMockSetting() {
19+
return mockSetting;
20+
}
21+
22+
public void setMockSetting(String mockSetting) {
23+
this.mockSetting = mockSetting;
24+
}
1525

16-
/* (non-Javadoc)
17-
* @see com.serotonin.m2m2.vo.publish.PublishedPointVO#asModel()
18-
*/
1926
@Override
2027
public AbstractPublishedPointModel<?> asModel() {
2128
return null;
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
/**
2+
* Copyright (C) 2019 Infinite Automation Software. All rights reserved.
3+
*/
4+
package com.infiniteautomation.mango.spring.db;
5+
6+
import com.fasterxml.jackson.annotation.JsonTypeInfo;
7+
8+
/**
9+
* @author Terry Packer
10+
*
11+
*/
12+
@JsonTypeInfo(use=JsonTypeInfo.Id.NAME, include=JsonTypeInfo.As.EXISTING_PROPERTY, property=AbstractDatabaseModel.VERSION_FIELD)
13+
public abstract class AbstractDatabaseModel {
14+
15+
public static final String VERSION_FIELD = "version";
16+
17+
/**
18+
* Ensure the model has a version
19+
* @return
20+
*/
21+
public abstract String getVersion();
22+
23+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
/**
2+
* Copyright (C) 2019 Infinite Automation Software. All rights reserved.
3+
*/
4+
package com.infiniteautomation.mango.spring.db;
5+
6+
/**
7+
* Used to ensure Jackson is able to de-serialize the model (type T) in this mapping
8+
*
9+
* @author Terry Packer
10+
*
11+
*/
12+
public interface DatabaseModelJacksonMapping <F, T> extends DatabaseModelMapping<F, T> {
13+
14+
/**
15+
* Return the type name that maps the T class (Model) to a Type in Jackson
16+
* in the DAO layer we call this the version
17+
*/
18+
public String getVersion();
19+
20+
}
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
/**
2+
* Copyright (C) 2019 Infinite Automation Software. All rights reserved.
3+
*/
4+
package com.infiniteautomation.mango.spring.db;
5+
6+
import java.util.Collections;
7+
import java.util.List;
8+
import java.util.Objects;
9+
import java.util.Optional;
10+
11+
import org.springframework.beans.factory.annotation.Autowired;
12+
import org.springframework.beans.factory.annotation.Qualifier;
13+
import org.springframework.stereotype.Component;
14+
15+
import com.fasterxml.jackson.databind.ObjectMapper;
16+
import com.fasterxml.jackson.databind.jsontype.NamedType;
17+
import com.infiniteautomation.mango.spring.MangoRuntimeContextConfiguration;
18+
import com.infiniteautomation.mango.util.exception.TranslatableRuntimeException;
19+
import com.serotonin.m2m2.i18n.TranslatableMessage;
20+
21+
/**
22+
* Gets a list of DatabaseModelMapping beans from the Spring context and uses them to convert an object to its model.
23+
* The DatabaseModelMapping beans can be annotated with @Order to specify their priority.
24+
*
25+
* @author Terry Packer
26+
*
27+
*/
28+
@Component
29+
public class DatabaseModelMapper {
30+
private final List<DatabaseModelMapping<?,?>> mappings;
31+
32+
@Autowired
33+
public DatabaseModelMapper(Optional<List<DatabaseModelMapping<?,?>>> mappings,
34+
@Qualifier(MangoRuntimeContextConfiguration.DAO_OBJECT_MAPPER_NAME)ObjectMapper objectMapper) {
35+
this.mappings = mappings.orElseGet(Collections::emptyList);
36+
37+
//Load in the mappings for Jackson
38+
for(DatabaseModelMapping<?,?> mapping : this.mappings) {
39+
if(mapping instanceof DatabaseModelJacksonMapping)
40+
objectMapper.registerSubtypes(new NamedType(mapping.toClass(), ((DatabaseModelJacksonMapping<?,?>)mapping).getVersion()));
41+
}
42+
}
43+
44+
public <T> T map(Object from, Class<T> model) {
45+
Objects.requireNonNull(from);
46+
Objects.requireNonNull(model);
47+
48+
for (DatabaseModelMapping<?,?> mapping : mappings) {
49+
if (mapping.supports(from, model)) {
50+
@SuppressWarnings("unchecked")
51+
T result = (T) mapping.map(from, this);
52+
if (result != null) {
53+
return result;
54+
}
55+
}
56+
}
57+
58+
throw new TranslatableRuntimeException(new TranslatableMessage("database.missingModelMapping", from.getClass(), model));
59+
}
60+
61+
}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
/**
2+
* Copyright (C) 2019 Infinite Automation Software. All rights reserved.
3+
*/
4+
package com.infiniteautomation.mango.spring.db;
5+
6+
/**
7+
* @author Terry Packer
8+
*
9+
*/
10+
/**
11+
* Mapping to deliver support for converting between classes
12+
* when transporting payloads in/out of the Database
13+
*
14+
* @author Terry Packer
15+
*/
16+
public interface DatabaseModelMapping<F, T> {
17+
18+
public Class<? extends F> fromClass();
19+
public Class<? extends T> toClass();
20+
21+
/**
22+
* Checks if the mapping supports mapping the object to the desired model class.
23+
*
24+
* @param from
25+
* @param toClass
26+
* @return true if the mapping supports mapping the object to the desired model class
27+
*/
28+
public default boolean supports(Object from, Class<?> toClass) {
29+
return this.fromClass().isAssignableFrom(from.getClass()) &&
30+
toClass.isAssignableFrom(this.toClass());
31+
}
32+
33+
/**
34+
* Performs the mapping of the object to the desired model class. If null is returned other mappings will be tried in order.
35+
*
36+
* @param from
37+
* @param user
38+
* @param mapper
39+
* @return The model object or null
40+
*/
41+
public T map(Object from, DatabaseModelMapper mapper);
42+
43+
}

0 commit comments

Comments
 (0)