[New] Refactored XML import and export model

- added allowInclude for recursive parsing of xml importing
- ModelStatistics is now JAXB capable
- added handling of absolute paths
This commit is contained in:
Robert von Burg 2015-02-28 20:41:52 +01:00
parent c0b9ac930e
commit a832b2dc3e
10 changed files with 129 additions and 29 deletions

View File

@ -115,7 +115,7 @@ public class TransientRealm extends InternalStrolchRealm {
ModelStatistics statistics;
try (StrolchTransaction tx = openTx(privilegeContext.getCertificate(), DefaultRealmHandler.AGENT_BOOT)) {
InMemoryElementListener elementListener = new InMemoryElementListener(tx);
XmlModelSaxFileReader handler = new XmlModelSaxFileReader(elementListener, this.modelFile);
XmlModelSaxFileReader handler = new XmlModelSaxFileReader(elementListener, this.modelFile, true);
handler.parseFile();
statistics = handler.getStatistics();
tx.commitOnClose();

View File

@ -4,14 +4,34 @@ import static ch.eitchnet.utils.helper.StringHelper.NULL;
import java.util.Date;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
import li.strolch.model.xml.Iso8601DateAdapter;
import ch.eitchnet.utils.helper.StringHelper;
import ch.eitchnet.utils.iso8601.ISO8601FormatFactory;
/**
* @author Robert von Burg <eitch@eitchnet.ch>
*/
@XmlRootElement(name = "ModelStatistics")
@XmlAccessorType(XmlAccessType.NONE)
public class ModelStatistics {
@XmlAttribute(name = "startTime")
@XmlJavaTypeAdapter(value = Iso8601DateAdapter.class)
public Date startTime;
@XmlAttribute(name = "duractionNanos")
public long durationNanos;
@XmlAttribute(name = "nrOfResources")
public long nrOfResources;
@XmlAttribute(name = "nrOfOrders")
public long nrOfOrders;
/**
@ -28,6 +48,9 @@ public class ModelStatistics {
return this.nrOfResources;
}
/**
* @return the nrOfResources + nrOfOrders
*/
public long getNrOfElements() {
return this.nrOfOrders + this.nrOfResources;
}

View File

@ -16,11 +16,9 @@
package li.strolch.model.xml;
import java.io.File;
import java.io.IOException;
import java.text.MessageFormat;
import java.util.Date;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
@ -34,19 +32,21 @@ import ch.eitchnet.utils.helper.StringHelper;
/**
* @author Robert von Burg <eitch@eitchnet.ch>
*
*/
public class XmlModelSaxFileReader extends XmlModelSaxReader {
private File modelFile;
private boolean allowInclude;
/**
* @param listener
* @param modelFile
* @param allowInclude
*/
public XmlModelSaxFileReader(StrolchElementListener listener, File modelFile) {
public XmlModelSaxFileReader(StrolchElementListener listener, File modelFile, boolean allowInclude) {
super(listener);
this.modelFile = modelFile;
this.allowInclude = allowInclude;
}
@Override
@ -56,11 +56,17 @@ public class XmlModelSaxFileReader extends XmlModelSaxReader {
case Tags.INCLUDE_FILE:
if (!this.allowInclude) {
String msg = "ModelFile {0} has includes which are disabled for this parse invocation!";
throw new IllegalArgumentException(MessageFormat.format(msg, this.modelFile.getAbsolutePath())); //$NON-NLS-1$
}
String includeFileS = attributes.getValue(Tags.FILE);
if (StringHelper.isEmpty(includeFileS)) {
throw new IllegalArgumentException(MessageFormat.format(
"The attribute {0} is missing for IncludeFile!", Tags.FILE)); //$NON-NLS-1$
}
File includeFile = new File(this.modelFile.getParentFile(), includeFileS);
if (!includeFile.exists() || !includeFile.canRead()) {
String msg = "The IncludeFile does not exist, or is not readable. Source model: {0} with IncludeFile: {1}"; //$NON-NLS-1$
@ -68,7 +74,7 @@ public class XmlModelSaxFileReader extends XmlModelSaxReader {
throw new IllegalArgumentException(msg);
}
XmlModelSaxFileReader handler = new XmlModelSaxFileReader(this.listener, includeFile);
XmlModelSaxFileReader handler = new XmlModelSaxFileReader(this.listener, includeFile, this.allowInclude);
handler.parseFile();
this.statistics.nrOfOrders += handler.statistics.nrOfOrders;
this.statistics.nrOfResources += handler.statistics.nrOfResources;
@ -96,10 +102,10 @@ public class XmlModelSaxFileReader extends XmlModelSaxReader {
logger.info(MessageFormat.format(msg, this.modelFile.getAbsolutePath(),
StringHelper.formatNanoDuration(this.statistics.durationNanos)));
} catch (ParserConfigurationException | SAXException | IOException e) {
} catch (Exception e) {
String msg = "Parsing failed due to internal error: {0}"; //$NON-NLS-1$
throw new StrolchException(MessageFormat.format(msg, e.getMessage()), e);
String msg = "Parsing of {0} failed due to internal error: {1}"; //$NON-NLS-1$
throw new StrolchException(MessageFormat.format(msg, this.modelFile.getAbsolutePath(), e.getMessage()), e);
}
}
}

View File

@ -57,7 +57,7 @@ public class XmlModelDefaultHandlerTest {
orderMap.put(order.getId(), order);
}
};
XmlModelSaxFileReader handler = new XmlModelSaxFileReader(listener, file);
XmlModelSaxFileReader handler = new XmlModelSaxFileReader(listener, file, true);
handler.parseFile();
assertEquals(3, resourceMap.size());

View File

@ -80,7 +80,7 @@ public abstract class PostgreSqlInitializer implements SystemUserAction {
File dataStoreF = getDataStoreFile(this.runtimeConfig, this.realmConfig, realmName);
StoreToDaoElementListener listener = new StoreToDaoElementListener(tx);
XmlModelSaxFileReader handler = new XmlModelSaxFileReader(listener, dataStoreF);
XmlModelSaxFileReader handler = new XmlModelSaxFileReader(listener, dataStoreF, true);
handler.parseFile();
statistics = handler.getStatistics();
tx.commitOnClose();

View File

@ -42,6 +42,7 @@ public class XmlImportModelCommand extends Command {
// output
private ModelStatistics statistics;
private boolean allowInclude;
/**
* @param container
@ -68,7 +69,7 @@ public class XmlImportModelCommand extends Command {
elementListener.setOrderTypes(this.orderTypes);
elementListener.setResourceTypes(this.resourceTypes);
XmlModelSaxFileReader handler = new XmlModelSaxFileReader(elementListener, this.modelFile);
XmlModelSaxFileReader handler = new XmlModelSaxFileReader(elementListener, this.modelFile, this.allowInclude);
handler.parseFile();
this.statistics = handler.getStatistics();
@ -86,6 +87,13 @@ public class XmlImportModelCommand extends Command {
this.modelFile = modelFileName;
}
/**
* @param allowInclude
*/
public void setAllowInclude(boolean allowInclude) {
this.allowInclude = allowInclude;
}
/**
* @param addOrders
* the addOrders to set

View File

@ -40,7 +40,7 @@ public class XmlExportModelArgument extends ServiceArgument {
builder.append("external=");
builder.append(this.external);
builder.append("modelFileName=");
builder.append(", modelFileName=");
builder.append(this.modelFileName);
builder.append(", overwrite=");

View File

@ -24,10 +24,53 @@ public class XmlImportModelArgument extends ServiceArgument {
private static final long serialVersionUID = 1L;
public String modelFileName;
public boolean external = false;
public boolean allowInclude = true;
public boolean addOrders = true;
public boolean addResources = true;
public boolean updateOrders = true;
public boolean updateResources = true;
public Set<String> orderTypes = new HashSet<>();
public Set<String> resourceTypes = new HashSet<>();
@Override
public String toString() {
StringBuilder builder = new StringBuilder();
builder.append("XmlImportModelArgument [ ");
builder.append("external=");
builder.append(this.external);
builder.append(", allowInclude=");
builder.append(this.allowInclude);
builder.append(", modelFileName=");
builder.append(this.modelFileName);
if (this.addOrders)
builder.append(", addOrders");
if (this.addResources)
builder.append(", addResources");
if (this.updateOrders)
builder.append(", updateOrders");
if (this.updateResources)
builder.append(", updateResources");
if (this.resourceTypes != null && !this.resourceTypes.isEmpty()) {
builder.append(", resourceTypes=");
builder.append(this.resourceTypes);
} else {
builder.append(", resourceTypes=*");
}
if (this.orderTypes != null && !this.orderTypes.isEmpty()) {
builder.append(", orderTypes=");
builder.append(this.orderTypes);
} else {
builder.append(", orderTypes=*");
}
builder.append("]");
return builder.toString();
}
}

View File

@ -23,30 +23,49 @@ import li.strolch.exception.StrolchException;
import li.strolch.model.ModelStatistics;
import li.strolch.persistence.api.StrolchTransaction;
import li.strolch.service.api.AbstractService;
import li.strolch.service.api.ServiceResult;
import li.strolch.service.api.ServiceResultState;
import ch.eitchnet.utils.helper.StringHelper;
/**
* @author Robert von Burg <eitch@eitchnet.ch>
*/
public class XmlImportModelService extends AbstractService<XmlImportModelArgument, ServiceResult> {
public class XmlImportModelService extends AbstractService<XmlImportModelArgument, XmlImportModelResult> {
private static final long serialVersionUID = 1L;
@Override
protected ServiceResult getResultInstance() {
return new ServiceResult();
protected XmlImportModelResult getResultInstance() {
return new XmlImportModelResult();
}
@Override
protected ServiceResult internalDoService(XmlImportModelArgument arg) {
protected XmlImportModelResult internalDoService(XmlImportModelArgument arg) {
File dataPath = getRuntimeConfiguration().getDataPath();
File modelFile = new File(dataPath, arg.modelFileName);
if (!modelFile.exists()) {
String msg = "Model File does not exist with name {0} in data path {1}"; //$NON-NLS-1$
msg = MessageFormat.format(msg, arg.modelFileName, dataPath);
throw new StrolchException(msg);
File modelFile;
File modelFileName = new File(arg.modelFileName);
if (modelFileName.isAbsolute()) {
if (!arg.external) {
return new XmlImportModelResult(ServiceResultState.FAILED,
"Model file is absolute, yet service argument is not marked as external!");
}
modelFile = modelFileName;
if (!modelFile.exists()) {
String msg = "Model File does not exist at {0}"; //$NON-NLS-1$
msg = MessageFormat.format(msg, modelFile.getAbsolutePath());
throw new StrolchException(msg);
}
} else {
File dataPath = getRuntimeConfiguration().getDataPath();
modelFile = new File(dataPath, arg.modelFileName);
if (!modelFile.exists()) {
String msg = "Model File does not exist with name {0} in data path {1}"; //$NON-NLS-1$
msg = MessageFormat.format(msg, arg.modelFileName, dataPath);
throw new StrolchException(msg);
}
}
XmlImportModelCommand command;
@ -54,6 +73,7 @@ public class XmlImportModelService extends AbstractService<XmlImportModelArgumen
command = new XmlImportModelCommand(getContainer(), tx);
command.setModelFile(modelFile);
command.setAllowInclude(arg.allowInclude);
command.setAddOrders(arg.addOrders);
command.setAddResources(arg.addResources);
command.setUpdateOrders(arg.updateOrders);
@ -72,6 +92,6 @@ public class XmlImportModelService extends AbstractService<XmlImportModelArgumen
logger.info(MessageFormat.format("Loaded {0} Orders", statistics.nrOfOrders)); //$NON-NLS-1$
logger.info(MessageFormat.format("Loaded {0} Resources", statistics.nrOfResources)); //$NON-NLS-1$
return ServiceResult.success();
return new XmlImportModelResult(statistics);
}
}

View File

@ -40,8 +40,8 @@ public class ServiceExecutionStatus {
this.result = svcResult;
}
@XmlAttribute(name = "resultMessage")
public String getResultMessage() {
@XmlAttribute(name = "msg")
public String getMsg() {
if (this.result == null)
return StringHelper.DASH;
if (this.result.getMessage() == null)
@ -49,8 +49,8 @@ public class ServiceExecutionStatus {
return this.result.getMessage();
}
@XmlAttribute(name = "resultState")
public String getResultState() {
@XmlAttribute(name = "state")
public String getState() {
if (this.result == null)
return StringHelper.DASH;
return this.result.getState().name();