@Test public void testReadOnlyEntryFromMultidirectory() throws Exception { MultiDirectory readonlyMultidir = (MultiDirectory) directoryService.getDirectory("readonlymulti"); MultiDirectorySession readonlyDir = (MultiDirectorySession) readonlyMultidir.getSession(); // all should be readonly assertTrue(BaseSession.isReadOnlyEntry(readonlyDir.getEntry("1"))); assertTrue(BaseSession.isReadOnlyEntry(readonlyDir.getEntry("2"))); assertTrue(BaseSession.isReadOnlyEntry(readonlyDir.getEntry("3"))); assertTrue(BaseSession.isReadOnlyEntry(readonlyDir.getEntry("4"))); }
@Override @SuppressWarnings("boxing") public DocumentModelList query( Map<String, Serializable> filter, Set<String> fulltext, Map<String, String> orderBy, boolean fetchReferences) { // list of entries final DocumentModelList results = new DocumentModelListImpl(); if (!isCurrentUserAllowed(SecurityConstants.READ)) { return results; } init(); // entry ids already seen (mapped to the source name) final Map<String, String> seen = new HashMap<String, String>(); if (fulltext == null) { fulltext = Collections.emptySet(); } Set<String> readOnlyEntries = new HashSet<String>(); for (SourceInfo sourceInfo : sourceInfos) { // accumulated map for each entry final Map<String, Map<String, Object>> maps = new HashMap<String, Map<String, Object>>(); // number of dirs seen for each entry final Map<String, Integer> counts = new HashMap<String, Integer>(); // list of optional dirs where filter matches default values List<SubDirectoryInfo> optionalDirsMatching = new ArrayList<SubDirectoryInfo>(); for (SubDirectoryInfo dirInfo : sourceInfo.subDirectoryInfos) { // compute filter final Map<String, Serializable> dirFilter = new HashMap<String, Serializable>(); for (Entry<String, Serializable> e : filter.entrySet()) { final String fieldName = dirInfo.fromSource.get(e.getKey()); if (fieldName == null) { continue; } dirFilter.put(fieldName, e.getValue()); } if (dirInfo.isOptional) { // check if filter matches directory default values boolean matches = true; for (Map.Entry<String, Serializable> dirFilterEntry : dirFilter.entrySet()) { Object defaultValue = dirInfo.defaultEntry.get(dirFilterEntry.getKey()); Object filterValue = dirFilterEntry.getValue(); if (defaultValue == null && filterValue != null) { matches = false; } else if (defaultValue != null && !defaultValue.equals(filterValue)) { matches = false; } } if (matches) { optionalDirsMatching.add(dirInfo); } } // compute fulltext Set<String> dirFulltext = new HashSet<String>(); for (String sourceFieldName : fulltext) { final String fieldName = dirInfo.fromSource.get(sourceFieldName); if (fieldName != null) { dirFulltext.add(fieldName); } } // make query to subdirectory DocumentModelList l = dirInfo.getSession().query(dirFilter, dirFulltext, null, fetchReferences); for (DocumentModel entry : l) { final String id = entry.getId(); Map<String, Object> map = maps.get(id); if (map == null) { map = new HashMap<String, Object>(); maps.put(id, map); counts.put(id, 1); } else { counts.put(id, counts.get(id) + 1); } for (Entry<String, String> e : dirInfo.toSource.entrySet()) { map.put(e.getValue(), entry.getProperty(dirInfo.dirSchemaName, e.getKey())); } if (BaseSession.isReadOnlyEntry(entry)) { readOnlyEntries.add(id); } } } // add default entry values for optional dirs for (SubDirectoryInfo dirInfo : optionalDirsMatching) { // add entry for every data found in other dirs Set<String> existingIds = new HashSet<String>( dirInfo .getSession() .getProjection(Collections.<String, Serializable>emptyMap(), dirInfo.idField)); for (Entry<String, Map<String, Object>> result : maps.entrySet()) { final String id = result.getKey(); if (!existingIds.contains(id)) { counts.put(id, counts.get(id) + 1); final Map<String, Object> map = result.getValue(); for (Entry<String, String> e : dirInfo.toSource.entrySet()) { String value = e.getValue(); if (!map.containsKey(value)) { map.put(value, dirInfo.defaultEntry.get(e.getKey())); } } } } } // intersection, ignore entries not in all subdirectories final int numdirs = sourceInfo.subDirectoryInfos.size(); for (Iterator<String> it = maps.keySet().iterator(); it.hasNext(); ) { final String id = it.next(); if (counts.get(id) != numdirs) { it.remove(); } } // now create entries ((ArrayList<?>) results).ensureCapacity(results.size() + maps.size()); for (Entry<String, Map<String, Object>> e : maps.entrySet()) { final String id = e.getKey(); if (seen.containsKey(id)) { log.warn( String.format( "Entry '%s' is present in source '%s' but also in source '%s'. " + "The second one will be ignored.", id, seen.get(id), sourceInfo.source.name)); continue; } final Map<String, Object> map = e.getValue(); seen.put(id, sourceInfo.source.name); final DocumentModel entry = BaseSession.createEntryModel(null, schemaName, id, map, readOnlyEntries.contains(id)); results.add(entry); } } if (orderBy != null && !orderBy.isEmpty()) { directory.orderEntries(results, orderBy); } return results; }
@Override @SuppressWarnings("boxing") public DocumentModelList getEntries() { if (!isCurrentUserAllowed(SecurityConstants.READ)) { return null; } init(); // list of entries final DocumentModelList results = new DocumentModelListImpl(); // entry ids already seen (mapped to the source name) final Map<String, String> seen = new HashMap<String, String>(); Set<String> readOnlyEntries = new HashSet<String>(); for (SourceInfo sourceInfo : sourceInfos) { // accumulated map for each entry final Map<String, Map<String, Object>> maps = new HashMap<String, Map<String, Object>>(); // number of dirs seen for each entry final Map<String, Integer> counts = new HashMap<String, Integer>(); for (SubDirectoryInfo dirInfo : sourceInfo.requiredSubDirectoryInfos) { final DocumentModelList entries = dirInfo.getSession().getEntries(); for (DocumentModel entry : entries) { final String id = entry.getId(); // find or create map for this entry Map<String, Object> map = maps.get(id); if (map == null) { map = new HashMap<String, Object>(); maps.put(id, map); counts.put(id, 1); } else { counts.put(id, counts.get(id) + 1); } // put entry data in map for (Entry<String, String> e : dirInfo.toSource.entrySet()) { map.put(e.getValue(), entry.getProperty(dirInfo.dirSchemaName, e.getKey())); } if (BaseSession.isReadOnlyEntry(entry)) { readOnlyEntries.add(id); } } } for (SubDirectoryInfo dirInfo : sourceInfo.optionalSubDirectoryInfos) { final DocumentModelList entries = dirInfo.getSession().getEntries(); Set<String> existingIds = new HashSet<String>(); for (DocumentModel entry : entries) { final String id = entry.getId(); final Map<String, Object> map = maps.get(id); if (map != null) { existingIds.add(id); // put entry data in map for (Entry<String, String> e : dirInfo.toSource.entrySet()) { map.put(e.getValue(), entry.getProperty(dirInfo.dirSchemaName, e.getKey())); } } else { log.warn( String.format( "Entry '%s' for source '%s' is present in optional directory '%s' " + "but not in any required one. " + "It will be skipped.", id, sourceInfo.source.name, dirInfo.dirName)); } } for (Entry<String, Map<String, Object>> mapEntry : maps.entrySet()) { if (!existingIds.contains(mapEntry.getKey())) { final Map<String, Object> map = mapEntry.getValue(); // put entry data in map for (Entry<String, String> e : dirInfo.toSource.entrySet()) { // fill with default values for this directory if (!map.containsKey(e.getValue())) { map.put(e.getValue(), dirInfo.defaultEntry.get(e.getKey())); } } } } } // now create entries for all full maps int numdirs = sourceInfo.requiredSubDirectoryInfos.size(); ((ArrayList<?>) results).ensureCapacity(results.size() + maps.size()); for (Entry<String, Map<String, Object>> e : maps.entrySet()) { final String id = e.getKey(); if (seen.containsKey(id)) { log.warn( String.format( "Entry '%s' is present in source '%s' but also in source '%s'. " + "The second one will be ignored.", id, seen.get(id), sourceInfo.source.name)); continue; } final Map<String, Object> map = e.getValue(); if (counts.get(id) != numdirs) { log.warn( String.format( "Entry '%s' for source '%s' is not present in all directories. " + "It will be skipped.", id, sourceInfo.source.name)); continue; } seen.put(id, sourceInfo.source.name); final DocumentModel entry = BaseSession.createEntryModel(null, schemaName, id, map, readOnlyEntries.contains(id)); results.add(entry); } } return results; }
@Test public void testReadOnlyEntryInGetEntriesResults() throws Exception { Map<String, String> orderBy = new HashMap<String, String>(); orderBy.put("schema3:uid", "asc"); DocumentModelComparator comp = new DocumentModelComparator(orderBy); DocumentModelList results = dir.getEntries(); Collections.sort(results, comp); // by default no backing dir is readonly assertFalse(BaseSession.isReadOnlyEntry(results.get(0))); assertFalse(BaseSession.isReadOnlyEntry(results.get(1))); assertFalse(BaseSession.isReadOnlyEntry(results.get(2))); assertFalse(BaseSession.isReadOnlyEntry(results.get(3))); memdir1.setReadOnly(true); memdir2.setReadOnly(false); memdir3.setReadOnly(false); results = dir.getEntries(); Collections.sort(results, comp); assertTrue(BaseSession.isReadOnlyEntry(results.get(0))); assertTrue(BaseSession.isReadOnlyEntry(results.get(1))); assertFalse(BaseSession.isReadOnlyEntry(results.get(2))); assertFalse(BaseSession.isReadOnlyEntry(results.get(3))); memdir1.setReadOnly(false); memdir2.setReadOnly(false); memdir3.setReadOnly(true); results = dir.getEntries(); Collections.sort(results, comp); assertFalse(BaseSession.isReadOnlyEntry(results.get(0))); assertFalse(BaseSession.isReadOnlyEntry(results.get(1))); assertTrue(BaseSession.isReadOnlyEntry(results.get(2))); assertTrue(BaseSession.isReadOnlyEntry(results.get(3))); }
@Test public void testReadOnlyEntryFromGetEntry() throws Exception { // by default no backing dir is readonly assertFalse(BaseSession.isReadOnlyEntry(dir.getEntry("1"))); assertFalse(BaseSession.isReadOnlyEntry(dir.getEntry("2"))); assertFalse(BaseSession.isReadOnlyEntry(dir.getEntry("3"))); assertFalse(BaseSession.isReadOnlyEntry(dir.getEntry("4"))); memdir1.setReadOnly(true); memdir2.setReadOnly(false); memdir3.setReadOnly(false); assertFalse(BaseSession.isReadOnlyEntry(dir.getEntry("1"))); assertFalse(BaseSession.isReadOnlyEntry(dir.getEntry("2"))); assertFalse(BaseSession.isReadOnlyEntry(dir.getEntry("3"))); assertFalse(BaseSession.isReadOnlyEntry(dir.getEntry("4"))); memdir1.setReadOnly(false); memdir2.setReadOnly(true); memdir3.setReadOnly(true); assertFalse(BaseSession.isReadOnlyEntry(dir.getEntry("1"))); assertFalse(BaseSession.isReadOnlyEntry(dir.getEntry("2"))); assertTrue(BaseSession.isReadOnlyEntry(dir.getEntry("3"))); assertTrue(BaseSession.isReadOnlyEntry(dir.getEntry("4"))); memdir1.setReadOnly(false); memdir2.setReadOnly(false); memdir3.setReadOnly(true); assertFalse(BaseSession.isReadOnlyEntry(dir.getEntry("1"))); assertFalse(BaseSession.isReadOnlyEntry(dir.getEntry("2"))); assertTrue(BaseSession.isReadOnlyEntry(dir.getEntry("3"))); assertTrue(BaseSession.isReadOnlyEntry(dir.getEntry("4"))); memdir1.setReadOnly(true); memdir2.setReadOnly(true); memdir3.setReadOnly(false); assertTrue(BaseSession.isReadOnlyEntry(dir.getEntry("1"))); assertTrue(BaseSession.isReadOnlyEntry(dir.getEntry("2"))); assertFalse(BaseSession.isReadOnlyEntry(dir.getEntry("3"))); assertFalse(BaseSession.isReadOnlyEntry(dir.getEntry("4"))); }