package ash.reverse.struct;
import java.util.List;
import java.util.Map;
import java.util.LinkedHashMap;

/**
 * VisitorパターンのConcreteVisitor:
 * <p>
 * 複数のパッケージを訪問し、そこで定義されているクラス情報を収集し、
 * クラスマップ（クラス名と対応するClassRecordのマップ）を生成する。
 * 副作用として訪問したクラスに連番を付ける。
 */
public class ClassVisitor implements ObjectVisitor {
	/**
	 * 指定されたパッケージリストからクラスマップを生成する。
	 * @param fileList パッケージリスト
	 * @return クラスマップ
	 */
	public static
	Map<String,ClassRecord> createClassMap(List<FileRecord> fileList) {
		return new ClassVisitor(fileList).classMap;
	}

	public ClassVisitor(List<FileRecord> fileList) {
		for(FileRecord frec : fileList) visit(frec);
	}

	private Map<String,ClassRecord>
		classMap = new LinkedHashMap<String,ClassRecord>();
	private Map<String,ClassRecord>
		fqcnMap = new LinkedHashMap<String,ClassRecord>();
	private int classID = 0;

	public Map<String,ClassRecord> classMap() { return classMap; }
	public Map<String,ClassRecord> fqcnMap() { return fqcnMap; }

	/**
	 * FileRecordを訪問する。
	 * @param frec 訪問対象のFileRecord
	 */
	@Override public void visit(FileRecord frec) {
		for(ObjectRecord rec : frec.members) rec.accept(this);
	}

	/**
	 * ClassRecordを訪問する。
	 * @param crec 訪問対象のClassRecord
	 */
	@Override public void visit(ClassRecord crec) {
		crec.id(++classID);
		classMap.put(crec.name, crec);
		fqcnMap.put(crec.fqcn(), crec);
		for(ObjectRecord rec : crec.members) rec.accept(this);
	}

	@Override public void visit(MethodRecord mrec) {}

	@Override public void visit(FieldRecord field) {}
}
