1 package org.unicode.cldr.util; 2 3 import com.google.common.collect.ImmutableSet; 4 import java.io.File; 5 import java.lang.annotation.Annotation; 6 import java.util.Collections; 7 import java.util.Set; 8 import java.util.regex.Matcher; 9 import java.util.regex.Pattern; 10 11 public enum DtdType { 12 ldml( 13 "common/dtd/ldml.dtd", 14 null, 15 null, 16 "main", 17 "annotations", 18 "annotationsDerived", 19 "casing", 20 "collation", 21 "rbnf", 22 "segments", 23 "subdivisions"), 24 ldmlICU("common/dtd/ldmlICU.dtd", ldml), 25 supplementalData( 26 "common/dtd/ldmlSupplemental.dtd", 27 null, 28 null, 29 "supplemental", 30 "supplemental-temp", 31 "transforms", 32 "validity"), 33 ldmlBCP47("common/dtd/ldmlBCP47.dtd", "1.7.2", null, "bcp47"), 34 // keyboard 3.0 35 keyboard3("keyboards/dtd/ldmlKeyboard3.dtd", "45.0", null, "../keyboards/3.0"), 36 keyboardTest3("keyboards/dtd/ldmlKeyboardTest3.dtd", "45.0", null, "../keyboards/test"); 37 38 public static final Set<DtdType> STANDARD_SET = 39 ImmutableSet.of(ldmlBCP47, supplementalData, ldml, keyboard3); 40 41 static Pattern FIRST_ELEMENT = PatternCache.get("//([^/\\[]*)"); 42 43 public final String dtdPath; 44 /** 45 * The actual root type used with the DTD. Used for ldmlICU.dtd which is used with the <ldml> 46 * root type. This mechanism isn't used for keyboard2, which simply has a different element 47 * name, but is not used with the prior DTD. 48 */ 49 public final DtdType rootType; 50 51 public final String firstVersion; 52 public final Set<String> directories; 53 54 private final DtdStatus status; 55 56 /** Get the ststus, whether this is an active DTD or not */ getStatus()57 public DtdStatus getStatus() { 58 return status; 59 } 60 61 public enum DtdStatus { 62 /** DTD active (default) */ 63 active, 64 /** DTD no longer used */ 65 removed, 66 }; 67 DtdType(String dtdPath)68 private DtdType(String dtdPath) { 69 this(dtdPath, null, null); 70 } 71 DtdType(DtdStatus status, String sinceVersion)72 private DtdType(DtdStatus status, String sinceVersion) { 73 this.directories = Collections.emptySet(); 74 this.dtdPath = null; 75 this.rootType = this; 76 this.firstVersion = sinceVersion; 77 this.status = status; 78 } 79 DtdType(String dtdPath, DtdType realType)80 private DtdType(String dtdPath, DtdType realType) { 81 this(dtdPath, null, realType); 82 } 83 DtdType(String dtdPath, String firstVersion, DtdType realType, String... directories)84 private DtdType(String dtdPath, String firstVersion, DtdType realType, String... directories) { 85 this.dtdPath = dtdPath; 86 this.rootType = realType == null ? this : realType; 87 this.firstVersion = firstVersion; 88 this.directories = ImmutableSet.copyOf(directories); 89 this.status = DtdStatus.active; 90 } 91 fromPath(String elementOrPath)92 public static DtdType fromPath(String elementOrPath) { 93 Matcher m = FIRST_ELEMENT.matcher(elementOrPath); 94 m.lookingAt(); 95 return fromElement(m.group(1)); 96 } 97 98 /** 99 * @return the DtdType, given an element name 100 */ fromElement(String element)101 public static DtdType fromElement(String element) { 102 return DtdType.valueOf(element); 103 } 104 105 /** 106 * Print a header for an XML file, where the generatedBy is normally 107 * MethodHandles.lookup().lookupClass(). The only time it needs to be changed is if it is not 108 * being called directly from the generating tool. 109 * 110 * @param generatedBy 111 * @return 112 */ header(Class<?> generatedBy)113 public String header(Class<?> generatedBy) { 114 String gline = ""; 115 if (generatedBy != null) { 116 gline = 117 "\n\tGENERATED DATA — do not manually update!" 118 + "\n\t\tGenerated by tool:\t" 119 + generatedBy.getSimpleName() 120 + "\n"; 121 for (Annotation annotation : generatedBy.getAnnotations()) { 122 if (annotation instanceof CLDRTool) { 123 gline += "\t\tTool documented on:\t" + ((CLDRTool) annotation).url() + "\n"; 124 break; 125 } 126 } 127 } 128 129 return "<?xml version='1.0' encoding='UTF-8' ?>\n" 130 + "<!DOCTYPE " 131 + rootElement() 132 + " SYSTEM '../../" 133 + dtdPath 134 + "'>\n" // "common/dtd/ldmlSupplemental.dtd" 135 + "<!--\n" 136 + CldrUtility.getCopyrightString("\t") 137 + gline 138 + " -->\n" 139 + "<" 140 + rootElement() 141 + ">\n"; 142 } 143 144 /** 145 * @return the root element for this DTD Type. Usually matches the DTD name. 146 */ rootElement()147 public String rootElement() { 148 if (rootType != null) { 149 return rootType.name(); 150 } else { 151 return name(); 152 } 153 } 154 getXsdPath()155 public String getXsdPath() { 156 return dtdPath.replaceAll("\\.dtd$", ".xsd"); 157 } 158 159 /** The xmlns name for this dtd type */ getNsUrl()160 public String getNsUrl() { 161 return CLDRURLS.CLDR_CURVER_BASE + "/" + name(); 162 } 163 164 /** The current version DTD as a URI */ getDtdUri()165 String getDtdUri() { 166 return new File(CLDRPaths.BASE_DIRECTORY, dtdPath).toURI().toString(); 167 } 168 169 /** DOCTYPE for this DTD (current version) */ getDoctype()170 String getDoctype() { 171 return "<!DOCTYPE " + name() + " SYSTEM \"" + getDtdUri() + "\">"; 172 } 173 } 174