stevedlawrence commented on a change in pull request #394: URL: https://github.com/apache/incubator-daffodil/pull/394#discussion_r455010022
########## File path: daffodil-core/src/main/scala/org/apache/daffodil/dsom/walker/RecordWalker.scala ########## @@ -0,0 +1,309 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 org.apache.daffodil.dsom.walker + +import java.io.File +import java.util + +import org.apache.daffodil.dsom.{Choice, ComplexTypeBase, ElementBase, GroupRef, Root, Sequence, SimpleTypeBase, Term} +import org.apache.nifi.serialization.SimpleRecordSchema +import org.apache.nifi.serialization.record.{DataType, RecordField, RecordFieldType, RecordSchema, SchemaIdentifier} +import org.apache.nifi.serialization.record.`type`.RecordDataType +import scala.collection.mutable.ListBuffer + +/** + * Direct subclass of the NIFI RecordField. NIFI doesn't have "Optional" fields, so + * eventually this will either be removed from the Schema if an Infoset doesn't have the field, + * or it will become a regular RecordField if it does. + * @param fieldName the name for the RecordField + * @param dataType the NIFI DataType of this RecordField + */ +class OptionalRecordField(fieldName: String, dataType: DataType) + extends RecordField(fieldName, dataType) { + // this is the easiest way to construct it; essentially a "copy constructor" except to denote + // that we want to treat it as this special optional subclass. + def this(recordField: RecordField) = this(recordField.getFieldName, recordField.getDataType) + override def equals(obj: Any): Boolean = + obj match { + case _: OptionalRecordField => super.equals(obj) + case _ => false + } + override def hashCode(): Int = 31 * super.hashCode() + 1 + override def toString: String = "Optional" + super.toString +} + +/** + * Concrete implementation of the AbstractDSOMWalker abstract class. + * This class produces a NIFI RecordSchema that is intended to match the original DFDL file. + * + * The RecordSchema is built in 3 primary stages: + * 1) A tree of SchemaNodes is created as the DFDL file is walked; this walk is performed + * through the various event handlers defined in the parent abstract class. + * 2) The tree of SchemaNodes undergoes some post-processing, mainly to remove redundant Record wrappers. + * 3) The tree of SchemaNodes is converted into a RecordSchema; it is walked recursively within this class. + * @param schemaFile an input DFDL Schema file to parse + */ +class RecordWalker(schemaFile: File) extends AbstractDSOMWalker[RecordSchema](schemaFile) { Review comment: Re: the nifi-daffodil repo, if you're able to modify the nifi-daffodil repo to support scala, it should work fine in theory. I suspect the new controllers are mostly separate from the existing processors? Re: walkDSOM on ProcessorFactory, I think after discussions the consensus is that while a recursive walk is useful, there may be cases where it isn't sufficient. So I would suggust that we move all the ``walkDSOM`` functions off of the Views and onto the AbstractDSOMWalker (just like you had originally), so the AbstractDSOM walker has all the logic for how to recursively walk a DSOM. Then the only new function need on the the ProcessorFactory is an ability to get the RootView. If one wants to traverse this RootView manually, they can do so. But if they just want to traverse it recrusively and get events, they can create a concrete implementation of the AbstractDSOMWalker and implement those events (and potential override the walkDSOM function if they want. So for example: ```scala val rootView = processorFactory.rootView val walker = new DSOMWalkerImpl() walker.walkDSOM(rootView) ``` So the View's don't contain any logic about how they should be traversed, since they don't really know that. Recurisve makes sense, but presumable there are reasonable traversals. And technically the AbstractDSOMWalker isn't even neccessary--the views have all the information needed to traverse them. But to be helpful, it makes sense to also provide a AbstractDSOMWalker interface that contains all the logic for traversing recursively so users don't have to think about that and can just think of it as a series of events. So this is very similar to what you originally started with, but just with Views to hide internal details of our dsom objects. ---------------------------------------------------------------- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. For queries about this service, please contact Infrastructure at: [email protected]
