Skip to content

Commit 334cde5

Browse files
committed
fixes #30 and #42 - support object fields and use Paths over fieldName
fix crud errors so that they actually are sent to the client
1 parent 7c5d598 commit 334cde5

File tree

17 files changed

+381
-118
lines changed

17 files changed

+381
-118
lines changed

lightblue-ldap-common/src/main/java/com/redhat/lightblue/common/ldap/LdapFieldNameTranslator.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@
1818
*/
1919
package com.redhat.lightblue.common.ldap;
2020

21+
import com.redhat.lightblue.util.Path;
22+
2123
/**
2224
* Represents a class that can translate back and forth between a fieldName and an LDAP attributeName.
2325
*
@@ -30,7 +32,7 @@ public interface LdapFieldNameTranslator {
3032
* @param fieldName - metadata field name
3133
* @return ldap attributeName or the fieldName back at you if no mapping is present.
3234
*/
33-
public String translateFieldName(String fieldName);
35+
public String translateFieldName(Path path);
3436

3537
/**
3638
* Returns the fieldName with the given attributeName.

lightblue-ldap-crud/src/main/java/com/redhat/lightblue/crud/ldap/EntryBuilder.java

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@
2929
import com.redhat.lightblue.metadata.ArrayElement;
3030
import com.redhat.lightblue.metadata.ArrayField;
3131
import com.redhat.lightblue.metadata.EntityMetadata;
32-
import com.redhat.lightblue.metadata.ObjectField;
3332
import com.redhat.lightblue.metadata.SimpleField;
3433
import com.redhat.lightblue.metadata.Type;
3534
import com.redhat.lightblue.metadata.types.BinaryType;
@@ -75,7 +74,7 @@ else if(type instanceof BinaryType){
7574

7675
@Override
7776
protected void translate(SimpleField field, Path path, JsonNode node, Entry target) {
78-
String attributeName = fieldNameTranslator.translateFieldName(field.getName());
77+
String attributeName = fieldNameTranslator.translateFieldName(path);
7978

8079
if(LdapConstant.ATTRIBUTE_DN.equalsIgnoreCase(attributeName)){
8180
throw new IllegalArgumentException(
@@ -101,16 +100,11 @@ else if(LightblueUtil.isFieldObjectType(attributeName)
101100
}
102101
}
103102

104-
@Override
105-
protected void translate(ObjectField field, Path path, JsonNode node, Entry target) {
106-
throw new UnsupportedOperationException("ObjectField type is not currently supported.");
107-
}
108-
109103
@Override
110104
protected void translateSimpleArray(ArrayField field, Path path, List<Object> items, Entry target) {
111105
ArrayElement arrayElement = field.getElement();
112106
Type arrayElementType = arrayElement.getType();
113-
String attributeName = fieldNameTranslator.translateFieldName(field.getName());
107+
String attributeName = fieldNameTranslator.translateFieldName(path);
114108

115109
if(arrayElementType instanceof BinaryType){
116110
List<byte[]> bytes = new ArrayList<byte[]>();
@@ -129,7 +123,7 @@ protected void translateSimpleArray(ArrayField field, Path path, List<Object> it
129123
}
130124

131125
@Override
132-
protected void translateObjectArray(ArrayField field, JsonNodeCursor cursor, Entry target) {
126+
protected void translateObjectArray(ArrayField field, JsonNodeCursor cursor, Path path, Entry target) {
133127
throw new UnsupportedOperationException("Object ArrayField type is not currently supported.");
134128
}
135129

lightblue-ldap-crud/src/main/java/com/redhat/lightblue/crud/ldap/LdapCRUDController.java

Lines changed: 22 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -107,10 +107,10 @@ public CRUDInsertionResponse insert(CRUDOperationContext ctx,
107107

108108
EntityMetadata md = ctx.getEntityMetadata(ctx.getEntityName());
109109
LdapDataStore store = getLdapDataStore(md);
110-
LdapFieldNameTranslator property = getLdapFieldNameTranslator(md);
110+
LdapFieldNameTranslator fieldNameTranslator = getLdapFieldNameTranslator(md);
111111

112112
FieldAccessRoleEvaluator roles = new FieldAccessRoleEvaluator(md, ctx.getCallerRoles());
113-
EntryBuilder entryBuilder = new EntryBuilder(md, property);
113+
EntryBuilder entryBuilder = new EntryBuilder(md, fieldNameTranslator);
114114

115115
//Create Entry instances for each document.
116116
List<com.unboundid.ldap.sdk.Entry> entries = new ArrayList<com.unboundid.ldap.sdk.Entry>();
@@ -127,7 +127,7 @@ public CRUDInsertionResponse insert(CRUDOperationContext ctx,
127127

128128
JsonNode rootNode = document.getRoot();
129129

130-
String uniqueFieldName = property.translateAttributeName(store.getUniqueAttribute());
130+
String uniqueFieldName = fieldNameTranslator.translateAttributeName(store.getUniqueAttribute());
131131
JsonNode uniqueNode = rootNode.get(uniqueFieldName);
132132
if(uniqueNode == null){
133133
throw new IllegalArgumentException(uniqueFieldName + " is a required field");
@@ -208,17 +208,17 @@ public CRUDFindResponse find(CRUDOperationContext ctx,
208208

209209
LDAPConnection connection = getNewLdapConnection(store);
210210

211-
LdapFieldNameTranslator property = getLdapFieldNameTranslator(md);
211+
LdapFieldNameTranslator fieldNameTranslator = getLdapFieldNameTranslator(md);
212212

213213
try {
214214
//TODO: Support scopes other than SUB
215215
SearchRequest request = new SearchRequest(
216216
store.getBaseDN(),
217217
SearchScope.SUB,
218-
new FilterTranslator(property).translate(query),
219-
translateFieldNames(property, gatherRequiredFields(md, projection, query, sort)).toArray(new String[0]));
218+
new FilterTranslator(fieldNameTranslator).translate(query),
219+
translateFieldNames(fieldNameTranslator, gatherRequiredFields(md, projection, query, sort)).toArray(new String[0]));
220220
if(sort != null){
221-
request.addControl(new ServerSideSortRequestControl(false, new SortTranslator(property).translate(sort)));
221+
request.addControl(new ServerSideSortRequestControl(false, new SortTranslator(fieldNameTranslator).translate(sort)));
222222
}
223223
if((from != null) && (from > 0)){
224224
int endPos = to.intValue() - from.intValue();
@@ -228,14 +228,14 @@ public CRUDFindResponse find(CRUDOperationContext ctx,
228228
SearchResult result = connection.search(request);
229229

230230
response.setSize(result.getEntryCount());
231-
ResultTranslator resultTranslator = new ResultTranslator(ctx.getFactory().getNodeFactory(), md, property);
231+
ResultTranslator resultTranslator = new ResultTranslator(ctx.getFactory().getNodeFactory(), md, fieldNameTranslator);
232232
List<DocCtx> translatedDocs = new ArrayList<DocCtx>();
233233
for(SearchResultEntry entry : result.getSearchEntries()){
234234
try{
235235
translatedDocs.add(resultTranslator.translate(entry));
236236
}
237237
catch(Exception e){
238-
DocCtx erroredDoc = new DocCtx(null);
238+
DocCtx erroredDoc = new DocCtx(new JsonDoc(null));
239239
erroredDoc.addError(Error.get(e));
240240
translatedDocs.add(erroredDoc);
241241
}
@@ -250,7 +250,7 @@ public CRUDFindResponse find(CRUDOperationContext ctx,
250250
ctx.getCallerRoles()).getExcludedFields(FieldAccessRoleEvaluator.Operation.find)
251251
),
252252
md);
253-
for (DocCtx document : ctx.getDocuments()) {
253+
for (DocCtx document : ctx.getDocumentsWithoutErrors()) {
254254
document.setOutputDocument(projector.project(document, ctx.getFactory().getNodeFactory()));
255255
}
256256
}
@@ -364,9 +364,9 @@ private String createDN(LdapDataStore store, String uniqueValue){
364364
* @param sort - (optional) {@link Sort}.
365365
* @return list of field names.
366366
*/
367-
private Set<String> gatherRequiredFields(EntityMetadata md,
367+
private Set<Path> gatherRequiredFields(EntityMetadata md,
368368
Projection projection, QueryExpression query, Sort sort){
369-
Set<String> fields = new HashSet<String>();
369+
Set<Path> paths = new HashSet<Path>();
370370

371371
FieldCursor cursor = md.getFieldCursor();
372372
while(cursor.next()) {
@@ -381,15 +381,16 @@ private Set<String> gatherRequiredFields(EntityMetadata md,
381381
* Handles the case of an array count field, which will not actually exist in
382382
* the ldap entity.
383383
*/
384-
fields.add(LightblueUtil.createArrayFieldNameFromCountField(fieldName));
384+
385+
paths.add(new Path(node.toString().replace(fieldName, "") + LightblueUtil.createArrayFieldNameFromCountField(fieldName)));
385386
}
386387
else{
387-
fields.add(fieldName);
388+
paths.add(node);
388389
}
389390
}
390391
}
391392

392-
return fields;
393+
return paths;
393394
}
394395

