net.n2oapp.framework.config.reader.N2oNamespaceReaderFactory Maven / Gradle / Ivy
The newest version!
package net.n2oapp.framework.config.reader;
import net.n2oapp.framework.api.metadata.aware.NamespaceUriAware;
import net.n2oapp.framework.api.metadata.io.IOProcessor;
import net.n2oapp.framework.api.metadata.io.IOProcessorAware;
import net.n2oapp.framework.api.metadata.io.NamespaceIO;
import net.n2oapp.framework.api.metadata.io.ProxyNamespaceIO;
import net.n2oapp.framework.api.metadata.reader.NamespaceReader;
import net.n2oapp.framework.api.metadata.reader.NamespaceReaderFactory;
import net.n2oapp.framework.config.ElementWrongLocation;
import net.n2oapp.framework.config.SchemaNotRegisteredException;
import org.jdom2.Namespace;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
/**
* Фабрика, генерирующая сервисы чтения xml файлов(метаданных) в объекты n2o.
* Подходящий сервис отыскивается сначала по имени DOM элемента, если он неуникальный поиск уточняется по namespaceUri.
*/
public class N2oNamespaceReaderFactory implements NamespaceReaderFactory>,
ApplicationContextAware, IOProcessorAware {
private ApplicationContext applicationContext;
private IOProcessor processor;
// первый параметр - namespace, второй element
private volatile Map>> engines;
@Override
public NamespaceReader produce(String elementName, Namespace... namespaces) {
if (engines == null)
initFactory();
Map> elementReaders = new HashMap<>();
for (Namespace namespace : namespaces) {
if (engines.containsKey(namespace.getURI()))
engines.get(namespace.getURI()).forEach(elementReaders::putIfAbsent);
}
if (elementReaders.isEmpty())
throw new SchemaNotRegisteredException(elementName);
NamespaceReader reader = elementReaders.get(elementName);
if (reader == null)
throw new ElementWrongLocation(elementName);
if (reader instanceof IOProcessorAware)
((IOProcessorAware) reader).setIOProcessor(this.processor);
return reader;
}
private synchronized void initFactory() {
if (engines == null) {
Map>> result = new HashMap<>();
Collection beans = new ArrayList<>(applicationContext.getBeansOfType(NamespaceReader.class).values());
if (processor != null) {
for (NamespaceIO ioBean : applicationContext.getBeansOfType(NamespaceIO.class).values()) {
beans.add(new ProxyNamespaceIO<>(ioBean, processor));
}
}
beans.forEach(b -> {
String namespaceUri = b.getNamespaceUri();
if (result.containsKey(namespaceUri)) {
result.get(namespaceUri).put(b.getElementName(), b);
} else {
Map> typedEngines = new HashMap<>();
typedEngines.put(b.getElementName(), b);
result.put(namespaceUri, typedEngines);
}
});
engines = result;
}
}
@Override
public void add(NamespaceReader reader) {
throw new UnsupportedOperationException();
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
}
@Override
public void setIOProcessor(IOProcessor processor) {
this.processor = processor;
}
}