import com.google.common.base.Preconditions;
import com.google.common.base.Splitter;
+import com.google.common.base.Strings;
import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.ImmutableSet.Builder;
-import com.google.common.collect.Iterables;
import java.util.Collection;
+import java.util.Date;
+import java.util.Optional;
import java.util.Set;
import java.util.function.Predicate;
import org.opendaylight.yangtools.yang.common.QName;
import org.opendaylight.yangtools.yang.common.QNameModule;
+import org.opendaylight.yangtools.yang.common.SimpleDateFormatUtil;
import org.opendaylight.yangtools.yang.common.YangVersion;
+import org.opendaylight.yangtools.yang.model.api.ModuleIdentifier;
import org.opendaylight.yangtools.yang.model.api.YangStmtMapping;
import org.opendaylight.yangtools.yang.model.api.meta.DeclaredStatement;
import org.opendaylight.yangtools.yang.model.api.meta.StatementDefinition;
+import org.opendaylight.yangtools.yang.model.api.stmt.BelongsToStatement;
import org.opendaylight.yangtools.yang.model.api.stmt.KeyStatement;
import org.opendaylight.yangtools.yang.model.api.stmt.LeafStatement;
import org.opendaylight.yangtools.yang.model.api.stmt.MandatoryStatement;
import org.opendaylight.yangtools.yang.model.api.stmt.MinElementsStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.ModuleStatement;
import org.opendaylight.yangtools.yang.model.api.stmt.PresenceStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.RevisionStatement;
import org.opendaylight.yangtools.yang.model.api.stmt.SchemaNodeIdentifier;
+import org.opendaylight.yangtools.yang.model.api.stmt.SubmoduleStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.UnknownStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.UnrecognizedStatement;
+import org.opendaylight.yangtools.yang.model.repo.api.RevisionSourceIdentifier;
+import org.opendaylight.yangtools.yang.model.repo.api.SourceIdentifier;
+import org.opendaylight.yangtools.yang.parser.spi.source.BelongsToPrefixToModuleName;
+import org.opendaylight.yangtools.yang.parser.spi.source.ImpPrefixToModuleIdentifier;
+import org.opendaylight.yangtools.yang.parser.spi.source.ModuleCtxToModuleQName;
+import org.opendaylight.yangtools.yang.parser.spi.source.ModuleIdentifierToModuleQName;
+import org.opendaylight.yangtools.yang.parser.spi.source.ModuleNameToModuleQName;
import org.opendaylight.yangtools.yang.parser.spi.source.SourceException;
-import org.opendaylight.yangtools.yang.parser.spi.source.SupportedFeaturesNamespace;
-import org.opendaylight.yangtools.yang.parser.spi.source.SupportedFeaturesNamespace.SupportedFeatures;
-import org.opendaylight.yangtools.yang.parser.stmt.reactor.RootStatementContext;
-import org.opendaylight.yangtools.yang.parser.stmt.reactor.StatementContextBase;
-import org.opendaylight.yangtools.yang.parser.stmt.rfc6020.UnknownStatementImpl;
-import org.opendaylight.yangtools.yang.parser.stmt.rfc6020.YangDataStatementImpl;
public final class StmtContextUtils {
public static final Splitter LIST_KEY_SPLITTER = Splitter.on(' ').omitEmptyStrings().trimResults();
}
@SuppressWarnings("unchecked")
- public static <AT, DT extends DeclaredStatement<AT>> AT firstAttributeOf(
- final Iterable<? extends StmtContext<?, ?, ?>> contexts, final Class<DT> declaredType) {
+ public static <A, D extends DeclaredStatement<A>> A firstAttributeOf(
+ final Iterable<? extends StmtContext<?, ?, ?>> contexts, final Class<D> declaredType) {
for (final StmtContext<?, ?, ?> ctx : contexts) {
if (producesDeclared(ctx, declaredType)) {
- return (AT) ctx.getStatementArgument();
+ return (A) ctx.getStatementArgument();
}
}
return null;
}
@SuppressWarnings("unchecked")
- public static <AT, DT extends DeclaredStatement<AT>> AT firstAttributeOf(final StmtContext<?, ?, ?> ctx,
- final Class<DT> declaredType) {
- return producesDeclared(ctx, declaredType) ? (AT) ctx.getStatementArgument() : null;
+ public static <A, D extends DeclaredStatement<A>> A firstAttributeOf(final StmtContext<?, ?, ?> ctx,
+ final Class<D> declaredType) {
+ return producesDeclared(ctx, declaredType) ? (A) ctx.getStatementArgument() : null;
}
- public static <AT, DT extends DeclaredStatement<AT>> AT firstSubstatementAttributeOf(
- final StmtContext<?, ?, ?> ctx, final Class<DT> declaredType) {
- final AT firstAttribute = firstAttributeOf(ctx.effectiveSubstatements(), declaredType);
- return firstAttribute != null ? firstAttribute : firstAttributeOf(ctx.declaredSubstatements(), declaredType);
+ public static <A, D extends DeclaredStatement<A>> A firstSubstatementAttributeOf(
+ final StmtContext<?, ?, ?> ctx, final Class<D> declaredType) {
+ return firstAttributeOf(ctx.allSubstatements(), declaredType);
}
@SuppressWarnings("unchecked")
- public static <AT, DT extends DeclaredStatement<AT>> StmtContext<AT, ?, ?> findFirstDeclaredSubstatement(
- final StmtContext<?, ?, ?> stmtContext, final Class<DT> declaredType) {
+ public static <A, D extends DeclaredStatement<A>> StmtContext<A, ?, ?> findFirstDeclaredSubstatement(
+ final StmtContext<?, ?, ?> stmtContext, final Class<D> declaredType) {
for (final StmtContext<?, ?, ?> subStmtContext : stmtContext.declaredSubstatements()) {
if (producesDeclared(subStmtContext, declaredType)) {
- return (StmtContext<AT, ?, ?>) subStmtContext;
+ return (StmtContext<A, ?, ?>) subStmtContext;
}
}
return null;
}
@SuppressWarnings("unchecked")
- public static <AT, DT extends DeclaredStatement<AT>> Collection<StmtContext<AT, DT, ?>> findAllDeclaredSubstatements(
- final StmtContext<?, ?, ?> stmtContext, final Class<DT> declaredType) {
- final ImmutableList.Builder<StmtContext<AT, DT, ?>> listBuilder = ImmutableList.builder();
+ public static <A, D extends DeclaredStatement<A>> Collection<StmtContext<A, D, ?>> findAllDeclaredSubstatements(
+ final StmtContext<?, ?, ?> stmtContext, final Class<D> declaredType) {
+ final ImmutableList.Builder<StmtContext<A, D, ?>> listBuilder = ImmutableList.builder();
for (final StmtContext<?, ?, ?> subStmtContext : stmtContext.declaredSubstatements()) {
if (producesDeclared(subStmtContext, declaredType)) {
- listBuilder.add((StmtContext<AT, DT, ?>) subStmtContext);
+ listBuilder.add((StmtContext<A, D, ?>) subStmtContext);
}
}
return listBuilder.build();
}
@SuppressWarnings("unchecked")
- public static <AT, DT extends DeclaredStatement<AT>> Collection<StmtContext<AT, DT, ?>> findAllEffectiveSubstatements(
- final StmtContext<?, ?, ?> stmtContext, final Class<DT> type) {
- final ImmutableList.Builder<StmtContext<AT, DT, ?>> listBuilder = ImmutableList.builder();
+ public static <A, D extends DeclaredStatement<A>> Collection<StmtContext<A, D, ?>> findAllEffectiveSubstatements(
+ final StmtContext<?, ?, ?> stmtContext, final Class<D> type) {
+ final ImmutableList.Builder<StmtContext<A, D, ?>> listBuilder = ImmutableList.builder();
for (final StmtContext<?, ?, ?> subStmtContext : stmtContext.effectiveSubstatements()) {
if (producesDeclared(subStmtContext, type)) {
- listBuilder.add((StmtContext<AT, DT, ?>) subStmtContext);
+ listBuilder.add((StmtContext<A, D, ?>) subStmtContext);
}
}
return listBuilder.build();
}
- public static <AT, DT extends DeclaredStatement<AT>> Collection<StmtContext<AT, DT, ?>> findAllSubstatements(
- final StmtContext<?, ?, ?> stmtContext, final Class<DT> type) {
- final ImmutableList.Builder<StmtContext<AT, DT, ?>> listBuilder = ImmutableList.builder();
+ public static <A, D extends DeclaredStatement<A>> Collection<StmtContext<A, D, ?>> findAllSubstatements(
+ final StmtContext<?, ?, ?> stmtContext, final Class<D> type) {
+ final ImmutableList.Builder<StmtContext<A, D, ?>> listBuilder = ImmutableList.builder();
listBuilder.addAll(findAllDeclaredSubstatements(stmtContext, type));
listBuilder.addAll(findAllEffectiveSubstatements(stmtContext, type));
return listBuilder.build();
}
@SuppressWarnings("unchecked")
- public static <AT, DT extends DeclaredStatement<AT>> StmtContext<AT, ?, ?> findFirstEffectiveSubstatement(
- final StmtContext<?, ?, ?> stmtContext, final Class<DT> declaredType) {
+ public static <A, D extends DeclaredStatement<A>> StmtContext<A, ?, ?> findFirstEffectiveSubstatement(
+ final StmtContext<?, ?, ?> stmtContext, final Class<D> declaredType) {
for (final StmtContext<?, ?, ?> subStmtContext : stmtContext.effectiveSubstatements()) {
if (producesDeclared(subStmtContext, declaredType)) {
- return (StmtContext<AT, ?, ?>) subStmtContext;
+ return (StmtContext<A, ?, ?>) subStmtContext;
}
}
return null;
*
* @param stmtContext statement context to search in
* @param declaredType substatement type to search for
- * @param <AT> statement argument type
- * @param <DT> declared statement type
+ * @param <A> statement argument type
+ * @param <D> declared statement type
* @return statement context that was searched for or null if was not found
*/
- public static <AT, DT extends DeclaredStatement<AT>> StmtContext<AT, ?, ?> findFirstSubstatement(
- final StmtContext<?, ?, ?> stmtContext, final Class<DT> declaredType) {
- final StmtContext<AT, ?, ?> effectiveSubstatement = findFirstEffectiveSubstatement(stmtContext, declaredType);
+ public static <A, D extends DeclaredStatement<A>> StmtContext<A, ?, ?> findFirstSubstatement(
+ final StmtContext<?, ?, ?> stmtContext, final Class<D> declaredType) {
+ final StmtContext<A, ?, ?> effectiveSubstatement = findFirstEffectiveSubstatement(stmtContext, declaredType);
return effectiveSubstatement != null ? effectiveSubstatement : findFirstDeclaredSubstatement(stmtContext,
declaredType);
}
return null;
}
- public static <DT extends DeclaredStatement<?>> StmtContext<?, ?, ?> findFirstDeclaredSubstatementOnSublevel(
- final StmtContext<?, ?, ?> stmtContext, final Class<DT> declaredType, int sublevel) {
+ public static <D extends DeclaredStatement<?>> StmtContext<?, ?, ?> findFirstDeclaredSubstatementOnSublevel(
+ final StmtContext<?, ?, ?> stmtContext, final Class<D> declaredType, int sublevel) {
for (final StmtContext<?, ?, ?> subStmtContext : stmtContext.declaredSubstatements()) {
if (sublevel == 1 && producesDeclared(subStmtContext, declaredType)) {
return subStmtContext;
return null;
}
- public static <DT extends DeclaredStatement<?>> StmtContext<?, ?, ?> findDeepFirstDeclaredSubstatement(
- final StmtContext<?, ?, ?> stmtContext, final Class<DT> declaredType) {
+ public static <D extends DeclaredStatement<?>> StmtContext<?, ?, ?> findDeepFirstDeclaredSubstatement(
+ final StmtContext<?, ?, ?> stmtContext, final Class<D> declaredType) {
for (final StmtContext<?, ?, ?> subStmtContext : stmtContext.declaredSubstatements()) {
if (producesDeclared(subStmtContext, declaredType)) {
return subStmtContext;
public static boolean isInExtensionBody(final StmtContext<?, ?, ?> stmtCtx) {
StmtContext<?, ?, ?> current = stmtCtx;
- while (!current.getParentContext().isRootContext()) {
+ while (current.getParentContext().getParentContext() != null) {
current = current.getParentContext();
- if (producesDeclared(current, UnknownStatementImpl.class)) {
+ if (isUnknownStatement(current)) {
return true;
}
}
}
/**
- * Checks if the statement context has a 'yang-data' extension node as its parent.
+ * Returns true if supplied statement context represents unknown statement,
+ * otherwise returns false.
*
- * @param stmtCtx statement context to be checked
- * @return true if the parent node is a 'yang-data' node, otherwise false
+ * @param stmtCtx
+ * statement context to be checked
+ * @return true if supplied statement context represents unknown statement,
+ * otherwise false
+ * @throws NullPointerException
+ * if supplied statement context is null
*/
- public static boolean hasYangDataExtensionParent(final StmtContext<?, ?, ?> stmtCtx) {
- return producesDeclared(stmtCtx.getParentContext(), YangDataStatementImpl.class);
- }
-
public static boolean isUnknownStatement(final StmtContext<?, ?, ?> stmtCtx) {
- return producesDeclared(stmtCtx, UnknownStatementImpl.class);
- }
-
- public static Collection<SchemaNodeIdentifier> replaceModuleQNameForKey(
- final StmtContext<Collection<SchemaNodeIdentifier>, KeyStatement, ?> keyStmtCtx,
- final QNameModule newQNameModule) {
-
- final Builder<SchemaNodeIdentifier> builder = ImmutableSet.builder();
- boolean replaced = false;
- for (final SchemaNodeIdentifier arg : keyStmtCtx.getStatementArgument()) {
- final QName qname = arg.getLastComponent();
- if (!newQNameModule.equals(qname)) {
- final QName newQname = keyStmtCtx.getFromNamespace(QNameCacheNamespace.class,
- QName.create(newQNameModule, qname.getLocalName()));
- builder.add(SchemaNodeIdentifier.create(false, newQname));
- replaced = true;
- } else {
- builder.add(arg);
- }
- }
-
- // This makes sure we reuse the collection when a grouping is
- // instantiated in the same module
- return replaced ? builder.build() : keyStmtCtx.getStatementArgument();
+ return UnknownStatement.class
+ .isAssignableFrom(stmtCtx.getPublicDefinition().getDeclaredRepresentationClass());
}
- public static boolean areFeaturesSupported(final StmtContext.Mutable<?, ?, ?> stmtContext) {
- switch (stmtContext.getSupportedByFeatures()) {
- case SUPPORTED:
- return true;
- case NOT_SUPPORTED:
- return false;
- default:
- break;
- }
-
- final Set<QName> supportedFeatures = stmtContext.getFromNamespace(SupportedFeaturesNamespace.class,
- SupportedFeatures.SUPPORTED_FEATURES);
- /*
- * If set of supported features has not been provided, all features are
- * supported by default.
- */
- if (supportedFeatures == null) {
- stmtContext.setSupportedByFeatures(true);
- return true;
- }
-
- final boolean result = checkFeatureSupport(stmtContext, supportedFeatures);
- stmtContext.setSupportedByFeatures(result);
- return result;
+ /**
+ * Returns true if supplied statement context represents unrecognized
+ * statement, otherwise returns false.
+ *
+ * @param stmtCtx
+ * statement context to be checked
+ * @return true if supplied statement context represents unrecognized
+ * statement, otherwise false
+ * @throws NullPointerException
+ * if supplied statement context is null
+ */
+ public static boolean isUnrecognizedStatement(final StmtContext<?, ?, ?> stmtCtx) {
+ return UnrecognizedStatement.class
+ .isAssignableFrom(stmtCtx.getPublicDefinition().getDeclaredRepresentationClass());
}
- private static boolean checkFeatureSupport(final StmtContext.Mutable<?, ?, ?> stmtContext,
+ public static boolean checkFeatureSupport(final StmtContext<?, ?, ?> stmtContext,
final Set<QName> supportedFeatures) {
boolean isSupported = false;
boolean containsIfFeature = false;
- for (final StatementContextBase<?, ?, ?> stmt : stmtContext.declaredSubstatements()) {
+ for (final StmtContext<?, ?, ?> stmt : stmtContext.declaredSubstatements()) {
if (YangStmtMapping.IF_FEATURE.equals(stmt.getPublicDefinition())) {
- if (stmtContext.isInYangDataExtensionBody()) {
- break;
- }
-
containsIfFeature = true;
if (((Predicate<Set<QName>>) stmt.getStatementArgument()).test(supportedFeatures)) {
isSupported = true;
* statement context
* @return true if it is a presence container
*/
- public static boolean isPresenceContainer(final StatementContextBase<?, ?, ?> stmtCtx) {
+ public static boolean isPresenceContainer(final StmtContext<?, ?, ?> stmtCtx) {
return stmtCtx.getPublicDefinition() == YangStmtMapping.CONTAINER && containsPresenceSubStmt(stmtCtx);
}
* statement context
* @return true if it is a non-presence container
*/
- public static boolean isNonPresenceContainer(final StatementContextBase<?, ?, ?> stmtCtx) {
+ public static boolean isNonPresenceContainer(final StmtContext<?, ?, ?> stmtCtx) {
return stmtCtx.getPublicDefinition() == YangStmtMapping.CONTAINER && !containsPresenceSubStmt(stmtCtx);
}
- private static boolean containsPresenceSubStmt(final StatementContextBase<?, ?, ?> stmtCtx) {
+ private static boolean containsPresenceSubStmt(final StmtContext<?, ?, ?> stmtCtx) {
return findFirstSubstatement(stmtCtx, PresenceStatement.class) != null;
}
* @return true if it is a mandatory leaf, choice, anyxml, list or leaf-list
* according to RFC6020.
*/
- public static boolean isMandatoryNode(final StatementContextBase<?, ?, ?> stmtCtx) {
+ public static boolean isMandatoryNode(final StmtContext<?, ?, ?> stmtCtx) {
if (!(stmtCtx.getPublicDefinition() instanceof YangStmtMapping)) {
return false;
}
* statement definition and if it is not mandatory leaf, choice,
* anyxml, list or leaf-list according to RFC6020
*/
- public static boolean isNotMandatoryNodeOfType(final StatementContextBase<?, ?, ?> stmtCtx,
+ public static boolean isNotMandatoryNodeOfType(final StmtContext<?, ?, ?> stmtCtx,
final StatementDefinition stmtDef) {
return stmtCtx.getPublicDefinition().equals(stmtDef) && !isMandatoryNode(stmtCtx);
}
*
* @return true if all of StmtContext's ancestors of specified type have a child of specified type, otherwise false
*/
- public static <AT, DT extends DeclaredStatement<AT>> boolean hasAncestorOfTypeWithChildOfType(final StmtContext<?, ?, ?> ctx,
+ public static <A, D extends DeclaredStatement<A>> boolean hasAncestorOfTypeWithChildOfType(final StmtContext<?, ?, ?> ctx,
final StatementDefinition ancestorType, final StatementDefinition ancestorChildType) {
Preconditions.checkNotNull(ctx);
Preconditions.checkNotNull(ancestorType);
Preconditions.checkNotNull(ancestorChildType);
+
StmtContext<?, ?, ?> current = ctx.getParentContext();
- while (!(current instanceof RootStatementContext)) {
+ StmtContext<?, ?, ?> parent = current.getParentContext();
+ while (parent != null) {
if (ancestorType.equals(current.getPublicDefinition())) {
@SuppressWarnings("unchecked")
- final Class<DT> ancestorChildTypeClass = (Class<DT>) ancestorChildType.getDeclaredRepresentationClass();
+ final Class<D> ancestorChildTypeClass = (Class<D>) ancestorChildType.getDeclaredRepresentationClass();
if (findFirstSubstatement(current, ancestorChildTypeClass) == null) {
return false;
}
}
- current = current.getParentContext();
+
+ current = parent;
+ parent = current.getParentContext();
}
return true;
}
private static void disallowIfFeatureAndWhenOnListKeys(final StmtContext<?, ?, ?> leafStmtCtx) {
- Iterables.concat(leafStmtCtx.declaredSubstatements(), leafStmtCtx.effectiveSubstatements()).forEach(
- leafSubstmtCtx -> {
+ leafStmtCtx.allSubstatements().forEach(leafSubstmtCtx -> {
final StatementDefinition statementDef = leafSubstmtCtx.getPublicDefinition();
SourceException.throwIf(YangStmtMapping.IF_FEATURE.equals(statementDef)
|| YangStmtMapping.WHEN.equals(statementDef), leafStmtCtx.getStatementSourceReference(),
statementDef.getStatementName(), leafStmtCtx.getStatementArgument());
});
}
+
+ public static QName qnameFromArgument(StmtContext<?, ?, ?> ctx, final String value) {
+ if (Strings.isNullOrEmpty(value)) {
+ return ctx.getPublicDefinition().getStatementName();
+ }
+
+ String prefix;
+ QNameModule qNameModule = null;
+ String localName = null;
+
+ final String[] namesParts = value.split(":");
+ switch (namesParts.length) {
+ case 1:
+ localName = namesParts[0];
+ qNameModule = StmtContextUtils.getRootModuleQName(ctx);
+ break;
+ default:
+ prefix = namesParts[0];
+ localName = namesParts[1];
+ qNameModule = StmtContextUtils.getModuleQNameByPrefix(ctx, prefix);
+ // in case of unknown statement argument, we're not going to parse it
+ if (qNameModule == null && isUnknownStatement(ctx)) {
+ localName = value;
+ qNameModule = StmtContextUtils.getRootModuleQName(ctx);
+ }
+ if (qNameModule == null
+ && ctx.getCopyHistory().getLastOperation() == CopyType.ADDED_BY_AUGMENTATION) {
+ ctx = ctx.getOriginalCtx().orElse(null);
+ qNameModule = StmtContextUtils.getModuleQNameByPrefix(ctx, prefix);
+ }
+ break;
+ }
+
+ qNameModule = InferenceException.throwIfNull(qNameModule, ctx.getStatementSourceReference(),
+ "Cannot resolve QNameModule for '%s'", value);
+
+ final QNameModule resultQNameModule;
+ if (qNameModule.getRevision() == null) {
+ resultQNameModule = QNameModule.create(qNameModule.getNamespace(), SimpleDateFormatUtil.DEFAULT_DATE_REV)
+ .intern();
+ } else {
+ resultQNameModule = qNameModule;
+ }
+
+ return ctx.getFromNamespace(QNameCacheNamespace.class, QName.create(resultQNameModule, localName));
+ }
+
+ public static QNameModule getRootModuleQName(final StmtContext<?, ?, ?> ctx) {
+ if (ctx == null) {
+ return null;
+ }
+
+ final StmtContext<?, ?, ?> rootCtx = ctx.getRoot();
+ final QNameModule qNameModule;
+
+ if (producesDeclared(rootCtx, ModuleStatement.class)) {
+ qNameModule = rootCtx.getFromNamespace(ModuleCtxToModuleQName.class, rootCtx);
+ } else if (producesDeclared(rootCtx, SubmoduleStatement.class)) {
+ final String belongsToModuleName = firstAttributeOf(rootCtx.declaredSubstatements(),
+ BelongsToStatement.class);
+ qNameModule = rootCtx.getFromNamespace(ModuleNameToModuleQName.class, belongsToModuleName);
+ } else {
+ qNameModule = null;
+ }
+
+ Preconditions.checkArgument(qNameModule != null, "Failed to look up root QNameModule for %s", ctx);
+ if (qNameModule.getRevision() != null) {
+ return qNameModule;
+ }
+
+ return QNameModule.create(qNameModule.getNamespace(), SimpleDateFormatUtil.DEFAULT_DATE_REV).intern();
+ }
+
+ public static QNameModule getModuleQNameByPrefix(final StmtContext<?, ?, ?> ctx, final String prefix) {
+ final ModuleIdentifier modId = ctx.getRoot().getFromNamespace(ImpPrefixToModuleIdentifier.class, prefix);
+ final QNameModule qNameModule = ctx.getFromNamespace(ModuleIdentifierToModuleQName.class, modId);
+
+ if (qNameModule == null && producesDeclared(ctx.getRoot(), SubmoduleStatement.class)) {
+ final String moduleName = ctx.getRoot().getFromNamespace(BelongsToPrefixToModuleName.class, prefix);
+ return ctx.getFromNamespace(ModuleNameToModuleQName.class, moduleName);
+ }
+ return qNameModule;
+ }
+
+ public static SourceIdentifier createSourceIdentifier(final StmtContext<?, ?, ?> root) {
+ final QNameModule qNameModule = root.getFromNamespace(ModuleCtxToModuleQName.class, root);
+ if (qNameModule != null) {
+ // creates SourceIdentifier for a module
+ return RevisionSourceIdentifier.create((String) root.getStatementArgument(),
+ qNameModule.getFormattedRevision());
+ }
+
+ // creates SourceIdentifier for a submodule
+ final Date revision = Optional.ofNullable(getLatestRevision(root.declaredSubstatements()))
+ .orElse(SimpleDateFormatUtil.DEFAULT_DATE_REV);
+ final String formattedRevision = SimpleDateFormatUtil.getRevisionFormat().format(revision);
+ return RevisionSourceIdentifier.create((String) root.getStatementArgument(), formattedRevision);
+ }
+
+ public static Date getLatestRevision(final Iterable<? extends StmtContext<?, ?, ?>> subStmts) {
+ Date revision = null;
+ for (final StmtContext<?, ?, ?> subStmt : subStmts) {
+ if (subStmt.getPublicDefinition().getDeclaredRepresentationClass().isAssignableFrom(RevisionStatement
+ .class)) {
+ if (revision == null && subStmt.getStatementArgument() != null) {
+ revision = (Date) subStmt.getStatementArgument();
+ } else if (subStmt.getStatementArgument() != null && ((Date) subStmt.getStatementArgument()).compareTo
+ (revision) > 0) {
+ revision = (Date) subStmt.getStatementArgument();
+ }
+ }
+ }
+ return revision;
+ }
}