001package systems.dmx.core.util; 002 003import systems.dmx.core.DMXObject; 004import systems.dmx.core.Identifiable; 005import systems.dmx.core.JSONEnabled; 006import systems.dmx.core.Topic; 007import systems.dmx.core.model.AssociationModel; 008import systems.dmx.core.model.RoleModel; 009import systems.dmx.core.model.TopicModel; 010import systems.dmx.core.model.TopicRoleModel; 011import systems.dmx.core.service.CoreService; 012 013import org.codehaus.jettison.json.JSONArray; 014import org.codehaus.jettison.json.JSONObject; 015 016import java.net.URL; 017import java.util.ArrayList; 018import java.util.Collection; 019import java.util.HashMap; 020import java.util.Iterator; 021import java.util.List; 022import java.util.Map; 023import java.util.logging.Logger; 024 025 026 027public class DMXUtils { 028 029 private static final Logger logger = Logger.getLogger(DMXUtils.class.getName()); 030 031 private static final String DM4_HOST_URL = System.getProperty("dmx.host.url"); // ### TODO: default value (#734) 032 static { 033 logger.info("Host setting:\ndmx.host.url=\"" + DM4_HOST_URL + "\""); 034 } 035 036 037 038 // ************ 039 // *** URLs *** 040 // ************ 041 042 043 044 /** 045 * Checks if an URL refers to this DMX installation. 046 * The check relies on the "dmx.host.url" system property. 047 */ 048 public static boolean isDMXURL(URL url) { 049 try { 050 return url.toString().startsWith(DM4_HOST_URL); 051 } catch (Exception e) { 052 throw new RuntimeException("Checking for DMX URL failed (url=\"" + url + "\")", e); 053 } 054 } 055 056 057 058 // ******************* 059 // *** Collections *** 060 // ******************* 061 062 063 064 public static List<Long> idList(Iterable<? extends Identifiable> items) { 065 List<Long> ids = new ArrayList(); 066 for (Identifiable item : items) { 067 ids.add(item.getId()); 068 } 069 return ids; 070 } 071 072 public static <M> List<M> toModelList(Iterable<? extends DMXObject> objects) { 073 List<M> modelList = new ArrayList(); 074 for (DMXObject object : objects) { 075 modelList.add((M) object.getModel()); 076 } 077 return modelList; 078 } 079 080 public static String topicNames(Iterable<? extends Topic> topics) { 081 StringBuilder names = new StringBuilder(); 082 Iterator<? extends Topic> i = topics.iterator(); 083 while (i.hasNext()) { 084 Topic topic = i.next(); 085 names.append('"').append(topic.getSimpleValue()).append('"'); 086 if (i.hasNext()) { 087 names.append(", "); 088 } 089 } 090 return names.toString(); 091 } 092 093 public static <T extends DMXObject> List<T> loadChildTopics(List<T> objects) { 094 for (DMXObject object : objects) { 095 object.loadChildTopics(); 096 } 097 return objects; 098 } 099 100 101 102 // ************ 103 // *** JSON *** 104 // ************ 105 106 107 108 // === Generic === 109 110 public static Map toMap(JSONObject o) { 111 return toMap(o, new HashMap()); 112 } 113 114 public static Map toMap(JSONObject o, Map map) { 115 try { 116 Iterator<String> i = o.keys(); 117 while (i.hasNext()) { 118 String key = i.next(); 119 map.put(key, o.get(key)); // throws JSONException 120 } 121 return map; 122 } catch (Exception e) { 123 throw new RuntimeException("Converting JSONObject to Map failed", e); 124 } 125 } 126 127 // --- 128 129 public static List toList(JSONArray o) { 130 try { 131 List list = new ArrayList(); 132 for (int i = 0; i < o.length(); i++) { 133 list.add(o.get(i)); // throws JSONException 134 } 135 return list; 136 } catch (Exception e) { 137 throw new RuntimeException("Converting JSONArray to List failed", e); 138 } 139 } 140 141 // === DMX specific === 142 143 public static JSONArray toJSONArray(Iterable<? extends JSONEnabled> items) { 144 JSONArray array = new JSONArray(); 145 for (JSONEnabled item : items) { 146 array.put(item.toJSON()); 147 } 148 return array; 149 } 150 151 152 153 // ******************************* 154 // *** Association Auto-Typing *** 155 // ******************************* 156 157 158 159 /** 160 * Retypes the given association if its player types match the given topic types. 161 */ 162 public static RoleModel[] associationAutoTyping(AssociationModel assoc, String topicTypeUri1, String topicTypeUri2, 163 String assocTypeUri, String roleTypeUri1, String roleTypeUri2, CoreService dmx) { 164 if (!assoc.getTypeUri().equals("dmx.core.association")) { 165 return null; 166 } 167 RoleModel[] roles = getRoleModels(assoc, topicTypeUri1, topicTypeUri2, dmx); 168 if (roles != null) { 169 logger.info("### Auto typing association into \"" + assocTypeUri + 170 "\" (\"" + topicTypeUri1 + "\" <-> \"" + topicTypeUri2 + "\")"); 171 assoc.setTypeUri(assocTypeUri); 172 roles[0].setRoleTypeUri(roleTypeUri1); 173 roles[1].setRoleTypeUri(roleTypeUri2); 174 } 175 return roles; 176 } 177 178 public static RoleModel[] getRoleModels(AssociationModel assoc, String topicTypeUri1, String topicTypeUri2, 179 CoreService dmx) { 180 RoleModel r1 = assoc.getRoleModel1(); 181 RoleModel r2 = assoc.getRoleModel2(); 182 // ### FIXME: auto-typing is supported only for topic players, and if they are identified by-ID. 183 // Note: we can't call roleModel.getPlayer() as this would build an entire object model, but its "value" 184 // is not yet available in case this association is part of the player's composite structure. 185 // Compare to AssociationModelImpl.duplicateCheck() 186 if (!(r1 instanceof TopicRoleModel) || ((TopicRoleModel) r1).topicIdentifiedByUri() || 187 !(r2 instanceof TopicRoleModel) || ((TopicRoleModel) r2).topicIdentifiedByUri()) { 188 return null; 189 } 190 String t1 = (String) dmx.getProperty(r1.getPlayerId(), "typeUri"); 191 String t2 = (String) dmx.getProperty(r2.getPlayerId(), "typeUri"); 192 RoleModel roleModel1 = getRoleModel(r1, r2, t1, t2, topicTypeUri1, 1); 193 RoleModel roleModel2 = getRoleModel(r1, r2, t1, t2, topicTypeUri2, 2); 194 if (roleModel1 != null && roleModel2 != null) { 195 return new RoleModel[] {roleModel1, roleModel2}; 196 } 197 return null; 198 } 199 200 // ------------------------------------------------------------------------------------------------- Private Methods 201 202 private static RoleModel getRoleModel(RoleModel r1, RoleModel r2, String t1, String t2, String topicTypeUri, 203 int nr) { 204 boolean m1 = t1.equals(topicTypeUri); 205 boolean m2 = t2.equals(topicTypeUri); 206 if (m1 && m2) { 207 return nr == 1 ? r1 : r2; 208 } 209 return m1 ? r1 : m2 ? r2 : null; 210 } 211}