395396
/**
@@ -399,10 +400,10 @@ private Set<String> gatherRequiredFields(EntityMetadata md,
399400
* @param fieldNames - <code>Collection</code> of fieldNames to translated
400401
* @return <code>Set</code> of translated attributeNames.
401402
*/
402-
private Set<String> translateFieldNames(LdapFieldNameTranslator property, Collection<String> fieldNames){
403+
private Set<String> translateFieldNames(LdapFieldNameTranslator property, Collection<Path> fieldNames){
403404
Set<String> attributes = new HashSet<String>();
404-
for(String fieldName : fieldNames){
405-
attributes.add(property.translateFieldName(fieldName));
405+
for(Path path : fieldNames){
406+
attributes.add(property.translateFieldName(path));
406407
}
407408

408409
return attributes;
@@ -422,9 +423,9 @@ private void projectChanges(Projection projection, CRUDOperationContext ctx, Map
422423

423424
EntityMetadata md = ctx.getEntityMetadata(ctx.getEntityName());
424425
JsonNodeFactory factory = ctx.getFactory().getNodeFactory();
425-
LdapFieldNameTranslator property = getLdapFieldNameTranslator(md);
426+
LdapFieldNameTranslator fieldNameTranslator = getLdapFieldNameTranslator(md);
426427

427-
Set<String> requiredAttributeNames = translateFieldNames(property, gatherRequiredFields(md, projection, null, null));
428+
Set<String> requiredAttributeNames = translateFieldNames(fieldNameTranslator, gatherRequiredFields(md, projection, null, null));
428429
Projector projector = Projector.getInstance(
429430
Projection.add(
430431
projection,
@@ -434,7 +435,7 @@ private void projectChanges(Projection projection, CRUDOperationContext ctx, Map
434435
),
435436
md);
436437

437-
String dnFieldName = property.translateAttributeName(LdapConstant.ATTRIBUTE_DN);
438+
String dnFieldName = fieldNameTranslator.translateAttributeName(LdapConstant.ATTRIBUTE_DN);
438439

439440
for(Entry<DocCtx, String> insertedDn : documentToDnMap.entrySet()){
440441
DocCtx document = insertedDn.getKey();

lightblue-ldap-crud/src/main/java/com/redhat/lightblue/crud/ldap/TranslatorFromJson.java

Lines changed: 32 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,8 @@
4545
*
4646
* @param <T> - A entity that the specific datastore knows how
4747
* to interact with.
48+
*
49+
* @see #translate(JsonDoc, Object)
4850
*/
4951
public abstract class TranslatorFromJson<T> {
5052

@@ -54,7 +56,7 @@ public TranslatorFromJson(EntityMetadata md){
5456
this.md = md;
5557
}
5658

57-
protected EntityMetadata getEntityMetadata(){
59+
public EntityMetadata getEntityMetadata(){
5860
return md;
5961
}
6062

@@ -67,7 +69,12 @@ protected Object fromJson(Type type, JsonNode node){
6769
}
6870
}
6971

70-
protected void translate(JsonDoc document, T target){
72+
/**
73+
* Translates an entire {@link JsonDoc} to T.
74+
* @param document - {@link JsonDoc}
75+
* @param target - T
76+
*/
77+
public void translate(JsonDoc document, T target){
7178
JsonNodeCursor cursor = document.cursor();
7279
if (!cursor.firstChild()) {
7380
//TODO throw exception?
@@ -79,7 +86,14 @@ protected void translate(JsonDoc document, T target){
7986
} while (cursor.nextSibling());
8087
}
8188

82-
private void translate(JsonNodeCursor cursor, T target){
89+
/**
90+
* Uses the current position of the cursor to translate the current node and any children it may have.
91+
* This is ultimately the driver behind this class and may be called recursively by implementing classes to process child nodes.<br>
92+
* <b>NOTE:</b> Calling method is responsible for moving the cursor to where it needs to be.
93+
* @param cursor - {@link JsonNodeCursor}
94+
* @param target - T
95+
*/
96+
protected void translate(JsonNodeCursor cursor, T target){
8397
Path path = cursor.getCurrentPath();
8498
JsonNode node = cursor.getCurrentNode();
8599
FieldTreeNode fieldNode = md.resolve(path);
@@ -92,7 +106,7 @@ private void translate(JsonNodeCursor cursor, T target){
92106
translate((SimpleField) fieldNode, path, node, target);
93107
}
94108
else if (fieldNode instanceof ObjectField) {
95-
translate((ObjectField) fieldNode, path, node, target);
109+
translate((ObjectField) fieldNode, cursor, path, target);
96110
}
97111
else if (fieldNode instanceof ArrayField) {
98112
translate((ArrayField) fieldNode, cursor, path, target);
@@ -121,7 +135,7 @@ private void translate(ArrayField field, JsonNodeCursor cursor, Path path, T tar
121135
translateSimpleArray(field, path, items, target);
122136
}
123137
else if(arrayElement instanceof ObjectArrayElement){
124-
translateObjectArray(field, cursor, target);
138+
translateObjectArray(field, cursor, path, target);
125139
}
126140
else{
127141
throw new UnsupportedOperationException("ArrayElement type is not supported: " + arrayElement.getClass().getName());
@@ -130,13 +144,24 @@ else if(arrayElement instanceof ObjectArrayElement){
130144
cursor.parent();
131145
}
132146

147+
protected void translate(ObjectField field, JsonNodeCursor cursor, Path path, T target){
148+
if(!cursor.firstChild()){
149+
//TODO: throw exception?
150+
return;
151+
}
152+
do {
153+
translate(cursor, target);
154+
} while (cursor.nextSibling());
155+
156+
cursor.parent();
157+
}
158+
133159
protected void translate(ReferenceField field, Path path, JsonNode node, T target){
134160
//Do nothing by default!
135161
}
136162

137163
protected abstract void translate(SimpleField field, Path path, JsonNode node, T target);
138-
protected abstract void translate(ObjectField field, Path path, JsonNode node, T target);
139164
protected abstract void translateSimpleArray(ArrayField field, Path path, List<Object> items, T target);
140-
protected abstract void translateObjectArray(ArrayField field, JsonNodeCursor cursor, T target);
165+
protected abstract void translateObjectArray(ArrayField field, JsonNodeCursor cursor, Path path, T target);
141166

142167
}

lightblue-ldap-crud/src/main/java/com/redhat/lightblue/crud/ldap/model/TrivialLdapFieldNameTranslator.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
package com.redhat.lightblue.crud.ldap.model;
2020

2121
import com.redhat.lightblue.common.ldap.LdapFieldNameTranslator;
22+
import com.redhat.lightblue.util.Path;
2223

2324
/**
2425
* An implementation of {@link LdapFieldNameTranslator} used by crud when
@@ -29,8 +30,8 @@
2930
public class TrivialLdapFieldNameTranslator implements LdapFieldNameTranslator{
3031

3132
@Override
32-
public String translateFieldName(String fieldName) {
33-
return fieldName;
33+
public String translateFieldName(Path path) {
34+
return path.getLast();
3435
}
3536

3637
@Override

lightblue-ldap-crud/src/main/java/com/redhat/lightblue/crud/ldap/translator/FilterTranslator.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ else if (query instanceof ValueComparisonExpression){
8686
}
8787

8888
private Filter translate(ArrayContainsExpression query){
89-
String attributeName = fieldNameTranslator.translateFieldName(query.getArray().toString());
89+
String attributeName = fieldNameTranslator.translateFieldName(query.getArray());
9090

9191
List<Filter> filters = new ArrayList<Filter>();
9292
for(Value value : query.getValues()){
@@ -131,7 +131,7 @@ private Filter translate(NaryLogicalExpression query){
131131
}
132132

133133
private Filter translate(NaryRelationalExpression query){
134-
String attributeName = fieldNameTranslator.translateFieldName(query.getField().toString());
134+
String attributeName = fieldNameTranslator.translateFieldName(query.getField());
135135
List<Filter> filters = new ArrayList<Filter>();
136136
for(Value value : query.getValues()){
137137
filters.add(Filter.createEqualityFilter(attributeName, value.getValue().toString()));
@@ -162,7 +162,7 @@ private Filter translate(UnaryLogicalExpression query){
162162
}
163163

164164
private Filter translate(ValueComparisonExpression query){
165-
String attributeName = fieldNameTranslator.translateFieldName(query.getField().toString());
165+
String attributeName = fieldNameTranslator.translateFieldName(query.getField());
166166
String rValue = query.getRvalue().getValue().toString();
167167

168168
switch(query.getOp()){

0 commit comments

Comments
 (0)