I am currently working on a "code parser" parsing Valve Map Format (.vmf files) into a java readable Object.

In vmf files,

* there are 2 types of objects: Classes and Properties.
* classes have a name and can contain other classes and properties.
* properties have a name and an unlimited number of values.

Therefore I created a `VMFClass` Object Class and a `VMFProperty` Object Class.
I created a List with self-created `HierarchyObject`s, containing the `VMFClass`/`VMFProperty` Object, an UUID and the parentUUID.
The `VMFClass` Object Contains 2 Lists one with sub-`VMFClass`es, one with properties.

My Problem is that I have no clue on how to achieve that a Class contains all of its subclasses, since I can't tell how much subclasses the subclasses have and so on...

Here is my Code ([Github](https://github.com/RoiEXLab/SourceCraftReloaded/tree/master/src/net/minecraft/sourcecraftreloaded/source)):

`HierachyObject`:

```
package net.minecraft.sourcecraftreloaded.utils;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class HierarchyObject {
    private static Map<Long, Long> usedUUIDs = new HashMap<>();
    private long parentUUID;
    private long UUID;
    private Object object;

    /**
     * 
     * @param Object
     * @param parent -1 is maximum level
     */
    public HierarchyObject(Object object, long parent) {
        this.object = object;
        this.parentUUID = parent;
        while (true) {
            long random = (long) (Math.random() * Long.MAX_VALUE);
            if (usedUUIDs.containsKey(random)) {
                this.UUID = random;
                usedUUIDs.put(random, parent);
                break;
            }
        }
    }

    public long getUUID() {
        return UUID;
    }
    public long getParentUUID() {
        return parentUUID;
    }

    public static long getParentUUIDbyUUID(long UUID) {
        if (usedUUIDs.containsKey(UUID)) {
            return usedUUIDs.get(UUID);
        }
        return -1;
    }

    public Object getObject() {
        return object;
    }

    public static boolean hasChild(long UUID){
        if(usedUUIDs.containsValue(UUID)){
            return true;
        }
        if(UUID == -1){
            return true;
        }
        return false;
    }

    public boolean hasChild(){
        return hasChild(this.UUID);
    }

    public static long[] getChildUUIDs(long UUID){
        if(hasChild(UUID)){
            List<Long> cUUIDs = new ArrayList<>();
            for(int i = 0; i < usedUUIDs.size(); i++){
                for (Map.Entry<Long, Long> e : usedUUIDs.entrySet()) {
                    if(e.getValue().longValue() == UUID){
                        cUUIDs.add(e.getKey());
                    }
                }
            }
            return ListUtils.toPrimitivebyList(cUUIDs);
        }
        return null;
    }
}

```

`VMFProperty`:

```
package net.minecraft.sourcecraftreloaded.source;

public class VMFProperty{

    private String name;
    private String[] values;

    public VMFProperty(String name, String... values) {
        this.name = name;
        this.values = values;
    }

    public String getName() {
        return name;
    }
    public String[] getValues() {
        return values;
    }

    @Override
    public boolean equals(Object paramObject){
        if(paramObject instanceof VMFProperty){
            return ((VMFProperty)paramObject).name.equals(this.name) && ((VMFProperty)paramObject).values.equals(this.values);
        }
        return false;
    }
}

```

`VMFClass`:

```
package net.minecraft.sourcecraftreloaded.source;

import java.util.List;

public class VMFClass{
    private List<VMFClass> classes;
    private List<VMFProperty> properties;
    private String name;

    public VMFClass(String name, List<VMFClass> classes, List<VMFProperty> properties) {
        this.name = name;
        this.classes = classes;
        this.properties = properties;
    }

    public String getName() {
        return name;
    }
    public List<VMFClass> getClasses() {
        return classes;
    }
    public List<VMFProperty> getProperties() {
        return properties;
    }
    public void add(VMFClass vmfclass) {
        classes.add(vmfclass);
    }
    public void add(VMFProperty vmfproperty) {
        properties.add(vmfproperty);
    }
    public void remove(VMFClass vmfclass) {
        classes.remove(vmfclass);
    }
    public void remove(VMFProperty vmfproperty) {
        properties.remove(vmfproperty);
    }

    @Override
    public boolean equals(Object paramObject){
        if(paramObject instanceof VMFClass){
            return ((VMFClass)paramObject).properties.equals(this.properties) && ((VMFClass)paramObject).classes.equals(this.classes) && ((VMFClass)paramObject).name.equals(this.name);
        }
        return false;
    }
}

```

`VMFObject` (the class executing all the code):

```
package net.minecraft.sourcecraftreloaded.source;

import java.io.File;
import java.util.ArrayList;
import java.util.List;

import net.minecraft.sourcecraftreloaded.utils.HierarchyObject;

public class VMFObject {
    private String rawfile = "";
    private List<VMFClass> toplevelclasses;

    private static final String INVALID_CHARS = "\\*,;<>|?=`´#'+~^°!§$%&()[].:-_";

    public VMFObject(List<VMFClass> toplevelclasses) {
        this.toplevelclasses = toplevelclasses;
    }

    public VMFObject() {
        this(new ArrayList<VMFClass>());
    }

    public void write(File file) {
        VMFWriter.write(file, rawfile);
    }

    public VMFObject read(File file) throws VMFParsingException {
        this.rawfile = VMFReader.read(file);
        parse();
        return this;
    }
    public List<VMFClass> getClasses() {
        return toplevelclasses;
    }

    private void parse() throws VMFParsingException {
        evaluate();
        get();
    }

    private void evaluate() throws VMFParsingException {
        char[] textchars = rawfile.toCharArray();
        int[] c = new int[]{0, 0, 0};
        int line = 0;
        int linepos = 0;
        for (int i : textchars) {
            linepos++;
            if (textchars[i] == '\n') {
                line++;
                linepos = 0;
                c[3] = 0;
                if (c[3] % 2 != 0) {
                    throw new VMFParsingException("Invalid quotes on line" + line + ":" + linepos);
                }
            }
            if (textchars[i] == '{') {
                c[1]++;
            }
            if (textchars[i] == '}') {
                c[2]++;
            }
            if (textchars[i] == '"') {
                c[3]++;
                if (c[1] - c[2] == 0) {

                }
            }
            if (textchars[i] == '/' && textchars[i + 1] == '/') {
                while (true) {
                    i++;
                    if (textchars[i] == '\n') {
                        break;
                    }
                }
            }
            if (textchars[i] == '/' && textchars[i + 1] == ' ') {
                throw new VMFParsingException("Invalid Character '/' on line" + line + ":" + linepos);
            }
            if (INVALID_CHARS.indexOf(textchars[i]) != -1) {
                throw new VMFParsingException("Invalid Character '" + textchars[i] + "' on line" + line + ":" + linepos);
            }
        }
        if (c[1] != c[2]) {
            throw new VMFParsingException("Unbalanced brackets in vmf File");
        }
    }

    public void add(VMFClass vmfclass) {
        toplevelclasses.add(vmfclass);
    }

    private void get() throws VMFParsingException {
        List<HierarchyObject> content = new ArrayList<>();
        long curparent = -1;
        String[] text = rawfile.split("\n");
        for (int i = 0; i < text.length; i++) {
            String line = text[i].trim();
            if (line.startsWith("//")) {
                continue;
            } else {
                byte quotec = 0;
                char[] linechar = line.toCharArray();
                boolean readp = false;
                List<String> reads = new ArrayList<>();
                byte creads = 0;
                for (int y = 0; y < linechar.length; y++) {
                    if (linechar[y] == '/' && linechar[y + 1] == '/') {
                        break;
                    }
                    if (linechar[y] == '"') {
                        quotec++;
                        if (quotec % 2 == 0) {
                            readp = false;
                            creads++;
                        } else {
                            readp = true;
                        }
                    }
                    if (readp) {
                        reads.set(creads, reads.get(creads) + linechar[y]);
                    }
                    if (linechar[y] == '{') {
                        HierarchyObject object = new HierarchyObject(new VMFClass(line.substring(line.substring(0, y).lastIndexOf(' '), y).trim(), null, null), curparent);
                        content.add(object);
                        curparent = object.getUUID();
                    }
                    if (linechar[y] == '}') {
                        curparent = HierarchyObject.getParentUUIDbyUUID(curparent);
                    }

                }
                content.add(new HierarchyObject(new VMFProperty(reads.remove(0), reads.toArray(new String[reads.size()])), curparent));
            }
        }
        buildObject(content);
    }

    private void buildObject(List<HierarchyObject> content) {
        long curUUID = -1;
        for(int i = 0; i < HierarchyObject.getChildUUIDs(curUUID).length; i++){
            HierarchyObject.getChildUUIDs(curUUID);
        }
        //TODO implement
    }
}

```

the //TODO part is where the Hierachy Object should get "converted" to the actual object.