2011-11-21 10 views
6

W naszych aplikacjach bardzo często używamy plików właściwości. Od kilku miesięcy zacząłem uczyć się Guawy i bardzo mi się to podobało.Tworzenie obiektów za pomocą Guavy z plików właściwości

Jaki jest najlepszy sposób utworzenia Map<String, Datasource>?

Format pliku właściwości nie jest ścisły. Można go zmienić, jeśli można go lepiej wyrazić w innym formacie?

Przykładowy plik nieruchomości:

datasource1.url=jdbc:mysql://192.168.11.46/db1 
datasource1.password=password 
datasource1.user=root 
datasource2.url=jdbc:mysql://192.168.11.45/db2 
datasource2.password=password 
datasource2.user=root 

Odpowiedz

5

Właściwości klasa jest podklasą HashTable, który z kolei realizuje mapę.

załadować go jak zwykle:

Properties properties = new Properties(); 
    try { 
     properties.load(new FileInputStream("filename.properties")); 
    } catch (IOException e) { 
} 

EDIT: Ok, więc chcesz ją przekształcić na mapie < String, DataSource >;)

//First convert properties to Map<String, String> 
Map<String, String> m = Maps.fromProperties(properties); 

//Sort them so that password < url < user for each datasource and dataSource1.* < dataSource2.*. In your case default string ordering is ok so we can take a normal treemap 
Map<String, String> sorted = Maps.newTreeMap(); 
sorted.putAll(m); 

//Create Multimap<String, List<String>> mapping datasourcename->[password,url, user ] 

    Function<Map.Entry<String, String>, String> propToList = new Function<String, Integer>() { 
     @Override 
     public String apply(Map.Entry<String, String> entry) { 
      return entry.getKey().split("\\.")[0]; 
     } 
    }; 

Multimap<Integer, String> nameToParamMap = Multimaps.index(m.entrySet(), propToList); 

//Convert it to map 
Map<String, Collection<String>> mm = nameToParamMap.asMap(); 

//Transform it to Map<String, Datasource> 
Map<String, Datasource> mSD = Maps.transformEntries(mm, new EntryTransformer<String, Collection<String>, DataSource>() { 
     public DataSource transformEntry(String key, Collection<String> value) { 
      // Create your datasource. You know by now that Collection<String> is actually a list so you can assume elements are in order: [password, url, user] 
      return new Datasource(.....) 
     } 
     }; 

//Copy transformed map so it's no longer a view 
Map<String, Datasource> finalMap = Maps.newHashMap(mSD); 

tam prawdopodobnie łatwiejszy sposób, ale powinno to zadziałać :)

Nadal lepiej z jsonem lub xml. Możesz także załadować właściwości różnych źródeł danych z różnych plików.

Edit2: mniej guawa, bardziej Java:

//Sort them so that password < url < user for each datasource and dataSource1.* < dataSource2.*. In your case default string ordering is ok so we can take a normal SortedSet 
SortedSet <String> sorted = new SortedSet<String>(); 
sorted.putAll(m.keySet); 

//Divide keys into lists of 3 
Iterable<List<String>> keyLists = Iterables.partition(sorted.keySet(), 3); 


Map<String, Datasource> m = new HashMap<String, Datasource>(); 
for (keyList : keyLists) { 
    //Contains datasourcex.password, datasroucex.url, datasourcex.user 
    String[] params = keyList.toArray(new String[keyList.size()]); 
    String password = properties.get(params[0]); 
    String url = properties.get(params[1]); 
    String user = properties.get(params[2]); 
    m.put(params[0].split("\\.")[0], new DataSource(....) 
} 
+0

Jestem tego świadomy, ale po tym, co sugerujesz, aby stworzyć Mapa Cemo

+0

Możesz zapisać kilka linii w moim rozwiązaniu. Zostawiłem je, aby były bardziej czytelne. – soulcheck

+0

Głosowałem w górę :) Ale chciałbym poczekać jeszcze trochę. Dzięki :) Po drodze przepraszam za niejasność pytania po raz pierwszy. Stackoverflow zignorował to :) – Cemo

0

Jeśli plik, którego używasz do konfiguracji nie jest ścisłe, można użyć pliku XML do przechowywania Definition.

Przykład definicji:

<resources> 
<configuration> 
    <datasrouce> 
    <connection name="" url="" password="" user=""/> 
    <connection name="" url="" password="" user=""/> 
    </datasource> 
</configuration> 
</resources> 

Stosując klasy Connection Manager można tylko odczytać XML w celu uzyskania informacji o połączeniu i utworzyć instancję połączeń i mange im.

6

Najłatwiej jest prawdopodobnie używać JSON zamiast pliku właściwości tego:

{ 
    "datasources": [ 
    { 
     "name": "datasource1", 
     "url": "jdbc:mysql://192.168.11.46/db1", 
     "user": "root", 
     "password": "password" 
    }, 
    { 
     "name": "datasource2", 
     "url": "jdbc:mysql://192.168.11.46/db2", 
     "user": "root", 
     "password": "password" 
    } 
    ] 
}

Następnie można po prostu użyć biblioteki takie jak Gson przekonwertować że do obiektów:

public class DataSources { 
    private List<DataSourceInfo> dataSources; 

    public Map<String, DataSource> getDataSources() { 
    // create the map 
    } 
} 

public class DataSourceInfo { 
    private String name; 
    private String url; 
    private String user; 
    private String password; 

    // constructor, getters 
} 

Następnie, aby uzyskać mapę:

Gson gson = new Gson(); 
Map<String, DataSource> dataSources = gson.fromJson(/* file or stream here */, 
    DataSources.class).getDataSources(); 
+0

Głosowałem za sprawą pomysłu i eleganckiego rozwiązania, a także prawdopodobnie skorzystam z rozwiązania, które sugerujesz, ale w celu dopasowania odpowiedzi na pytanie wybieram inny. :) Przy okazji, Colin, jestem także wielkim fanem ciebie. :) Dzięki za twoje uwagi. Chciałbym jednak zobaczyć twoją kolejną wspaniałą implementację, aby lepiej się uczyć. ;) – Cemo

+0

@Sessizlik Myślę, że moim celem jest użycie odpowiedniego narzędzia do pracy.To, co tu masz, to niektóre dane strukturalne, które chcesz odczytać. Pliki właściwości są płaskie i nie wyrażają dobrze struktury. Guava nie zmienia tego faktu. Gson (przypadkowo biblioteka konwersji JSON firmy Google) wydaje się bardziej odpowiedni i sprawia, że ​​jest to wręcz łatwe. – ColinD

Powiązane problemy