implemented service that handles manufacturer-OUI translation

This commit is contained in:
Dmitry Toptygin
2020-06-17 16:48:49 -04:00
parent f9f250b925
commit 6cee9c317d
44 changed files with 3321 additions and 2093 deletions

View File

@@ -109,6 +109,12 @@
<groupId>com.telecominfraproject.wlan</groupId>
<version>${tip-wlan-cloud.release.version}</version>
</dependency>
<dependency>
<artifactId>manufacturer-service-local</artifactId>
<groupId>com.telecominfraproject.wlan</groupId>
<version>${tip-wlan-cloud.release.version}</version>
</dependency>
<!-- prov services -->
<dependency>

View File

@@ -101,6 +101,12 @@
<groupId>com.telecominfraproject.wlan</groupId>
<version>${tip-wlan-cloud.release.version}</version>
</dependency>
<dependency>
<artifactId>manufacturer-service-local</artifactId>
<groupId>com.telecominfraproject.wlan</groupId>
<version>${tip-wlan-cloud.release.version}</version>
</dependency>
<!-- prov services -->
<dependency>

View File

@@ -3,287 +3,384 @@ package com.telecominfraproject.wlan.manufacturer.datastore;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.HashMap;
import java.util.List;
import java.util.Set;
import java.util.concurrent.atomic.AtomicLong;
import java.util.Map;
import java.util.zip.GZIPOutputStream;
import org.junit.Before;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
import com.telecominfraproject.wlan.core.model.pagination.ColumnAndSort;
import com.telecominfraproject.wlan.core.model.pagination.PaginationContext;
import com.telecominfraproject.wlan.core.model.pagination.PaginationResponse;
import com.telecominfraproject.wlan.core.model.pagination.SortOrder;
import com.telecominfraproject.wlan.core.model.json.GenericResponse;
import com.telecominfraproject.wlan.datastore.exceptions.DsConcurrentModificationException;
import com.telecominfraproject.wlan.datastore.exceptions.DsEntityNotFoundException;
import com.telecominfraproject.wlan.manufacturer.models.Manufacturer;
import com.telecominfraproject.wlan.manufacturer.models.ManufacturerDetails;
import com.telecominfraproject.wlan.manufacturer.models.ManufacturerDetailsRecord;
import com.telecominfraproject.wlan.manufacturer.models.ManufacturerOuiDetails;
/**
* @author dtoptygin
* @author mpreston
*
*/
public abstract class BaseManufacturerDatastoreTest {
@Autowired
protected ManufacturerDatastore testInterface;
private static final String TESTNAME = "testname";
private static final String TESTALIAS = "testalias";
private static final AtomicLong testSequence = new AtomicLong(1);
@Autowired private ManufacturerDatastoreInterface manufacturerDatastore;
@Before
public void setUp() {
// nothing
}
@Test
public void testCRUD() {
Manufacturer manufacturer = createManufacturerObject();
//create
Manufacturer created = testInterface.create(manufacturer);
assertNotNull(created);
assertTrue(created.getId() > 0);
assertEquals(manufacturer.getSampleStr(), created.getSampleStr());
assertEquals(manufacturer.getCustomerId(), created.getCustomerId());
assertNotNull(created.getDetails());
assertEquals(manufacturer.getDetails(), created.getDetails());
public void testClientManufacturerDetailsCRUD() {
final String companyName1 = "Complex Company Inc.";
final String companyName2 = "Simple Co.";
final String companyName3 = "Simplor Co.";
final String companyAlias1 = "Complex";
final String companyAlias2 = "Simple";
final String companyAlias3 = "Simplor";
// update
created.setSampleStr(created.getSampleStr()+"_updated");
Manufacturer updated = testInterface.update(created);
assertNotNull(updated);
assertEquals(created.getSampleStr(), updated.getSampleStr());
while(updated.getLastModifiedTimestamp() == created.getLastModifiedTimestamp()) {
//update again to make the timestamps different
created.setSampleStr(created.getSampleStr()+"_updated_1");
updated = testInterface.update(created);
}
//CREATE test
ManufacturerDetailsRecord manufacturerDetails = new ManufacturerDetailsRecord();
manufacturerDetails.setManufacturerName(companyName1);
manufacturerDetails.setManufacturerAlias(companyAlias1);
ManufacturerDetailsRecord ret = manufacturerDatastore.createManufacturerDetails(manufacturerDetails);
//GET by id
ret = manufacturerDatastore.getById(ret.getId());
assertTrue(manufacturerDetails.equals(ret));
// GET by manufacturer
List<ManufacturerDetailsRecord> resultList = manufacturerDatastore.getByManufacturer(companyName1, true);
assertTrue(manufacturerDetails.equals(resultList.get(0)));
resultList.clear();
resultList = manufacturerDatastore.getByManufacturer("Compl", false);
assertTrue(manufacturerDetails.equals(resultList.get(0)));
resultList.clear();
resultList = manufacturerDatastore.getByManufacturer("mpl", false);
assertTrue(resultList.isEmpty());
resultList.clear();
resultList = manufacturerDatastore.getByManufacturer("bad stuff here", false);
assertTrue(resultList.isEmpty());
//UPDATE test - success
manufacturerDetails = ret;
manufacturerDetails.setManufacturerAlias("New Alias");
ret = manufacturerDatastore.updateManufacturerDetails(manufacturerDetails);
assertTrue(manufacturerDetails.equals(ret));
//UPDATE test - fail because of concurrent modification exception
try{
Manufacturer modelConcurrentUpdate = created.clone();
modelConcurrentUpdate.setSampleStr("not important");
testInterface.update(modelConcurrentUpdate);
fail("failed to detect concurrent modification");
ManufacturerDetailsRecord manufacturerDetailsConcurrentUpdate = manufacturerDetails.clone();
manufacturerDetailsConcurrentUpdate.setLastModifiedTimestamp(manufacturerDetailsConcurrentUpdate.getLastModifiedTimestamp()-1);
manufacturerDetailsConcurrentUpdate.setManufacturerAlias("This should not work");
manufacturerDatastore.updateManufacturerDetails(manufacturerDetailsConcurrentUpdate);
fail("failed to detect concurrent modification");
}catch (DsConcurrentModificationException e) {
// expected it
// expected it
}
//retrieve
Manufacturer retrieved = testInterface.get(created.getId());
assertNotNull(retrieved);
assertEquals(retrieved.getLastModifiedTimestamp(), updated.getLastModifiedTimestamp());
ManufacturerDetailsRecord manufacturerDetails2 = new ManufacturerDetailsRecord();
manufacturerDetails2.setManufacturerName(companyName2);
manufacturerDetails2.setManufacturerAlias(companyAlias2);
ManufacturerDetailsRecord ret2 = manufacturerDatastore.createManufacturerDetails(manufacturerDetails2);
ManufacturerDetailsRecord manufacturerDetails3 = new ManufacturerDetailsRecord();
manufacturerDetails3.setManufacturerName(companyName3);
manufacturerDetails3.setManufacturerAlias(companyAlias3);
ManufacturerDetailsRecord ret3 = manufacturerDatastore.createManufacturerDetails(manufacturerDetails3);
// GET by manufacturer partial list
resultList.clear();
resultList = manufacturerDatastore.getByManufacturer("Simp", false);
assertEquals(2, resultList.size());
resultList.clear();
resultList = manufacturerDatastore.getByManufacturer("Simple", true);
assertEquals(1, resultList.size());
resultList.clear();
resultList = manufacturerDatastore.getByManufacturer("Simple", false);
assertEquals(1, resultList.size());
retrieved = testInterface.getOrNull(created.getId());
assertNotNull(retrieved);
assertEquals(retrieved.getLastModifiedTimestamp(), updated.getLastModifiedTimestamp());
//DELETE Test
manufacturerDatastore.deleteManufacturerDetails(ret.getId());
//retrieve non-existent
try {
testInterface.get(-1);
fail("retrieve non-existing record");
}catch(DsEntityNotFoundException e ){
//expected it
try{
manufacturerDatastore.deleteManufacturerDetails(ret.getId());
fail("failed to delete ClientManufacturerDetails");
}catch (Exception e) {
// expected it
}
assertNull(testInterface.getOrNull(-1));
//delete
retrieved = testInterface.delete(created.getId());
assertNotNull(retrieved);
//delete non-existent
try {
testInterface.delete(-1);
fail("delete non-existing record");
}catch(DsEntityNotFoundException e ){
//expected it
}
//update non-existent
try {
testInterface.update(retrieved);
fail("update non-existing record");
}catch(DsEntityNotFoundException e ){
//expected it
}
// Clean Up.
manufacturerDatastore.deleteManufacturerDetails(ret2.getId());
manufacturerDatastore.deleteManufacturerDetails(ret3.getId());
}
@Test
public void testGetAllInSet() {
Set<Manufacturer> createdSet = new HashSet<>();
Set<Manufacturer> createdTestSet = new HashSet<>();
//Create test Manufacturers
Manufacturer manufacturer = new Manufacturer();
for (int i = 0; i < 10; i++) {
manufacturer.setSampleStr("test_" + i);
manufacturer.setCustomerId(i);
Manufacturer ret = testInterface.create(manufacturer);
// Only keep track of half of the created ones for testing
if (i % 2 == 0) {
createdTestSet.add(ret.clone());
public void testOuiDatastoreOperations() {
final String companyName1 = "Complex Company Inc.";
final String companyName2 = "Simple Co.";
final String companyName3 = "Simplor Co.";
final String companyAlias1 = "Complex";
final String companyAlias2 = "Simple";
final String companyAlias3 = null;
final String oui1 = "0000a1";
final String oui2 = "0000a2";
final String oui3 = "0000a3";
// CREATE test
ManufacturerOuiDetails ouiDetails1 = new ManufacturerOuiDetails();
ouiDetails1.setOui(oui1);
ouiDetails1.setManufacturerName(companyName1);
ouiDetails1.setManufacturerAlias(companyAlias1);
ManufacturerOuiDetails ret1 = manufacturerDatastore.createOuiDetails(ouiDetails1);
assertTrue(ouiDetails1.equals(ret1));
// Make sure the details object was properly created as well.
ManufacturerDetailsRecord manufacturerDetailsRecord1 = manufacturerDatastore.getByManufacturer(companyName1, true).get(0);
assertTrue(manufacturerDetailsRecord1.getManufacturerName().equals(companyName1));
assertTrue(manufacturerDetailsRecord1.getManufacturerAlias().equals(companyAlias1));
// GET by oui test
ret1 = manufacturerDatastore.getByOui(oui1);
assertTrue(ouiDetails1.equals(ret1));
// GET mfr details id test
long mfrDetailsId = manufacturerDatastore.getManufacturerDetialsId(oui1);
ManufacturerDetailsRecord mfrDetialsRecord = manufacturerDatastore.getById(mfrDetailsId);
assertTrue(mfrDetialsRecord.getManufacturerAlias().equals(ret1.getManufacturerAlias()));
assertTrue(mfrDetialsRecord.getManufacturerName().equals(ret1.getManufacturerName()));
// GET Alias starts with test.
List<String> aliasList = manufacturerDatastore.getAliasValuesThatBeginWith("Com", -1);
assertEquals(1, aliasList.size());
assertTrue(aliasList.get(0).equals(companyAlias1));
aliasList = manufacturerDatastore.getAliasValuesThatBeginWith("Sim", 2000);
assertTrue(aliasList.isEmpty());
// GET by manufacturer tests
ManufacturerOuiDetails ouiDetails2 = new ManufacturerOuiDetails();
ouiDetails2.setOui(oui2);
ouiDetails2.setManufacturerName(companyName2);
ouiDetails2.setManufacturerAlias(companyAlias2);
ManufacturerOuiDetails ret2 = manufacturerDatastore.createOuiDetails(ouiDetails2);
ManufacturerOuiDetails ouiDetails3 = new ManufacturerOuiDetails();
ouiDetails3.setOui(oui3);
ouiDetails3.setManufacturerName(companyName3);
ouiDetails3.setManufacturerAlias(companyAlias3);
ManufacturerOuiDetails ret3 = manufacturerDatastore.createOuiDetails(ouiDetails3);
List<String> ouiResultList = manufacturerDatastore.getOuiListForManufacturer(companyName1, true);
assertEquals(1, ouiResultList.size());
assertTrue(ouiDetails1.equals(manufacturerDatastore.getByOui(ouiResultList.get(0))));
ouiResultList = manufacturerDatastore.getOuiListForManufacturer("Bad Name", true);
assertTrue(ouiResultList.isEmpty());
ouiResultList = manufacturerDatastore.getOuiListForManufacturer("Compl", false);
assertEquals(1, ouiResultList.size());
assertTrue(ouiDetails1.equals(manufacturerDatastore.getByOui(ouiResultList.get(0))));
ouiResultList = manufacturerDatastore.getOuiListForManufacturer("ompl", false);
assertTrue(ouiResultList.isEmpty());
ouiResultList = manufacturerDatastore.getOuiListForManufacturer("Simp", false);
assertEquals(2, ouiResultList.size());
for (int i = 0 ; i < ouiResultList.size(); i++) {
if (ouiResultList.get(i).equals(oui2)) {
assertTrue(ouiDetails2.equals(manufacturerDatastore.getByOui(ouiResultList.get(i))));
} else if (ouiResultList.get(i).equals(oui3)) {
assertTrue(ouiDetails3.equals(manufacturerDatastore.getByOui(ouiResultList.get(i))));
} else {
createdSet.add(ret.clone());
fail("Unknown OUI was found: " + ouiResultList.get(i));
}
}
// Use only the IDs from the test set to retrieve records.
Set<Long> testSetIds = new HashSet<>();
for (Manufacturer c : createdTestSet) {
testSetIds.add(c.getId());
// GET ALL Manufacturer data test
List<ManufacturerOuiDetails> allManufacturerData = manufacturerDatastore.getAllManufacturerData();
assertEquals(3, allManufacturerData.size());
for (int i = 0 ; i < allManufacturerData.size(); i++) {
if (allManufacturerData.get(i).getOui().equals(oui2)) {
assertTrue(ouiDetails2.equals(allManufacturerData.get(i)));
} else if (allManufacturerData.get(i).getOui().equals(oui3)) {
assertTrue(ouiDetails3.equals(allManufacturerData.get(i)));
} else if (allManufacturerData.get(i).getOui().equals(oui1)) {
assertTrue(ouiDetails1.equals(allManufacturerData.get(i)));
} else {
if (isTestRecord(allManufacturerData.get(i))) {
// This is the test record from the test data resources.
continue;
}
fail("Unknown OUI was found: " + ouiResultList.get(i));
}
}
assertEquals(5, testSetIds.size());
List<Manufacturer> manufacturersRetrievedByIdSet = testInterface.get(testSetIds);
assertEquals(5, manufacturersRetrievedByIdSet.size());
for (Manufacturer c : manufacturersRetrievedByIdSet) {
assertTrue(createdTestSet.contains(c));
// GET by OUI list test:
Map<String, ManufacturerOuiDetails> ouiListSearchResult = manufacturerDatastore.getManufacturerDetailsForOuiList(null);
assertTrue(ouiListSearchResult.isEmpty());
List<String> ouiList = new ArrayList<>();
ouiList.add(oui1);
ouiListSearchResult = manufacturerDatastore.getManufacturerDetailsForOuiList(ouiList);
assertEquals(1, ouiListSearchResult.size());
assertTrue(ouiListSearchResult.get(oui1).equals(ret1));
ouiList.add(oui2);
ouiListSearchResult = manufacturerDatastore.getManufacturerDetailsForOuiList(ouiList);
assertEquals(2, ouiListSearchResult.size());
assertTrue(ouiListSearchResult.get(oui1).equals(ret1));
assertTrue(ouiListSearchResult.get(oui2).equals(ret2));
ouiList.add(oui3);
ouiListSearchResult = manufacturerDatastore.getManufacturerDetailsForOuiList(ouiList);
assertEquals(3, ouiListSearchResult.size());
assertTrue(ouiListSearchResult.get(oui1).equals(ret1));
assertTrue(ouiListSearchResult.get(oui2).equals(ret2));
assertTrue(ouiListSearchResult.get(oui3).equals(ret3));
// CREATE without manufacturer fail test
ManufacturerOuiDetails badCreate = new ManufacturerOuiDetails();
badCreate.setOui(oui3);
badCreate.setManufacturerName(null);
badCreate.setManufacturerAlias(companyAlias2);
try {
ManufacturerOuiDetails badRet = manufacturerDatastore.createOuiDetails(badCreate);
fail("Should not be able to create OUI details with a null manufacturer name: " + badRet);
} catch (Exception e) {
// Expected
}
// Make sure the manufacturers from the non-test set are not in the list
for (Manufacturer c : manufacturersRetrievedByIdSet) {
assertTrue(!createdSet.contains(c));
badCreate.setManufacturerName("");
try {
ManufacturerOuiDetails badRet = manufacturerDatastore.createOuiDetails(badCreate);
fail("Should not be able to create OUI details with a blank manufacturer name: " + badRet);
} catch (Exception e) {
// Expected
}
// Clean up after test
for (Manufacturer c : createdSet) {
testInterface.delete(c.getId());
// DELETE test
manufacturerDatastore.deleteOuiDetails(ret1.getOui());
try{
manufacturerDatastore.deleteOuiDetails(ret1.getOui());
fail("failed to delete ClientOuiDetails");
}catch (Exception e) {
// expected it
}
for (Manufacturer c : createdTestSet) {
testInterface.delete(c.getId());
}
// Clean up:
manufacturerDatastore.deleteOuiDetails(ret2.getOui());
manufacturerDatastore.deleteOuiDetails(ret3.getOui());
}
@Test
public void testManufacturerPagination()
{
//create 100 Manufacturers
Manufacturer mdl;
int customerId_1 = (int) testSequence.incrementAndGet();
int customerId_2 = (int) testSequence.incrementAndGet();
int apNameIdx = 0;
for(int i = 0; i< 50; i++){
mdl = new Manufacturer();
mdl.setCustomerId(customerId_1);
mdl.setSampleStr("qr_"+apNameIdx);
apNameIdx++;
testInterface.create(mdl);
}
for(int i = 0; i< 50; i++){
mdl = new Manufacturer();
mdl.setCustomerId(customerId_2);
mdl.setSampleStr("qr_"+apNameIdx);
apNameIdx++;
testInterface.create(mdl);
}
//paginate over Manufacturers
List<ColumnAndSort> sortBy = new ArrayList<>();
sortBy.addAll(Arrays.asList(new ColumnAndSort("sampleStr")));
PaginationContext<Manufacturer> context = new PaginationContext<>(10);
PaginationResponse<Manufacturer> page1 = testInterface.getForCustomer(customerId_1, sortBy, context);
PaginationResponse<Manufacturer> page2 = testInterface.getForCustomer(customerId_1, sortBy, page1.getContext());
PaginationResponse<Manufacturer> page3 = testInterface.getForCustomer(customerId_1, sortBy, page2.getContext());
PaginationResponse<Manufacturer> page4 = testInterface.getForCustomer(customerId_1, sortBy, page3.getContext());
PaginationResponse<Manufacturer> page5 = testInterface.getForCustomer(customerId_1, sortBy, page4.getContext());
PaginationResponse<Manufacturer> page6 = testInterface.getForCustomer(customerId_1, sortBy, page5.getContext());
PaginationResponse<Manufacturer> page7 = testInterface.getForCustomer(customerId_1, sortBy, page6.getContext());
//verify returned pages
assertEquals(10, page1.getItems().size());
assertEquals(10, page2.getItems().size());
assertEquals(10, page3.getItems().size());
assertEquals(10, page4.getItems().size());
assertEquals(10, page5.getItems().size());
page1.getItems().forEach(e -> assertEquals(customerId_1, e.getCustomerId()) );
page2.getItems().forEach(e -> assertEquals(customerId_1, e.getCustomerId()) );
page3.getItems().forEach(e -> assertEquals(customerId_1, e.getCustomerId()) );
page4.getItems().forEach(e -> assertEquals(customerId_1, e.getCustomerId()) );
page5.getItems().forEach(e -> assertEquals(customerId_1, e.getCustomerId()) );
assertEquals(0, page6.getItems().size());
assertEquals(0, page7.getItems().size());
assertFalse(page1.getContext().isLastPage());
assertFalse(page2.getContext().isLastPage());
assertFalse(page3.getContext().isLastPage());
assertFalse(page4.getContext().isLastPage());
assertFalse(page5.getContext().isLastPage());
assertTrue(page6.getContext().isLastPage());
assertTrue(page7.getContext().isLastPage());
List<String> expectedPage3Strings = new ArrayList< >(Arrays.asList(new String[]{"qr_27", "qr_28", "qr_29", "qr_3", "qr_30", "qr_31", "qr_32", "qr_33", "qr_34", "qr_35" }));
List<String> actualPage3Strings = new ArrayList<>();
page3.getItems().stream().forEach( ce -> actualPage3Strings.add(ce.getSampleStr()) );
assertEquals(expectedPage3Strings, actualPage3Strings);
// System.out.println("================================");
// for(Manufacturer pmdl: page3.getItems()){
// System.out.println(pmdl);
// }
// System.out.println("================================");
// System.out.println("Context: "+ page3.getContext());
// System.out.println("================================");
//test first page of the results with empty sort order -> default sort order (by Id ascending)
PaginationResponse<Manufacturer> page1EmptySort = testInterface.getForCustomer(customerId_1, Collections.emptyList(), context);
assertEquals(10, page1EmptySort.getItems().size());
List<String> expectedPage1EmptySortStrings = new ArrayList<>(Arrays.asList(new String[]{"qr_0", "qr_1", "qr_2", "qr_3", "qr_4", "qr_5", "qr_6", "qr_7", "qr_8", "qr_9" }));
List<String> actualPage1EmptySortStrings = new ArrayList<>();
page1EmptySort.getItems().stream().forEach( ce -> actualPage1EmptySortStrings.add(ce.getSampleStr()) );
assertEquals(expectedPage1EmptySortStrings, actualPage1EmptySortStrings);
//test first page of the results with null sort order -> default sort order (by Id ascending)
PaginationResponse<Manufacturer> page1NullSort = testInterface.getForCustomer(customerId_1, null, context);
assertEquals(10, page1NullSort.getItems().size());
List<String> expectedPage1NullSortStrings = new ArrayList<>(Arrays.asList(new String[]{"qr_0", "qr_1", "qr_2", "qr_3", "qr_4", "qr_5", "qr_6", "qr_7", "qr_8", "qr_9" }));
List<String> actualPage1NullSortStrings = new ArrayList<>();
page1NullSort.getItems().stream().forEach( ce -> actualPage1NullSortStrings.add(ce.getSampleStr()) );
assertEquals(expectedPage1NullSortStrings, actualPage1NullSortStrings);
//test first page of the results with sort descending order by a sampleStr property
PaginationResponse<Manufacturer> page1SingleSortDesc = testInterface.getForCustomer(customerId_1, Collections.singletonList(new ColumnAndSort("sampleStr", SortOrder.desc)), context);
assertEquals(10, page1SingleSortDesc.getItems().size());
List<String> expectedPage1SingleSortDescStrings = new ArrayList< >(Arrays.asList(new String[]{"qr_9", "qr_8", "qr_7", "qr_6", "qr_5", "qr_49", "qr_48", "qr_47", "qr_46", "qr_45" }));
List<String> actualPage1SingleSortDescStrings = new ArrayList<>();
page1SingleSortDesc.getItems().stream().forEach( ce -> actualPage1SingleSortDescStrings.add(ce.getSampleStr()) );
assertEquals(expectedPage1SingleSortDescStrings, actualPage1SingleSortDescStrings);
public void testBadUpload() {
// Try to upload a invalid file
GenericResponse result = manufacturerDatastore.uploadOuiDataFile("This is Bad Data", new byte[] { 0x1, 0x2 });
assertFalse("uploaded bad file", result.isSuccess());
}
private Manufacturer createManufacturerObject() {
Manufacturer result = new Manufacturer();
long nextId = testSequence.getAndIncrement();
result.setCustomerId((int) nextId);
result.setSampleStr("test-" + nextId);
ManufacturerDetails details = new ManufacturerDetails();
details.setSampleDetailsStr("test-details-" + nextId);
result.setDetails(details );
return result;
@Test
public void testPopulateOuiDatastore() throws IOException {
Map<String, String> knownTestMacs = new HashMap<>();
knownTestMacs.put("bc3aea", "GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD");
knownTestMacs.put("e8bba8", "GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD");
knownTestMacs.put("8c0ee3", "GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD");
knownTestMacs.put("7c4ca5", "BSkyB Ltd");
knownTestMacs.put("0012f2", "Brocade Communications Systems, Inc.");
knownTestMacs.put("001bed", "Brocade Communications Systems, Inc.");
knownTestMacs.put("002438", "Brocade Communications Systems, Inc.");
knownTestMacs.put("8ce748", "Private (8CE748)");
knownTestMacs.put("0084ed", "Private (0084ED)");
final String filePath = "test-oui.txt";
InputStream inFile = BaseManufacturerDatastoreTest.class.getResource(filePath).openStream();
ByteArrayOutputStream compressedStream = new ByteArrayOutputStream();
GZIPOutputStream gzOut = new GZIPOutputStream(compressedStream);
byte[] buffer = new byte[512];
while(inFile.available() > 0) {
int read = inFile.read(buffer);
gzOut.write(buffer, 0, read);
}
gzOut.finish();
manufacturerDatastore.uploadOuiDataFile(filePath, compressedStream.toByteArray());
List<ManufacturerOuiDetails> entireMfrDatastore = manufacturerDatastore.getAllManufacturerData();
assertNotNull(entireMfrDatastore);
assertEquals(knownTestMacs.size(), entireMfrDatastore.size());
for (ManufacturerOuiDetails record : entireMfrDatastore) {
if (knownTestMacs.containsKey(record.getOui())) {
if (record.getManufacturerName().equals(knownTestMacs.get(record.getOui()))) {
continue;
}
fail("Incorrect mfr name found. Expected: " + knownTestMacs.get(record.getOui()) + ", found: " + record.getManufacturerName());
} else {
if (isTestRecord(record)) {
// This is the test record from the test data resources.
continue;
}
fail("Unknown OUI was found: " + record);
}
}
// Populate it again with the same file, verify the results are the same
manufacturerDatastore.uploadOuiDataFile(filePath, compressedStream.toByteArray());
entireMfrDatastore.clear();
entireMfrDatastore = manufacturerDatastore.getAllManufacturerData();
assertEquals(knownTestMacs.size(), entireMfrDatastore.size());
for (ManufacturerOuiDetails record : entireMfrDatastore) {
if (knownTestMacs.containsKey(record.getOui())) {
if (record.getManufacturerName().equals(knownTestMacs.get(record.getOui()))) {
continue;
}
fail("Incorrect mfr name found. Expected: " + knownTestMacs.get(record.getOui()) + ", found: " + record.getManufacturerName());
} else {
if (isTestRecord(record)) {
// This is the test record from the test data resources.
continue;
}
fail("Unknown OUI was found: " + record);
}
}
// Clean up:
for(ManufacturerOuiDetails record : entireMfrDatastore) {
if (knownTestMacs.containsKey(record.getOui())) {
manufacturerDatastore.deleteOuiDetails(record.getOui());
} else {
if (isTestRecord(record)) {
// This is the test record from the test data resources.
continue;
}
fail("Unknown OUI was found: " + record);
}
}
}
private boolean isTestRecord(ManufacturerOuiDetails record) {
return (record != null) && TESTNAME.equals(record.getManufacturerName())
&& TESTALIAS.equals(record.getManufacturerAlias());
}
}

View File

@@ -0,0 +1,51 @@
OUI/MA-L Organization
company_id Organization
Address
BC-3A-EA (hex) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD
BC3AEA (base 16) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD
NO.18 HAIBIN ROAD,WUSHA,CHANG'AN,DONGGUAN,GUANGDONG,CHINA
DONGGUAN GUANGDONG 523860
CN
E8-BB-A8 (hex) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD
E8BBA8 (base 16) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD
NO.18 HAIBIN ROAD,WUSHA,CHANG'AN,DONGGUAN,GUANGDONG,CHINA
DONGGUAN GUANGDONG 523860
CN
8C-0E-E3 (hex) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD
8C0EE3 (base 16) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD
NO.18 HAIBIN ROAD,WUSHA,CHANG'AN
DONGGUAN GUANGDONG 523860
CN
7C-4C-A5 (hex) BSkyB Ltd
7C4CA5 (base 16) BSkyB Ltd
130 Kings Road
Brentwood Essex CM14 4EQ
GB
00-12-F2 (hex) Brocade Communications Systems, Inc.
0012F2 (base 16) Brocade Communications Systems, Inc.
130 Holger Way
San Jose CA 95134
US
00-1B-ED (hex) Brocade Communications Systems, Inc.
001BED (base 16) Brocade Communications Systems, Inc.
130 Holger Way
San Jose CA 95134
US
00-24-38 (hex) Brocade Communications Systems, Inc.
002438 (base 16) Brocade Communications Systems, Inc.
130 Holger Way
San Jose CA 95134
US
8C-E7-48 (hex) Private
8CE748 (base 16) Private
00-84-ED (hex) Private
0084ED (base 16) Private

View File

@@ -1,245 +1,348 @@
package com.telecominfraproject.wlan.manufacturer.datastore.inmemory;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.LinkedList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Map.Entry;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicLong;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.zip.GZIPInputStream;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Configuration;
import org.springframework.util.CollectionUtils;
import com.telecominfraproject.wlan.core.model.pagination.ColumnAndSort;
import com.telecominfraproject.wlan.core.model.pagination.PaginationContext;
import com.telecominfraproject.wlan.core.model.pagination.PaginationResponse;
import com.telecominfraproject.wlan.core.model.pagination.SortOrder;
import com.telecominfraproject.wlan.core.model.json.GenericResponse;
import com.telecominfraproject.wlan.datastore.exceptions.DsConcurrentModificationException;
import com.telecominfraproject.wlan.datastore.exceptions.DsDataValidationException;
import com.telecominfraproject.wlan.datastore.exceptions.DsDuplicateEntityException;
import com.telecominfraproject.wlan.datastore.exceptions.DsEntityNotFoundException;
import com.telecominfraproject.wlan.datastore.inmemory.BaseInMemoryDatastore;
import com.telecominfraproject.wlan.manufacturer.datastore.ManufacturerDatastore;
import com.telecominfraproject.wlan.manufacturer.models.Manufacturer;
import com.telecominfraproject.wlan.manufacturer.datastore.ManufacturerDatastoreInterface;
import com.telecominfraproject.wlan.manufacturer.datastore.ManufacturerDatastoreUtilities;
import com.telecominfraproject.wlan.manufacturer.models.ManufacturerDetailsRecord;
import com.telecominfraproject.wlan.manufacturer.models.ManufacturerOuiDetails;
/**
* @author dtoptygin
* @author mpreston
*
*/
@Configuration
public class ManufacturerDatastoreInMemory extends BaseInMemoryDatastore implements ManufacturerDatastore {
public class ManufacturerDatastoreInMemory extends BaseInMemoryDatastore implements ManufacturerDatastoreInterface {
private static final Logger LOG = LoggerFactory.getLogger(ManufacturerDatastoreInMemory.class);
private static final Map<Long, Manufacturer> idToManufacturerMap = new ConcurrentHashMap<Long, Manufacturer>();
private static final AtomicLong manufacturerIdCounter = new AtomicLong();
private final Map<String, Long> ouiToManufacturerDetailsMap = new ConcurrentHashMap<>();
private final Map<Long, ManufacturerDetailsRecord> idToManufacturerDetailsRecordMap = new ConcurrentHashMap<>();
@Override
public Manufacturer create(Manufacturer manufacturer) {
Manufacturer manufacturerCopy = manufacturer.clone();
long id = manufacturerIdCounter.incrementAndGet();
manufacturerCopy.setId(id);
manufacturerCopy.setCreatedTimestamp(System.currentTimeMillis());
manufacturerCopy.setLastModifiedTimestamp(manufacturerCopy.getCreatedTimestamp());
idToManufacturerMap.put(id, manufacturerCopy);
LOG.debug("Stored Manufacturer {}", manufacturerCopy);
return manufacturerCopy.clone();
}
@Override
public Manufacturer get(long manufacturerId) {
LOG.debug("Looking up Manufacturer for id {}", manufacturerId);
Manufacturer manufacturer = idToManufacturerMap.get(manufacturerId);
if(manufacturer==null){
LOG.debug("Cannot find Manufacturer for id {}", manufacturerId);
throw new DsEntityNotFoundException("Cannot find Manufacturer for id " + manufacturerId);
} else {
LOG.debug("Found Manufacturer {}", manufacturer);
}
return manufacturer.clone();
}
@Override
public Manufacturer getOrNull(long manufacturerId) {
LOG.debug("Looking up Manufacturer for id {}", manufacturerId);
Manufacturer manufacturer = idToManufacturerMap.get(manufacturerId);
if(manufacturer==null){
LOG.debug("Cannot find Manufacturer for id {}", manufacturerId);
return null;
} else {
LOG.debug("Found Manufacturer {}", manufacturer);
}
return manufacturer.clone();
}
private static AtomicLong clientManufacturerDetailsIdCounter = new AtomicLong(0);
@Override
public Manufacturer update(Manufacturer manufacturer) {
Manufacturer existingManufacturer = get(manufacturer.getId());
if(existingManufacturer.getLastModifiedTimestamp()!=manufacturer.getLastModifiedTimestamp()){
LOG.debug("Concurrent modification detected for Manufacturer with id {} expected version is {} but version in db was {}",
manufacturer.getId(),
manufacturer.getLastModifiedTimestamp(),
existingManufacturer.getLastModifiedTimestamp()
);
throw new DsConcurrentModificationException("Concurrent modification detected for Manufacturer with id " + manufacturer.getId()
+" expected version is " + manufacturer.getLastModifiedTimestamp()
+" but version in db was " + existingManufacturer.getLastModifiedTimestamp()
);
public ManufacturerOuiDetails createOuiDetails(ManufacturerOuiDetails ouiDetails) {
if (ouiDetails.getManufacturerName() == null || ouiDetails.getManufacturerName().isEmpty()) {
throw new DsDataValidationException("Unable to create ManufacturerOuiDetails when no Manufacturer name is provided.");
}
Manufacturer manufacturerCopy = manufacturer.clone();
manufacturerCopy.setLastModifiedTimestamp(getNewLastModTs(manufacturer.getLastModifiedTimestamp()));
idToManufacturerMap.put(manufacturerCopy.getId(), manufacturerCopy);
LOG.debug("Updated Manufacturer {}", manufacturerCopy);
return manufacturerCopy.clone();
}
@Override
public Manufacturer delete(long manufacturerId) {
Manufacturer manufacturer = get(manufacturerId);
idToManufacturerMap.remove(manufacturer.getId());
LOG.debug("Deleted Manufacturer {}", manufacturer);
return manufacturer.clone();
}
@Override
public List<Manufacturer> get(Set<Long> manufacturerIdSet) {
List<Manufacturer> ret = new ArrayList<>();
if(manufacturerIdSet!=null && !manufacturerIdSet.isEmpty()) {
idToManufacturerMap.forEach(
(id, c) -> {
if(manufacturerIdSet.contains(id)) {
ret.add(c.clone());
} }
);
}
LOG.debug("Found Manufacturers by ids {}", ret);
return ret;
}
@Override
public PaginationResponse<Manufacturer> getForCustomer(int customerId,
final List<ColumnAndSort> sortBy, PaginationContext<Manufacturer> context) {
if(context == null) {
context = new PaginationContext<>();
}
PaginationResponse<Manufacturer> ret = new PaginationResponse<>();
ret.setContext(context.clone());
if (ret.getContext().isLastPage()) {
// no more pages available according to the context
return ret;
Long existingDetailsId = ouiToManufacturerDetailsMap.get(ouiDetails.getOui().toLowerCase());
if (existingDetailsId != null) {
throw new DsDuplicateEntityException("Unable to create ManufacturerOuiDetails for an OUI that already exists.");
}
List<Manufacturer> items = new LinkedList<>();
// apply filters and build the full result list first - inefficient, but ok for testing
for (Manufacturer mdl : idToManufacturerMap.values()) {
if (mdl.getCustomerId() != customerId) {
continue;
}
items.add(mdl);
}
// apply sortBy columns
Collections.sort(items, new Comparator<Manufacturer>() {
@Override
public int compare(Manufacturer o1, Manufacturer o2) {
if (sortBy == null || sortBy.isEmpty()) {
// sort ascending by id by default
return Long.compare(o1.getId(), o2.getId());
} else {
int cmp;
for (ColumnAndSort column : sortBy) {
switch (column.getColumnName()) {
case "id":
cmp = Long.compare(o1.getId(), o2.getId());
break;
case "sampleStr":
cmp = o1.getSampleStr().compareTo(o2.getSampleStr());
break;
default:
// skip unknown column
continue;
}
if (cmp != 0) {
return (column.getSortOrder() == SortOrder.asc) ? cmp : (-cmp);
}
}
}
return 0;
}
});
// now select only items for the requested page
// find first item to add
int fromIndex = 0;
if (context.getStartAfterItem() != null) {
for (Manufacturer mdl : items) {
fromIndex++;
if (mdl.getId() == context.getStartAfterItem().getId()) {
// Check to see if there is already Manufacturer details for this manufacturer:
ManufacturerDetailsRecord manufacturerDetails = null;
String manufacturerName = ManufacturerDatastoreUtilities.getByManufacturerName(ouiDetails.getOui(), ouiDetails.getManufacturerName());
List<ManufacturerDetailsRecord> manufacturerDetailList = getByManufacturer(manufacturerName, true);
if (!manufacturerDetailList.isEmpty()) {
// we will use the one match the name, not the alias because alias can change.
for (ManufacturerDetailsRecord detail: manufacturerDetailList) {
if (detail.getManufacturerName().equalsIgnoreCase(manufacturerName)) {
manufacturerDetails = detail;
break;
}
}
}
if (null == manufacturerDetails) {
// There was no existing manufacturer details entry. create that,
// then create the OU entry.
manufacturerDetails = new ManufacturerDetailsRecord();
manufacturerDetails.setManufacturerName(manufacturerName);
manufacturerDetails.setManufacturerAlias(ouiDetails.getManufacturerAlias());
manufacturerDetails = createManufacturerDetails(manufacturerDetails);
}
ouiToManufacturerDetailsMap.put(ouiDetails.getOui().toLowerCase(), manufacturerDetails.getId());
LOG.debug("Stored ClientOuiDetails {}", ouiDetails);
return ouiDetails.clone();
}
@Override
public ManufacturerOuiDetails deleteOuiDetails(String oui) {
ManufacturerOuiDetails clientOuiDetails = getByOui(oui);
ouiToManufacturerDetailsMap.remove(clientOuiDetails.getOui().toLowerCase());
LOG.debug("Deleted ManufacturerOuiDetails {}", clientOuiDetails);
return clientOuiDetails.clone();
}
@Override
public List<String> getOuiListForManufacturer(String manufacturer, boolean exactMatch) {
List<ManufacturerDetailsRecord> detailsRecordList = getByManufacturer(manufacturer, exactMatch);
List<String> resultList = new ArrayList<>();
for (Entry<String, Long> ouiEntry : ouiToManufacturerDetailsMap.entrySet()) {
for (ManufacturerDetailsRecord record : detailsRecordList) {
if (ouiEntry.getValue() == record.getId()) {
resultList.add(ouiEntry.getKey());
}
}
}
return resultList;
}
@Override
public ManufacturerOuiDetails getByOui(String oui) {
Long detailsId = ouiToManufacturerDetailsMap.get(oui.toLowerCase());
if (null == detailsId) {
LOG.debug("Unable to find ManufacturerDetailsRecord with oui {}", oui);
throw new DsEntityNotFoundException("ManufacturerDetailsRecord not found for OUI " + oui);
}
ManufacturerOuiDetails result = new ManufacturerOuiDetails();
result.setOui(oui);
ManufacturerDetailsRecord detailsRecord = idToManufacturerDetailsRecordMap.get(detailsId);
result.setManufacturerName(detailsRecord.getManufacturerName());
result.setManufacturerAlias(detailsRecord.getManufacturerAlias());
LOG.debug("Found ManufacturerOuiDetails {}", result);
return result;
}
@Override
public ManufacturerDetailsRecord createManufacturerDetails(
ManufacturerDetailsRecord clientManufacturerDetails) {
long id = clientManufacturerDetailsIdCounter.incrementAndGet();
clientManufacturerDetails.setId(id);
clientManufacturerDetails.setCreatedTimestamp(System.currentTimeMillis());
clientManufacturerDetails.setLastModifiedTimestamp(clientManufacturerDetails.getCreatedTimestamp());
idToManufacturerDetailsRecordMap.put(id, clientManufacturerDetails);
ManufacturerDetailsRecord clientManufacturerDetailsCopy = clientManufacturerDetails.clone();
LOG.debug("Stored Manufacturer details {}", clientManufacturerDetailsCopy);
return clientManufacturerDetailsCopy;
}
@Override
public ManufacturerDetailsRecord updateManufacturerDetails(
ManufacturerDetailsRecord clientManufacturerDetails) {
ManufacturerDetailsRecord existingClientManufacturerDetails = getById(clientManufacturerDetails.getId());
if(existingClientManufacturerDetails.getLastModifiedTimestamp()!=clientManufacturerDetails.getLastModifiedTimestamp()){
LOG.debug("Concurrent modification detected for ManufacturerDetailsRecord with id {} expected version is {} but version in db was {}",
clientManufacturerDetails.getId(),
clientManufacturerDetails.getLastModifiedTimestamp(),
existingClientManufacturerDetails.getLastModifiedTimestamp()
);
throw new DsConcurrentModificationException("Concurrent modification detected for ManufacturerDetailsRecord with id " + clientManufacturerDetails.getId()
+" expected version is " + clientManufacturerDetails.getLastModifiedTimestamp()
+" but version in db was " + existingClientManufacturerDetails.getLastModifiedTimestamp()
);
// find last item to add
int toIndexExclusive = fromIndex + context.getMaxItemsPerPage();
if (toIndexExclusive > items.size()) {
toIndexExclusive = items.size();
}
// copy page items into result
List<Manufacturer> selectedItems = new ArrayList<>(context.getMaxItemsPerPage());
for (Manufacturer mdl : items.subList(fromIndex, toIndexExclusive)) {
selectedItems.add(mdl.clone());
ManufacturerDetailsRecord clientManufacturerDetailsCopy = clientManufacturerDetails.clone();
clientManufacturerDetailsCopy.setLastModifiedTimestamp(getNewLastModTs(clientManufacturerDetails.getLastModifiedTimestamp()));
idToManufacturerDetailsRecordMap.put(clientManufacturerDetailsCopy.getId(), clientManufacturerDetailsCopy);
LOG.debug("Updated ManufacturerDetailsRecord {}", clientManufacturerDetailsCopy);
return clientManufacturerDetailsCopy.clone();
}
@Override
public ManufacturerDetailsRecord deleteManufacturerDetails(long id) {
ManufacturerDetailsRecord clientManufacturerDetails = getById(id);
idToManufacturerDetailsRecordMap.remove(clientManufacturerDetails.getId());
LOG.debug("Deleted ManufacturerDetailsRecord {}", clientManufacturerDetails);
return clientManufacturerDetails;
}
@Override
public ManufacturerDetailsRecord getById(long id) {
ManufacturerDetailsRecord existingRecord = idToManufacturerDetailsRecordMap.get(id);
if (existingRecord == null) {
LOG.debug("Unable to find ManufacturerDetailsRecord with id {}", id);
throw new DsEntityNotFoundException("ManufacturerDetailsRecord not found " + id);
}
LOG.debug("Found ManufacturerDetailsRecord {}", existingRecord);
return existingRecord.clone();
}
ret.setItems(selectedItems);
// adjust context for the next page
ret.prepareForNextPage();
if(ret.getContext().getStartAfterItem()!=null) {
//this datastore is only interested in the last item's id, so we'll clear all other fields on the startAfterItem in the pagination context
Manufacturer newStartAfterItem = new Manufacturer();
newStartAfterItem.setId(ret.getContext().getStartAfterItem().getId());
ret.getContext().setStartAfterItem(newStartAfterItem);
@Override
public List<ManufacturerDetailsRecord> getByManufacturer(String manufacturer, boolean exactMatch) {
List<ManufacturerDetailsRecord> resultList = new ArrayList<>();
for (ManufacturerDetailsRecord record : idToManufacturerDetailsRecordMap.values()) {
if (exactMatch) {
if (record.getManufacturerName().equals(manufacturer)) {
resultList.add(record.clone());
} else if (record.getManufacturerAlias() != null && record.getManufacturerAlias().equals(manufacturer)) {
resultList.add(record.clone());
}
} else {
if (record.getManufacturerName().startsWith(manufacturer)) {
resultList.add(record.clone());
} else if (record.getManufacturerAlias() != null && record.getManufacturerAlias().startsWith(manufacturer)) {
resultList.add(record.clone());
}
}
}
LOG.debug("Found {} ManufacturerDetailsRecords", resultList.size());
return resultList;
}
@Override
public List<ManufacturerOuiDetails> getAllManufacturerData() {
List<ManufacturerOuiDetails> result = new ArrayList<>();
for (Entry<String, Long> entry : ouiToManufacturerDetailsMap.entrySet()) {
long detailsId = entry.getValue();
ManufacturerOuiDetails addItem = new ManufacturerOuiDetails();
addItem.setOui(entry.getKey());
ManufacturerDetailsRecord detailsRecord = idToManufacturerDetailsRecordMap.get(detailsId);
addItem.setManufacturerName(detailsRecord.getManufacturerName());
addItem.setManufacturerAlias(detailsRecord.getManufacturerAlias());
result.add(addItem);
}
LOG.debug("Found {} ManufacturerOuiDetails", result.size());
return result;
}
@Override
public GenericResponse uploadOuiDataFile(String filePath, byte[] gzipContent) {
Pattern ouiPattern = Pattern.compile("^[0-9A-F]{6}");
Pattern companyPattern = Pattern.compile("[\t ]([^\t]+)$");
try
{
InputStream in = new GZIPInputStream(new ByteArrayInputStream(gzipContent));
BufferedReader input = new BufferedReader(new InputStreamReader(in));
while(input.ready())
{
String line = input.readLine();
Matcher matcher = ouiPattern.matcher(line);
if(matcher.find())
{
String prefix = line.substring(matcher.start(), matcher.end());
Matcher companyMatcher = companyPattern.matcher(line);
if(companyMatcher.find())
{
String company = line.substring(companyMatcher.start() + 1, companyMatcher.end());
ManufacturerOuiDetails addDetails = new ManufacturerOuiDetails();
addDetails.setOui(prefix);
addDetails.setManufacturerName(company);
createOuiDetails(addDetails);
}
}
}
}
catch(Exception e)
{
GenericResponse response = new GenericResponse();
response.setSuccess(false);
response.setMessage("Failed to load " + filePath + " resource for Mac datastore population: " + e.getLocalizedMessage());
return response;
}
GenericResponse response = new GenericResponse();
response.setSuccess(true);
return response;
}
@Override
public Map<String, ManufacturerOuiDetails> getManufacturerDetailsForOuiList(List<String> ouiList) {
Map<String, ManufacturerOuiDetails> result = new HashMap<>();
if (CollectionUtils.isEmpty(ouiList)) {
return result;
}
for (Entry<String, Long> entry : ouiToManufacturerDetailsMap.entrySet()) {
if (ouiList.contains(entry.getKey())) {
long detailsId = entry.getValue();
ManufacturerOuiDetails addItem = new ManufacturerOuiDetails();
addItem.setOui(entry.getKey());
ManufacturerDetailsRecord detailsRecord = idToManufacturerDetailsRecordMap.get(detailsId);
addItem.setManufacturerName(detailsRecord.getManufacturerName());
addItem.setManufacturerAlias(detailsRecord.getManufacturerAlias());
result.put(entry.getKey(), addItem);
}
}
LOG.debug("Found {} ManufacturerOuiDetails for OUI list", result.size());
return result;
}
@Override
public long getManufacturerDetialsId(String oui) {
Long retrievedResult = ouiToManufacturerDetailsMap.get(oui);
if (retrievedResult != null) {
return retrievedResult;
}
return -1;
}
@Override
public List<String> getAliasValuesThatBeginWith(String prefix, int maxResults) {
List<String> result = new ArrayList<>();
if (maxResults < 0 || maxResults > 1000) {
maxResults = 1000;
}
for (ManufacturerDetailsRecord rec : idToManufacturerDetailsRecordMap.values()) {
if (result.size() >= maxResults) {
break;
}
if (rec.getManufacturerAlias() != null && rec.getManufacturerAlias().startsWith(prefix)) {
result.add(rec.getManufacturerAlias());
}
}
return result;
}
return ret;
}
}

View File

@@ -7,7 +7,6 @@ import org.springframework.context.annotation.Import;
import org.springframework.test.context.junit4.SpringRunner;
import com.telecominfraproject.wlan.manufacturer.datastore.BaseManufacturerDatastoreTest;
import com.telecominfraproject.wlan.manufacturer.datastore.inmemory.ManufacturerDatastoreInMemory;
/**
* @author dtoptygin

View File

@@ -1,51 +0,0 @@
package com.telecominfraproject.wlan.manufacturer.datastore;
import java.util.List;
import java.util.Set;
import com.telecominfraproject.wlan.core.model.pagination.ColumnAndSort;
import com.telecominfraproject.wlan.core.model.pagination.PaginationContext;
import com.telecominfraproject.wlan.core.model.pagination.PaginationResponse;
import com.telecominfraproject.wlan.manufacturer.models.Manufacturer;
/**
* @author dtoptygin
*
*/
public interface ManufacturerDatastore {
Manufacturer create(Manufacturer manufacturer);
Manufacturer get(long manufacturerId);
Manufacturer getOrNull(long manufacturerId);
Manufacturer update(Manufacturer manufacturer);
Manufacturer delete(long manufacturerId);
/**
* Retrieves a list of Manufacturer records that which have their Id in the provided set.
*
* @param manufacturerIdSet
* @return list of matching Manufacturer objects.
*/
List<Manufacturer> get(Set<Long> manufacturerIdSet);
/**
* <br>Retrieves all of the Manufacturer records that are mapped to the provided customerId.
* Results are returned in pages.
*
* <br>When changing sort order or filters, pagination should be restarted again from the first page.
* Old pagination contexts would be invalid and should not be used in that case.
* <br>The only time when a caller should be interacting with the properties of the paginationContext is during the
* call to the first page by setting property maxItemsPerPage.
* <br>If initial context is not provided, then the maxItemsPerPage will be set to 20.
* <br>If sortBy is not provided, then the data will be ordered by id.
* <ul>Allowed columns for sorting are:
*<li> "id"
*<li> "sampleStr"
*<br>
* @param customerId
* @return next page of matching Manufacturer objects.
*/
PaginationResponse<Manufacturer> getForCustomer(int customerId, List<ColumnAndSort> sortBy, PaginationContext<Manufacturer> context);
}

View File

@@ -0,0 +1,33 @@
package com.telecominfraproject.wlan.manufacturer.datastore;
import java.util.List;
import java.util.Map;
import com.telecominfraproject.wlan.core.model.json.GenericResponse;
import com.telecominfraproject.wlan.manufacturer.models.ManufacturerDetailsRecord;
import com.telecominfraproject.wlan.manufacturer.models.ManufacturerOuiDetails;
/**
* @author mpreston
*
*/
public interface ManufacturerDatastoreInterface {
ManufacturerOuiDetails createOuiDetails(ManufacturerOuiDetails ouiDetails);
ManufacturerOuiDetails deleteOuiDetails(String oui);
List<String> getOuiListForManufacturer(String manufacturer, boolean exactMatch);
ManufacturerOuiDetails getByOui(String oui);
ManufacturerDetailsRecord createManufacturerDetails(ManufacturerDetailsRecord clientManufacturerDetails);
ManufacturerDetailsRecord updateManufacturerDetails(ManufacturerDetailsRecord clientManufacturerDetails);
ManufacturerDetailsRecord deleteManufacturerDetails(long id);
ManufacturerDetailsRecord getById(long id);
List<ManufacturerDetailsRecord> getByManufacturer(String manufacturer, boolean exactMatch);
List<ManufacturerOuiDetails> getAllManufacturerData();
GenericResponse uploadOuiDataFile(String filePath, byte[] gzipContent);
Map<String, ManufacturerOuiDetails> getManufacturerDetailsForOuiList(List<String> ouiList);
long getManufacturerDetialsId(String oui);
List<String> getAliasValuesThatBeginWith(String prefix, int maxResults);
}

View File

@@ -0,0 +1,35 @@
package com.telecominfraproject.wlan.manufacturer.datastore;
/**
* Utility Class
*
* @author yongli
*
*/
public class ManufacturerDatastoreUtilities {
/**
* We will construct the manufacture name for Private with Private (OUI)
*/
public static final String PRIVATE_MANUFACTURER_NAME = "Private";
private ManufacturerDatastoreUtilities() {
}
/**
* Process Manufacturer name. It will generate a new one if the name is
* {@value PRIVATE_MANUFACTURER_NAME}. In all other case it will simply
* trim the string.
*
* @param originOUI
* @param originName
* @return formated result
*/
public static String getByManufacturerName(final String originOUI, final String originName) {
String result = originName.trim();
if (PRIVATE_MANUFACTURER_NAME.equalsIgnoreCase(result)) {
result = String.format("%s (%s)", PRIVATE_MANUFACTURER_NAME, originOUI);
}
return result;
}
}

View File

@@ -1,445 +0,0 @@
package com.telecominfraproject.wlan.manufacturer.datastore.rdbms;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import javax.sql.DataSource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.dao.EmptyResultDataAccessException;
import org.springframework.jdbc.core.PreparedStatementCreator;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.jdbc.support.GeneratedKeyHolder;
import org.springframework.jdbc.support.KeyHolder;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import com.telecominfraproject.wlan.core.model.pagination.ColumnAndSort;
import com.telecominfraproject.wlan.core.model.pagination.PaginationContext;
import com.telecominfraproject.wlan.core.model.pagination.PaginationResponse;
import com.telecominfraproject.wlan.core.model.pagination.SortOrder;
import com.telecominfraproject.wlan.core.server.jdbc.BaseJdbcDao;
import com.telecominfraproject.wlan.datastore.exceptions.DsConcurrentModificationException;
import com.telecominfraproject.wlan.datastore.exceptions.DsDuplicateEntityException;
import com.telecominfraproject.wlan.datastore.exceptions.DsEntityNotFoundException;
import com.telecominfraproject.wlan.manufacturer.models.Manufacturer;
/**
* @author dtoptygin
*
*/
@Repository
@Transactional(propagation = Propagation.MANDATORY)
public class ManufacturerDAO extends BaseJdbcDao {
private static final Logger LOG = LoggerFactory.getLogger(ManufacturerDatastoreRdbms.class);
private static final String COL_ID = "id";
private static final String[] GENERATED_KEY_COLS = { COL_ID };
private static final String[] ALL_COLUMNS_LIST = {
COL_ID,
//TODO: add colums from properties Manufacturer in here
"customerId",
"sampleStr",
"details",
//make sure the order of properties matches this list and list in ManufacturerRowMapper and list in create/update methods
"createdTimestamp",
"lastModifiedTimestamp"
};
private static final Set<String> columnsToSkipForInsert = new HashSet<>(Arrays.asList(COL_ID));
private static final Set<String> columnsToSkipForUpdate = new HashSet<>(Arrays.asList(COL_ID, "createdTimestamp"));
private static final String TABLE_NAME = "manufacturer";
private static final String TABLE_PREFIX = "s.";
private static final String ALL_COLUMNS;
private static final Set<String> ALL_COLUMNS_LOWERCASE = new HashSet<>();
@SuppressWarnings("unused")
//use this for queries where multiple tables are involved
private static final String ALL_COLUMNS_WITH_PREFIX;
private static final String ALL_COLUMNS_FOR_INSERT;
private static final String BIND_VARS_FOR_INSERT;
private static final String ALL_COLUMNS_UPDATE;
static{
StringBuilder strbAllColumns = new StringBuilder(1024);
StringBuilder strbAllColumnsWithPrefix = new StringBuilder(1024);
StringBuilder strbAllColumnsForInsert = new StringBuilder(1024);
StringBuilder strbBindVarsForInsert = new StringBuilder(128);
StringBuilder strbColumnsForUpdate = new StringBuilder(512);
for(String colName: ALL_COLUMNS_LIST){
ALL_COLUMNS_LOWERCASE.add(colName.toLowerCase());
strbAllColumns.append(colName).append(",");
strbAllColumnsWithPrefix.append(TABLE_PREFIX).append(colName).append(",");
if(!columnsToSkipForInsert.contains(colName)){
strbAllColumnsForInsert.append(colName).append(",");
strbBindVarsForInsert.append("?,");
}
if(!columnsToSkipForUpdate.contains(colName)){
strbColumnsForUpdate.append(colName).append("=?,");
}
}
// remove trailing ','
strbAllColumns.deleteCharAt(strbAllColumns.length() - 1);
strbAllColumnsWithPrefix.deleteCharAt(strbAllColumnsWithPrefix.length() - 1);
strbAllColumnsForInsert.deleteCharAt(strbAllColumnsForInsert.length() - 1);
strbBindVarsForInsert.deleteCharAt(strbBindVarsForInsert.length() - 1);
strbColumnsForUpdate.deleteCharAt(strbColumnsForUpdate.length() - 1);
ALL_COLUMNS = strbAllColumns.toString();
ALL_COLUMNS_WITH_PREFIX = strbAllColumnsWithPrefix.toString();
ALL_COLUMNS_FOR_INSERT = strbAllColumnsForInsert.toString();
BIND_VARS_FOR_INSERT = strbBindVarsForInsert.toString();
ALL_COLUMNS_UPDATE = strbColumnsForUpdate.toString();
}
private static final String SQL_GET_BY_ID =
"select " + ALL_COLUMNS +
" from "+TABLE_NAME+" " +
" where " + COL_ID + " = ?";
private static final String SQL_GET_BY_CUSTOMER_ID =
"select " + ALL_COLUMNS +
" from " + TABLE_NAME + " " +
" where customerId = ? ";
private static final String SQL_GET_LASTMOD_BY_ID =
"select lastModifiedTimestamp " +
" from "+TABLE_NAME+" " +
" where " + COL_ID + " = ?";
private static final String SQL_INSERT =
"insert into "+TABLE_NAME+" ( "
+ ALL_COLUMNS_FOR_INSERT
+ " ) values ( "+BIND_VARS_FOR_INSERT+" ) ";
private static final String SQL_DELETE =
"delete from "+TABLE_NAME+" where " + COL_ID + " = ? ";
private static final String SQL_UPDATE =
"update "+TABLE_NAME+" set "
+ ALL_COLUMNS_UPDATE +
" where " + COL_ID + " = ? "
+ " and ( lastModifiedTimestamp = ? or ? = true) " //last parameter will allow us to skip check for concurrent modification, if necessary
;
private static final String SQL_GET_ALL_IN_SET = "select " + ALL_COLUMNS + " from "+TABLE_NAME + " where "+ COL_ID +" in ";
private static final String SQL_PAGING_SUFFIX = " LIMIT ? OFFSET ? ";
private static final String SORT_SUFFIX = "";
private static final RowMapper<Manufacturer> manufacturerRowMapper = new ManufacturerRowMapper();
@Autowired(required=false)
public void setDataSource(ManufacturerDataSourceInterface dataSource) {
setDataSource((DataSource)dataSource);
}
public Manufacturer create(final Manufacturer manufacturer) {
KeyHolder keyHolder = new GeneratedKeyHolder();
final long ts = System.currentTimeMillis();
try{
jdbcTemplate.update(
new PreparedStatementCreator() {
public PreparedStatement createPreparedStatement(Connection connection) throws SQLException {
PreparedStatement ps = connection.prepareStatement(SQL_INSERT, keyColumnConverter.getKeyColumnName(GENERATED_KEY_COLS) );
int colIdx = 1;
//TODO: add remaining properties from Manufacturer here
ps.setInt(colIdx++, manufacturer.getCustomerId());
ps.setString(colIdx++, manufacturer.getSampleStr());
ps.setBytes(colIdx++, (manufacturer.getDetails()!=null)?manufacturer.getDetails().toZippedBytes():null);
ps.setLong(colIdx++, ts);
ps.setLong(colIdx++, ts);
return ps;
}
},
keyHolder);
}catch (DuplicateKeyException e) {
throw new DsDuplicateEntityException(e);
}
// keyHolder.getKey() now contains the generated key
manufacturer.setId(((Long)keyHolder.getKeys().get(COL_ID)));
manufacturer.setCreatedTimestamp(ts);
manufacturer.setLastModifiedTimestamp(ts);
LOG.debug("Stored Manufacturer {}", manufacturer);
return manufacturer.clone();
}
public Manufacturer get(long manufacturerId) {
LOG.debug("Looking up Manufacturer for id {}", manufacturerId);
try{
Manufacturer manufacturer = this.jdbcTemplate.queryForObject(
SQL_GET_BY_ID,
manufacturerRowMapper, manufacturerId);
LOG.debug("Found Manufacturer {}", manufacturer);
return manufacturer;
}catch (EmptyResultDataAccessException e) {
throw new DsEntityNotFoundException(e);
}
}
@Transactional(noRollbackFor = { EmptyResultDataAccessException.class })
public Manufacturer getOrNull(long manufacturerId) {
LOG.debug("Looking up Manufacturer for id {}", manufacturerId);
try{
Manufacturer manufacturer = this.jdbcTemplate.queryForObject(
SQL_GET_BY_ID,
manufacturerRowMapper, manufacturerId);
LOG.debug("Found Manufacturer {}", manufacturer);
return manufacturer;
}catch (EmptyResultDataAccessException e) {
LOG.debug("Could not find Manufacturer for id {}", manufacturerId);
return null;
}
}
public Manufacturer update(Manufacturer manufacturer) {
long newLastModifiedTs = System.currentTimeMillis();
long incomingLastModifiedTs = manufacturer.getLastModifiedTimestamp();
int updateCount = this.jdbcTemplate.update(SQL_UPDATE, new Object[]{
//manufacturer.getId(), - not updating this one
//TODO: add remaining properties from Manufacturer here
manufacturer.getCustomerId(),
manufacturer.getSampleStr(),
(manufacturer.getDetails()!=null)?manufacturer.getDetails().toZippedBytes():null ,
//manufacturer.getCreatedTimestamp(), - not updating this one
newLastModifiedTs,
// use id for update operation
manufacturer.getId(),
// use lastModifiedTimestamp for data protection against concurrent modifications
incomingLastModifiedTs,
isSkipCheckForConcurrentUpdates()
});
if(updateCount==0){
try{
if(isSkipCheckForConcurrentUpdates()){
//in this case we did not request protection against concurrent updates,
//so the updateCount is 0 because record in db was not found
throw new EmptyResultDataAccessException(1);
}
//find out if record could not be updated because it does not exist or because it was modified concurrently
long recordTimestamp = this.jdbcTemplate.queryForObject(
SQL_GET_LASTMOD_BY_ID,
Long.class,
manufacturer.getId()
);
LOG.debug("Concurrent modification detected for Manufacturer with id {} expected version is {} but version in db was {}",
manufacturer.getId(),
incomingLastModifiedTs,
recordTimestamp
);
throw new DsConcurrentModificationException("Concurrent modification detected for Manufacturer with id " + manufacturer.getId()
+" expected version is " + incomingLastModifiedTs
+" but version in db was " + recordTimestamp
);
}catch (EmptyResultDataAccessException e) {
LOG.debug("Cannot find Manufacturer for {}", manufacturer.getId());
throw new DsEntityNotFoundException("Manufacturer not found " + manufacturer.getId());
}
}
//make a copy so that we don't accidentally update caller's version by reference
Manufacturer manufacturerCopy = manufacturer.clone();
manufacturerCopy.setLastModifiedTimestamp(newLastModifiedTs);
LOG.debug("Updated Manufacturer {}", manufacturerCopy);
return manufacturerCopy;
}
public Manufacturer delete(long manufacturerId) {
Manufacturer ret = get(manufacturerId);
this.jdbcTemplate.update(SQL_DELETE, manufacturerId);
LOG.debug("Deleted Manufacturer {}", ret);
return ret;
}
public List<Manufacturer> getAllForCustomer(int customerId) {
LOG.debug("Looking up Manufacturers for customer {}", customerId);
List<Manufacturer> ret = this.jdbcTemplate.query(SQL_GET_BY_CUSTOMER_ID,
manufacturerRowMapper, customerId);
if (ret == null) {
LOG.debug("Cannot find Manufacturers for customer {}", customerId);
} else {
LOG.debug("Found Manufacturers for customer {} : {}", customerId, ret);
}
return ret;
}
public List<Manufacturer> get(Set<Long> manufacturerIdSet) {
LOG.debug("calling get({})", manufacturerIdSet);
if (manufacturerIdSet == null || manufacturerIdSet.isEmpty()) {
return Collections.emptyList();
}
StringBuilder set = new StringBuilder(256);
set.append("(");
for(int i =0; i< manufacturerIdSet.size(); i++) {
set.append("?,");
}
//remove last comma
set.deleteCharAt(set.length()-1);
set.append(")");
String query = SQL_GET_ALL_IN_SET + set;
List<Manufacturer> results = this.jdbcTemplate.query(query, manufacturerIdSet.toArray(), manufacturerRowMapper);
LOG.debug("get({}) returns {} record(s)", manufacturerIdSet, (null == results) ? 0 : results.size());
return results;
}
public PaginationResponse<Manufacturer> getForCustomer(int customerId, List<ColumnAndSort> sortBy,
PaginationContext<Manufacturer> context) {
PaginationResponse<Manufacturer> ret = new PaginationResponse<>();
ret.setContext(context.clone());
if (ret.getContext().isLastPage()) {
// no more pages available according to the context
LOG.debug(
"No more pages available when looking up Manufacturers for customer {} with last returned page number {}",
customerId, context.getLastReturnedPageNumber());
return ret;
}
LOG.debug("Looking up Manufacturers for customer {} with last returned page number {}",
customerId, context.getLastReturnedPageNumber());
String query = SQL_GET_BY_CUSTOMER_ID;
// add filters for the query
ArrayList<Object> queryArgs = new ArrayList<>();
queryArgs.add(customerId);
// add sorting options for the query
StringBuilder strbSort = new StringBuilder(100);
strbSort.append(" order by ");
if (sortBy != null && !sortBy.isEmpty()) {
// use supplied sorting options
for (ColumnAndSort column : sortBy) {
if (!ALL_COLUMNS_LOWERCASE.contains(column.getColumnName().toLowerCase())) {
// unknown column, skip it
continue;
}
strbSort.append(column.getColumnName());
if (column.getSortOrder() == SortOrder.desc) {
strbSort.append(" desc");
}
strbSort.append(",");
}
// remove last ','
strbSort.deleteCharAt(strbSort.length() - 1);
} else {
// no sort order was specified - sort by id to have consistent
// paging
strbSort.append(COL_ID);
}
query += strbSort.toString();
// add pagination parameters for the query
query += SQL_PAGING_SUFFIX ;
queryArgs.add(context.getMaxItemsPerPage());
queryArgs.add(context.getTotalItemsReturned());
/*
* https://www.citusdata.com/blog/2016/03/30/five-ways-to-paginate/
* Choosing offset=1000 makes cost about 19 and has a 0.609 ms execution
* time. Once offset=5,000,000 the cost goes up to 92734 and execution
* time is 758.484 ms. - DT: still acceptable for our use case
*/
List<Manufacturer> pageItems = this.jdbcTemplate.query(query, queryArgs.toArray(),
manufacturerRowMapper);
if (pageItems == null) {
LOG.debug("Cannot find Manufacturers for customer {} with last returned page number {}",
customerId, context.getLastReturnedPageNumber());
} else {
LOG.debug("Found {} Manufacturers for customer {} with last returned page number {}",
pageItems.size(), customerId, context.getLastReturnedPageNumber());
}
ret.setItems(pageItems);
// adjust context for the next page
ret.prepareForNextPage();
// startAfterItem is not used in RDBMS datastores, set it to null
ret.getContext().setStartAfterItem(null);
return ret;
}
}

View File

@@ -8,7 +8,7 @@ import org.springframework.stereotype.Component;
import com.telecominfraproject.wlan.core.server.jdbc.BaseDataSourceConfig;
/**
* @author dtoptygin
* @author mpreston
*
*/
@Component
@@ -20,7 +20,8 @@ public class ManufacturerDataSourceConfig extends BaseDataSourceConfig {
@Bean
public ManufacturerDataSourceInterface manufacturerDataSourceInterface(){
ManufacturerDataSourceInterface ret = new ManufacturerDataSourceImpl(getDataSource(), getKeyColumnConverter());
ManufacturerDataSourceInterface ret = new ManufacturerDataSourceImpl(getDataSource(),
getKeyColumnConverter());
return ret;
}

View File

@@ -6,7 +6,7 @@ import com.telecominfraproject.wlan.core.server.jdbc.BaseJDbcDataSource;
import com.telecominfraproject.wlan.core.server.jdbc.BaseKeyColumnConverter;
/**
* @author dtoptygin
* @author mpreston
* SQL DataSource that is used by Manufacturer Service
*/
public class ManufacturerDataSourceImpl extends BaseJDbcDataSource implements ManufacturerDataSourceInterface {

View File

@@ -3,7 +3,7 @@ package com.telecominfraproject.wlan.manufacturer.datastore.rdbms;
import javax.sql.DataSource;
/**
* @author dtoptygin
* @author mpreston
* Marker interface to distinguish SQL DataSource that is used by Manufacturer Service
*/
public interface ManufacturerDataSourceInterface extends DataSource {

View File

@@ -1,65 +1,187 @@
package com.telecominfraproject.wlan.manufacturer.datastore.rdbms;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.List;
import java.util.Set;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.zip.GZIPInputStream;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import com.telecominfraproject.wlan.core.model.pagination.ColumnAndSort;
import com.telecominfraproject.wlan.core.model.pagination.PaginationContext;
import com.telecominfraproject.wlan.core.model.pagination.PaginationResponse;
import com.telecominfraproject.wlan.core.model.json.GenericResponse;
import com.telecominfraproject.wlan.datastore.exceptions.DsDataValidationException;
import com.telecominfraproject.wlan.manufacturer.datastore.ManufacturerDatastoreInterface;
import com.telecominfraproject.wlan.manufacturer.datastore.ManufacturerDatastoreUtilities;
import com.telecominfraproject.wlan.manufacturer.models.ManufacturerDetailsRecord;
import com.telecominfraproject.wlan.manufacturer.models.ManufacturerOuiDetails;
import com.telecominfraproject.wlan.manufacturer.datastore.ManufacturerDatastore;
import com.telecominfraproject.wlan.manufacturer.models.Manufacturer;
/**
* @author dtoptygin
* @author mpreston
*
*/
@Configuration
public class ManufacturerDatastoreRdbms implements ManufacturerDatastore {
@Autowired ManufacturerDAO manufacturerDAO;
@Override
public Manufacturer create(Manufacturer manufacturer) {
return manufacturerDAO.create(manufacturer);
}
@Override
public Manufacturer get(long manufacturerId) {
return manufacturerDAO.get(manufacturerId);
}
@Override
public Manufacturer getOrNull(long manufacturerId) {
return manufacturerDAO.getOrNull(manufacturerId);
}
public class ManufacturerDatastoreRdbms implements ManufacturerDatastoreInterface {
private static final Logger LOG = LoggerFactory.getLogger(ManufacturerDatastoreRdbms.class);
@Autowired ManufacturerOuiDAO manufacturerOuiDAO;
@Autowired ManufacturerDetailsDAO manufacturerDetailsDAO;
@Override
public Manufacturer update(Manufacturer manufacturer) {
return manufacturerDAO.update(manufacturer);
public ManufacturerOuiDetails createOuiDetails(ManufacturerOuiDetails ouiDetails) {
LOG.trace("createOuiDetails({})", ouiDetails);
if (ouiDetails.getManufacturerName() == null || ouiDetails.getManufacturerName().isEmpty()) {
throw new DsDataValidationException("Unable to create ClientOuiDetails when no Manufacturer name is provided.");
}
// Check to see if there is already an entry for this OUI:
ManufacturerOuiDetails result = manufacturerOuiDAO.getByOui(ouiDetails.getOui());
if (result == null) {
result = createNewOuiDetails(ouiDetails);
}
LOG.trace("createOuiDetails({}) returns {}", ouiDetails, result);
return result;
}
@Override
public Manufacturer delete(long manufacturerId) {
return manufacturerDAO.delete(manufacturerId);
public ManufacturerOuiDetails deleteOuiDetails(String oui) {
return manufacturerOuiDAO.delete(oui);
}
@Override
public List<Manufacturer> get(Set<Long> manufacturerIdSet) {
return manufacturerDAO.get(manufacturerIdSet);
public List<String> getOuiListForManufacturer(String manufacturer, boolean exactMatch) {
return manufacturerOuiDAO.getOuiListForManufacturer(manufacturer, exactMatch);
}
@Override
public PaginationResponse<Manufacturer> getForCustomer(int customerId, List<ColumnAndSort> sortBy,
PaginationContext<Manufacturer> context) {
if(context == null) {
context = new PaginationContext<>();
}
return manufacturerDAO.getForCustomer( customerId, sortBy, context);
public ManufacturerOuiDetails getByOui(String oui) {
return manufacturerOuiDAO.getByOui(oui);
}
@Override
public ManufacturerDetailsRecord createManufacturerDetails(ManufacturerDetailsRecord clientManufacturerDetails) {
return manufacturerDetailsDAO.create(clientManufacturerDetails);
}
@Override
public ManufacturerDetailsRecord updateManufacturerDetails(ManufacturerDetailsRecord clientManufacturerDetails) {
return manufacturerDetailsDAO.update(clientManufacturerDetails);
}
@Override
public ManufacturerDetailsRecord deleteManufacturerDetails(long id) {
return manufacturerDetailsDAO.delete(id);
}
@Override
public ManufacturerDetailsRecord getById(long id) {
return manufacturerDetailsDAO.getById(id);
}
@Override
public List<ManufacturerDetailsRecord> getByManufacturer(String manufacturer, boolean exactMatch) {
return manufacturerDetailsDAO.getByManufacturer(manufacturer, exactMatch);
}
@Override
public List<ManufacturerOuiDetails> getAllManufacturerData() {
return manufacturerOuiDAO.getAllManufacturerData();
}
@Override
public GenericResponse uploadOuiDataFile(String filePath, byte[] gzipContent) {
Pattern ouiPattern = Pattern.compile("^[0-9A-F]{6}");
Pattern companyPattern = Pattern.compile("[\t ]([^\t]+)$");
long totalProcessed = 0;
long importedEntry = 0;
try {
InputStream in = new GZIPInputStream(new ByteArrayInputStream(gzipContent));
BufferedReader input = new BufferedReader(new InputStreamReader(in));
while (input.ready()) {
String line = input.readLine();
Matcher matcher = ouiPattern.matcher(line);
if (matcher.find()) {
++totalProcessed;
String prefix = line.substring(matcher.start(), matcher.end());
ManufacturerOuiDetails result = manufacturerOuiDAO.getByOui(prefix);
if (null != result) {
// already exists
continue;
}
Matcher companyMatcher = companyPattern.matcher(line);
if (!companyMatcher.find()) {
continue;
}
String company = line.substring(companyMatcher.start() + 1, companyMatcher.end());
ManufacturerOuiDetails addDetails = new ManufacturerOuiDetails();
addDetails.setOui(prefix);
addDetails.setManufacturerName(company.trim());
createNewOuiDetails(addDetails);
++importedEntry;
}
}
} catch (Exception e) {
return new GenericResponse(false, e.getLocalizedMessage());
}
return new GenericResponse(true, "Successfully processed " + totalProcessed
+ " OUI record(s), imported " + importedEntry + " OUI record(s)");
}
@Override
public Map<String, ManufacturerOuiDetails> getManufacturerDetailsForOuiList(List<String> ouiList) {
return manufacturerOuiDAO.getManufacturerDetailsForOuiList(ouiList);
}
@Override
public long getManufacturerDetialsId(String oui) {
return manufacturerOuiDAO.getManufacturerDetialsId(oui);
}
@Override
public List<String> getAliasValuesThatBeginWith(String prefix, int maxResults) {
return manufacturerDetailsDAO.getStoresAliasValuesThatBeginWith(prefix, maxResults);
}
private ManufacturerOuiDetails createNewOuiDetails(ManufacturerOuiDetails ouiDetails) {
// Check to see if there is already Manufacturer details for this
// manufacturer:
ManufacturerDetailsRecord manufacturerDetails = null;
String manufacturerName = ManufacturerDatastoreUtilities.getByManufacturerName(ouiDetails.getOui(), ouiDetails.getManufacturerName());
List<ManufacturerDetailsRecord> manufacturerDetailList = getByManufacturer(manufacturerName, true);
if (!manufacturerDetailList.isEmpty()) {
// we will use the one match the name, not the alias because alias can change.
for (ManufacturerDetailsRecord detail: manufacturerDetailList) {
if (detail.getManufacturerName().equalsIgnoreCase(manufacturerName)) {
manufacturerDetails = detail;
break;
}
}
}
if (null == manufacturerDetails) {
// There was no existing manufacturer details entry. create
// that,
// then create the OU entry.
manufacturerDetails = new ManufacturerDetailsRecord();
manufacturerDetails.setManufacturerName(manufacturerName);
manufacturerDetails.setManufacturerAlias(ouiDetails.getManufacturerAlias());
manufacturerDetails = manufacturerDetailsDAO.create(manufacturerDetails);
}
return manufacturerOuiDAO.create(ouiDetails, manufacturerDetails.getId());
}
}

View File

@@ -0,0 +1,296 @@
package com.telecominfraproject.wlan.manufacturer.datastore.rdbms;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.dao.EmptyResultDataAccessException;
import org.springframework.jdbc.core.PreparedStatementCreator;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.jdbc.support.GeneratedKeyHolder;
import org.springframework.jdbc.support.KeyHolder;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import com.telecominfraproject.wlan.core.server.jdbc.BaseJdbcDao;
import com.telecominfraproject.wlan.datastore.exceptions.DsConcurrentModificationException;
import com.telecominfraproject.wlan.datastore.exceptions.DsDuplicateEntityException;
import com.telecominfraproject.wlan.datastore.exceptions.DsEntityNotFoundException;
import com.telecominfraproject.wlan.manufacturer.models.ManufacturerDetailsRecord;
/**
* @author mpreston
*
*/
@Repository
@Transactional(propagation = Propagation.MANDATORY)
public class ManufacturerDetailsDAO extends BaseJdbcDao {
private static final Logger LOG = LoggerFactory.getLogger(ManufacturerDetailsDAO.class);
private static final String COL_ID = "id";
private static final String[] GENERATED_KEY_COLS = { COL_ID };
private static final int MAX_RESULTS = 400;
private static final String[] ALL_COLUMNS_LIST = {
// bigint
COL_ID,
// add colums from properties ClientManufacturerDetailsRecord in
// here
// string
"manufacturerName",
// string
"manufacturerAlias",
// big int
"createdTimestamp",
// bigint
"lastModifiedTimestamp" };
private static final Set<String> columnsToSkipForInsert = new HashSet<>(Arrays.asList(COL_ID));
private static final Set<String> columnsToSkipForUpdate = new HashSet<>(Arrays.asList(COL_ID, "createdTimestamp"));
private static final String TABLE_NAME = "manufacturer_details";
private static final String ALL_COLUMNS;
private static final String ALL_COLUMNS_FOR_INSERT;
private static final String BIND_VARS_FOR_INSERT;
private static final String ALL_COLUMNS_UPDATE;
static {
StringBuilder strbAllColumns = new StringBuilder(1024);
StringBuilder strbAllColumnsForInsert = new StringBuilder(1024);
StringBuilder strbBindVarsForInsert = new StringBuilder(128);
StringBuilder strbColumnsForUpdate = new StringBuilder(512);
for (String colName : ALL_COLUMNS_LIST) {
strbAllColumns.append(colName).append(",");
if (!columnsToSkipForInsert.contains(colName)) {
strbAllColumnsForInsert.append(colName).append(",");
strbBindVarsForInsert.append("?,");
}
if (!columnsToSkipForUpdate.contains(colName)) {
strbColumnsForUpdate.append(colName).append("=?,");
}
}
// remove trailing ','
strbAllColumns.deleteCharAt(strbAllColumns.length() - 1);
strbAllColumnsForInsert.deleteCharAt(strbAllColumnsForInsert.length() - 1);
strbBindVarsForInsert.deleteCharAt(strbBindVarsForInsert.length() - 1);
strbColumnsForUpdate.deleteCharAt(strbColumnsForUpdate.length() - 1);
ALL_COLUMNS = strbAllColumns.toString();
ALL_COLUMNS_FOR_INSERT = strbAllColumnsForInsert.toString();
BIND_VARS_FOR_INSERT = strbBindVarsForInsert.toString();
ALL_COLUMNS_UPDATE = strbColumnsForUpdate.toString();
}
private static final String SQL_INSERT = "insert into " + TABLE_NAME + " ( " + ALL_COLUMNS_FOR_INSERT
+ " ) values ( " + BIND_VARS_FOR_INSERT + " ) ";
// last parameter will allow us to skip check for concurrent modification,
// if necessary
private static final String SQL_UPDATE = "update " + TABLE_NAME + " set " + ALL_COLUMNS_UPDATE + " where id = ? "
+ " and ( lastModifiedTimestamp = ? or ? = true) ";
private static final String SQL_GET_LASTMOD_BY_ID = "select lastModifiedTimestamp " + " from " + TABLE_NAME + " "
+ " where id = ?";
private static final String SQL_DELETE = "delete from " + TABLE_NAME + " where id = ? ";
private static final String SQL_GET_BY_ID = "select " + ALL_COLUMNS + " from " + TABLE_NAME + " " + " where id = ?";
private static final String SQL_GET_BY_MANUFACTURER = "select " + ALL_COLUMNS + " from " + TABLE_NAME
+ " where lower(manufacturerName) like lower(?) or lower(manufacturerAlias) like lower(?) limit "
+ MAX_RESULTS;
private static final String SQL_GET_ALIAS_BEGINS_WITH = "select manufacturerAlias " + " from " + TABLE_NAME
+ " where lower(manufacturerAlias) like lower(?) limit ?";
private static final RowMapper<ManufacturerDetailsRecord> ManufacturerDetailsRowMapper = new ManufacturerDetailsRowMapper();
@Transactional(noRollbackFor = { DuplicateKeyException.class })
public ManufacturerDetailsRecord create(final ManufacturerDetailsRecord manufacturerDetails) {
LOG.debug("create({})", manufacturerDetails);
KeyHolder keyHolder = new GeneratedKeyHolder();
final long ts = System.currentTimeMillis();
try {
jdbcTemplate.update(new PreparedStatementCreator() {
public PreparedStatement createPreparedStatement(Connection connection) throws SQLException {
PreparedStatement ps = connection.prepareStatement(SQL_INSERT,
keyColumnConverter.getKeyColumnName(GENERATED_KEY_COLS));
int colIdx = 1;
ps.setString(colIdx++, manufacturerDetails.getManufacturerName());
ps.setString(colIdx++, manufacturerDetails.getManufacturerAlias());
ps.setLong(colIdx++, ts);
ps.setLong(colIdx++, ts);
return ps;
}
}, keyHolder);
} catch (DuplicateKeyException e) {
DsDuplicateEntityException exp = new DsDuplicateEntityException(e);
LOG.debug("create({}) throws {}", manufacturerDetails, exp.getLocalizedMessage(), exp);
throw exp;
}
// keyHolder.getKey() now contains the generated key
ManufacturerDetailsRecord result = manufacturerDetails.clone();
result.setId(((Long) keyHolder.getKeys().get(COL_ID)));
result.setCreatedTimestamp(ts);
result.setLastModifiedTimestamp(ts);
LOG.debug("create() returns {}", result);
return result;
}
@Transactional(noRollbackFor = { EmptyResultDataAccessException.class })
public List<ManufacturerDetailsRecord> getByManufacturer(String manufacturer, boolean exactMatch) {
LOG.debug("getByManufacturer('{}', {})", manufacturer, exactMatch);
List<ManufacturerDetailsRecord> result = new ArrayList<>();
try {
String searchString = (exactMatch) ? manufacturer : (manufacturer + "%");
result = this.jdbcTemplate.query(SQL_GET_BY_MANUFACTURER, ManufacturerDetailsRowMapper, searchString,
searchString);
} catch (EmptyResultDataAccessException e) {
// ignore
}
LOG.debug("getByManufacturer('{}', {}) returns {}", manufacturer, exactMatch, result.size());
return result;
}
@Transactional(noRollbackFor = { EmptyResultDataAccessException.class })
public ManufacturerDetailsRecord getById(long id) {
LOG.debug("getById({})", id);
try {
ManufacturerDetailsRecord manufacturerDetails = this.jdbcTemplate.queryForObject(SQL_GET_BY_ID,
ManufacturerDetailsRowMapper, id);
LOG.debug("getById({}) returns {}", id, manufacturerDetails);
return manufacturerDetails;
} catch (EmptyResultDataAccessException e) {
throw new DsEntityNotFoundException(e);
}
}
public ManufacturerDetailsRecord update(ManufacturerDetailsRecord manufacturerDetails) {
LOG.debug("update({})", manufacturerDetails);
long incomingLastModifiedTs = manufacturerDetails.getLastModifiedTimestamp();
long newLastModifiedTs = getNewLastModTs(incomingLastModifiedTs);
int updateCount = this.jdbcTemplate.update(SQL_UPDATE,
// manufacturerDetails.getId(), - not updating this one
// Add remaining properties from ClientInfoRecord here
manufacturerDetails.getManufacturerName(), manufacturerDetails.getManufacturerAlias(),
// clientInfo.getCreatedTimestamp(), - not updating this one
newLastModifiedTs,
// use id for update operation
manufacturerDetails.getId(),
// use lastModifiedTimestamp for data protection against
// concurrent modifications
incomingLastModifiedTs, isSkipCheckForConcurrentUpdates());
if (updateCount == 0) {
try {
if (isSkipCheckForConcurrentUpdates()) {
// in this case we did not request protection against
// concurrent updates,
// so the updateCount is 0 because record in db was not
// found
throw new EmptyResultDataAccessException(1);
}
// find out if record could not be updated because it does not
// exist or because it was modified concurrently
long recordTimestamp = this.jdbcTemplate.queryForObject(SQL_GET_LASTMOD_BY_ID, Long.class,
manufacturerDetails.getId());
LOG.debug(
"Concurrent modification detected for ManufacturerDetailsRecord with id {} expected version is {} but version in db was {}",
manufacturerDetails.getId(), incomingLastModifiedTs, recordTimestamp);
throw new DsConcurrentModificationException(
"Concurrent modification detected for ManufacturerDetailsRecord with id "
+ manufacturerDetails.getId() + " expected version is " + incomingLastModifiedTs
+ " but version in db was " + recordTimestamp);
} catch (EmptyResultDataAccessException e) {
LOG.debug("Cannot find ManufacturerDetailsRecord for {}", manufacturerDetails.getId());
throw new DsEntityNotFoundException(
"ManufacturerDetailsRecord not found " + manufacturerDetails.getId());
}
}
// make a copy so that we don't accidentally update caller's version by
// reference
ManufacturerDetailsRecord manufacturerDetailsCopy = manufacturerDetails.clone();
manufacturerDetailsCopy.setLastModifiedTimestamp(newLastModifiedTs);
LOG.debug("update() returns {}", manufacturerDetailsCopy);
return manufacturerDetailsCopy;
}
@Transactional(noRollbackFor = { EmptyResultDataAccessException.class })
public ManufacturerDetailsRecord delete(long id) {
LOG.debug("delete({})", id);
try {
ManufacturerDetailsRecord ret = getById(id);
if (null != ret) {
this.jdbcTemplate.update(SQL_DELETE, ret.getId());
}
LOG.debug("delete({}) returns {}", id, ret);
return ret;
} catch (EmptyResultDataAccessException e) {
LOG.debug("Cannot find ManufacturerDetailsRecord for {} to delete", id);
throw new DsEntityNotFoundException("ManufacturerDetailsRecord not found " + id);
}
}
@Transactional(noRollbackFor = { EmptyResultDataAccessException.class })
public List<String> getStoresAliasValuesThatBeginWith(String prefix, int maxResults) {
LOG.debug("Looking up alias names that begin with {}", prefix);
List<String> result = new ArrayList<>();
if (maxResults < 0 || maxResults > 1000) {
maxResults = 1000;
}
try {
result = this.jdbcTemplate.queryForList(SQL_GET_ALIAS_BEGINS_WITH, String.class, prefix + "%", maxResults);
LOG.debug("Found {} aliases", result.size());
return result;
} catch (EmptyResultDataAccessException e) {
return result;
}
}
}

View File

@@ -0,0 +1,33 @@
package com.telecominfraproject.wlan.manufacturer.datastore.rdbms;
import java.sql.ResultSet;
import java.sql.SQLException;
import org.springframework.jdbc.core.RowMapper;
import com.telecominfraproject.wlan.manufacturer.models.ManufacturerDetailsRecord;
/**
* @author mpreston
*
*/
public class ManufacturerDetailsRowMapper implements RowMapper<ManufacturerDetailsRecord> {
public ManufacturerDetailsRecord mapRow(ResultSet rs, int rowNum) throws SQLException {
ManufacturerDetailsRecord manufacturerDetails = new ManufacturerDetailsRecord();
int colIdx=1;
manufacturerDetails.setId(rs.getLong(colIdx++));
//add columns from properties ManufacturerDetailsRecord in here.
//make sure order of fields is the same as defined in ManufacturerDetailsRecord
manufacturerDetails.setManufacturerName(rs.getString(colIdx++));
manufacturerDetails.setManufacturerAlias(rs.getString(colIdx++));
manufacturerDetails.setCreatedTimestamp(rs.getLong(colIdx++));
manufacturerDetails.setLastModifiedTimestamp(rs.getLong(colIdx++));
return manufacturerDetails;
}
}

View File

@@ -0,0 +1,266 @@
package com.telecominfraproject.wlan.manufacturer.datastore.rdbms;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.dao.EmptyResultDataAccessException;
import org.springframework.jdbc.core.PreparedStatementCreator;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.jdbc.support.GeneratedKeyHolder;
import org.springframework.jdbc.support.KeyHolder;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import com.telecominfraproject.wlan.core.server.jdbc.BaseJdbcDao;
import com.telecominfraproject.wlan.datastore.exceptions.DsEntityNotFoundException;
import com.telecominfraproject.wlan.manufacturer.models.ManufacturerOuiDetails;
/**
* @author mpreston
*
*/
@Repository
@Transactional(propagation = Propagation.MANDATORY)
public class ManufacturerOuiDAO extends BaseJdbcDao {
private static final Logger LOG = LoggerFactory.getLogger(ManufacturerOuiDAO.class);
private static final String COL_ID = "oui";
private static final int MAX_RESULTS = 400;
private static final String[] ALL_COLUMNS_LIST = {
// string
COL_ID,
// add columns from properties ClientOuiDetails in here
"manufacturerDetails"
};
private static final Set<String> columnsToSkipForInsert = Collections.emptySet();
private static final String TABLE_NAME = "manufacturer_oui";
private static final String MANUFACTURER_DETAILS_TABLE_NAME = "manufacturer_details";
private static final String ALL_COLUMNS;
private static final String ALL_COLUMNS_FOR_INSERT;
private static final String BIND_VARS_FOR_INSERT;
static{
StringBuilder strbAllColumns = new StringBuilder(1024);
StringBuilder strbAllColumnsForInsert = new StringBuilder(1024);
StringBuilder strbBindVarsForInsert = new StringBuilder(128);
for(String colName: ALL_COLUMNS_LIST){
strbAllColumns.append(colName).append(",");
if(!columnsToSkipForInsert.contains(colName)){
strbAllColumnsForInsert.append(colName).append(",");
strbBindVarsForInsert.append("?,");
}
}
//remove trailing ','
strbAllColumns.deleteCharAt(strbAllColumns.length()-1);
strbAllColumnsForInsert.deleteCharAt(strbAllColumnsForInsert.length()-1);
strbBindVarsForInsert.deleteCharAt(strbBindVarsForInsert.length()-1);
ALL_COLUMNS = strbAllColumns.toString();
ALL_COLUMNS_FOR_INSERT = strbAllColumnsForInsert.toString();
BIND_VARS_FOR_INSERT = strbBindVarsForInsert.toString();
}
private static final String SQL_INSERT =
"insert into "+TABLE_NAME+" ( "
+ ALL_COLUMNS_FOR_INSERT
+ " ) values ( "+BIND_VARS_FOR_INSERT+" ) ";
private static final String SQL_DELETE =
"delete from "+TABLE_NAME+" where oui = ? ";
private static final String SQL_GET_BY_OUI =
"select oui, manufacturerName, manufacturerAlias" +
" from "+TABLE_NAME+", " +MANUFACTURER_DETAILS_TABLE_NAME+
" where " + COL_ID + " = ? and manufacturerDetails = id";
private static final String SQL_GET_OUD_LIST_BY_MANUFACTURER =
"select " + COL_ID +
" from "+TABLE_NAME+" " +
" where manufacturerDetails in " +
"(select id from " + MANUFACTURER_DETAILS_TABLE_NAME+
" where manufacturerName like ? or manufacturerAlias like ?)" +
" limit " + MAX_RESULTS;
private static final String SQL_GET_ALL_MANUFACTURER_DATA =
"select oui, manufacturerName, manufacturerAlias" +
" from "+TABLE_NAME+", " +MANUFACTURER_DETAILS_TABLE_NAME+
" where manufacturerDetails = id";
private static final String SQL_GET_MANUFACTURER_DATA_FOR_OUI_LIST =
"select oui, manufacturerName, manufacturerAlias" +
" from "+TABLE_NAME+", " +MANUFACTURER_DETAILS_TABLE_NAME+
" where oui in (%s) and manufacturerDetails = id";
private static final String SQL_GET_DETAILS_ID =
"select manufacturerDetails " +
" from "+TABLE_NAME+" " +
" where oui = ?";
private static final RowMapper<ManufacturerOuiDetails> ManufacturerOuiRowMapper = new ManufacturerOuiRowMapper();
@Transactional(noRollbackFor={DuplicateKeyException.class})
public ManufacturerOuiDetails create(final ManufacturerOuiDetails ouiDetails, final long manufacturerDetailsId) {
KeyHolder keyHolder = new GeneratedKeyHolder();
try {
jdbcTemplate.update(new PreparedStatementCreator() {
public PreparedStatement createPreparedStatement(Connection connection) throws SQLException {
PreparedStatement ps = connection.prepareStatement(SQL_INSERT);
int colIdx = 1;
ps.setString(colIdx++, ouiDetails.getOui().toLowerCase());
ps.setLong(colIdx++, manufacturerDetailsId);
return ps;
}
}, keyHolder);
} catch (DuplicateKeyException e) {
// Don't worry about it, there is already a record:
LOG.debug("Already stored entry for OUI {}", ouiDetails);
throw(e);
}
LOG.debug("Stored ManufacturerOuiDetails {}", ouiDetails);
return ouiDetails.clone();
}
@Transactional(noRollbackFor={EmptyResultDataAccessException.class})
public List<String> getOuiListForManufacturer(String manufacturer, boolean exactMatch) {
LOG.debug("Looking up OUI values for {}", manufacturer);
try {
String searchString = (exactMatch) ? manufacturer : (manufacturer + "%");
List<String> resultList = this.jdbcTemplate.queryForList(SQL_GET_OUD_LIST_BY_MANUFACTURER, String.class,
searchString, searchString);
LOG.debug("Found {} for {}", resultList, manufacturer);
return resultList;
}catch (EmptyResultDataAccessException e) {
throw new DsEntityNotFoundException(e);
}
}
@Transactional(noRollbackFor={EmptyResultDataAccessException.class})
public ManufacturerOuiDetails getByOui(String oui) {
LOG.debug("Looking up ManufacturerOuiDetails record with oui {}", oui);
try {
ManufacturerOuiDetails clientOuiDetails = this.jdbcTemplate.queryForObject(SQL_GET_BY_OUI,
ManufacturerOuiRowMapper, oui.toLowerCase());
LOG.debug("Found ManufacturerOuiDetails {}", clientOuiDetails);
return clientOuiDetails;
}catch (EmptyResultDataAccessException e) {
LOG.debug("No Manufacturer Details currently stored for oui {}", oui);
return null;
}
}
@Transactional(noRollbackFor={EmptyResultDataAccessException.class})
public ManufacturerOuiDetails delete(String oui) {
ManufacturerOuiDetails ret = null;
try {
ret = getByOui(oui);
this.jdbcTemplate.update(SQL_DELETE, ret.getOui());
LOG.debug("Deleted ManufacturerOuiDetails {}", ret);
return ret;
} catch (EmptyResultDataAccessException e) {
LOG.debug("Cannot find ManufacturerOuiDetails for {} to delete", oui);
throw new DsEntityNotFoundException("ManufacturerOuiDetails not found " + oui);
}
}
public List<ManufacturerOuiDetails> getAllManufacturerData() {
LOG.debug("Retrieving all Manufacturer data ");
try {
List<ManufacturerOuiDetails> resultList = this.jdbcTemplate.query(SQL_GET_ALL_MANUFACTURER_DATA,
ManufacturerOuiRowMapper);
LOG.debug("Resulting Manufacturer data has {} entries", resultList.size());
return resultList;
} catch (Exception e) {
LOG.debug("Error retrieving all Manufacturer data: {}", e);
return Collections.emptyList();
}
}
public Map<String, ManufacturerOuiDetails> getManufacturerDetailsForOuiList(List<String> ouiList) {
Map<String, ManufacturerOuiDetails> result = new HashMap<>();
if (CollectionUtils.isEmpty(ouiList)) {
return result;
}
StringBuilder ouiListSB = new StringBuilder();
for (String oui : ouiList) {
ouiListSB.append("'");
ouiListSB.append(oui.toLowerCase());
ouiListSB.append("'");
ouiListSB.append(",");
}
ouiListSB.setLength(ouiListSB.length()-1);
List<ManufacturerOuiDetails> resultList = new ArrayList<>();
try {
// Create our own SQL prepared statement as variable number of
// arguments causes weird behaviour.
resultList = this.jdbcTemplate.query(
String.format(SQL_GET_MANUFACTURER_DATA_FOR_OUI_LIST, ouiListSB.toString()),
ManufacturerOuiRowMapper);
LOG.debug("Resulting Manufacturer data has {} entries", resultList.size());
for (ManufacturerOuiDetails details : resultList) {
result.put(details.getOui(), details);
}
return result;
}catch (Exception e) {
LOG.debug("Error retrieving Manufacturer data for OUI list: {}" , e);
return result;
}
}
@Transactional(noRollbackFor = { EmptyResultDataAccessException.class })
public long getManufacturerDetialsId(String oui) {
LOG.debug("Looking up manufacturer details id for oui {}", oui);
try {
long mfrDetailsId = this.jdbcTemplate.queryForObject(SQL_GET_DETAILS_ID, Long.class, oui.toLowerCase());
LOG.debug("Found details record id {} for oui {}", mfrDetailsId, oui);
return mfrDetailsId;
} catch (EmptyResultDataAccessException e) {
LOG.debug("No Manufacturer Details record currently stored for oui {}", oui);
return -1;
}
}
}

View File

@@ -0,0 +1,26 @@
package com.telecominfraproject.wlan.manufacturer.datastore.rdbms;
import java.sql.ResultSet;
import java.sql.SQLException;
import org.springframework.jdbc.core.RowMapper;
import com.telecominfraproject.wlan.manufacturer.models.ManufacturerOuiDetails;
/**
* @author mpreston
*
*/
public class ManufacturerOuiRowMapper implements RowMapper<ManufacturerOuiDetails> {
public ManufacturerOuiDetails mapRow(ResultSet rs, int rowNum) throws SQLException {
ManufacturerOuiDetails clientOui = new ManufacturerOuiDetails();
int colIdx=1;
clientOui.setOui(rs.getString(colIdx++));
clientOui.setManufacturerName(rs.getString(colIdx++));
clientOui.setManufacturerAlias(rs.getString(colIdx++));
return clientOui;
}
}

View File

@@ -1,49 +0,0 @@
package com.telecominfraproject.wlan.manufacturer.datastore.rdbms;
import java.sql.ResultSet;
import java.sql.SQLException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.jdbc.core.RowMapper;
import com.telecominfraproject.wlan.core.model.json.BaseJsonModel;
import com.telecominfraproject.wlan.manufacturer.models.Manufacturer;
import com.telecominfraproject.wlan.manufacturer.models.ManufacturerDetails;
/**
* @author dtoptygin
*
*/
public class ManufacturerRowMapper implements RowMapper<Manufacturer> {
private static final Logger LOG = LoggerFactory.getLogger(ManufacturerRowMapper.class);
public Manufacturer mapRow(ResultSet rs, int rowNum) throws SQLException {
Manufacturer manufacturer = new Manufacturer();
int colIdx=1;
manufacturer.setId(rs.getLong(colIdx++));
//TODO: add columns from properties Manufacturer in here.
//make sure order of fields is the same as defined in Manufacturer
manufacturer.setCustomerId(rs.getInt(colIdx++));
manufacturer.setSampleStr(rs.getString(colIdx++));
byte[] zippedBytes = rs.getBytes(colIdx++);
if (zippedBytes !=null) {
try {
ManufacturerDetails details = BaseJsonModel.fromZippedBytes(zippedBytes, ManufacturerDetails.class);
manufacturer.setDetails(details);
} catch (RuntimeException exp) {
LOG.error("Failed to decode ManufacturerDetails from database for id = {}", manufacturer.getId());
}
}
manufacturer.setCreatedTimestamp(rs.getLong(colIdx++));
manufacturer.setLastModifiedTimestamp(rs.getLong(colIdx++));
return manufacturer;
}
}

View File

@@ -1,16 +1,25 @@
create table manufacturer (
create table manufacturer_details(
-- postgresql
id BIGSERIAL PRIMARY KEY,
customerId int,
sampleStr varchar(50),
details bytea,
manufacturerName varchar(128) unique not null,
manufacturerAlias varchar(20),
createdTimestamp bigint not null,
lastModifiedTimestamp bigint not null
);
create index idx_manufacturer_customerId on manufacturer (customerId);
create index idx_manufacturer_alias on manufacturer_details (manufacturerAlias);
create table manufacturer_oui(
-- postgresql
oui varchar(6) PRIMARY KEY,
manufacturerDetails bigint not null,
FOREIGN KEY(manufacturerDetails) REFERENCES manufacturer_details(id) ON DELETE CASCADE
);
create index idx_oui_manufacturer_details on manufacturer_oui (manufacturerDetails);

View File

@@ -1,72 +0,0 @@
package com.telecominfraproject.wlan.manufacturer.datastore.rdbms;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;
import org.junit.Before;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Import;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabase;
import com.telecominfraproject.wlan.core.server.jdbc.test.BaseJdbcTest;
import com.telecominfraproject.wlan.core.server.jdbc.test.TestWithEmbeddedDB;
import com.telecominfraproject.wlan.manufacturer.models.Manufacturer;
/**
* @author dtoptygin
*
*/
@Import(value = {
ManufacturerDatastoreRdbms.class,
ManufacturerDataSourceConfig.class,
ManufacturerDAO.class,
BaseJdbcTest.Config.class
})
@TestWithEmbeddedDB
public class ManufacturerDatastoreRdbmsPlumbingTests extends BaseJdbcTest {
@Autowired(required=false) private EmbeddedDatabase db;
@Autowired private ManufacturerDatastoreRdbms manufacturerDatastore;
@Autowired private ManufacturerDAO manufacturerDAO;
@Before
public void setUp() {
}
@Test
public void testDataAccess() {
if(db!=null){
//this is a simple test to see if embedded db is working in test environment
JdbcTemplate jdbcTemplate = new JdbcTemplate(db);
Long ret = jdbcTemplate.queryForObject(
"select id from manufacturer where id = ?",
Long.class, 1);
assertEquals((Long)1L, ret);
}
}
@Test
public void testCreateUpdateDeleteManufacturer() {
//GET by Id test
Manufacturer ret = manufacturerDatastore.get(1L);
//DELETE Test
manufacturerDAO.delete(ret.getId());
try{
manufacturerDatastore.get(ret.getId());
fail("failed to delete Manufacturer");
}catch (Exception e) {
// expected it
}
}
}

View File

@@ -10,7 +10,6 @@ import org.springframework.transaction.annotation.Transactional;
import com.telecominfraproject.wlan.core.server.jdbc.test.BaseJdbcTest;
import com.telecominfraproject.wlan.core.server.jdbc.test.TestWithEmbeddedDB;
import com.telecominfraproject.wlan.manufacturer.datastore.BaseManufacturerDatastoreTest;
/**
@@ -22,7 +21,9 @@ import com.telecominfraproject.wlan.manufacturer.datastore.BaseManufacturerDatas
@Rollback(value = true)
@Transactional
@Import(value = { ManufacturerDatastoreRdbms.class, ManufacturerDataSourceConfig.class,
ManufacturerDAO.class, BaseJdbcTest.Config.class })
ManufacturerOuiDAO.class,
ManufacturerDetailsDAO.class,
BaseJdbcTest.Config.class })
@TestWithEmbeddedDB
public class ManufacturerDatastoreRdbmsTests extends BaseManufacturerDatastoreTest {

View File

@@ -1,16 +1,28 @@
drop table manufacturer if exists;
drop table manufacturer_oui if exists;
drop table manufacturer_details if exists;
create table manufacturer (
-- hsqldb
create table manufacturer_details(
-- hsqldb
id BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
customerId int,
sampleStr varchar(50),
details varbinary(65535),
manufacturerName varchar(128) unique not null,
manufacturerAlias varchar(20),
createdTimestamp bigint not null,
lastModifiedTimestamp bigint not null
);
create index idx_manufacturer_customerId on manufacturer (customerId);
create index idx_manufacturer_alias on manufacturer_details (manufacturerAlias);
create table manufacturer_oui(
oui varchar(6) PRIMARY KEY,
manufacturerDetails bigint not null,
FOREIGN KEY(manufacturerDetails) REFERENCES manufacturer_details(id) ON DELETE CASCADE
);
create index idx_oui_manufacturer_details on manufacturer_oui (manufacturerDetails);

View File

@@ -1,15 +1,5 @@
insert into manufacturer (
id,
customerId,
sampleStr,
details,
createdTimestamp,
lastModifiedTimestamp
) values (
1,
1,
'test',
null,
0,0
);
select count(0) from manufacturer_details;
select count(0) from manufacturer_oui;

View File

@@ -1,117 +0,0 @@
package com.telecominfraproject.wlan.manufacturer.models;
import java.util.Objects;
import com.telecominfraproject.wlan.core.model.json.BaseJsonModel;
import com.telecominfraproject.wlan.core.model.json.interfaces.HasCustomerId;
/**
* @author dtoptygin
*
*/
public class Manufacturer extends BaseJsonModel implements HasCustomerId {
private static final long serialVersionUID = 5570757656953699233L;
private long id;
private int customerId;
//TODO: put more fields here, generate getters/setters for them
private String sampleStr;
private ManufacturerDetails details;
private long createdTimestamp;
private long lastModifiedTimestamp;
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public int getCustomerId() {
return customerId;
}
public void setCustomerId(int customerId) {
this.customerId = customerId;
}
public long getCreatedTimestamp() {
return createdTimestamp;
}
public void setCreatedTimestamp(long createdTimestamp) {
this.createdTimestamp = createdTimestamp;
}
public long getLastModifiedTimestamp() {
return lastModifiedTimestamp;
}
public void setLastModifiedTimestamp(long lastModifiedTimestamp) {
this.lastModifiedTimestamp = lastModifiedTimestamp;
}
public void setSampleStr(String sampleStr) {
this.sampleStr = sampleStr;
}
public String getSampleStr() {
return sampleStr;
}
public ManufacturerDetails getDetails() {
return details;
}
public void setDetails(ManufacturerDetails details) {
this.details = details;
}
@Override
public boolean hasUnsupportedValue() {
if (super.hasUnsupportedValue()) {
return true;
}
if(details!=null && details.hasUnsupportedValue()) {
return true;
}
return false;
}
@Override
public Manufacturer clone() {
Manufacturer ret = (Manufacturer) super.clone();
if(details!=null) {
ret.setDetails(details.clone());
}
return ret;
}
@Override
public int hashCode() {
return Objects.hash(createdTimestamp, customerId, id, lastModifiedTimestamp, sampleStr, details);
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (!(obj instanceof Manufacturer)) {
return false;
}
Manufacturer other = (Manufacturer) obj;
return createdTimestamp == other.createdTimestamp && customerId == other.customerId && id == other.id
&& lastModifiedTimestamp == other.lastModifiedTimestamp
&& Objects.equals(sampleStr, other.sampleStr)
&& Objects.equals(details, other.details);
}
}

View File

@@ -1,57 +0,0 @@
package com.telecominfraproject.wlan.manufacturer.models;
import java.util.Objects;
import com.telecominfraproject.wlan.core.model.json.BaseJsonModel;
/**
* @author dtoptygin
*
*/
public class ManufacturerDetails extends BaseJsonModel {
private static final long serialVersionUID = 5570757656953699233L;
//TODO: put more fields here, generate getters/setters for them
private String sampleDetailsStr;
public String getSampleDetailsStr() {
return sampleDetailsStr;
}
public void setSampleDetailsStr(String sampleDetailsStr) {
this.sampleDetailsStr = sampleDetailsStr;
}
@Override
public boolean hasUnsupportedValue() {
if (super.hasUnsupportedValue()) {
return true;
}
return false;
}
@Override
public ManufacturerDetails clone() {
return (ManufacturerDetails) super.clone();
}
@Override
public int hashCode() {
return Objects.hash(sampleDetailsStr);
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (!(obj instanceof ManufacturerDetails)) {
return false;
}
ManufacturerDetails other = (ManufacturerDetails) obj;
return Objects.equals(sampleDetailsStr, other.sampleDetailsStr);
}
}

View File

@@ -0,0 +1,98 @@
package com.telecominfraproject.wlan.manufacturer.models;
import com.telecominfraproject.wlan.core.model.json.BaseJsonModel;
/**
* @author mpreston
*
*/
public class ManufacturerDetailsRecord extends BaseJsonModel {
private static final long serialVersionUID = -1094384189381503822L;
private long id;
private String manufacturerName;
private String manufacturerAlias;
private long createdTimestamp;
private long lastModifiedTimestamp;
public ManufacturerDetailsRecord() {}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getManufacturerName() {
return manufacturerName;
}
public void setManufacturerName(String manufacturerName) {
this.manufacturerName = manufacturerName;
}
public String getManufacturerAlias() {
return manufacturerAlias;
}
public void setManufacturerAlias(String manufacturerAlias) {
this.manufacturerAlias = manufacturerAlias;
}
public long getCreatedTimestamp() {
return createdTimestamp;
}
public void setCreatedTimestamp(long createdTimestamp) {
this.createdTimestamp = createdTimestamp;
}
public long getLastModifiedTimestamp() {
return lastModifiedTimestamp;
}
public void setLastModifiedTimestamp(long lastModifiedTimestamp) {
this.lastModifiedTimestamp = lastModifiedTimestamp;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((manufacturerAlias == null) ? 0 : manufacturerAlias.hashCode());
result = prime * result + ((manufacturerName == null) ? 0 : manufacturerName.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
ManufacturerDetailsRecord other = (ManufacturerDetailsRecord) obj;
if (manufacturerAlias == null) {
if (other.manufacturerAlias != null)
return false;
} else if (!manufacturerAlias.equals(other.manufacturerAlias))
return false;
if (manufacturerName == null) {
if (other.manufacturerName != null)
return false;
} else if (!manufacturerName.equals(other.manufacturerName))
return false;
return true;
}
@Override
public ManufacturerDetailsRecord clone() {
ManufacturerDetailsRecord ret = (ManufacturerDetailsRecord) super.clone();
return ret;
}
}

View File

@@ -0,0 +1,93 @@
package com.telecominfraproject.wlan.manufacturer.models;
import com.telecominfraproject.wlan.core.model.json.BaseJsonModel;
/**
* @author mpreston
*
* Properties of Manufacturer OUI mappings.
*/
public class ManufacturerOuiDetails extends BaseJsonModel {
private static final long serialVersionUID = 6097322123679241676L;
private String oui;
private String manufacturerName;
private String manufacturerAlias;
public ManufacturerOuiDetails() {}
public String getOui() {
return oui;
}
public void setOui(String oui) {
this.oui = oui;
}
public String getManufacturerName() {
return manufacturerName;
}
public void setManufacturerName(String manufacturerName) {
this.manufacturerName = manufacturerName;
}
public String getManufacturerAlias() {
return manufacturerAlias;
}
public void setManufacturerAlias(String manufacturerAlias) {
this.manufacturerAlias = manufacturerAlias;
}
public String calculateDisplayName() {
return (this.getManufacturerAlias() != null && this.getManufacturerAlias().length() != 0) ?
this.getManufacturerAlias() : this.getManufacturerName();
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((manufacturerAlias == null) ? 0 : manufacturerAlias.hashCode());
result = prime * result + ((manufacturerName == null) ? 0 : manufacturerName.hashCode());
result = prime * result + ((oui == null) ? 0 : oui.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
ManufacturerOuiDetails other = (ManufacturerOuiDetails) obj;
if (oui == null) {
if (other.oui != null)
return false;
} else if (!oui.equals(other.oui))
return false;
if (manufacturerName == null) {
if (other.manufacturerName != null)
return false;
} else if (!manufacturerName.equals(other.manufacturerName))
return false;
if (manufacturerAlias == null) {
if (other.manufacturerAlias != null)
return false;
} else if (!manufacturerAlias.equals(other.manufacturerAlias))
return false;
return true;
}
@Override
public ManufacturerOuiDetails clone() {
ManufacturerOuiDetails ret = (ManufacturerOuiDetails) super.clone();
return ret;
}
}

View File

@@ -1,24 +0,0 @@
package com.telecominfraproject.wlan.manufacturer.models.events;
import com.telecominfraproject.wlan.manufacturer.models.Manufacturer;
import com.telecominfraproject.wlan.systemevent.models.CustomerEvent;
/**
* @author dtoptygin
*
*/
public class ManufacturerAddedEvent extends CustomerEvent<Manufacturer> {
private static final long serialVersionUID = 7142208487917559985L;
public ManufacturerAddedEvent(Manufacturer manufacturer){
super(manufacturer.getCustomerId(), manufacturer.getLastModifiedTimestamp(), manufacturer);
}
/**
* Constructor used by JSON
*/
public ManufacturerAddedEvent() {
super(0, 0, null);
}
}

View File

@@ -1,24 +0,0 @@
package com.telecominfraproject.wlan.manufacturer.models.events;
import com.telecominfraproject.wlan.manufacturer.models.Manufacturer;
import com.telecominfraproject.wlan.systemevent.models.CustomerEvent;
/**
* @author dtoptygin
*
*/
public class ManufacturerChangedEvent extends CustomerEvent<Manufacturer> {
private static final long serialVersionUID = 7142209997917559985L;
public ManufacturerChangedEvent(Manufacturer manufacturer){
super(manufacturer.getCustomerId(), manufacturer.getLastModifiedTimestamp(), manufacturer);
}
/**
* Constructor used by JSON
*/
public ManufacturerChangedEvent() {
super(0, 0, null);
}
}

View File

@@ -1,24 +0,0 @@
package com.telecominfraproject.wlan.manufacturer.models.events;
import com.telecominfraproject.wlan.manufacturer.models.Manufacturer;
import com.telecominfraproject.wlan.systemevent.models.CustomerEvent;
/**
* @author dtoptygin
*
*/
public class ManufacturerRemovedEvent extends CustomerEvent<Manufacturer> {
private static final long serialVersionUID = 7142208488887559985L;
public ManufacturerRemovedEvent(Manufacturer manufacturer){
super(manufacturer.getCustomerId(), manufacturer.getLastModifiedTimestamp(), manufacturer);
}
/**
* Constructor used by JSON
*/
public ManufacturerRemovedEvent() {
super(0, 0, null);
}
}

View File

@@ -0,0 +1,140 @@
package com.telecominfraproject.wlan.manufacturer;
import java.util.List;
import java.util.Map;
import java.util.Set;
import com.telecominfraproject.wlan.core.model.json.GenericResponse;
import com.telecominfraproject.wlan.manufacturer.models.ManufacturerDetailsRecord;
import com.telecominfraproject.wlan.manufacturer.models.ManufacturerOuiDetails;
/**
* @author mpreston
*
*/
public interface ManufacturerInterface {
/**
* Create a mapping of OUI to the Manufacturer details.
*
* @param ouiDetails - object containing the parameters for the OUI to Manufacturer Details mapping.
*
* @return a copy of the stored OUI to Manufacturer Details mapping.
*/
ManufacturerOuiDetails createOuiDetails(ManufacturerOuiDetails ouiDetails);
/**
* Removes a mapping of OUI to Manufacturer Details from the datastore.
*
* @param oui - the unique OUI which identifies the Manufacturer details to be removed.
*
* @return a copy of the removed OUI to Manufacturer Details mapping.
*/
ManufacturerOuiDetails deleteOuiDetails(String oui);
/**
* Retrieves a list of all OUI values that are mapped to the passed in Manufacturer name.
*
* @param manufacturer - name of the manufacturer for which the OUIs will be retrieved.
* @param exactMatch - boolean flag determining if the search should be conducted for only an
* exact match of the passed in Manufacturer name, or if the search should match any record that
* begins with the passed in search string.
*
* @return a list of all OUIs that match the passed in Manufacturer name.
*/
List<String> getOuiListForManufacturer(String manufacturer, boolean exactMatch);
/**
* Retrieves the OUI to Manufacturer Details mapping specified by the passed in OUI.
*
* @param oui - unique identifier of a mapping between OUI and Manufacturer details.
*
* @return a copy of the OUI to Manufacturer details specified by the passed in OUI.
*/
ManufacturerOuiDetails getByOui(String oui);
/**
* Stores a Manufacturer Details record in the datasstore.
*
* @param clientManufacturerDetails - object containing the Manufacturer Details to be stored.
*
* @return a copy of the Manufacturer Details stored.
*/
ManufacturerDetailsRecord createManufacturerDetails(ManufacturerDetailsRecord clientManufacturerDetails);
/**
* Updates a Manufacturer Details record in the datasstore.
*
* @param clientManufacturerDetails - object containing the Manufacturer Details to be updated.
*
* @return a copy of the updated Manufacturer Details.
*/
ManufacturerDetailsRecord updateManufacturerDetails(ManufacturerDetailsRecord clientManufacturerDetails);
/**
* Removes a Manufacturer Details record from the datastore.
*
* @param id - unique identifier of the Manufacturer Details to be removed.
*
* @return a copy of the removed Manufacturer Details record.
*/
ManufacturerDetailsRecord deleteManufacturerDetails(long id);
/**
* Retrieves a Manufacturer Details record identified by the passed in id.
*
* @param id - unique identifier of a Manufacturer Details record.
*
* @return a copy of the Manufacturer Details record stored in the datastore
* that is identified by the passed in id.
*/
ManufacturerDetailsRecord getById(long id);
/**
* Retrieves the entire contents of the Manufacturer Management Datastore.
* @return result
*/
List<ManufacturerOuiDetails> getAllManufacturerData();
/**
* Appends any records from the passed in file to the Manufacturer Details datastore.
* Only adds in new records.
* @param fileName
* @param base64GzippedContent base64 encoded gzipped file
*
* @return result
*
*/
GenericResponse uploadOuiDataFile(String fileName, byte[] base64GzippedContent);
/**
* Retrieve all the OUI details for a specific list of OUI values.
* @param ouiSet - set of OUI values for which ManfacturerDetails shall be retrieved.
*
* @return a map of the OUI string to the Manufacturer details for the provided list of OUI values.
*/
Map<String, ManufacturerOuiDetails> getManufacturerDetailsForOuiSet(Set<String> ouiSet);
/**
* Update the alias of an OUI record in the datastore using the passed in object
* as the new value.
*
* @return - the newly updated and persisted OUI details.
*/
ManufacturerOuiDetails updateOuiAlias(ManufacturerOuiDetails ouiDetails);
/**
* Retrieves a list of Alias values persisted in the datastore that start with the passed in prefix.
*
* @param prefix
* @param maxResults - number of results to return. if maxResults is greater than 1000, then 1000 results will be returned.
*/
List<String> getAliasValuesThatBeginWith(String prefix, int maxResults);
}

View File

@@ -1,87 +0,0 @@
package com.telecominfraproject.wlan.manufacturer;
import java.util.List;
import java.util.Set;
import com.telecominfraproject.wlan.core.model.pagination.ColumnAndSort;
import com.telecominfraproject.wlan.core.model.pagination.PaginationContext;
import com.telecominfraproject.wlan.core.model.pagination.PaginationResponse;
import com.telecominfraproject.wlan.manufacturer.models.Manufacturer;
/**
* @author dtoptygin
*
*/
public interface ManufacturerServiceInterface {
/**
* Creates new Manufacturer
*
* @param Manufacturer
* @return stored Manufacturer object
* @throws RuntimeException if Manufacturer record already exists
*/
Manufacturer create(Manufacturer manufacturer );
/**
* Retrieves Manufacturer by id
* @param manufacturerId
* @return Manufacturer for the supplied id
* @throws RuntimeException if Manufacturer record does not exist
*/
Manufacturer get(long manufacturerId );
/**
* Retrieves Manufacturer by id
* @param manufacturerId
* @return Manufacturer for the supplied id
*/
Manufacturer getOrNull(long manufacturerId );
/**
* Retrieves a list of Manufacturer records that which have their Id in the provided set.
*
* @param manufacturerIdSet
* @return list of matching Manufacturer objects.
*/
List<Manufacturer> get(Set<Long> manufacturerIdSet);
/**
* Updates Manufacturer
*
* @param Manufacturer
* @return updated Manufacturer object
* @throws RuntimeException if Manufacturer record does not exist or if it was modified concurrently
*/
Manufacturer update(Manufacturer manufacturer);
/**
* Deletes Manufacturer
*
* @param manufacturerId
* @return deleted Manufacturer object
*/
Manufacturer delete(long manufacturerId );
/**
* <br>Retrieves all of the Manufacturer records that are mapped to the provided customerId.
* Results are returned in pages.
*
* <br>When changing sort order or filters, pagination should be restarted again from the first page.
* Old pagination contexts would be invalid and should not be used in that case.
* <br>The only time when a caller should be interacting with the properties of the paginationContext is during the
* call to the first page by setting property maxItemsPerPage.
* <br>If initial context is not provided, then the maxItemsPerPage will be set to 20.
* <br>If sortBy is not provided, then the data will be ordered by id.
* <ul>Allowed columns for sorting are:
*<li> "id"
*<li> "sampleStr"
*<br>
* @param customerId
* @return next page of matching Manufacturer objects.
*/
PaginationResponse<Manufacturer> getForCustomer(int customerId, List<ColumnAndSort> sortBy, PaginationContext<Manufacturer> context);
}

View File

@@ -1,72 +1,109 @@
package com.telecominfraproject.wlan.manufacturer;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import com.telecominfraproject.wlan.core.model.pagination.ColumnAndSort;
import com.telecominfraproject.wlan.core.model.pagination.PaginationContext;
import com.telecominfraproject.wlan.core.model.pagination.PaginationResponse;
import org.springframework.context.annotation.Configuration;
import org.springframework.util.CollectionUtils;
import com.telecominfraproject.wlan.core.model.json.GenericResponse;
import com.telecominfraproject.wlan.manufacturer.controller.ManufacturerController;
import com.telecominfraproject.wlan.manufacturer.models.Manufacturer;
import com.telecominfraproject.wlan.manufacturer.models.ManufacturerDetailsRecord;
import com.telecominfraproject.wlan.manufacturer.models.ManufacturerOuiDetails;
/**
* @author dtoptygin
* @author mpreston
*
*/
@Component
public class ManufacturerServiceLocal implements ManufacturerServiceInterface {
@Autowired private ManufacturerController manufacturerController;
@Configuration
public class ManufacturerServiceLocal implements ManufacturerInterface {
@Autowired
private ManufacturerController mfrController;
private static final Logger LOG = LoggerFactory.getLogger(ManufacturerServiceLocal.class);
@Override
public Manufacturer create(Manufacturer manufacturer) {
LOG.debug("calling manufacturerController.create {} ", manufacturer);
return manufacturerController.create(manufacturer);
}
@Override
public Manufacturer get(long manufacturerId) {
LOG.debug("calling manufacturerController.get {} ", manufacturerId);
return manufacturerController.get(manufacturerId);
public ManufacturerOuiDetails createOuiDetails(ManufacturerOuiDetails ouiDetails) {
LOG.debug("calling mfrController.createOuiDetails {} ", ouiDetails);
return mfrController.createOuiDetails(ouiDetails);
}
@Override
public Manufacturer getOrNull(long manufacturerId) {
LOG.debug("calling manufacturerController.getOrNull {} ", manufacturerId);
return manufacturerController.getOrNull(manufacturerId);
public ManufacturerOuiDetails deleteOuiDetails(String oui) {
LOG.debug("calling mfrController.deleteOuiDetails {} ", oui);
return mfrController.deleteOuiDetails(oui);
}
@Override
public List<Manufacturer> get(Set<Long> manufacturerIdSet) {
LOG.debug("calling manufacturerController.getAllInSet {} ", manufacturerIdSet);
return manufacturerController.getAllInSet(manufacturerIdSet);
public List<String> getOuiListForManufacturer(String manufacturer, boolean exactMatch) {
LOG.debug("calling mfrController.getOuiListForManufacturer {}, {} ", manufacturer, exactMatch);
return mfrController.getOuiListForManufacturer(manufacturer, exactMatch);
}
@Override
public PaginationResponse<Manufacturer> getForCustomer(int customerId, List<ColumnAndSort> sortBy,
PaginationContext<Manufacturer> context) {
LOG.debug("calling manufacturerController.getForCustomer {} ", customerId);
return manufacturerController.getForCustomer(customerId, sortBy, context);
public ManufacturerOuiDetails getByOui(String oui) {
LOG.debug("calling mfrController.getByOui {} ", oui);
return mfrController.getByOui(oui);
}
@Override
public ManufacturerDetailsRecord createManufacturerDetails(ManufacturerDetailsRecord clientManufacturerDetails) {
LOG.debug("calling mfrController.createManufacturerDetails {} ", clientManufacturerDetails);
return mfrController.createManufacturerDetails(clientManufacturerDetails);
}
@Override
public ManufacturerDetailsRecord updateManufacturerDetails(ManufacturerDetailsRecord clientManufacturerDetails) {
LOG.debug("calling mfrController.updateManufacturerDetails {} ", clientManufacturerDetails);
return mfrController.updateManufacturerDetails(clientManufacturerDetails);
}
@Override
public ManufacturerDetailsRecord deleteManufacturerDetails(long id) {
LOG.debug("calling mfrController.deleteManufacturerDetails {} ", id);
return mfrController.deleteManufacturerDetails(id);
}
@Override
public ManufacturerDetailsRecord getById(long id) {
LOG.debug("calling mfrController.getById {} ", id);
return mfrController.getById(id);
}
@Override
public List<ManufacturerOuiDetails> getAllManufacturerData() {
LOG.debug("calling mfrController.getAllManufacturerData()");
return mfrController.getAllManufacturerData();
}
@Override
public Manufacturer update(Manufacturer manufacturer) {
LOG.debug("calling manufacturerController.update {} ", manufacturer);
return manufacturerController.update(manufacturer);
public GenericResponse uploadOuiDataFile(String fileName, byte[] base64GzippedContent) {
return mfrController.uploadOuiDataFile(fileName, base64GzippedContent);
}
@Override
public Manufacturer delete(long manufacturerId) {
LOG.debug("calling manufacturerController.delete {} ", manufacturerId);
return manufacturerController.delete(manufacturerId);
public Map<String, ManufacturerOuiDetails> getManufacturerDetailsForOuiSet(Set<String> ouiSet) {
LOG.debug("calling mfrController.getManufacturerDetailsForOuiList ");
if (CollectionUtils.isEmpty(ouiSet)) {
return new HashMap<>();
}
return mfrController.getManufacturerDetailsForOuiList(new ArrayList<>(ouiSet));
}
}
@Override
public ManufacturerOuiDetails updateOuiAlias(ManufacturerOuiDetails ouiDetails) {
return mfrController.updateOuiAlias(ouiDetails);
}
@Override
public List<String> getAliasValuesThatBeginWith(String prefix, int maxResults) {
return mfrController.getStoredAliasValuesThatBeginWith(prefix, maxResults);
}
}

View File

@@ -0,0 +1,33 @@
package com.telecominfraproject.wlan.manufacturer;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.Future;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.AsyncResult;
import org.springframework.stereotype.Component;
import com.telecominfraproject.wlan.manufacturer.models.ManufacturerOuiDetails;
@Component
public class ManufacturerAsyncInvokator {
private static final Logger LOG = LoggerFactory.getLogger(ManufacturerAsyncInvokator.class);
@Async //Async methods MUST be defined on separate Beans or Components, otherwise they will not be treated asynchronously
public Future<Map<String, ManufacturerOuiDetails>> getManufacturerDetailsForOuiSet(ManufacturerServiceRemote manufacturerServiceRemote, Set<String> ouiSet){
LOG.debug("getManufacturerDetailsForOuiSet(size={}) thread {}",ouiSet.size(), Thread.currentThread().getName());
try{
return new AsyncResult<>(manufacturerServiceRemote.getManufacturueDetailsForOuiSetImpl(ouiSet));
}catch (Exception e) {
return new AsyncResult<>(new HashMap<>());
}finally{
}
}
}

View File

@@ -1,183 +1,315 @@
package com.telecominfraproject.wlan.manufacturer;
import java.util.Collections;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import com.telecominfraproject.wlan.core.client.BaseRemoteClient;
import com.telecominfraproject.wlan.core.model.json.BaseJsonModel;
import com.telecominfraproject.wlan.core.model.pagination.ColumnAndSort;
import com.telecominfraproject.wlan.core.model.pagination.PaginationContext;
import com.telecominfraproject.wlan.core.model.pagination.PaginationResponse;
import com.telecominfraproject.wlan.datastore.exceptions.DsDataValidationException;
import com.telecominfraproject.wlan.manufacturer.models.Manufacturer;
import com.telecominfraproject.wlan.core.model.json.GenericResponse;
import com.telecominfraproject.wlan.manufacturer.models.ManufacturerDetailsRecord;
import com.telecominfraproject.wlan.manufacturer.models.ManufacturerOuiDetails;
import com.telecominfraproject.wlan.server.exceptions.GenericErrorException;
/**
* @author dtoptygin
* @author mpreston
*
*/
@Component
public class ManufacturerServiceRemote extends BaseRemoteClient implements ManufacturerServiceInterface {
@Configuration
public class ManufacturerServiceRemote extends BaseRemoteClient implements ManufacturerInterface {
private static final Logger LOG = LoggerFactory.getLogger(ManufacturerServiceRemote.class);
private static final ParameterizedTypeReference<List<Manufacturer>> Manufacturer_LIST_CLASS_TOKEN = new ParameterizedTypeReference<List<Manufacturer>>() {};
private static final ParameterizedTypeReference<PaginationResponse<Manufacturer>> Manufacturer_PAGINATION_RESPONSE_CLASS_TOKEN = new ParameterizedTypeReference<PaginationResponse<Manufacturer>>() {};
private static final int MAX_OUIS_PER_REQUEST = 200;
private static final ParameterizedTypeReference<List<ManufacturerOuiDetails>> manufacturerOuiDetailsListClassToken;
private static final ParameterizedTypeReference<Map<String, ManufacturerOuiDetails>> manufacturerOuiDetailsMapClassToken;
private static final ParameterizedTypeReference<List<String>> stringListClassToken;
static {
manufacturerOuiDetailsListClassToken = new ParameterizedTypeReference<List<ManufacturerOuiDetails>>() {
};
stringListClassToken = new ParameterizedTypeReference<List<String>>() {
};
manufacturerOuiDetailsMapClassToken = new ParameterizedTypeReference<Map<String, ManufacturerOuiDetails>>() {
};
}
@Autowired
private ManufacturerAsyncInvokator asyncInvokator;
private String baseUrl;
@Override
public Manufacturer create(Manufacturer manufacturer) {
LOG.debug("calling manufacturer.create {} ", manufacturer);
if (BaseJsonModel.hasUnsupportedValue(manufacturer)) {
LOG.error("Failed to create Manufacturer, unsupported value in {}", manufacturer);
throw new DsDataValidationException("Manufacturer contains unsupported value");
@Override
public ManufacturerOuiDetails createOuiDetails(ManufacturerOuiDetails ouiDetails) {
LOG.debug("calling createOuiDetails {} ", ouiDetails);
HttpEntity<ManufacturerOuiDetails> request = new HttpEntity<>(ouiDetails, headers);
ResponseEntity<ManufacturerOuiDetails> responseEntity = restTemplate
.postForEntity(getBaseUrl() + "/oui", request, ManufacturerOuiDetails.class);
ManufacturerOuiDetails ret = responseEntity.getBody();
LOG.debug("completed createOuiDetails {} ", ret);
return ret;
}
@Override
public ManufacturerOuiDetails deleteOuiDetails(String oui) {
LOG.debug("calling deleteOuiDetails {} ", oui);
ResponseEntity<ManufacturerOuiDetails> responseEntity = restTemplate.exchange(
getBaseUrl() + "/oui?oui={oui}", HttpMethod.DELETE, null,
ManufacturerOuiDetails.class, oui);
ManufacturerOuiDetails ret = responseEntity.getBody();
LOG.debug("completed delete {} ", ret);
return ret;
}
@Override
public List<String> getOuiListForManufacturer(String manufacturer, boolean exactMatch) {
LOG.debug("calling getOuiListForManufacturer {}, {} ", manufacturer, exactMatch);
ResponseEntity<List<String>> responseEntity = restTemplate.exchange(
getBaseUrl() + "/oui/forManufacturer?manufacturer={manufacturer}&exactMatch={exactMatch}",
HttpMethod.GET, null, stringListClassToken, manufacturer, exactMatch);
List<String> ret = responseEntity.getBody();
LOG.debug("completed getOuiListForManufacturer and found {} ", ret);
return ret;
}
@Override
public ManufacturerOuiDetails getByOui(String oui) {
LOG.debug("calling getByOui {} ", oui);
ResponseEntity<ManufacturerOuiDetails> responseEntity = restTemplate.exchange(
getBaseUrl() + "/oui?oui={pui}", HttpMethod.GET, null, ManufacturerOuiDetails.class, oui);
ManufacturerOuiDetails ret = responseEntity.getBody();
LOG.debug("completed getByOui and found {} ", ret);
return ret;
}
@Override
public ManufacturerDetailsRecord createManufacturerDetails(ManufacturerDetailsRecord clientManufacturerDetails) {
LOG.debug("calling createManufacturerDetails {} ", clientManufacturerDetails);
HttpEntity<ManufacturerDetailsRecord> request = new HttpEntity<>(
clientManufacturerDetails, headers);
ResponseEntity<ManufacturerDetailsRecord> responseEntity = restTemplate.postForEntity(
getBaseUrl(), request, ManufacturerDetailsRecord.class);
ManufacturerDetailsRecord ret = responseEntity.getBody();
LOG.debug("completed createManufacturerDetails and stored {} ", ret);
return ret;
}
@Override
public ManufacturerDetailsRecord updateManufacturerDetails(ManufacturerDetailsRecord clientManufacturerDetails) {
LOG.debug("calling updateManufacturerDetails {} ", clientManufacturerDetails);
HttpEntity<ManufacturerDetailsRecord> request = new HttpEntity<>(
clientManufacturerDetails, headers);
ResponseEntity<ManufacturerDetailsRecord> responseEntity = restTemplate.exchange(
getBaseUrl(), HttpMethod.PUT, request,
ManufacturerDetailsRecord.class);
ManufacturerDetailsRecord ret = responseEntity.getBody();
LOG.debug("completed updateManufacturerDetails and updated {} ", ret);
return ret;
}
@Override
public ManufacturerDetailsRecord deleteManufacturerDetails(long id) {
LOG.debug("calling deleteManufacturerDetails {} ", id);
ManufacturerDetailsRecord ret = getById(id);
restTemplate.delete(getBaseUrl() + "?id=" + id);
LOG.debug("completed deleteManufacturerDetails {} ", ret);
return ret;
}
@Override
public ManufacturerDetailsRecord getById(long id) {
LOG.debug("calling getById {} ", id);
ResponseEntity<ManufacturerDetailsRecord> responseEntity = restTemplate.exchange(
getBaseUrl() + "?id={id}", HttpMethod.GET, null,
ManufacturerDetailsRecord.class, id);
ManufacturerDetailsRecord ret = responseEntity.getBody();
LOG.debug("completed getById and found {} ", ret);
return ret;
}
@Override
public List<ManufacturerOuiDetails> getAllManufacturerData() {
LOG.debug("calling getAllManufacturerData");
ResponseEntity<List<ManufacturerOuiDetails>> responseEntity = restTemplate.exchange(
getBaseUrl() + "/oui/all", HttpMethod.GET, null,
manufacturerOuiDetailsListClassToken);
List<ManufacturerOuiDetails> ret = responseEntity.getBody();
LOG.debug("completed getAllManufacturerData and found {} records", ret.size());
return ret;
}
@Override
public GenericResponse uploadOuiDataFile(String fileName, byte[] base64GzippedContent) {
LOG.debug("uploadOuiDataFile({})", fileName);
GenericResponse ret;
if (null != base64GzippedContent) {
HttpHeaders fileHeaders = new HttpHeaders();
fileHeaders.setContentType(MediaType.APPLICATION_OCTET_STREAM);
fileHeaders.set("Accept-Encoding", "gzip,deflate");
HttpEntity<byte[]> request = new HttpEntity<>(base64GzippedContent, fileHeaders);
ResponseEntity<GenericResponse> responseEntity = restTemplate.postForEntity(
getBaseUrl() + "/oui/upload?fileName={fileName}", request, GenericResponse.class,
fileName);
ret = responseEntity.getBody();
} else {
ret = new GenericResponse(false, "missing compressed data file content");
}
LOG.debug("completed uploadOuiDataFile({}) with result {} ", fileName, ret);
return ret;
}
@Override
public Map<String, ManufacturerOuiDetails> getManufacturerDetailsForOuiSet(Set<String> ouiSet) {
LOG.debug("calling getManufacturerDetailsForOuiList, ouiSet.size={}",ouiSet==null?0:ouiSet.size());
if (CollectionUtils.isEmpty(ouiSet)) {
return new HashMap<>();
}
HttpEntity<String> request = new HttpEntity<String>( manufacturer.toString(), headers );
ResponseEntity<Manufacturer> responseEntity = restTemplate.postForEntity(
getBaseUrl(),
request, Manufacturer.class);
Manufacturer ret = responseEntity.getBody();
LOG.debug("completed manufacturer.create {} ", ret);
return ret;
}
@Override
public Manufacturer get(long manufacturerId) {
LOG.debug("calling manufacturer.get {} ", manufacturerId);
ResponseEntity<Manufacturer> responseEntity = restTemplate.getForEntity(
getBaseUrl()
+"?manufacturerId={manufacturerId}",
Manufacturer.class, manufacturerId);
Manufacturer ret = responseEntity.getBody();
LOG.debug("completed manufacturer.get {} ", ret);
return ret;
}
@Override
public Manufacturer getOrNull(long manufacturerId) {
LOG.debug("calling manufacturer.getOrNull {} ", manufacturerId);
ResponseEntity<Manufacturer> responseEntity = restTemplate.getForEntity(
getBaseUrl()
+"/orNull?manufacturerId={manufacturerId}",
Manufacturer.class, manufacturerId);
Manufacturer ret = responseEntity.getBody();
LOG.debug("completed manufacturer.getOrNull {} ", ret);
return ret;
}
@Override
public List<Manufacturer> get(Set<Long> manufacturerIdSet) {
LOG.debug("get({})", manufacturerIdSet);
if (manufacturerIdSet == null || manufacturerIdSet.isEmpty()) {
return Collections.emptyList();
Map<String, ManufacturerOuiDetails> ret;
if(ouiSet.size() <= MAX_OUIS_PER_REQUEST) {
ret = getManufacturueDetailsForOuiSetImpl(ouiSet);
}
String setString = manufacturerIdSet.toString().substring(1, manufacturerIdSet.toString().length() - 1);
try {
ResponseEntity<List<Manufacturer>> responseEntity = restTemplate.exchange(
getBaseUrl() + "/inSet?manufacturerIdSet={manufacturerIdSet}", HttpMethod.GET,
null, Manufacturer_LIST_CLASS_TOKEN, setString);
List<Manufacturer> result = responseEntity.getBody();
if (null == result) {
result = Collections.emptyList();
else {
List<Future<Map<String, ManufacturerOuiDetails>>> futures = new ArrayList<>();
Set<String> subSet = new HashSet<>(MAX_OUIS_PER_REQUEST);
for(String oui: ouiSet) {
subSet.add(oui);
if(subSet.size()>=MAX_OUIS_PER_REQUEST) {
futures.add(asyncInvokator.getManufacturerDetailsForOuiSet(this,new HashSet<>(subSet)));
subSet.clear();
}
}
LOG.debug("get({}) return {} entries", manufacturerIdSet, result.size());
return result;
} catch (Exception exp) {
LOG.error("getAllInSet({}) exception ", manufacturerIdSet, exp);
throw exp;
futures.add(asyncInvokator.getManufacturerDetailsForOuiSet(this,subSet));
ret = new HashMap<>();
for(Future<Map<String, ManufacturerOuiDetails>> future : futures) {
Map<String, ManufacturerOuiDetails> partialResult;
try {
partialResult = future.get();
} catch (InterruptedException | ExecutionException e) {
throw new GenericErrorException("Unable to get result", e);
}
if(partialResult != null) {
ret.putAll(partialResult);
}
}
}
}
@Override
public PaginationResponse<Manufacturer> getForCustomer(int customerId, List<ColumnAndSort> sortBy,
PaginationContext<Manufacturer> context) {
LOG.debug("calling getForCustomer( {}, {}, {} )", customerId, sortBy, context);
ResponseEntity<PaginationResponse<Manufacturer>> responseEntity = restTemplate.exchange(
getBaseUrl()
+ "/forCustomer?customerId={customerId}&sortBy={sortBy}&paginationContext={paginationContext}",
HttpMethod.GET, null, Manufacturer_PAGINATION_RESPONSE_CLASS_TOKEN, customerId, sortBy, context);
PaginationResponse<Manufacturer> ret = responseEntity.getBody();
LOG.debug("completed getForCustomer {} ", ret.getItems().size());
LOG.debug("completed getManufacturerDetailsForOuiList and found {} records", ret.size());
return ret;
}
@Override
public Manufacturer update(Manufacturer manufacturer) {
LOG.debug("calling manufacturer.update {} ", manufacturer);
}
if (BaseJsonModel.hasUnsupportedValue(manufacturer)) {
LOG.error("Failed to update Manufacturer, unsupported value in {}", manufacturer);
throw new DsDataValidationException("Manufacturer contains unsupported value");
Map<String, ManufacturerOuiDetails> getManufacturueDetailsForOuiSetImpl(Set<String> ouiSet) {
Map<String, ManufacturerOuiDetails> ret;
String ouiSetStr = null;
if (ouiSet != null && !ouiSet.isEmpty()) {
ouiSetStr = ouiSet.toString();
// remove [] around the string, otherwise will get:
// Failed to convert value of type 'java.lang.String' to required
// type 'java.util.Set'; nested exception is
// java.lang.NumberFormatException: For input string: "[690]"
ouiSetStr = ouiSetStr.substring(1, ouiSetStr.length() - 1);
}
HttpEntity<String> request = new HttpEntity<String>( manufacturer.toString(), headers );
ResponseEntity<Manufacturer> responseEntity = restTemplate.exchange(
getBaseUrl(),
HttpMethod.PUT, request, Manufacturer.class);
Manufacturer ret = responseEntity.getBody();
LOG.debug("completed manufacturer.update {} ", ret);
ResponseEntity<Map<String, ManufacturerOuiDetails>> responseEntity = restTemplate.exchange(
getBaseUrl() + "/oui/list?ouiList={ouiSetStr}" , HttpMethod.GET, null,
manufacturerOuiDetailsMapClassToken, ouiSetStr);
ret = responseEntity.getBody();
return ret;
}
@Override
public Manufacturer delete(long manufacturerId) {
LOG.debug("calling manufacturer.delete {} ", manufacturerId);
public ManufacturerOuiDetails updateOuiAlias(ManufacturerOuiDetails ouiDetails) {
LOG.debug("calling updateOuiAlias");
HttpEntity<ManufacturerOuiDetails> request = new HttpEntity<>(ouiDetails, headers);
ResponseEntity<ManufacturerOuiDetails> responseEntity = restTemplate.exchange(
getBaseUrl() + "/oui/alias",
HttpMethod.PUT, request, ManufacturerOuiDetails.class);
ManufacturerOuiDetails ret = responseEntity.getBody();
LOG.debug("completed updateOuiAlias and updated {} ", ret);
ResponseEntity<Manufacturer> responseEntity = restTemplate.exchange(
getBaseUrl()
+"?manufacturerId={manufacturerId}", HttpMethod.DELETE,
null, Manufacturer.class, manufacturerId);
Manufacturer ret = responseEntity.getBody();
LOG.debug("completed manufacturer.delete {} ", ret);
return ret;
}
}
@Override
public List<String> getAliasValuesThatBeginWith(String prefix, int maxResults) {
LOG.debug("calling getStoredAliasValuesThatBeginWith");
List<String> result = new ArrayList<>();
if (prefix == null || prefix.length() == 0) {
return result;
}
ResponseEntity<List<String>> responseEntity = restTemplate.exchange(getBaseUrl()
+ "/oui/alias?prefix={prefix}&maxResults={maxResults}", HttpMethod.GET, null, stringListClassToken, prefix, maxResults);
result = responseEntity.getBody();
LOG.debug("completed getStoredAliasValuesThatBeginWith and found {} records", result.size());
return result;
}
public String getBaseUrl() {
if(baseUrl==null) {
@@ -187,5 +319,4 @@ public class ManufacturerServiceRemote extends BaseRemoteClient implements Manuf
return baseUrl;
}
}

View File

@@ -3,17 +3,17 @@ package com.telecominfraproject.wlan.manufacturer;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.zip.GZIPOutputStream;
import org.junit.Before;
import org.junit.Test;
@@ -21,15 +21,15 @@ import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.util.Base64Utils;
import com.telecominfraproject.wlan.core.model.pagination.ColumnAndSort;
import com.telecominfraproject.wlan.core.model.pagination.PaginationContext;
import com.telecominfraproject.wlan.core.model.pagination.PaginationResponse;
import com.telecominfraproject.wlan.core.model.pagination.SortOrder;
import com.telecominfraproject.wlan.core.model.json.GenericResponse;
import com.telecominfraproject.wlan.datastore.exceptions.DsConcurrentModificationException;
import com.telecominfraproject.wlan.datastore.exceptions.DsEntityNotFoundException;
import com.telecominfraproject.wlan.manufacturer.models.ManufacturerDetailsRecord;
import com.telecominfraproject.wlan.manufacturer.models.ManufacturerOuiDetails;
import com.telecominfraproject.wlan.remote.tests.BaseRemoteTest;
import com.telecominfraproject.wlan.manufacturer.models.Manufacturer;
/**
* @author dtoptygin
*
@@ -48,243 +48,317 @@ public class ManufacturerServiceRemoteTest extends BaseRemoteTest {
configureBaseUrl("tip.wlan.manufacturerServiceBaseUrl");
}
@Test
public void testManufacturerCRUD() throws Exception {
public void testClientManufacturerDetailsCRUD() {
final String companyName1 = "Complex Company Inc.";
final String companyAlias1 = "Complex";
//Create new Manufacturer - success
Manufacturer manufacturer = new Manufacturer();
manufacturer.setSampleStr("test");
Manufacturer ret = remoteInterface.create(manufacturer);
assertNotNull(ret);
//CREATE test
ManufacturerDetailsRecord manufacturerDetails = new ManufacturerDetailsRecord();
manufacturerDetails.setManufacturerName(companyName1);
manufacturerDetails.setManufacturerAlias(companyAlias1);
ret = remoteInterface.get(ret.getId());
assertEqualManufacturers(manufacturer, ret);
ret = remoteInterface.getOrNull(ret.getId());
assertEqualManufacturers(manufacturer, ret);
ManufacturerDetailsRecord ret = remoteInterface.createManufacturerDetails(manufacturerDetails);
assertNull(remoteInterface.getOrNull(-1));
//Update success
ret.setSampleStr(ret.getSampleStr()+"_modified");
//TODO: add more Manufacturer fields to modify here
//GET by id
ret = remoteInterface.getById(ret.getId());
assertTrue(manufacturerDetails.equals(ret));
Manufacturer updatedManufacturer = remoteInterface.update(ret);
assertEqualManufacturers(ret, updatedManufacturer);
//Update - failure because of concurrent modification
// GET Alias starts with test.
List<String> aliasList = remoteInterface.getAliasValuesThatBeginWith("Com", -1);
assertTrue(aliasList.size() == 1);
assertTrue(aliasList.get(0).equals(companyAlias1));
aliasList = remoteInterface.getAliasValuesThatBeginWith("Sim", 2000);
assertTrue(aliasList.size() == 0);
//UPDATE test - success
manufacturerDetails = ret;
manufacturerDetails.setManufacturerAlias("New Alias");
ret = remoteInterface.updateManufacturerDetails(manufacturerDetails);
assertTrue(manufacturerDetails.equals(ret));
//UPDATE test - fail because of concurrent modification exception
try{
remoteInterface.update(ret);
ManufacturerDetailsRecord manufacturerDetailsConcurrentUpdate = manufacturerDetails.clone();
manufacturerDetailsConcurrentUpdate.setLastModifiedTimestamp(manufacturerDetailsConcurrentUpdate.getLastModifiedTimestamp()-1);
manufacturerDetailsConcurrentUpdate.setManufacturerAlias("This should not work");
remoteInterface.updateManufacturerDetails(manufacturerDetailsConcurrentUpdate);
fail("failed to detect concurrent modification");
}catch(RuntimeException e){
//expected it
}
//Update - failure because of non-existent record
try{
updatedManufacturer.setId(-1L);
remoteInterface.update(updatedManufacturer);
fail("updated non-existent Manufacturer");
}catch(RuntimeException e){
//expected it
}
//Delete - failure because of non-existent record
try{
remoteInterface.delete(-1);
fail("deleted non-existent Manufacturer");
}catch(RuntimeException e){
//expected it
}catch (DsConcurrentModificationException e) {
// expected it
}
//Delete - success
remoteInterface.delete(ret.getId());
//DELETE Test
remoteInterface.deleteManufacturerDetails(ret.getId());
try{
remoteInterface.get(ret.getId());
fail("Manufacturer was not deleted");
}catch(RuntimeException e){
//expected it
remoteInterface.deleteManufacturerDetails(ret.getId());
fail("failed to delete ClientManufacturerDetails");
}catch (Exception e) {
// expected it
}
}
@Test
public void testGetAllInSet() {
Set<Manufacturer> createdSet = new HashSet<>();
Set<Manufacturer> createdTestSet = new HashSet<>();
//Create test Manufacturers
Manufacturer manufacturer = new Manufacturer();
int customerId = getNextCustomerId();
public void testOuiDatastoreOperations() throws Exception {
final String companyName1 = "Complex Company Inc.";
final String companyName2 = "Simple Co.";
final String companyName3 = "Simplor Co.";
for (int i = 0; i < 10; i++) {
manufacturer.setSampleStr("test_" + i);
manufacturer.setCustomerId(customerId);
Manufacturer ret = remoteInterface.create(manufacturer);
// Only keep track of half of the created ones for testing
if (i % 2 == 0) {
createdTestSet.add(ret.clone());
final String companyAlias1 = "Complex";
final String companyAlias2 = "Simple";
final String companyAlias3 = null;
final String oui1 = "0000a1";
final String oui2 = "0000a2";
final String oui3 = "0000a3";
// CREATE test
ManufacturerOuiDetails ouiDetails1 = new ManufacturerOuiDetails();
ouiDetails1.setOui(oui1);
ouiDetails1.setManufacturerName(companyName1);
ouiDetails1.setManufacturerAlias(companyAlias1);
ManufacturerOuiDetails ret1 = remoteInterface.createOuiDetails(ouiDetails1);
assertTrue(ouiDetails1.equals(ret1));
// GET by oui test
ret1 = remoteInterface.getByOui(oui1);
assertTrue(ouiDetails1.equals(ret1));
// GET by manufacturer tests
ManufacturerOuiDetails ouiDetails2 = new ManufacturerOuiDetails();
ouiDetails2.setOui(oui2);
ouiDetails2.setManufacturerName(companyName2);
ouiDetails2.setManufacturerAlias(companyAlias2);
ManufacturerOuiDetails ret2 = remoteInterface.createOuiDetails(ouiDetails2);
ManufacturerOuiDetails ouiDetails3 = new ManufacturerOuiDetails();
ouiDetails3.setOui(oui3);
ouiDetails3.setManufacturerName(companyName3);
ouiDetails3.setManufacturerAlias(companyAlias3);
ManufacturerOuiDetails ret3 = remoteInterface.createOuiDetails(ouiDetails3);
List<String> ouiResultList = remoteInterface.getOuiListForManufacturer(companyName1, true);
assertTrue(ouiResultList.size() == 1);
assertTrue(ouiDetails1.equals(remoteInterface.getByOui(ouiResultList.get(0))));
ouiResultList = remoteInterface.getOuiListForManufacturer("Bad Name", true);
assertTrue(ouiResultList.size() == 0);
ouiResultList = remoteInterface.getOuiListForManufacturer("Compl", false);
assertTrue(ouiResultList.size() == 1);
assertTrue(ouiDetails1.equals(remoteInterface.getByOui(ouiResultList.get(0))));
ouiResultList = remoteInterface.getOuiListForManufacturer("ompl", false);
assertTrue(ouiResultList.size() == 0);
ouiResultList = remoteInterface.getOuiListForManufacturer("Simp", false);
assertTrue(ouiResultList.size() == 2);
for (int i = 0 ; i < ouiResultList.size(); i++) {
if (ouiResultList.get(i).equals(oui2)) {
assertTrue(ouiDetails2.equals(remoteInterface.getByOui(ouiResultList.get(i))));
} else if (ouiResultList.get(i).equals(oui3)) {
assertTrue(ouiDetails3.equals(remoteInterface.getByOui(ouiResultList.get(i))));
} else {
createdSet.add(ret.clone());
fail("Unknown OUI was found: " + ouiResultList.get(i));
}
}
// GET ALL Manufacturer data test
List<ManufacturerOuiDetails> allManufacturerData = remoteInterface.getAllManufacturerData();
assertEquals(3, allManufacturerData.size());
for (int i = 0 ; i < allManufacturerData.size(); i++) {
if (allManufacturerData.get(i).getOui().equals(oui2)) {
assertTrue(ouiDetails2.equals(allManufacturerData.get(i)));
} else if (allManufacturerData.get(i).getOui().equals(oui3)) {
assertTrue(ouiDetails3.equals(allManufacturerData.get(i)));
} else if (allManufacturerData.get(i).getOui().equals(oui1)) {
assertTrue(ouiDetails1.equals(allManufacturerData.get(i)));
} else {
if (allManufacturerData.get(i).getManufacturerName().equals("testname") && allManufacturerData.get(i).getManufacturerAlias().equals("testalias")) {
// This is the test record from the test data resources.
continue;
}
fail("Unknown OUI was found: " + ouiResultList.get(i));
}
}
// GET by OUI list test:
Map<String, ManufacturerOuiDetails> ouiListSearchResult = remoteInterface.getManufacturerDetailsForOuiSet(null);
assertTrue(ouiListSearchResult.size() == 0);
Set<String> ouiList = new HashSet<>();
ouiList.add(oui1);
ouiListSearchResult = remoteInterface.getManufacturerDetailsForOuiSet(ouiList);
assertTrue(ouiListSearchResult.size() == 1);
assertTrue(ouiListSearchResult.get(oui1).equals(ret1));
ouiList.add(oui2);
ouiListSearchResult = remoteInterface.getManufacturerDetailsForOuiSet(ouiList);
assertTrue(ouiListSearchResult.size() == 2);
assertTrue(ouiListSearchResult.get(oui1).equals(ret1));
assertTrue(ouiListSearchResult.get(oui2).equals(ret2));
ouiList.add(oui3);
ouiListSearchResult = remoteInterface.getManufacturerDetailsForOuiSet(ouiList);
assertTrue(ouiListSearchResult.size() == 3);
assertTrue(ouiListSearchResult.get(oui1).equals(ret1));
assertTrue(ouiListSearchResult.get(oui2).equals(ret2));
assertTrue(ouiListSearchResult.get(oui3).equals(ret3));
for(int i = 0 ; i < 900; i++) {
ouiList.add(String.format("%06d", i));
}
ouiListSearchResult = remoteInterface.getManufacturerDetailsForOuiSet(ouiList);
assertEquals(3,ouiListSearchResult.size());
assertTrue(ouiListSearchResult.get(oui1).equals(ret1));
assertTrue(ouiListSearchResult.get(oui2).equals(ret2));
assertTrue(ouiListSearchResult.get(oui3).equals(ret3));
// Use only the IDs from the test set to retrieve records.
Set<Long> testSetIds = new HashSet<>();
for (Manufacturer c : createdTestSet) {
testSetIds.add(c.getId());
// CREATE without manufacturer fail test
ManufacturerOuiDetails badCreate = new ManufacturerOuiDetails();
badCreate.setOui(oui3);
badCreate.setManufacturerName(null);
badCreate.setManufacturerAlias(companyAlias2);
try {
remoteInterface.createOuiDetails(badCreate);
fail("Should not be able to create OUI details with a null manufacturer name.");
} catch (Exception e) {
// Expected
}
assertEquals(5, testSetIds.size());
List<Manufacturer> manufacturersRetrievedByIdSet = remoteInterface.get(testSetIds);
assertEquals(5, manufacturersRetrievedByIdSet.size());
for (Manufacturer c : manufacturersRetrievedByIdSet) {
assertTrue(createdTestSet.contains(c));
badCreate.setManufacturerName("");
try {
remoteInterface.createOuiDetails(badCreate);
fail("Should not be able to create OUI details with a blank manufacturer name.");
} catch (Exception e) {
// Expected
}
// Make sure the manufacturers from the non-test set are not in the list
for (Manufacturer c : manufacturersRetrievedByIdSet) {
assertTrue(!createdSet.contains(c));
// CREATE test where OUI already exists.
badCreate.setManufacturerName("Something that would work");
try {
remoteInterface.createOuiDetails(badCreate);
fail("Should not be able to create OUI details for a OUI alread in the datastore.");
} catch (Exception e) {
// Expected
}
// Clean up after test
for (Manufacturer c : createdSet) {
remoteInterface.delete(c.getId());
// UPDATE alias test
ManufacturerOuiDetails update = new ManufacturerOuiDetails();
update.setOui(oui1);
update.setManufacturerName(companyName1);
update.setManufacturerAlias("UpdatedAlias");
remoteInterface.updateOuiAlias(update);
ManufacturerOuiDetails aliasUpdate = remoteInterface.getByOui(oui1);
assertTrue(aliasUpdate.getManufacturerAlias().equals("UpdatedAlias"));
// GET Alias starts with test.
List<String> aliasList = remoteInterface.getAliasValuesThatBeginWith("Upda", -1);
assertTrue(aliasList.size() == 1);
assertTrue(aliasList.get(0).equals("UpdatedAlias"));
aliasList = remoteInterface.getAliasValuesThatBeginWith("Sim", 2000);
assertTrue(aliasList.size() == 1);
// DELETE test
remoteInterface.deleteOuiDetails(ret1.getOui());
try{
remoteInterface.deleteOuiDetails(ret1.getOui());
fail("failed to delete ClientOuiDetails");
}catch (DsEntityNotFoundException e) {
// expected it
}
for (Manufacturer c : createdTestSet) {
remoteInterface.delete(c.getId());
}
// Clean up:
remoteInterface.deleteOuiDetails(ret2.getOui());
remoteInterface.deleteOuiDetails(ret3.getOui());
}
@Test
public void testBadUpload() throws Exception {
// Try to upload a invalid file
GenericResponse result = remoteInterface.uploadOuiDataFile("This is Bad Data", new byte[] { 0x1, 0x2 });
assertFalse("uploaded bad file", result.isSuccess());
}
@Test
public void testManufacturerPagination()
{
//create 100 Manufacturers
Manufacturer mdl;
int customerId_1 = getNextCustomerId();
int customerId_2 = getNextCustomerId();
int apNameIdx = 0;
for(int i = 0; i< 50; i++){
mdl = new Manufacturer();
mdl.setCustomerId(customerId_1);
mdl.setSampleStr("qr_"+apNameIdx);
apNameIdx++;
remoteInterface.create(mdl);
}
for(int i = 0; i< 50; i++){
mdl = new Manufacturer();
mdl.setCustomerId(customerId_2);
mdl.setSampleStr("qr_"+apNameIdx);
apNameIdx++;
remoteInterface.create(mdl);
}
//paginate over Manufacturers
List<ColumnAndSort> sortBy = new ArrayList<>();
sortBy.addAll(Arrays.asList(new ColumnAndSort("sampleStr")));
PaginationContext<Manufacturer> context = new PaginationContext<>(10);
PaginationResponse<Manufacturer> page1 = remoteInterface.getForCustomer(customerId_1, sortBy, context);
PaginationResponse<Manufacturer> page2 = remoteInterface.getForCustomer(customerId_1, sortBy, page1.getContext());
PaginationResponse<Manufacturer> page3 = remoteInterface.getForCustomer(customerId_1, sortBy, page2.getContext());
PaginationResponse<Manufacturer> page4 = remoteInterface.getForCustomer(customerId_1, sortBy, page3.getContext());
PaginationResponse<Manufacturer> page5 = remoteInterface.getForCustomer(customerId_1, sortBy, page4.getContext());
PaginationResponse<Manufacturer> page6 = remoteInterface.getForCustomer(customerId_1, sortBy, page5.getContext());
PaginationResponse<Manufacturer> page7 = remoteInterface.getForCustomer(customerId_1, sortBy, page6.getContext());
//verify returned pages
assertEquals(10, page1.getItems().size());
assertEquals(10, page2.getItems().size());
assertEquals(10, page3.getItems().size());
assertEquals(10, page4.getItems().size());
assertEquals(10, page5.getItems().size());
page1.getItems().forEach(e -> assertEquals(customerId_1, e.getCustomerId()) );
page2.getItems().forEach(e -> assertEquals(customerId_1, e.getCustomerId()) );
page3.getItems().forEach(e -> assertEquals(customerId_1, e.getCustomerId()) );
page4.getItems().forEach(e -> assertEquals(customerId_1, e.getCustomerId()) );
page5.getItems().forEach(e -> assertEquals(customerId_1, e.getCustomerId()) );
assertEquals(0, page6.getItems().size());
assertEquals(0, page7.getItems().size());
assertFalse(page1.getContext().isLastPage());
assertFalse(page2.getContext().isLastPage());
assertFalse(page3.getContext().isLastPage());
assertFalse(page4.getContext().isLastPage());
assertFalse(page5.getContext().isLastPage());
assertTrue(page6.getContext().isLastPage());
assertTrue(page7.getContext().isLastPage());
List<String> expectedPage3Strings = new ArrayList< >(Arrays.asList(new String[]{"qr_27", "qr_28", "qr_29", "qr_3", "qr_30", "qr_31", "qr_32", "qr_33", "qr_34", "qr_35" }));
List<String> actualPage3Strings = new ArrayList<>();
page3.getItems().stream().forEach( ce -> actualPage3Strings.add(ce.getSampleStr()) );
assertEquals(expectedPage3Strings, actualPage3Strings);
// System.out.println("================================");
// for(Manufacturer pmdl: page3.getItems()){
// System.out.println(pmdl);
// }
// System.out.println("================================");
// System.out.println("Context: "+ page3.getContext());
// System.out.println("================================");
//test first page of the results with empty sort order -> default sort order (by Id ascending)
PaginationResponse<Manufacturer> page1EmptySort = remoteInterface.getForCustomer(customerId_1, Collections.emptyList(), context);
assertEquals(10, page1EmptySort.getItems().size());
List<String> expectedPage1EmptySortStrings = new ArrayList<>(Arrays.asList(new String[]{"qr_0", "qr_1", "qr_2", "qr_3", "qr_4", "qr_5", "qr_6", "qr_7", "qr_8", "qr_9" }));
List<String> actualPage1EmptySortStrings = new ArrayList<>();
page1EmptySort.getItems().stream().forEach( ce -> actualPage1EmptySortStrings.add(ce.getSampleStr()) );
assertEquals(expectedPage1EmptySortStrings, actualPage1EmptySortStrings);
//test first page of the results with null sort order -> default sort order (by Id ascending)
PaginationResponse<Manufacturer> page1NullSort = remoteInterface.getForCustomer(customerId_1, null, context);
assertEquals(10, page1NullSort.getItems().size());
List<String> expectedPage1NullSortStrings = new ArrayList<>(Arrays.asList(new String[]{"qr_0", "qr_1", "qr_2", "qr_3", "qr_4", "qr_5", "qr_6", "qr_7", "qr_8", "qr_9" }));
List<String> actualPage1NullSortStrings = new ArrayList<>();
page1NullSort.getItems().stream().forEach( ce -> actualPage1NullSortStrings.add(ce.getSampleStr()) );
assertEquals(expectedPage1NullSortStrings, actualPage1NullSortStrings);
//test first page of the results with sort descending order by a sampleStr property
PaginationResponse<Manufacturer> page1SingleSortDesc = remoteInterface.getForCustomer(customerId_1, Collections.singletonList(new ColumnAndSort("sampleStr", SortOrder.desc)), context);
assertEquals(10, page1SingleSortDesc.getItems().size());
List<String> expectedPage1SingleSortDescStrings = new ArrayList< >(Arrays.asList(new String[]{"qr_9", "qr_8", "qr_7", "qr_6", "qr_5", "qr_49", "qr_48", "qr_47", "qr_46", "qr_45" }));
List<String> actualPage1SingleSortDescStrings = new ArrayList<>();
page1SingleSortDesc.getItems().stream().forEach( ce -> actualPage1SingleSortDescStrings.add(ce.getSampleStr()) );
assertEquals(expectedPage1SingleSortDescStrings, actualPage1SingleSortDescStrings);
}
private void assertEqualManufacturers(
Manufacturer expected,
Manufacturer actual) {
public void testPopulateOuiDatastore() throws Exception {
Map<String, String> knownTestMacs = new HashMap<>();
knownTestMacs.put("bc3aea", "GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD");
knownTestMacs.put("e8bba8", "GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD");
knownTestMacs.put("8c0ee3", "GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD");
knownTestMacs.put("7c4ca5", "BSkyB Ltd");
knownTestMacs.put("0012f2", "Brocade Communications Systems, Inc.");
knownTestMacs.put("001bed", "Brocade Communications Systems, Inc.");
knownTestMacs.put("002438", "Brocade Communications Systems, Inc.");
String fileName = "test-oui.txt";
InputStream inFile = ManufacturerServiceRemoteTest.class.getResource(fileName).openStream();
ByteArrayOutputStream compressedStream = new ByteArrayOutputStream();
GZIPOutputStream gzOut = new GZIPOutputStream(compressedStream);
byte[] buffer = new byte[512];
while(inFile.available() > 0) {
int read = inFile.read(buffer);
gzOut.write(buffer, 0, read);
}
gzOut.finish();
byte[] base64GzippedContent = Base64Utils.encode(compressedStream.toByteArray());
remoteInterface.uploadOuiDataFile(fileName, base64GzippedContent);
List<ManufacturerOuiDetails> entireMfrDatastore = remoteInterface.getAllManufacturerData();
assertEquals(knownTestMacs.size(), entireMfrDatastore.size());
for (ManufacturerOuiDetails record : entireMfrDatastore) {
if (knownTestMacs.containsKey(record.getOui())) {
if (record.getManufacturerName().equals(knownTestMacs.get(record.getOui()))) {
continue;
}
fail("Incorrect mfr name found. Expected: " + knownTestMacs.get(record.getOui()) + ", found: " + record.getManufacturerName());
} else {
if (record.getManufacturerName().equals("testname") && record.getManufacturerAlias().equals("testalias")) {
// This is the test record from the test data resources.
continue;
}
fail("Unknown OUI was found: " + record);
}
}
// Populate it again with the same file, verify the results are the same
remoteInterface.uploadOuiDataFile(fileName, base64GzippedContent);
entireMfrDatastore.clear();
entireMfrDatastore = remoteInterface.getAllManufacturerData();
assertEquals(knownTestMacs.size(), entireMfrDatastore.size());
for (ManufacturerOuiDetails record : entireMfrDatastore) {
if (knownTestMacs.containsKey(record.getOui())) {
if (record.getManufacturerName().equals(knownTestMacs.get(record.getOui()))) {
continue;
}
fail("Incorrect mfr name found. Expected: " + knownTestMacs.get(record.getOui()) + ", found: " + record.getManufacturerName());
} else {
if (record.getManufacturerName().equals("testname") && record.getManufacturerAlias().equals("testalias")) {
// This is the test record from the test data resources.
continue;
}
fail("Unknown OUI was found: " + record);
}
}
// Clean up:
for(ManufacturerOuiDetails record : entireMfrDatastore) {
if (knownTestMacs.containsKey(record.getOui())) {
remoteInterface.deleteOuiDetails(record.getOui());
} else {
if (record.getManufacturerName().equals("testname") && record.getManufacturerAlias().equals("testalias")) {
// This is the test record from the test data resources.
continue;
}
fail("Unknown OUI was found: " + record);
}
}
assertEquals(expected.getSampleStr(), actual.getSampleStr());
//TODO: add more fields to check here
}
}

View File

@@ -0,0 +1,45 @@
OUI/MA-L Organization
company_id Organization
Address
BC-3A-EA (hex) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD
BC3AEA (base 16) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD
NO.18 HAIBIN ROAD,WUSHA,CHANG'AN,DONGGUAN,GUANGDONG,CHINA
DONGGUAN GUANGDONG 523860
CN
E8-BB-A8 (hex) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD
E8BBA8 (base 16) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD
NO.18 HAIBIN ROAD,WUSHA,CHANG'AN,DONGGUAN,GUANGDONG,CHINA
DONGGUAN GUANGDONG 523860
CN
8C-0E-E3 (hex) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD
8C0EE3 (base 16) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD
NO.18 HAIBIN ROAD,WUSHA,CHANG'AN
DONGGUAN GUANGDONG 523860
CN
7C-4C-A5 (hex) BSkyB Ltd
7C4CA5 (base 16) BSkyB Ltd
130 Kings Road
Brentwood Essex CM14 4EQ
GB
00-12-F2 (hex) Brocade Communications Systems, Inc.
0012F2 (base 16) Brocade Communications Systems, Inc.
130 Holger Way
San Jose CA 95134
US
00-1B-ED (hex) Brocade Communications Systems, Inc.
001BED (base 16) Brocade Communications Systems, Inc.
130 Holger Way
San Jose CA 95134
US
00-24-38 (hex) Brocade Communications Systems, Inc.
002438 (base 16) Brocade Communications Systems, Inc.
130 Holger Way
San Jose CA 95134
US

View File

@@ -2,228 +2,183 @@ package com.telecominfraproject.wlan.manufacturer.controller;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.Map;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Base64Utils;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import com.telecominfraproject.wlan.cloudeventdispatcher.CloudEventDispatcherInterface;
import com.telecominfraproject.wlan.core.model.json.BaseJsonModel;
import com.telecominfraproject.wlan.core.model.pagination.ColumnAndSort;
import com.telecominfraproject.wlan.core.model.pagination.PaginationContext;
import com.telecominfraproject.wlan.core.model.pagination.PaginationResponse;
import com.telecominfraproject.wlan.datastore.exceptions.DsDataValidationException;
import com.telecominfraproject.wlan.systemevent.models.SystemEvent;
import com.telecominfraproject.wlan.manufacturer.datastore.ManufacturerDatastore;
import com.telecominfraproject.wlan.manufacturer.models.Manufacturer;
import com.telecominfraproject.wlan.manufacturer.models.events.ManufacturerAddedEvent;
import com.telecominfraproject.wlan.manufacturer.models.events.ManufacturerChangedEvent;
import com.telecominfraproject.wlan.manufacturer.models.events.ManufacturerRemovedEvent;
import com.telecominfraproject.wlan.core.model.json.GenericResponse;
import com.telecominfraproject.wlan.datastore.exceptions.DsEntityNotFoundException;
import com.telecominfraproject.wlan.manufacturer.datastore.ManufacturerDatastoreInterface;
import com.telecominfraproject.wlan.manufacturer.models.ManufacturerDetailsRecord;
import com.telecominfraproject.wlan.manufacturer.models.ManufacturerOuiDetails;
/**
* @author dtoptygin
* @author mpreston
*
*/
@RestController
@Transactional
@RequestMapping(value="/api/manufacturer")
@RequestMapping(value = "/api/manufacturer")
public class ManufacturerController {
private static final Logger LOG = LoggerFactory.getLogger(ManufacturerController.class);
public static class ListOfManufacturers extends ArrayList<Manufacturer> {
private static final long serialVersionUID = 3070319062835500930L;
@Autowired
private ManufacturerDatastoreInterface manufacturerDatastore;
public static class ListOfMfrOuiDetailRecords extends ArrayList<ManufacturerOuiDetails> {
private static final long serialVersionUID = -8035392255039609079L;
}
@Autowired private ManufacturerDatastore manufacturerDatastore;
@Autowired private CloudEventDispatcherInterface cloudEventDispatcher;
/**
* Creates new Manufacturer.
*
* @param Manufacturer
* @return stored Manufacturer object
* @throws RuntimeException if Manufacturer record already exists
*/
@RequestMapping(method=RequestMethod.POST)
public Manufacturer create(@RequestBody Manufacturer manufacturer ) {
LOG.debug("Creating Manufacturer {}", manufacturer);
if (BaseJsonModel.hasUnsupportedValue(manufacturer)) {
LOG.error("Failed to create Manufacturer, request contains unsupported value: {}", manufacturer);
throw new DsDataValidationException("Manufacturer contains unsupported value");
}
long ts = System.currentTimeMillis();
if (manufacturer.getCreatedTimestamp() == 0) {
manufacturer.setCreatedTimestamp(ts);
}
manufacturer.setLastModifiedTimestamp(ts);
Manufacturer ret = manufacturerDatastore.create(manufacturer);
LOG.debug("Created Manufacturer {}", ret);
ManufacturerAddedEvent event = new ManufacturerAddedEvent(ret);
publishEvent(event);
@PostMapping(value = "/oui")
public ManufacturerOuiDetails createOuiDetails(@RequestBody ManufacturerOuiDetails ouiDetails) {
LOG.debug("Creating OUI details {} ", ouiDetails);
ManufacturerOuiDetails ret = manufacturerDatastore.createOuiDetails(ouiDetails);
LOG.debug("Created OUI details {} ", ouiDetails);
return ret;
}
@DeleteMapping(value = "/oui")
public ManufacturerOuiDetails deleteOuiDetails(@RequestParam String oui) {
LOG.debug("Deleteing OUI details identified by OUI {} ", oui);
ManufacturerOuiDetails ret = manufacturerDatastore.deleteOuiDetails(oui);
LOG.debug("Removed OUI details {} ", ret);
return ret;
}
@GetMapping(value = "/oui/forManufacturer")
public List<String> getOuiListForManufacturer(@RequestParam String manufacturer, @RequestParam boolean exactMatch) {
LOG.debug("Retrieving all OUIs for manufacturer {}, exactMatch={} ", manufacturer, exactMatch);
List<String> ret = manufacturerDatastore.getOuiListForManufacturer(manufacturer, exactMatch);
LOG.debug("Retrieved found the following OUIs for manufacturer {}: {}", manufacturer, ret);
return ret;
}
@GetMapping(value = "/oui")
public ManufacturerOuiDetails getByOui(@RequestParam String oui) {
LOG.debug("Retrieving OUI details for OUI {} ", oui);
ManufacturerOuiDetails ret = manufacturerDatastore.getByOui(oui);
LOG.debug("Retrieved OUI details {} ", ret);
return ret;
}
@PostMapping
public ManufacturerDetailsRecord createManufacturerDetails(
@RequestBody ManufacturerDetailsRecord clientManufacturerDetails) {
LOG.debug("Creating Manufacturing Details Record for {} ", clientManufacturerDetails);
ManufacturerDetailsRecord ret = manufacturerDatastore.createManufacturerDetails(clientManufacturerDetails);
LOG.debug("Created Manufacturer details {} ", ret);
return ret;
}
@PutMapping
public ManufacturerDetailsRecord updateManufacturerDetails(
@RequestBody ManufacturerDetailsRecord clientManufacturerDetails) {
LOG.debug("Updating Manufacturing Details Record {} ", clientManufacturerDetails);
ManufacturerDetailsRecord ret = manufacturerDatastore.updateManufacturerDetails(clientManufacturerDetails);
LOG.debug("Updated Manufacturer details {} ", ret);
return ret;
}
@DeleteMapping
public ManufacturerDetailsRecord deleteManufacturerDetails(@RequestParam long id) {
LOG.debug("Removing Manufacturing Details Record {} ", id);
ManufacturerDetailsRecord ret = manufacturerDatastore.deleteManufacturerDetails(id);
LOG.debug("Removed Manufacturer details {} ", ret);
return ret;
}
@GetMapping
public ManufacturerDetailsRecord getById(@RequestParam long id) {
LOG.debug("Retrieving Manufacturing Details Record for id {} ", id);
ManufacturerDetailsRecord ret = manufacturerDatastore.getById(id);
LOG.debug("Retrieved Manufacturer details {} ", ret);
return ret;
}
@GetMapping(value = "/oui/all")
public List<ManufacturerOuiDetails> getAllManufacturerData() {
LOG.debug("Retrieving all Manufacturing Details Records");
List<ManufacturerOuiDetails> ret = manufacturerDatastore.getAllManufacturerData();
LOG.debug("Retrieved {} Manufacturing Details Records", ret.size());
return ret;
}
@PostMapping(value = "/oui/upload", consumes = { MediaType.APPLICATION_OCTET_STREAM_VALUE })
public GenericResponse uploadOuiDataFile(@RequestParam String fileName, @RequestBody byte[] base64GzippedContent) {
LOG.debug("uploadOuiDataFile({})", fileName);
GenericResponse ret;
if (null == base64GzippedContent) {
LOG.error("Unable to load OUI data file {}, missing file content", fileName);
ret = new GenericResponse(false, "missing compressed data file content");
} else {
try {
byte[] gzippedContent = Base64Utils.decode(base64GzippedContent);
ret = manufacturerDatastore.uploadOuiDataFile(fileName, gzippedContent);
} catch (IllegalArgumentException e) {
ret = new GenericResponse(false, "invalid b64 encoded data file content");
}
}
LOG.debug("uploadOuiDataFile({}) returns {}", fileName, ret);
return ret;
}
@GetMapping(value = "/oui/list")
public Map<String, ManufacturerOuiDetails> getManufacturerDetailsForOuiList(
@RequestParam List<String> ouiList) {
LOG.debug("calling getManufacturerDetailsForOuiList ");
return manufacturerDatastore.getManufacturerDetailsForOuiList(ouiList);
}
/**
* Retrieves Manufacturer by id
* @param manufacturerId
* @return Manufacturer for the supplied id
*/
@RequestMapping(method=RequestMethod.GET)
public Manufacturer get(@RequestParam long manufacturerId ) {
@PutMapping(value = "/oui/alias")
public ManufacturerOuiDetails updateOuiAlias(@RequestBody ManufacturerOuiDetails ouiDetails) {
LOG.debug("Updating alias for oui {} to {}", ouiDetails.getOui(), ouiDetails.getManufacturerAlias());
long mfrDetailsId = manufacturerDatastore.getManufacturerDetialsId(ouiDetails.getOui());
LOG.debug("Retrieving Manufacturer {}", manufacturerId);
Manufacturer ret = manufacturerDatastore.get(manufacturerId);
LOG.debug("Retrieved Manufacturer {}", ret);
return ret;
}
/**
* Retrieves Manufacturer by id
* @param manufacturerId
* @return Manufacturer for the supplied id
*/
@RequestMapping(value = "/orNull", method=RequestMethod.GET)
public Manufacturer getOrNull(@RequestParam long manufacturerId ) {
LOG.debug("Retrieving Manufacturer {}", manufacturerId);
Manufacturer ret = manufacturerDatastore.getOrNull(manufacturerId);
LOG.debug("Retrieved Manufacturer {}", ret);
return ret;
}
@RequestMapping(value = "/inSet", method = RequestMethod.GET)
public ListOfManufacturers getAllInSet(@RequestParam Set<Long> manufacturerIdSet) {
LOG.debug("getAllInSet({})", manufacturerIdSet);
try {
List<Manufacturer> result = manufacturerDatastore.get(manufacturerIdSet);
LOG.debug("getAllInSet({}) return {} entries", manufacturerIdSet, result.size());
ListOfManufacturers ret = new ListOfManufacturers();
ret.addAll(result);
return ret;
} catch (Exception exp) {
LOG.error("getAllInSet({}) exception ", manufacturerIdSet, exp);
throw exp;
}
}
@RequestMapping(value = "/forCustomer", method = RequestMethod.GET)
public PaginationResponse<Manufacturer> getForCustomer(@RequestParam int customerId,
@RequestParam List<ColumnAndSort> sortBy,
@RequestParam(required = false) PaginationContext<Manufacturer> paginationContext) {
if(paginationContext == null) {
paginationContext = new PaginationContext<>();
}
LOG.debug("Looking up Manufacturers for customer {} with last returned page number {}",
customerId, paginationContext.getLastReturnedPageNumber());
PaginationResponse<Manufacturer> ret = new PaginationResponse<>();
if (paginationContext.isLastPage()) {
// no more pages available according to the context
LOG.debug(
"No more pages available when looking up Manufacturers for customer {} with last returned page number {}",
customerId, paginationContext.getLastReturnedPageNumber());
ret.setContext(paginationContext);
return ret;
}
PaginationResponse<Manufacturer> onePage = this.manufacturerDatastore
.getForCustomer(customerId, sortBy, paginationContext);
ret.setContext(onePage.getContext());
ret.getItems().addAll(onePage.getItems());
LOG.debug("Retrieved {} Manufacturers for customer {} ", onePage.getItems().size(),
customerId);
return ret;
}
/**
* Updates Manufacturer record
*
* @param Manufacturer
* @return updated Manufacturer object
* @throws RuntimeException if Manufacturer record does not exist or if it was modified concurrently
*/
@RequestMapping(method=RequestMethod.PUT)
public Manufacturer update(@RequestBody Manufacturer manufacturer){
LOG.debug("Updating Manufacturer {}", manufacturer);
if (BaseJsonModel.hasUnsupportedValue(manufacturer)) {
LOG.error("Failed to update Manufacturer, request contains unsupported value: {}", manufacturer);
throw new DsDataValidationException("Manufacturer contains unsupported value");
}
Manufacturer ret = manufacturerDatastore.update(manufacturer);
LOG.debug("Updated Manufacturer {}", ret);
ManufacturerChangedEvent event = new ManufacturerChangedEvent(ret);
publishEvent(event);
return ret;
}
/**
* Deletes Manufacturer record
*
* @param manufacturerId
* @return deleted Manufacturer object
*/
@RequestMapping(method=RequestMethod.DELETE)
public Manufacturer delete(@RequestParam long manufacturerId ) {
LOG.debug("Deleting Manufacturer {}", manufacturerId);
Manufacturer ret = manufacturerDatastore.delete(manufacturerId);
LOG.debug("Deleted Manufacturer {}", ret);
ManufacturerRemovedEvent event = new ManufacturerRemovedEvent(ret);
publishEvent(event);
return ret;
}
private void publishEvent(SystemEvent event) {
if (event == null) {
return;
if (mfrDetailsId != -1) {
ManufacturerDetailsRecord rec = manufacturerDatastore.getById(mfrDetailsId);
rec.setManufacturerAlias(ouiDetails.getManufacturerAlias());
manufacturerDatastore.updateManufacturerDetails(rec);
return ouiDetails;
}
try {
cloudEventDispatcher.publishEvent(event);
} catch (Exception e) {
LOG.error("Failed to publish event : {}", event, e);
}
throw new DsEntityNotFoundException("Unable to update alias as no OUI is in the datastore for " + ouiDetails.getOui());
}
@GetMapping(value = "/oui/alias")
public List<String> getStoredAliasValuesThatBeginWith(@RequestParam String prefix, @RequestParam int maxResults) {
LOG.debug("Retrieving alias values that begin with {}", prefix);
return manufacturerDatastore.getAliasValuesThatBeginWith(prefix, maxResults);
}
}

View File

@@ -1,8 +1,6 @@
package com.telecominfraproject.wlan.manufacturer.controller;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -15,9 +13,8 @@ import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.junit4.SpringRunner;
import com.telecominfraproject.wlan.cloudeventdispatcher.CloudEventDispatcherEmpty;
import com.telecominfraproject.wlan.manufacturer.datastore.inmemory.ManufacturerDatastoreInMemory;
import com.telecominfraproject.wlan.manufacturer.models.Manufacturer;
import com.telecominfraproject.wlan.manufacturer.models.ManufacturerDetailsRecord;
/**
* @author dtoptygin
@@ -51,32 +48,24 @@ public class ManufacturerControllerTest {
@Test
public void testManufacturerCRUD() throws Exception {
//Create new Manufacturer - success
Manufacturer manufacturer = new Manufacturer();
manufacturer.setSampleStr("test");
Manufacturer ret = manufacturerController.create(manufacturer);
assertNotNull(ret);
ret = manufacturerController.get(ret.getId());
assertEqualManufacturers(manufacturer, ret);
ret = manufacturerController.getOrNull(ret.getId());
assertEqualManufacturers(manufacturer, ret);
final String companyName1 = "Complex Company Inc. 1";
final String companyAlias1 = "Complex 1";
assertNull(manufacturerController.getOrNull(-1));
//Delete - success
manufacturerController.delete(ret.getId());
//CREATE test
ManufacturerDetailsRecord manufacturerDetails = new ManufacturerDetailsRecord();
manufacturerDetails.setManufacturerName(companyName1);
manufacturerDetails.setManufacturerAlias(companyAlias1);
ManufacturerDetailsRecord ret = manufacturerController.createManufacturerDetails(manufacturerDetails);
//GET by id
ret = manufacturerController.getById(ret.getId());
assertTrue(manufacturerDetails.equals(ret));
manufacturerController.deleteManufacturerDetails(ret.getId());
}
private void assertEqualManufacturers(
Manufacturer expected,
Manufacturer actual) {
assertEquals(expected.getSampleStr(), actual.getSampleStr());
//TODO: add more fields to check here
}
}

View File

@@ -98,6 +98,12 @@
<groupId>com.telecominfraproject.wlan</groupId>
<version>${tip-wlan-cloud.release.version}</version>
</dependency>
<dependency>
<artifactId>manufacturer-service-interface</artifactId>
<groupId>com.telecominfraproject.wlan</groupId>
<version>${tip-wlan-cloud.release.version}</version>
</dependency>
</dependencies>
</project>

View File

@@ -0,0 +1,146 @@
package com.telecominfraproject.wlan.portal.controller.manufacturer;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import com.telecominfraproject.wlan.core.model.json.GenericResponse;
import com.telecominfraproject.wlan.manufacturer.ManufacturerInterface;
import com.telecominfraproject.wlan.manufacturer.models.ManufacturerDetailsRecord;
import com.telecominfraproject.wlan.manufacturer.models.ManufacturerOuiDetails;
/**
* @author dtoptygin
*
*/
@RestController
@Transactional
@RequestMapping(value = "/portal/manufacturer")
public class ManufacturerController {
private static final Logger LOG = LoggerFactory.getLogger(ManufacturerController.class);
@Autowired
private ManufacturerInterface manufacturerInterface;
public static class ListOfMfrOuiDetailRecords extends ArrayList<ManufacturerOuiDetails> {
private static final long serialVersionUID = -8035392255039609079L;
}
@PostMapping(value = "/oui")
public ManufacturerOuiDetails createOuiDetails(@RequestBody ManufacturerOuiDetails ouiDetails) {
LOG.debug("Creating OUI details {} ", ouiDetails);
ManufacturerOuiDetails ret = manufacturerInterface.createOuiDetails(ouiDetails);
LOG.debug("Created OUI details {} ", ouiDetails);
return ret;
}
@DeleteMapping(value = "/oui")
public ManufacturerOuiDetails deleteOuiDetails(@RequestParam String oui) {
LOG.debug("Deleteing OUI details identified by OUI {} ", oui);
ManufacturerOuiDetails ret = manufacturerInterface.deleteOuiDetails(oui);
LOG.debug("Removed OUI details {} ", ret);
return ret;
}
@GetMapping(value = "/oui/forManufacturer")
public List<String> getOuiListForManufacturer(@RequestParam String manufacturer, @RequestParam boolean exactMatch) {
LOG.debug("Retrieving all OUIs for manufacturer {}, exactMatch={} ", manufacturer, exactMatch);
List<String> ret = manufacturerInterface.getOuiListForManufacturer(manufacturer, exactMatch);
LOG.debug("Retrieved found the following OUIs for manufacturer {}: {}", manufacturer, ret);
return ret;
}
@GetMapping(value = "/oui")
public ManufacturerOuiDetails getByOui(@RequestParam String oui) {
LOG.debug("Retrieving OUI details for OUI {} ", oui);
ManufacturerOuiDetails ret = manufacturerInterface.getByOui(oui);
LOG.debug("Retrieved OUI details {} ", ret);
return ret;
}
@PostMapping
public ManufacturerDetailsRecord createManufacturerDetails(
@RequestBody ManufacturerDetailsRecord clientManufacturerDetails) {
LOG.debug("Creating Manufacturing Details Record for {} ", clientManufacturerDetails);
ManufacturerDetailsRecord ret = manufacturerInterface.createManufacturerDetails(clientManufacturerDetails);
LOG.debug("Created Manufacturer details {} ", ret);
return ret;
}
@PutMapping
public ManufacturerDetailsRecord updateManufacturerDetails(
@RequestBody ManufacturerDetailsRecord clientManufacturerDetails) {
LOG.debug("Updating Manufacturing Details Record {} ", clientManufacturerDetails);
ManufacturerDetailsRecord ret = manufacturerInterface.updateManufacturerDetails(clientManufacturerDetails);
LOG.debug("Updated Manufacturer details {} ", ret);
return ret;
}
@DeleteMapping
public ManufacturerDetailsRecord deleteManufacturerDetails(@RequestParam long id) {
LOG.debug("Removing Manufacturing Details Record {} ", id);
ManufacturerDetailsRecord ret = manufacturerInterface.deleteManufacturerDetails(id);
LOG.debug("Removed Manufacturer details {} ", ret);
return ret;
}
@GetMapping
public ManufacturerDetailsRecord getById(@RequestParam long id) {
LOG.debug("Retrieving Manufacturing Details Record for id {} ", id);
ManufacturerDetailsRecord ret = manufacturerInterface.getById(id);
LOG.debug("Retrieved Manufacturer details {} ", ret);
return ret;
}
@GetMapping(value = "/oui/all")
public List<ManufacturerOuiDetails> getAllManufacturerData() {
LOG.debug("Retrieving all Manufacturing Details Records");
List<ManufacturerOuiDetails> ret = manufacturerInterface.getAllManufacturerData();
LOG.debug("Retrieved {} Manufacturing Details Records", ret.size());
return ret;
}
@PostMapping(value = "/oui/upload", consumes = { MediaType.APPLICATION_OCTET_STREAM_VALUE })
public GenericResponse uploadOuiDataFile(@RequestParam String fileName, @RequestBody byte[] base64GzippedContent) {
LOG.debug("uploadOuiDataFile({})", fileName);
GenericResponse ret = manufacturerInterface.uploadOuiDataFile(fileName, base64GzippedContent);
LOG.debug("uploadOuiDataFile({}) returns {}", fileName, ret);
return ret;
}
@GetMapping(value = "/oui/list")
public Map<String, ManufacturerOuiDetails> getManufacturerDetailsForOuiSet(
@RequestParam List<String> ouiList) {
LOG.debug("calling getManufacturerDetailsForOuiList ");
return manufacturerInterface.getManufacturerDetailsForOuiSet(new HashSet<>(ouiList));
}
@PutMapping(value = "/oui/alias")
public ManufacturerOuiDetails updateOuiAlias(@RequestBody ManufacturerOuiDetails ouiDetails) {
LOG.debug("Updating alias for oui {} to {}", ouiDetails.getOui(), ouiDetails.getManufacturerAlias());
manufacturerInterface.updateOuiAlias(ouiDetails);
return ouiDetails;
}
@GetMapping(value = "/oui/alias")
public List<String> getAliasValuesThatBeginWith(@RequestParam String prefix, @RequestParam int maxResults) {
LOG.debug("Retrieving alias values that begin with {}", prefix);
return manufacturerInterface.getAliasValuesThatBeginWith(prefix, maxResults);
}
}

View File

@@ -7785,6 +7785,37 @@ components:
type: integer
format: int64
ManufacturerDetailsRecord:
properties:
id:
type: integer
format: int64
manufacturerName:
type: string
manufacturerAlias:
type: string
createdTimestamp:
type: integer
format: int64
lastModifiedTimestamp:
description: must be provided for update operation, update will be rejected if provided value does not match the one currently stored in the database
type: integer
format: int64
ManufacturerOuiDetails:
properties:
oui:
description: first 3 bytes of MAC address, expressed as a string like '1a2b3c'
type: string
manufacturerName:
type: string
manufacturerAlias:
type: string
ManufacturerOuiDetailsPerOuiMap:
additionalProperties:
$ref: '#/components/schemas/ManufacturerOuiDetails'
#
# Objects related to pagination
@@ -10416,7 +10447,7 @@ paths:
required: true
schema:
type: integer
format: int64
format: int32
responses:
200:
description: successful operation
@@ -10427,3 +10458,317 @@ paths:
500:
$ref: '#/components/responses/GenericApiError'
/portal/manufacturer:
post:
tags:
- Manufacturer OUI
summary: Create new ManufacturerDetailsRecord
operationId: createManufacturerDetailsRecord
requestBody:
description: ManufacturerDetailsRecord info
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/ManufacturerDetailsRecord'
responses:
200:
description: successful operation
content:
application/json:
schema:
$ref: '#/components/schemas/ManufacturerDetailsRecord'
500:
$ref: '#/components/responses/GenericApiError'
get:
tags:
- Manufacturer OUI
summary: Get ManufacturerDetailsRecord By id
operationId: getManufacturerDetailsRecord
parameters:
- name: id
in: query
description: ManufacturerDetailsRecord id
required: true
schema:
type: integer
format: int64
responses:
200:
description: successful operation
content:
application/json:
schema:
$ref: '#/components/schemas/ManufacturerDetailsRecord'
500:
$ref: '#/components/responses/GenericApiError'
put:
tags:
- Manufacturer OUI
summary: Update ManufacturerDetailsRecord
operationId: updateManufacturerDetailsRecord
requestBody:
description: ManufacturerDetailsRecord info
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/ManufacturerDetailsRecord'
responses:
200:
description: successful operation
content:
application/json:
schema:
$ref: '#/components/schemas/ManufacturerDetailsRecord'
500:
$ref: '#/components/responses/GenericApiError'
delete:
tags:
- Manufacturer OUI
summary: Delete ManufacturerDetailsRecord
operationId: deleteManufacturerDetailsRecord
parameters:
- name: id
in: query
description: ManufacturerDetailsRecord id
required: true
schema:
type: integer
format: int64
responses:
200:
description: successful operation
content:
application/json:
schema:
$ref: '#/components/schemas/ManufacturerDetailsRecord'
500:
$ref: '#/components/responses/GenericApiError'
/portal/manufacturer/oui:
post:
tags:
- Manufacturer OUI
summary: Create new ManufacturerOuiDetails
operationId: createManufacturerOuiDetails
requestBody:
description: ManufacturerOuiDetails info
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/ManufacturerOuiDetails'
responses:
200:
description: successful operation
content:
application/json:
schema:
$ref: '#/components/schemas/ManufacturerOuiDetails'
500:
$ref: '#/components/responses/GenericApiError'
get:
tags:
- Manufacturer OUI
summary: Get ManufacturerOuiDetails By oui
operationId: getManufacturerOuiDetailsByOui
parameters:
- name: oui
in: query
description: ManufacturerOuiDetails oui
required: true
schema:
type: string
responses:
200:
description: successful operation
content:
application/json:
schema:
$ref: '#/components/schemas/ManufacturerOuiDetails'
500:
$ref: '#/components/responses/GenericApiError'
delete:
tags:
- Manufacturer OUI
summary: Delete ManufacturerOuiDetails
operationId: deleteManufacturerOuiDetails
parameters:
- name: oui
in: query
description: ManufacturerOuiDetails oui
required: true
schema:
type: string
responses:
200:
description: successful operation
content:
application/json:
schema:
$ref: '#/components/schemas/ManufacturerOuiDetails'
500:
$ref: '#/components/responses/GenericApiError'
/portal/manufacturer/oui/forManufacturer:
get:
tags:
- Manufacturer OUI
summary: Get Oui List for manufacturer
operationId: getOuiListForManufacturer
parameters:
- name: manufacturer
in: query
description: Manufacturer name or alias
required: true
schema:
type: string
- name: exactMatch
in: query
description: Perform exact match (true) or prefix match (false) for the manufacturer name or alias
required: true
schema:
type: boolean
responses:
200:
description: successful operation
content:
application/json:
schema:
type: array
items:
type: string
500:
$ref: '#/components/responses/GenericApiError'
/portal/manufacturer/oui/all:
get:
tags:
- Manufacturer OUI
summary: Get all ManufacturerOuiDetails
operationId: getAllManufacturerOuiDetails
responses:
200:
description: successful operation
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/ManufacturerOuiDetails'
500:
$ref: '#/components/responses/GenericApiError'
/portal/manufacturer/oui/list:
get:
tags:
- Manufacturer OUI
summary: Get ManufacturerOuiDetails for the list of OUIs
operationId: getManufacturerDetailsForOuiList
parameters:
- name: ouiList
in: query
required: true
content:
text/plain:
schema:
type: array
items:
type: string
responses:
200:
description: successful operation
content:
application/json:
schema:
$ref: '#/components/schemas/ManufacturerOuiDetailsPerOuiMap'
500:
$ref: '#/components/responses/GenericApiError'
/portal/manufacturer/oui/alias:
put:
tags:
- Manufacturer OUI
summary: Update alias for ManufacturerOuiDetails
operationId: updateOuiAlias
requestBody:
description: ManufacturerOuiDetails info
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/ManufacturerOuiDetails'
responses:
200:
description: successful operation
content:
application/json:
schema:
$ref: '#/components/schemas/ManufacturerOuiDetails'
500:
$ref: '#/components/responses/GenericApiError'
get:
tags:
- Manufacturer OUI
summary: Get alias values that begin with the given prefix
operationId: getAliasValuesThatBeginWith
parameters:
- name: prefix
in: query
description: OUI prefix
required: true
schema:
type: string
- name: maxResults
in: query
description: max results to return, use -1 for no limit
required: true
schema:
type: integer
format: int32
default: -1
responses:
200:
description: successful operation
content:
application/json:
schema:
type: array
items:
type: string
500:
$ref: '#/components/responses/GenericApiError'
/portal/manufacturer/oui/upload:
post:
tags:
- Manufacturer OUI
summary: Upload the gziped OUI DataFile, in the format that is published by IEEE. Latest sanitized IEEE OUI data file (oui.txt.gz) can be obtained from https://linuxnet.ca/ieee/oui/
operationId: uploadOuiDataFile
parameters:
- name: fileName
in: query
description: file name that is being uploaded
required: true
schema:
type: string
requestBody:
description: Contents of gziped OUI DataFile
required: true
content:
application/octet-stream:
schema:
type: string
format: base64
responses:
200:
description: successful operation
content:
application/json:
schema:
$ref: '#/components/schemas/GenericResponse'
500:
$ref: '#/components/responses/GenericApiError'

View File

@@ -65,7 +65,7 @@
</dependency>
<dependency>
<!-- Use in-memory DS for now, later switch to RDBMS -->
<!-- Use in-memory DS for now, later switch to Cassandra -->
<artifactId>service-metric-datastore-inmemory</artifactId>
<groupId>com.telecominfraproject.wlan</groupId>
<version>${tip-wlan-cloud.release.version}</version>
@@ -78,7 +78,7 @@
</dependency>
<dependency>
<!-- Use in-memory DS for now, later switch to RDBMS -->
<!-- Use in-memory DS for now, later switch to Cassandra -->
<artifactId>system-event-datastore-inmemory</artifactId>
<groupId>com.telecominfraproject.wlan</groupId>
<version>${tip-wlan-cloud.release.version}</version>
@@ -91,7 +91,7 @@
</dependency>
<dependency>
<!-- Use in-memory DS for now, later switch to RDBMS -->
<!-- Use in-memory DS for now, later switch to Cassandra -->
<artifactId>alarm-datastore-inmemory</artifactId>
<groupId>com.telecominfraproject.wlan</groupId>
<version>${tip-wlan-cloud.release.version}</version>
@@ -104,7 +104,7 @@
</dependency>
<dependency>
<!-- Use in-memory DS for now, later switch to RDBMS -->
<!-- Use in-memory DS for now, later switch to Cassandra -->
<artifactId>status-datastore-inmemory</artifactId>
<groupId>com.telecominfraproject.wlan</groupId>
<version>${tip-wlan-cloud.release.version}</version>
@@ -117,7 +117,7 @@
</dependency>
<dependency>
<!-- Use in-memory DS for now, later switch to RDBMS -->
<!-- Use in-memory DS for now, later switch to Cassandra -->
<artifactId>client-datastore-inmemory</artifactId>
<groupId>com.telecominfraproject.wlan</groupId>
<version>${tip-wlan-cloud.release.version}</version>
@@ -130,7 +130,7 @@
</dependency>
<dependency>
<!-- Use in-memory DS for now, later switch to RDBMS -->
<!-- Use in-memory DS for now, later switch to Cassandra -->
<artifactId>routing-datastore-inmemory</artifactId>
<groupId>com.telecominfraproject.wlan</groupId>
<version>${tip-wlan-cloud.release.version}</version>