/*
* Copyright 2017 Anton Tananaev (anton@traccar.org)
* Copyright 2017 Andrey Kunitsyn (andrey@traccar.org)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.traccar.database;
import java.sql.SQLException;
import java.util.Collection;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import org.traccar.Context;
import org.traccar.helper.Log;
import org.traccar.model.AttributePermission;
import org.traccar.model.Attribute;
import org.traccar.model.Device;
import org.traccar.model.DeviceAttribute;
import org.traccar.model.GroupAttribute;
public class AttributesManager {
private final DataManager dataManager;
private final Map<Long, Attribute> attributes = new ConcurrentHashMap<>();
private final Map<Long, Set<Long>> deviceAttributes = new ConcurrentHashMap<>();
private final Map<Long, Set<Long>> deviceAttributesWithGroups = new ConcurrentHashMap<>();
private final Map<Long, Set<Long>> groupAttributes = new ConcurrentHashMap<>();
private final Map<Long, Set<Long>> userAttributes = new ConcurrentHashMap<>();
public AttributesManager(DataManager dataManager) {
this.dataManager = dataManager;
refreshAttributes();
}
public Set<Long> getUserAttributes(long userId) {
if (!userAttributes.containsKey(userId)) {
userAttributes.put(userId, new HashSet<Long>());
}
return userAttributes.get(userId);
}
public Set<Long> getGroupAttributes(long groupId) {
if (!groupAttributes.containsKey(groupId)) {
groupAttributes.put(groupId, new HashSet<Long>());
}
return groupAttributes.get(groupId);
}
public Set<Long> getDeviceAttributes(long deviceId) {
return getDeviceAttributes(deviceAttributes, deviceId);
}
public Set<Long> getAllDeviceAttributes(long deviceId) {
return getDeviceAttributes(deviceAttributesWithGroups, deviceId);
}
private Set<Long> getDeviceAttributes(Map<Long, Set<Long>> deviceAttributes, long deviceId) {
if (!deviceAttributes.containsKey(deviceId)) {
deviceAttributes.put(deviceId, new HashSet<Long>());
}
return deviceAttributes.get(deviceId);
}
public final void refreshAttributes() {
if (dataManager != null) {
try {
attributes.clear();
for (Attribute attribute : dataManager.getAttributes()) {
attributes.put(attribute.getId(), attribute);
}
} catch (SQLException error) {
Log.warning(error);
}
}
refreshUserAttributes();
refresh();
}
public final void refreshUserAttributes() {
if (dataManager != null) {
try {
userAttributes.clear();
for (AttributePermission attributePermission : dataManager.getAttributePermissions()) {
getUserAttributes(attributePermission.getUserId()).add(attributePermission.getAttributeId());
}
} catch (SQLException error) {
Log.warning(error);
}
}
}
public final void refresh() {
if (dataManager != null) {
try {
Collection<GroupAttribute> databaseGroupAttributes = dataManager.getGroupAttributes();
groupAttributes.clear();
for (GroupAttribute groupAttribute : databaseGroupAttributes) {
getGroupAttributes(groupAttribute.getGroupId()).add(groupAttribute.getAttributeId());
}
Collection<DeviceAttribute> databaseDeviceAttributes = dataManager.getDeviceAttributes();
Collection<Device> allDevices = Context.getDeviceManager().getAllDevices();
deviceAttributes.clear();
deviceAttributesWithGroups.clear();
for (DeviceAttribute deviceAttribute : databaseDeviceAttributes) {
getDeviceAttributes(deviceAttribute.getDeviceId())
.add(deviceAttribute.getAttributeId());
getAllDeviceAttributes(deviceAttribute.getDeviceId())
.add(deviceAttribute.getAttributeId());
}
for (Device device : allDevices) {
long groupId = device.getGroupId();
while (groupId != 0) {
getAllDeviceAttributes(device.getId()).addAll(getGroupAttributes(groupId));
if (Context.getDeviceManager().getGroupById(groupId) != null) {
groupId = Context.getDeviceManager().getGroupById(groupId).getGroupId();
} else {
groupId = 0;
}
}
}
} catch (SQLException error) {
Log.warning(error);
}
}
}
public void addAttribute(Attribute attribute) throws SQLException {
dataManager.addAttribute(attribute);
attributes.put(attribute.getId(), attribute);
}
public void updateAttribute(Attribute attribute) throws SQLException {
dataManager.updateAttribute(attribute);
Attribute cachedAttribute = attributes.get(attribute.getId());
cachedAttribute.setDescription(attribute.getDescription());
cachedAttribute.setAttribute(attribute.getAttribute());
cachedAttribute.setExpression(attribute.getExpression());
cachedAttribute.setType(attribute.getType());
}
public void removeAttribute(long computedAttributeId) throws SQLException {
dataManager.removeAttribute(computedAttributeId);
attributes.remove(computedAttributeId);
refreshUserAttributes();
refresh();
}
public boolean checkAttribute(long userId, long attributeId) {
return getUserAttributes(userId).contains(attributeId);
}
public Attribute getAttribute(long id) {
return attributes.get(id);
}
public final Collection<Attribute> getAttributes(Set<Long> attributeIds) {
Collection<Attribute> result = new LinkedList<>();
for (long attributeId : attributeIds) {
result.add(getAttribute(attributeId));
}
return result;
}
public final Set<Long> getAllAttributes() {
return attributes.keySet();
}
public final Set<Long> getManagedAttributes(long userId) {
Set<Long> attributes = new HashSet<>();
attributes.addAll(getUserAttributes(userId));
for (long managedUserId : Context.getPermissionsManager().getUserPermissions(userId)) {
attributes.addAll(getUserAttributes(managedUserId));
}
return attributes;
}
}