/* * Copyright 2013 Robert von Burg <eitch@eitchnet.ch> * * 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 li.strolch.model.xml; import java.text.MessageFormat; import java.util.ArrayDeque; import java.util.Date; import java.util.Deque; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.xml.sax.Attributes; import org.xml.sax.SAXException; import org.xml.sax.helpers.DefaultHandler; import li.strolch.exception.StrolchException; import li.strolch.exception.StrolchPolicyException; import li.strolch.model.GroupedParameterizedElement; import li.strolch.model.ModelStatistics; import li.strolch.model.Order; import li.strolch.model.ParameterBag; import li.strolch.model.Resource; import li.strolch.model.State; import li.strolch.model.StrolchValueType; import li.strolch.model.Tags; import li.strolch.model.activity.Action; import li.strolch.model.activity.Activity; import li.strolch.model.parameter.Parameter; import li.strolch.model.policy.PolicyDef; import li.strolch.model.policy.PolicyDefs; import li.strolch.model.timedstate.StrolchTimedState; import li.strolch.model.timevalue.IValue; import li.strolch.model.timevalue.impl.ValueChange; import li.strolch.utils.helper.StringHelper; import li.strolch.utils.iso8601.ISO8601FormatFactory; /** * @author Robert von Burg <eitch@eitchnet.ch> */ public class XmlModelSaxReader extends DefaultHandler { protected static final Logger logger = LoggerFactory.getLogger(XmlModelSaxReader.class); protected StrolchElementListener listener; protected ModelStatistics statistics; private GroupedParameterizedElement parameterizedElement; private Deque<Activity> activityStack; private ParameterBag pBag; private StrolchTimedState<? extends IValue<?>> state; private StrolchValueType stateType; private PolicyDefs policies; public XmlModelSaxReader(StrolchElementListener listener) { this.listener = listener; this.statistics = new ModelStatistics(); this.activityStack = new ArrayDeque<>(); } /** * @return the statistics */ public ModelStatistics getStatistics() { return this.statistics; } @Override public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { // TODO split each root object into its own file switch (qName) { case Tags.STROLCH_MODEL: break; case Tags.RESOURCE: String resId = attributes.getValue(Tags.ID); String resName = attributes.getValue(Tags.NAME); String resType = attributes.getValue(Tags.TYPE); Resource resource = new Resource(resId, resName, resType); this.parameterizedElement = resource; break; case Tags.ACTIVITY: String activityId = attributes.getValue(Tags.ID); String activityName = attributes.getValue(Tags.NAME); String activityType = attributes.getValue(Tags.TYPE); Activity activity = new Activity(activityId, activityName, activityType); this.parameterizedElement = activity; this.activityStack.push(activity); break; case Tags.ACTION: String actionId = attributes.getValue(Tags.ID); String actionName = attributes.getValue(Tags.NAME); String actionType = attributes.getValue(Tags.TYPE); String actionResourceId = attributes.getValue(Tags.RESOURCE_ID); String actionResourceType = attributes.getValue(Tags.RESOURCE_TYPE); String actionState = attributes.getValue(Tags.STATE); Action action = new Action(actionId, actionName, actionType); action.setResourceId(actionResourceId); action.setResourceType(actionResourceType); if (StringHelper.isNotEmpty(actionState)) action.setState(State.valueOf(actionState)); this.parameterizedElement = action; break; case Tags.VALUE_CHANGE: String valueChangeStateId = attributes.getValue(Tags.STATE_ID); String valueChangeTimeS = attributes.getValue(Tags.TIME); String valueChangeValue = attributes.getValue(Tags.VALUE); String valueChangeType = attributes.getValue(Tags.TYPE); IValue<?> value = StrolchValueType.parse(valueChangeType).valueInstance(valueChangeValue); long valueChangeTime = ISO8601FormatFactory.getInstance().getDateFormat().parse(valueChangeTimeS).getTime(); ValueChange<IValue<?>> valueChange = new ValueChange<>(valueChangeTime, value, valueChangeStateId); ((Action) this.parameterizedElement).addChange(valueChange); break; case Tags.ORDER: String orderId = attributes.getValue(Tags.ID); String orderName = attributes.getValue(Tags.NAME); String orderType = attributes.getValue(Tags.TYPE); String orderDateS = attributes.getValue(Tags.DATE); String orderStateS = attributes.getValue(Tags.STATE); Order order = new Order(orderId, orderName, orderType); if (orderDateS != null) { Date orderDate = ISO8601FormatFactory.getInstance().getDateFormat().parse(orderDateS); order.setDate(orderDate); } if (StringHelper.isNotEmpty(orderStateS)) order.setState(State.valueOf(orderStateS)); this.parameterizedElement = order; break; case Tags.PARAMETER_BAG: String pBagId = attributes.getValue(Tags.ID); String pBagName = attributes.getValue(Tags.NAME); String pBagType = attributes.getValue(Tags.TYPE); ParameterBag pBag = new ParameterBag(pBagId, pBagName, pBagType); this.pBag = pBag; break; case Tags.PARAMETER: String paramId = attributes.getValue(Tags.ID); String paramName = attributes.getValue(Tags.NAME); String paramType = attributes.getValue(Tags.TYPE); String paramValue = attributes.getValue(Tags.VALUE); String paramHiddenS = attributes.getValue(Tags.HIDDEN); String paramIndexS = attributes.getValue(Tags.INDEX); try { int index = StringHelper.isEmpty(paramIndexS) ? 0 : Integer.valueOf(paramIndexS); boolean paramHidden = StringHelper.isEmpty(paramHiddenS) ? false : StringHelper.parseBoolean(paramHiddenS); String paramUom = attributes.getValue(Tags.UOM); String paramInterpretation = attributes.getValue(Tags.INTERPRETATION); StrolchValueType type = StrolchValueType.parse(paramType); Parameter<?> param = type.parameterInstance(); param.setId(paramId); param.setName(paramName); param.setValueFromString(paramValue); param.setHidden(paramHidden); param.setUom(paramUom); param.setInterpretation(paramInterpretation); param.setIndex(index); this.pBag.addParameter(param); } catch (Exception e) { throw new StrolchException("Failed to instantiate parameter " + paramId + " for bag " + this.pBag.getLocator() + " due to " + e.getMessage(), e); } break; case Tags.TIMED_STATE: String stateId = attributes.getValue(Tags.ID); String stateName = attributes.getValue(Tags.NAME); String stateType = attributes.getValue(Tags.TYPE); this.stateType = StrolchValueType.parse(stateType); this.state = this.stateType.timedStateInstance(); this.state.setId(stateId); this.state.setName(stateName); break; case Tags.VALUE: String valueTime = attributes.getValue(Tags.TIME); Date date = ISO8601FormatFactory.getInstance().parseDate(valueTime); long time = date.getTime(); String valueValue = attributes.getValue(Tags.VALUE); this.state.setStateFromStringAt(time, valueValue); break; case Tags.POLICIES: this.policies = new PolicyDefs(); break; case Tags.POLICY: String policyType = attributes.getValue(Tags.TYPE); String policyValue = attributes.getValue(Tags.VALUE); PolicyDef policyDef = PolicyDef.valueOf(policyType, policyValue); this.policies.addOrUpdate(policyDef); break; default: throw new IllegalArgumentException(MessageFormat.format("The element ''{0}'' is unhandled!", qName)); //$NON-NLS-1$ } } @Override public void endElement(String uri, String localName, String qName) throws SAXException { switch (qName) { case Tags.RESOURCE: this.listener.notifyResource((Resource) this.parameterizedElement); this.statistics.nrOfResources++; this.parameterizedElement = null; break; case Tags.ACTIVITY: Activity activity = this.activityStack.pop(); if (this.activityStack.isEmpty()) { this.listener.notifyActivity(activity); this.statistics.nrOfActivities++; } else { this.activityStack.peek().addElement(activity); } this.parameterizedElement = null; break; case Tags.ORDER: this.listener.notifyOrder((Order) this.parameterizedElement); this.statistics.nrOfOrders++; this.parameterizedElement = null; break; case Tags.ACTION: this.activityStack.peek().addElement((Action) parameterizedElement); this.parameterizedElement = null; break; case Tags.PARAMETER_BAG: this.parameterizedElement.addParameterBag(pBag); this.pBag = null; break; case Tags.TIMED_STATE: ((Resource) this.parameterizedElement).addTimedState(this.state); break; case Tags.POLICIES: if (this.parameterizedElement instanceof Resource) { ((Resource) this.parameterizedElement).setPolicyDefs(this.policies); } else if (this.parameterizedElement instanceof Order) { ((Order) this.parameterizedElement).setPolicyDefs(this.policies); } else if (this.parameterizedElement instanceof Activity) { ((Activity) this.parameterizedElement).setPolicyDefs(this.policies); } else if (this.parameterizedElement instanceof Action) { ((Action) this.parameterizedElement).setPolicyDefs(this.policies); } else { throw new StrolchPolicyException( "Policies are currently not allowed on " + this.parameterizedElement.getClass()); } this.policies = null; case Tags.POLICY: case Tags.PARAMETER: case Tags.INCLUDE_FILE: case Tags.VALUE: case Tags.VALUE_CHANGE: case Tags.STROLCH_MODEL: break; default: throw new IllegalArgumentException(MessageFormat.format("The element ''{0}'' is unhandled!", qName)); //$NON-NLS-1$ } } }