package org.opendaylight.yangtools.binding.generator.util;
import com.google.common.base.CharMatcher;
-import com.google.common.base.Splitter;
import com.google.common.collect.Iterables;
import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.IOException;
-import java.io.Serializable;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
-import java.text.SimpleDateFormat;
import java.util.ArrayList;
+import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-import org.opendaylight.yangtools.binding.generator.util.generated.type.builder.GeneratedPropertyBuilderImpl;
-import org.opendaylight.yangtools.binding.generator.util.generated.type.builder.GeneratedTOBuilderImpl;
import org.opendaylight.yangtools.sal.binding.model.api.AccessModifier;
import org.opendaylight.yangtools.sal.binding.model.api.Restrictions;
import org.opendaylight.yangtools.sal.binding.model.api.Type;
import org.opendaylight.yangtools.sal.binding.model.api.type.builder.TypeMemberBuilder;
import org.opendaylight.yangtools.yang.binding.BindingMapping;
import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.common.QNameModule;
import org.opendaylight.yangtools.yang.model.api.Module;
import org.opendaylight.yangtools.yang.model.api.SchemaPath;
import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
*/
public final class BindingGeneratorUtil {
- private static final ThreadLocal<SimpleDateFormat> DATE_FORMAT = new ThreadLocal<SimpleDateFormat>() {
-
- @Override
- protected SimpleDateFormat initialValue() {
- return new SimpleDateFormat("yyMMdd");
- }
-
- @Override
- public void set(final SimpleDateFormat value) {
- throw new UnsupportedOperationException();
- }
- };
-
/**
* Impossible to instantiate this class. All of the methods or attributes
* are static.
/**
* Pre-compiled replacement pattern.
*/
- private static final Pattern COLON_SLASH_SLASH = Pattern.compile("://", Pattern.LITERAL);
- private static final String QUOTED_DOT = Matcher.quoteReplacement(".");
- private static final Splitter DOT = Splitter.on('.');
private static final CharMatcher DOT_MATCHER = CharMatcher.is('.');
+ private static final CharMatcher DASH_COLON_MATCHER = CharMatcher.anyOf("-:");
- /**
- * Converts string <code>packageName</code> to valid JAVA package name.
- *
- * If some words of package name are digits of JAVA reserved words they are
- * prefixed with underscore character.
- *
- * @param packageName
- * string which contains words separated by point.
- * @return package name which contains words separated by point.
- */
- private static String validateJavaPackage(final String packageName) {
- if (packageName == null) {
- return null;
+ private static final Restrictions EMPTY_RESTRICTIONS = new Restrictions() {
+ @Override
+ public List<LengthConstraint> getLengthConstraints() {
+ return Collections.emptyList();
}
- final StringBuilder builder = new StringBuilder();
- boolean first = true;
+ @Override
+ public List<PatternConstraint> getPatternConstraints() {
+ return Collections.emptyList();
+ }
- for (String p : DOT.split(packageName.toLowerCase())) {
- if (first) {
- first = false;
- } else {
- builder.append('.');
- }
+ @Override
+ public List<RangeConstraint> getRangeConstraints() {
+ return Collections.emptyList();
+ }
- if (Character.isDigit(p.charAt(0)) || BindingMapping.JAVA_RESERVED_WORDS.contains(p)) {
- builder.append('_');
- }
- builder.append(p);
+ @Override
+ public boolean isEmpty() {
+ return true;
}
+ };
- return builder.toString();
- }
+ private static final Comparator<TypeMemberBuilder<?>> SUID_MEMBER_COMPARATOR = new Comparator<TypeMemberBuilder<?>>() {
+ @Override
+ public int compare(final TypeMemberBuilder<?> o1, final TypeMemberBuilder<?> o2) {
+ return o1.getName().compareTo(o2.getName());
+ }
+ };
+
+ private static final Comparator<Type> SUID_NAME_COMPARATOR = new Comparator<Type>() {
+ @Override
+ public int compare(final Type o1, final Type o2) {
+ return o1.getFullyQualifiedName().compareTo(o2.getFullyQualifiedName());
+ }
+ };
/**
* Converts <code>parameterName</code> to valid JAVA parameter name.
* @throws IllegalArgumentException
* if the revision date of the <code>module</code> equals
* <code>null</code>
+ * @deprecated USe {@link BindingMapping#getRootPackageName(QNameModule)} with {@link Module#getQNameModule()}.
*/
+ @Deprecated
public static String moduleNamespaceToPackageName(final Module module) {
- final StringBuilder packageNameBuilder = new StringBuilder();
-
- if (module.getRevision() == null) {
- throw new IllegalArgumentException("Module " + module.getName() + " does not specify revision date!");
- }
- packageNameBuilder.append(BindingMapping.PACKAGE_PREFIX);
- packageNameBuilder.append('.');
-
- String namespace = module.getNamespace().toString();
- namespace = COLON_SLASH_SLASH.matcher(namespace).replaceAll(QUOTED_DOT);
-
- final char[] chars = namespace.toCharArray();
- for (int i = 0; i < chars.length; ++i) {
- switch (chars[i]) {
- case '/':
- case ':':
- case '-':
- case '@':
- case '$':
- case '#':
- case '\'':
- case '*':
- case '+':
- case ',':
- case ';':
- case '=':
- chars[i] = '.';
- }
- }
-
- packageNameBuilder.append(chars);
- packageNameBuilder.append(".rev");
- packageNameBuilder.append(DATE_FORMAT.get().format(module.getRevision()));
-
- return validateJavaPackage(packageNameBuilder.toString());
+ return BindingMapping.getRootPackageName(module.getQNameModule());
}
public static String packageNameForGeneratedType(final String basePackageName, final SchemaPath schemaPath) {
for (int i = 0; i < traversalSteps; ++i) {
builder.append('.');
String nodeLocalName = iterator.next().getLocalName();
-
- nodeLocalName = nodeLocalName.replace(':', '.');
- nodeLocalName = nodeLocalName.replace('-', '.');
- builder.append(nodeLocalName);
+ // FIXME: Collon ":" is invalid in node local name as per RFC6020, identifier statement.
+ builder.append(DASH_COLON_MATCHER.replaceFrom(nodeLocalName, '.'));
}
- return validateJavaPackage(builder.toString());
+ return BindingMapping.normalizePackageName(builder.toString());
}
/**
final StringBuilder builder = new StringBuilder();
builder.append(basePackageName);
- return validateJavaPackage(builder.toString());
+ return BindingMapping.normalizePackageName(builder.toString());
}
/**
String correctStr = DOT_MATCHER.removeFrom(token.trim());
if (correctStr.isEmpty()) {
- throw new IllegalArgumentException("Name can not be emty");
+ throw new IllegalArgumentException("Name can not be empty");
}
correctStr = replaceWithCamelCase(correctStr, ' ');
return sb.toString();
}
- /**
- * Add {@link Serializable} to implemented interfaces of this TO. Also
- * compute and add serialVersionUID property.
- *
- * @param gto
- * transfer object which needs to be serializable
- */
- public static void makeSerializable(final GeneratedTOBuilderImpl gto) {
- gto.addImplementsType(Types.typeForClass(Serializable.class));
- GeneratedPropertyBuilder prop = new GeneratedPropertyBuilderImpl("serialVersionUID");
- prop.setValue(Long.toString(computeDefaultSUID(gto)));
- gto.setSUID(prop);
+ private static <T> Iterable<T> sortedCollection(final Comparator<? super T> comparator, final Collection<T> input) {
+ if (input.size() > 1) {
+ final List<T> ret = new ArrayList<>(input);
+ Collections.sort(ret, comparator);
+ return ret;
+ } else {
+ return input;
+ }
}
public static long computeDefaultSUID(final GeneratedTypeBuilderBase<?> to) {
dout.writeUTF(to.getName());
dout.writeInt(to.isAbstract() ? 3 : 7);
- List<Type> impl = to.getImplementsTypes();
- Collections.sort(impl, new Comparator<Type>() {
- @Override
- public int compare(final Type o1, final Type o2) {
- return o1.getFullyQualifiedName().compareTo(o2.getFullyQualifiedName());
- }
- });
- for (Type ifc : impl) {
+ for (Type ifc : sortedCollection(SUID_NAME_COMPARATOR, to.getImplementsTypes())) {
dout.writeUTF(ifc.getFullyQualifiedName());
}
- Comparator<TypeMemberBuilder<?>> comparator = new Comparator<TypeMemberBuilder<?>>() {
- @Override
- public int compare(final TypeMemberBuilder<?> o1, final TypeMemberBuilder<?> o2) {
- return o1.getName().compareTo(o2.getName());
- }
- };
-
- List<GeneratedPropertyBuilder> props = to.getProperties();
- Collections.sort(props, comparator);
- for (GeneratedPropertyBuilder gp : props) {
+ for (GeneratedPropertyBuilder gp : sortedCollection(SUID_MEMBER_COMPARATOR, to.getProperties())) {
dout.writeUTF(gp.getName());
}
- List<MethodSignatureBuilder> methods = to.getMethodDefinitions();
- Collections.sort(methods, comparator);
- for (MethodSignatureBuilder m : methods) {
+ for (MethodSignatureBuilder m : sortedCollection(SUID_MEMBER_COMPARATOR, to.getMethodDefinitions())) {
if (!(m.getAccessModifier().equals(AccessModifier.PRIVATE))) {
dout.writeUTF(m.getName());
dout.write(m.getAccessModifier().ordinal());
dout.flush();
- MessageDigest md = MessageDigest.getInstance("SHA");
- byte[] hashBytes = md.digest(bout.toByteArray());
- long hash = 0;
- for (int i = Math.min(hashBytes.length, 8) - 1; i >= 0; i--) {
- hash = (hash << 8) | (hashBytes[i] & 0xFF);
+ try {
+ MessageDigest md = MessageDigest.getInstance("SHA");
+ byte[] hashBytes = md.digest(bout.toByteArray());
+ long hash = 0;
+ for (int i = Math.min(hashBytes.length, 8) - 1; i >= 0; i--) {
+ hash = (hash << 8) | (hashBytes[i] & 0xFF);
+ }
+ return hash;
+ } catch (NoSuchAlgorithmException ex) {
+ throw new SecurityException(ex.getMessage());
}
- return hash;
} catch (IOException ex) {
throw new InternalError();
- } catch (NoSuchAlgorithmException ex) {
- throw new SecurityException(ex.getMessage());
}
}
public static Restrictions getRestrictions(final TypeDefinition<?> type) {
- final List<LengthConstraint> length = new ArrayList<>();
- final List<PatternConstraint> pattern = new ArrayList<>();
- final List<RangeConstraint> range = new ArrayList<>();
-
- if (type instanceof ExtendedType) {
- ExtendedType ext = (ExtendedType)type;
- TypeDefinition<?> base = ext.getBaseType();
- length.addAll(ext.getLengthConstraints());
- pattern.addAll(ext.getPatternConstraints());
- range.addAll(ext.getRangeConstraints());
-
- if (base instanceof IntegerTypeDefinition && range.isEmpty()) {
- range.addAll(((IntegerTypeDefinition)base).getRangeConstraints());
- } else if (base instanceof UnsignedIntegerTypeDefinition && range.isEmpty()) {
- range.addAll(((UnsignedIntegerTypeDefinition)base).getRangeConstraints());
- } else if (base instanceof DecimalTypeDefinition && range.isEmpty()) {
- range.addAll(((DecimalTypeDefinition)base).getRangeConstraints());
+ // Base types have no constraints, so get over it quickly
+ if (!(type instanceof ExtendedType)) {
+ return EMPTY_RESTRICTIONS;
+ }
+
+ // Take care of the extended types ...
+ final ExtendedType ext = (ExtendedType)type;
+ final List<LengthConstraint> length = ext.getLengthConstraints();
+ final List<PatternConstraint> pattern = ext.getPatternConstraints();
+
+ List<RangeConstraint> tmp = ext.getRangeConstraints();
+ if (tmp.isEmpty()) {
+ final TypeDefinition<?> base = ext.getBaseType();
+ if (base instanceof IntegerTypeDefinition) {
+ tmp = ((IntegerTypeDefinition)base).getRangeConstraints();
+ } else if (base instanceof UnsignedIntegerTypeDefinition) {
+ tmp = ((UnsignedIntegerTypeDefinition)base).getRangeConstraints();
+ } else if (base instanceof DecimalTypeDefinition) {
+ tmp = ((DecimalTypeDefinition)base).getRangeConstraints();
}
+ }
+ // Now, this may have ended up being empty, too...
+ if (length.isEmpty() && pattern.isEmpty() && tmp.isEmpty()) {
+ return EMPTY_RESTRICTIONS;
}
+ // Nope, not empty allocate a holder
+ final List<RangeConstraint> range = tmp;
return new Restrictions() {
@Override
public List<RangeConstraint> getRangeConstraints() {
}
@Override
public boolean isEmpty() {
- return range.isEmpty() && pattern.isEmpty() && length.isEmpty();
+ return false;
}
};
}