// @Override
 public Object[] getChildren(Object e) {
   try {
     if (e instanceof ContentType<?>) {
       return content.get((ContentType<?>) e);
     }
     return null;
   } catch (Throwable error) {
     WizardPlugin.log(error);
     return new Object[] {error};
   }
 }
 @Override
 public URL getHomePage() {
   // Looks like this now:
   // http://${spring.guides.url}/gs/spring-boot/
   try {
     String gsGuideName = getName();
     if (gsGuideName.startsWith("gs-")) {
       String guideName = gsGuideName.substring(3);
       return new URL(springGuidesUrl + "/gs/" + guideName);
     }
   } catch (MalformedURLException e) {
     WizardPlugin.log(e);
   }
   // Fallback on default implementation if custom logic failed
   return super.getHomePage();
 }
 public List<CodeSet> getCodeSets() throws UIThreadDownloadDisallowed {
   if (codesets == null) {
     CodeSet root = CodeSet.fromZip("ROOT", getZip(), getRootPath());
     if (root.hasFile(CODE_SET_METADATA)) {
       try {
         // TODO: we have to parse the metadata file and extract the codeset names and locations
         // from it.
         CodeSetMetaData[] metadata =
             root.readFileEntry(
                 CODE_SET_METADATA,
                 new CodeSet.Processor<CodeSetMetaData[]>() {
                   @Override
                   public CodeSetMetaData[] doit(CodeSetEntry e) throws Exception {
                     InputStream in = e.getData();
                     try {
                       ObjectMapper mapper = new ObjectMapper();
                       return mapper.readValue(in, CodeSetMetaData[].class);
                     } finally {
                       in.close();
                     }
                   }
                 });
         if (metadata == null) {
           metadata = new CodeSetMetaData[0];
         }
         CodeSet[] array = new CodeSet[metadata.length];
         for (int i = 0; i < array.length; i++) {
           String name = metadata[i].name;
           String dir = metadata[i].dir;
           Assert.isLegal(name != null, ".codesets.json objects must specify at least a 'name'.");
           if (dir == null) {
             dir =
                 name; // Use the name as the default. The convention is that a codeset is in a
                       // sudirectory with the same name as
             // the codeset name.
           }
           // 'dir' can't be null at this point because of the assert above and the default value
           // computed from the name
           IPath zipPath = getRootPath().append(dir);
           array[i] = CodeSet.fromZip(name, getZip(), zipPath);
         }
         // Success parsing .codesets.json and initialising codesets field.
         codesets = Arrays.asList(array);
         return codesets;
       } catch (Throwable e) {
         WizardPlugin.log(e);
       }
     }
     // We get here if either
     //   - there's no .codeset.json
     //   - .codeset.json is broken.
     CodeSet[] array = new CodeSet[defaultCodesetNames().length];
     for (int i = 0; i < array.length; i++) {
       array[i] =
           CodeSet.fromZip(
               defaultCodesetNames()[i], getZip(), getRootPath().append(defaultCodesetNames()[i]));
     }
     codesets = Arrays.asList(array);
   }
   return codesets;
 }