use of org.openremote.model.AssetModelProvider in project openremote by openremote.
the class ValueUtil method doInitialise.
/**
* Initialise the asset model and throw an {@link IllegalStateException} exception if a problem is detected; this
* can be called by applications at startup to fail hard and fast if the asset model is un-usable
*/
protected static void doInitialise() throws IllegalStateException {
assetInfoMap = new HashMap<>();
assetTypeMap = new HashMap<>();
agentLinkMap = new HashMap<>();
metaItemDescriptors = new ArrayList<>();
valueDescriptors = new ArrayList<>();
generator = null;
// Provide basic Object Mapper and enhance once asset model is initialised
JSON = configureObjectMapper(new ObjectMapper());
LOG.info("Initialising asset model...");
Map<Class<? extends Asset<?>>, List<NameHolder>> assetDescriptorProviders = new TreeMap<>(new ClassHierarchyComparator());
// noinspection RedundantCast
assetDescriptorProviders.put((Class<? extends Asset<?>>) (Class<?>) Asset.class, new ArrayList<>(getDescriptorFields(Asset.class)));
getModelProviders().forEach(assetModelProvider -> {
LOG.fine("Processing asset model provider: " + assetModelProvider.getClass().getSimpleName());
LOG.fine("Auto scan = " + assetModelProvider.useAutoScan());
if (assetModelProvider.useAutoScan()) {
Set<Class<? extends Asset<?>>> assetClasses = getAssetClasses(assetModelProvider);
LOG.fine("Found " + assetClasses.size() + " asset class(es)");
assetClasses.forEach(assetClass -> assetDescriptorProviders.computeIfAbsent(assetClass, aClass -> new ArrayList<>(getDescriptorFields(aClass))));
ModelDescriptors modelDescriptors = assetModelProvider.getClass().getAnnotation(ModelDescriptors.class);
if (modelDescriptors != null) {
for (ModelDescriptor modelDescriptor : modelDescriptors.value()) {
Class<? extends Asset<?>> assetClass = (Class<? extends Asset<?>>) modelDescriptor.assetType();
assetDescriptorProviders.compute(assetClass, (aClass, list) -> {
if (list == null) {
list = new ArrayList<>();
}
list.addAll(getDescriptorFields(modelDescriptor.provider()));
return list;
});
}
}
}
if (assetModelProvider.getAssetDescriptors() != null) {
for (AssetDescriptor<?> assetDescriptor : assetModelProvider.getAssetDescriptors()) {
Class<? extends Asset<?>> assetClass = assetDescriptor.getType();
assetDescriptorProviders.compute(assetClass, (aClass, list) -> {
if (list == null) {
list = new ArrayList<>();
}
list.add(assetDescriptor);
return list;
});
}
}
if (assetModelProvider.getAttributeDescriptors() != null) {
assetModelProvider.getAttributeDescriptors().forEach((assetClass, attributeDescriptors) -> assetDescriptorProviders.compute(assetClass, (aClass, list) -> {
if (list == null) {
list = new ArrayList<>();
}
list.addAll(attributeDescriptors);
return list;
}));
}
if (assetModelProvider.getMetaItemDescriptors() != null) {
assetModelProvider.getMetaItemDescriptors().forEach((assetClass, metaDescriptors) -> assetDescriptorProviders.compute(assetClass, (aClass, list) -> {
if (list == null) {
list = new ArrayList<>();
}
list.addAll(metaDescriptors);
return list;
}));
}
if (assetModelProvider.getValueDescriptors() != null) {
assetModelProvider.getValueDescriptors().forEach((assetClass, valueDescriptors) -> assetDescriptorProviders.compute(assetClass, (aClass, list) -> {
if (list == null) {
list = new ArrayList<>();
}
list.addAll(valueDescriptors);
return list;
}));
}
});
// Build each asset info checking that no conflicts occur
Map<Class<? extends Asset<?>>, List<NameHolder>> copy = new HashMap<>(assetDescriptorProviders);
assetDescriptorProviders.forEach((assetClass, descriptors) -> {
// Skip abstract classes as a start point - they should be in the class hierarchy of concrete class
if (!Modifier.isAbstract(assetClass.getModifiers())) {
AssetTypeInfo assetInfo = buildAssetInfo(assetClass, copy);
assetInfoMap.put(assetClass, assetInfo);
assetTypeMap.put(assetInfo.getAssetDescriptor().getName(), assetClass);
if (assetInfo.getAssetDescriptor() instanceof AgentDescriptor) {
AgentDescriptor<?, ?, ?> agentDescriptor = (AgentDescriptor<?, ?, ?>) assetInfo.getAssetDescriptor();
String agentLinkName = agentDescriptor.getAgentLinkClass().getSimpleName();
if (agentLinkMap.containsKey(agentLinkName) && agentLinkMap.get(agentLinkName) != agentDescriptor.getAgentLinkClass()) {
throw new IllegalStateException("AgentLink simple class name must be unique, duplicate found for: " + agentDescriptor.getAgentLinkClass());
}
agentLinkMap.put(agentLinkName, agentDescriptor.getAgentLinkClass());
}
}
});
// Check each value type implements serializable interface
List<ValueDescriptor<?>> nonSerializableValueDescriptors = new ArrayList<>();
valueDescriptors.forEach(vd -> {
if (!Serializable.class.isAssignableFrom(vd.getType())) {
nonSerializableValueDescriptors.add(vd);
}
});
if (!nonSerializableValueDescriptors.isEmpty()) {
String vds = nonSerializableValueDescriptors.stream().map(ValueDescriptor::toString).collect(Collectors.joining(",\n"));
throw new IllegalStateException("One or more value types do not implement java.io.Serializable: " + vds);
}
// Call on finished on each provider
assetModelProviders.forEach(AssetModelProvider::onAssetModelFinished);
// Add agent link sub types to object mapper (need to avoid circular dependency)
NamedType[] agentLinkSubTypes = Arrays.stream(getAgentLinkClasses()).map(agentLinkClass -> new NamedType(agentLinkClass, agentLinkClass.getSimpleName())).toArray(NamedType[]::new);
JSON.registerSubtypes(agentLinkSubTypes);
doSchemaInit();
}
use of org.openremote.model.AssetModelProvider in project openremote by openremote.
the class ValueUtil method getAssetClasses.
protected static Set<Class<? extends Asset<?>>> getAssetClasses(AssetModelProvider assetModelProvider) {
Set<Class<? extends Asset<?>>> assetClasses;
// Search for concrete asset classes in the same JAR as the provided AssetModelProvider
Reflections reflections = new Reflections(new ConfigurationBuilder().setUrls(ClasspathHelper.forClass(assetModelProvider.getClass())).setScanners(new SubTypesScanner(true)));
LOG.fine("Scanning for Asset classes");
assetClasses = reflections.getSubTypesOf(Asset.class).stream().map(assetClass -> (Class<? extends Asset<?>>) assetClass).filter(assetClass -> assetClass.getAnnotation(ModelIgnore.class) == null).collect(Collectors.toSet());
LOG.fine("Found asset class count = " + assetClasses.size());
return assetClasses;
}
Aggregations