com.freedomotic.things.impl.ThingRepositoryImpl Maven / Gradle / Ivy
/**
*
* Copyright (c) 2009-2014 Freedomotic team http://freedomotic.com
*
* This file is part of Freedomotic
*
* This Program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License as published by the Free Software
* Foundation; either version 2, or (at your option) any later version.
*
* This Program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* Freedomotic; see the file COPYING. If not, see
* .
*/
package com.freedomotic.things.impl;
import com.freedomotic.environment.EnvironmentLogic;
import com.freedomotic.exceptions.DataUpgradeException;
import com.freedomotic.exceptions.RepositoryException;
import com.freedomotic.model.object.EnvObject;
import com.freedomotic.model.object.Representation;
import com.freedomotic.things.EnvObjectLogic;
import com.freedomotic.things.ThingFactory;
import com.freedomotic.things.ThingRepository;
import com.freedomotic.persistence.FreedomXStream;
import com.freedomotic.persistence.DataUpgradeService;
import com.freedomotic.persistence.XmlPreprocessor;
import com.freedomotic.util.Info;
import com.freedomotic.util.SerialClone;
import com.freedomotic.util.UidGenerator;
import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.XStreamException;
import java.io.File;
import java.io.FileFilter;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.UUID;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.inject.Inject;
import org.apache.shiro.authz.annotation.RequiresPermissions;
/**
*
* @author Enrico
*/
class ThingRepositoryImpl implements ThingRepository {
public static final boolean MAKE_UNIQUE = true;
public static final boolean MAKE_NOT_UNIQUE = false;
private static final Map objectList = new HashMap<>();
private final ThingFactory thingsFactory;
private final DataUpgradeService dataUpgradeService;
/**
*
* @param thingsFactory
* @param environmentRepository
*/
@Inject
public ThingRepositoryImpl(
ThingFactory thingsFactory,
DataUpgradeService dataUpgradeService) {
this.thingsFactory = thingsFactory;
this.dataUpgradeService = dataUpgradeService;
}
@Deprecated
@RequiresPermissions("objects:read")
public static Collection getObjectList() {
return objectList.values();
}
/**
*
* @param folder
* @throws RepositoryException
*/
@RequiresPermissions("objects:save")
public static void saveObjects(File folder) throws RepositoryException {
if (objectList.isEmpty()) {
throw new RepositoryException("There are no object to persist, " + folder.getAbsolutePath()
+ " will not be altered.");
}
if (!folder.isDirectory()) {
throw new RepositoryException(folder.getAbsoluteFile() + " is not a valid object folder. Skipped");
}
deleteObjectFiles(folder);
for (EnvObjectLogic envObject : objectList.values()) {
String uuid = envObject.getPojo().getUUID();
if ((uuid == null) || uuid.isEmpty()) {
envObject.getPojo().setUUID(UUID.randomUUID().toString());
}
//REGRESSION
// if ((envObject.getPojo().getEnvironmentID() == null)
// || envObject.getPojo().getEnvironmentID().isEmpty()) {
// envObject.getPojo()
// .setEnvironmentID(EnvironmentPersistence.getEnvironments().get(0).getPojo().getUUID());
// }
String fileName = envObject.getPojo().getUUID() + ".xobj";
File file = new File(folder + "/" + fileName);
FreedomXStream.toXML(envObject.getPojo(), file);
}
}
private static void deleteObjectFiles(File folder)
throws RepositoryException {
if ((folder == null) || !folder.isDirectory()) {
throw new IllegalArgumentException("Unable to delete objects files in a null or not valid folder");
}
File[] files = folder.listFiles();
// This filter only returns object files
FileFilter objectFileFileter
= new FileFilter() {
@Override
public boolean accept(File file) {
if (file.isFile() && file.getName().endsWith(".xobj")) {
return true;
} else {
return false;
}
}
};
files = folder.listFiles(objectFileFileter);
for (File file : files) {
boolean deleted = file.delete();
if (!deleted) {
throw new RepositoryException("Unable to delete file " + file.getAbsoluteFile());
}
}
}
/**
*
* @return
*/
@Deprecated
@RequiresPermissions("objects:read")
public static Iterator iterator() {
return objectList.values().iterator();
}
/**
* Gets the object by name
*
* @param name
* @return
*/
@RequiresPermissions("objects:read")
public static EnvObjectLogic getObjectByName(String name) {
for (Iterator it = ThingRepositoryImpl.iterator(); it.hasNext();) {
EnvObjectLogic object = it.next();
if (object.getPojo().getName().equalsIgnoreCase(name) //&& auth.isPermitted("objects:read:" + object.getPojo().getUUID())
) {
return object;
}
}
return null;
}
/**
*
* @param tags
* @return
*/
@RequiresPermissions("objects:read")
public static ArrayList getObjectByTags(String tags) {
ArrayList results = new ArrayList();
// split tags string
String[] tagList = tags.split(",");
// search every object for at least one tag
for (EnvObjectLogic obj : objectList.values()) {
Set tagSet = new HashSet();
for (String tag : tagList) {
if (!tag.trim().isEmpty()) {
tagSet.add(tag.trim());
}
}
int prevCount = tagSet.size();
tagSet.removeAll(obj.getPojo().getTagsList());
if (prevCount > tagSet.size()) {
results.add(obj);
}
}
return results;
}
/**
* Gets the object by name
*
* @param uuid
* @return
*/
@Deprecated
@RequiresPermissions("objects:read")
public static EnvObjectLogic getObjectByUUID(String uuid) {
for (Iterator it = iterator(); it.hasNext();) {
EnvObjectLogic object = it.next();
if (object.getPojo().getUUID().equalsIgnoreCase(uuid)) {
return object;
}
}
return null;
}
/**
* Gets the object by its address and protocol
*
* @param protocol
* @param address
* @return
*/
@RequiresPermissions("objects:read")
public static ArrayList getObjectByAddress(String protocol, String address) {
if ((protocol == null)
|| (address == null)
|| protocol.trim().equalsIgnoreCase("unknown")
|| address.trim().equalsIgnoreCase("unknown")
|| protocol.isEmpty()
|| address.isEmpty()) {
throw new IllegalArgumentException();
}
ArrayList list = new ArrayList();
for (Iterator it = ThingRepositoryImpl.iterator(); it.hasNext();) {
EnvObjectLogic object = it.next();
if ((object.getPojo().getProtocol().equalsIgnoreCase(protocol.trim()))
&& (object.getPojo().getPhisicalAddress().equalsIgnoreCase(address.trim())) // && auth.isPermitted("objects:read:" + object.getPojo().getUUID())
) {
list.add(object);
}
}
if (list.isEmpty()) {
LOG.warning("An object with protocol '" + protocol + "' and address '"
+ address + "' doesn't exist");
}
return list;
}
/**
* Gets the object by its protocol
*
* @param protocol
* @return
*/
@RequiresPermissions("objects:read")
public static ArrayList getObjectByProtocol(String protocol) {
ArrayList list = new ArrayList();
for (Iterator it = ThingRepositoryImpl.iterator(); it.hasNext();) {
EnvObjectLogic object = it.next();
if (object.getPojo().getProtocol().equalsIgnoreCase(protocol.trim()) // && auth.isPermitted("objects:read:" + object.getPojo().getUUID())
) {
list.add(object);
}
}
return list;
}
/**
* Gets the object by its environment
*
* @param uuid
* @return
*/
@RequiresPermissions("objects:read")
public static ArrayList getObjectByEnvironment(String uuid) {
ArrayList list = new ArrayList();
for (Iterator it = ThingRepositoryImpl.iterator(); it.hasNext();) {
EnvObjectLogic object = it.next();
if (object.getPojo().getEnvironmentID().equalsIgnoreCase(uuid) //&& auth.isPermitted("objects:read:" + object.getPojo().getUUID().substring(0, 7))
) {
list.add(object);
}
}
return list;
}
/**
*
* @return
*/
@RequiresPermissions("objects:read")
public static int size() {
return objectList.size();
}
/**
* Add an object to the environment. You can use
* EnvObjectPersistnce.MAKE_UNIQUE to saveAll an object that will surely be
* unique. Beware this means it is created with defensive copy of the object
* in input and name, protocol, address and UUID are reset to a default
* value.
*
* @param obj the environment object to add
* @param MAKE_UNIQUE can be true or false. Creates a defensive copy
* reference to the object in input.
* @return A pointer to the newly created environment object
*/
@Deprecated
@RequiresPermissions("objects:create")
public EnvObjectLogic add(final EnvObjectLogic obj, final boolean MAKE_UNIQUE) {
if ((obj == null)) {
throw new IllegalArgumentException("Cannot add a null object to the environment");
}
if ((obj.getPojo() == null)) {
throw new IllegalArgumentException("Cannot add an object with null pojo to the environment");
}
if ((obj.getPojo().getName() == null) || obj.getPojo().getName().isEmpty()) {
throw new IllegalArgumentException("The data pojo has no name");
}
EnvObjectLogic envObjectLogic = obj;
if (MAKE_UNIQUE) {
//defensive copy to not affect the passed object with the changes
EnvObject pojoCopy = SerialClone.clone(obj.getPojo());
pojoCopy.setName(obj.getPojo().getName() + "-" + UidGenerator.getNextStringUid());
pojoCopy.setProtocol(obj.getPojo().getProtocol());
pojoCopy.setPhisicalAddress("unknown");
for (Representation rep : pojoCopy.getRepresentations()) {
rep.getOffset().setX(obj.getPojo().getCurrentRepresentation().getOffset().getX() + 30);
rep.getOffset().setY(obj.getPojo().getCurrentRepresentation().getOffset().getY() + 30);
}
pojoCopy.setUUID(UUID.randomUUID().toString());
try {
envObjectLogic = thingsFactory.create(pojoCopy);
} catch (RepositoryException ex) {
LOG.warning(ex.getMessage());
}
}
envObjectLogic.init();
if (!objectList.containsValue(envObjectLogic)) {
objectList.put(envObjectLogic.getPojo().getUUID(), envObjectLogic);
try {
envObjectLogic.setChanged(true);
} catch (Exception e) {
LOG.log(Level.WARNING, "Object was created, but cannot set it as Changed", e);
}
} else {
throw new RuntimeException("Cannot add the same object more than one time");
}
return envObjectLogic;
}
/**
*
* @param input
*/
@Deprecated
@RequiresPermissions("objects:delete")
public static void remove(EnvObjectLogic input) {
objectList.remove(input.getPojo().getUUID());
input.setChanged(true); //force repainting on frontends clients
input.destroy(); //free memory
}
/**
*
*/
@RequiresPermissions("objects:delete")
@Override
public void deleteAll() {
try {
for (EnvObjectLogic el : objectList.values()) {
delete(el);
}
} catch (Exception e) {
} finally {
objectList.clear();
}
}
private static final Logger LOG = Logger.getLogger(ThingRepositoryImpl.class.getName());
@Override
@RequiresPermissions("objects:read")
public List findAll() {
List el = new ArrayList();
el.addAll(objectList.values());
return el;
}
@Override
@RequiresPermissions("objects:read")
public List findByName(String name) {
List el = new ArrayList();
for (EnvObjectLogic e : findAll()) {
if (e.getPojo().getName().equalsIgnoreCase(name)) {
el.add(e);
}
}
return el;
}
@Override
@RequiresPermissions("objects:read")
public EnvObjectLogic findOne(String uuid) {
return getObjectByUUID(uuid);
}
@Override
@RequiresPermissions("objects:create")
public boolean create(EnvObjectLogic item) {
try {
int preSize = objectList.size();
add(item, false);
if (preSize + 1 == objectList.size()) {
return true;
} else {
return false;
}
} catch (Exception e) {
LOG.log(Level.SEVERE, "Cannot create object", e);
return false;
}
}
@Override
@RequiresPermissions("objects:delete")
public boolean delete(EnvObjectLogic item) {
return delete(item.getPojo().getUUID());
}
@Override
@RequiresPermissions("objects:delete")
public boolean delete(String uuid) {
try {
EnvObjectLogic eol = objectList.remove(uuid);
try {
eol.setChanged(true); //force repainting on frontends clients
} catch (Exception e) {
LOG.warning("Cannot notify object changes");
}
eol.destroy();
return true;
} catch (Exception e) {
LOG.log(Level.SEVERE, "Cannot delete object" + uuid, e);
return false;
}
}
@Override
@RequiresPermissions("objects:update")
public EnvObjectLogic modify(String uuid, EnvObjectLogic data) {
try {
delete(uuid);
data.getPojo().setUUID(uuid);
create(data);
return data;
} catch (Exception e) {
return null;
}
}
@Override
@RequiresPermissions("objects:create")
public EnvObjectLogic copy(EnvObjectLogic thing) {
return add(thing, true);
}
public static List getObjectsNames() {
List list = new ArrayList();
for (EnvObjectLogic obj : objectList.values()) {
list.add(obj.getPojo().getName());
}
return list;
}
@Override
public List findByEnvironment(EnvironmentLogic env) {
return getObjectByEnvironment(env.getPojo().getUUID());
}
@Override
public List findByEnvironment(String uuid) {
return getObjectByEnvironment(uuid);
}
@Override
public List findByAddress(String protocol, String address) {
return getObjectByAddress(protocol, address);
}
/**
*
* @param file
* @return
* @throws RepositoryException
*/
@Override
public EnvObjectLogic load(File file) throws RepositoryException {
// Arguments validation
if (file == null) {
throw new IllegalArgumentException("Cannot load a null Thing file");
}
if (!file.isFile()) {
throw new IllegalArgumentException("Thing file in input is not a file");
}
// Configure the deserialization engine
LOG.log(Level.CONFIG, "Loading Thing from file {0}", file.getAbsolutePath());
XStream xstream = FreedomXStream.getXstream();
// Validate the object against a predefined DTD
String xml;
try {
// Validate the upgraded xml against a DTD file
xml = XmlPreprocessor.validate(file, Info.PATHS.PATH_CONFIG_FOLDER + "/validator/object.dtd");
//TODO: merge this upgrade code with the XmlPreprocessor (validation should be after the upgrade)
// Upgrade the data to be compatible with the current version (skipped if already up to date)
try {
Properties dataProperties = new Properties();
String fromVersion;
try {
dataProperties.load(new FileInputStream(new File(Info.PATHS.PATH_DATA_FOLDER + "/data.properties")));
fromVersion = dataProperties.getProperty("data.version");
} catch (IOException iOException) {
// Fallback to a default version for older version without that properties file
fromVersion = "5.5.0";
}
xml = (String) dataUpgradeService.upgrade(EnvObject.class, xml, fromVersion);
} catch (DataUpgradeException dataUpgradeException) {
throw new RepositoryException("Cannot upgrade Thing file " + file.getAbsolutePath(), dataUpgradeException);
}
// Deserialize the object from the upgraded and validated xml
EnvObject pojo = (EnvObject) xstream.fromXML(xml);
EnvObjectLogic objectLogic = thingsFactory.create(pojo);
LOG.log(Level.CONFIG, "Created a new logic for {0} [id:{1}] of type {2}", new Object[]{objectLogic.getPojo().getName(), objectLogic.getPojo().getUUID(), objectLogic.getClass().getCanonicalName()});
return objectLogic;
} catch (IOException ex) {
throw new RepositoryException("Cannot read Thing file " + file.getAbsolutePath(), ex);
} catch (XStreamException e) {
throw new RepositoryException("Error while deserializing Thing file " + file.getAbsolutePath(), e);
}
}
@Override
public List loadAll(File folder) throws RepositoryException {
objectList.clear();
List results = new ArrayList();
File[] files = folder.listFiles();
// This filter only returns object files
FileFilter objectFileFilter
= new FileFilter() {
@Override
public boolean accept(File file) {
if (file.isFile() && file.getName().endsWith(".xobj")) {
return true;
} else {
return false;
}
}
};
files = folder.listFiles(objectFileFilter);
if (files != null) {
for (File file : files) {
EnvObjectLogic loaded = load(file);
results.add(loaded);
}
}
return results;
}
@Override
public void saveAll(File folder) throws RepositoryException {
saveObjects(folder);
}
@Override
public List findByProtocol(String protocolName) {
return getObjectByProtocol(protocolName);
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy