-
Notifications
You must be signed in to change notification settings - Fork 408
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
added Attribute #478
added Attribute #478
Conversation
Added an AttributeSet as well. It's intention is to represent a set of attributes that must adhere to a set of rules, e.g. no duplicates among them, if they contain pmin and pmax then pmin must be less than pmax etc. |
@@ -0,0 +1,8 @@ | |||
package org.eclipse.leshan.core.attr; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I will go for org.eclipse.leshan.core.attributes
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK
public enum AssignationLevel { | ||
OBJECT(1<<0), | ||
INSTANCE(1<<1), | ||
RESOURCE(1<<2); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why do we need to set value for this enum ?
/** | ||
* The attachment level of an LwM2m attribute. | ||
*/ | ||
public enum Attachment { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we really attachment ? this sounds not so useful ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it will be necessary to be able to compile a proper DiscoverResponse, e.g. if you perform Discover on a resource, the inherited attributes from Object and Instance level should be included only if they have Attachment = Resource
@@ -34,24 +36,35 @@ private AttributeModel(String coRELinkParam, Attachment attachment, Set<Assignat | |||
static { | |||
modelMap = new HashMap<>(); | |||
modelMap.put(AttributeName.DIMENSION, new Attribute.AttributeModel("dim", Attachment.RESOURCE, EnumSet.of(AssignationLevel.RESOURCE), | |||
AccessMode.R)); | |||
AccessMode.R, Integer.class)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The spec say:
Integer : An 8, 16, 32 or 64-bit signed integer. The valid range of the value for a Resource SHOULD be defined. This data type is also used for the purpose of enumeration.
So maybe we should use Long .class for LWM2M integer.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, that's true.
public class AttributeSet { | ||
|
||
private static final String PARAM_SEP = "&"; | ||
private static final String CANCEL = "cancel"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I did search so much but I did not find any reference to cancel attribute. Could you point where this is defined in the spec ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not me either :) I saw that this construct existed in ObserveSpec. I'll remove it for now.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Probably out of date you can remove it.
for (Attribute attr : attributes) { | ||
// Check for duplicates | ||
if (attributeMap.containsKey(attr.getName())) { | ||
throw new InvalidRequestException("Cannot create attribute set with duplicates (attr: '%s')", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should use IllegalArgumentException
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK. Fixed in all places
Attribute pmin = attributeMap.get(AttributeName.MINIMUM_PERIOD); | ||
Attribute pmax = attributeMap.get(AttributeName.MAXIMUM_PERIOD); | ||
if ((pmin != null) && (pmax != null) && (Integer) pmin.getValue() > (Integer) pmax.getValue()) { | ||
throw new InvalidRequestException("Cannot write attributes where '%s' > '%s'", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should use IllegalArgumentException
return attributeMap.values().toArray(new Attribute[attributeMap.size()]); | ||
} | ||
|
||
public String[] toQueryParams() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe we don't really need to make it public.
We can maybe merge it with toString, but we will see later depending on how we are using AttributeSet.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's used for ObserveSpec in https://github.com/eclipse/leshan/blob/master/leshan-server-cf/src/main/java/org/eclipse/leshan/server/californium/impl/CoapRequestBuilder.java so I'll leave it public for now.
I'll add unit tests and better comments when we're agreed on the basics. If you could point me to a file header to use (e.g. copyright and contributor info), I'll add that too. |
Just inspire your self from the other header, updating years and company name this should be OK :) |
/* | ||
* Utility method: static creator | ||
*/ | ||
public Attribute create(AttributeName name, Object value) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should it be static ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, it definitely should...
return b.toString(); | ||
// Sort to get a consistent ordering | ||
String[] queryParams = toQueryParams(); | ||
Arrays.sort(queryParams); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we really sort it ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I get it. It's about testing.
I would go for LinkedHashMap which keeps order. This should be determinist enough for testing.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK, that sounds good, I'll look into that as well.
|
||
sut.validate(AssignationLevel.RESOURCE); | ||
|
||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
detail : not needed \n
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK
I do not understand why my 2nd comment is outdated ... |
I'm working in parallel with integrating AttributeSet and Discover, so I've added some needed features to AttributeSet as well. |
4fe63a6
to
61d1e65
Compare
* @param attributes the AttributeSet that should be merged | ||
*/ | ||
public void merge(AttributeSet attributes) { | ||
for (Attribute sourceAttr: attributes.getAttributes()) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should this return a new Attribute with the merged result? Might be cleaner...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you mean a new AttributeSet ?
If we do that we can make AttributeSet immutable.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, AttributeSet... :) I'll try to make it immutable, I don't think it will add too much complexity
This is ready for final review now. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you rebase on master and squash all your commit in one, once you think it's ok ?
private final String coRELinkParam; | ||
private final Attachment attachment; | ||
private final Set<AssignationLevel> assignationLevels; | ||
private AccessMode accessMode; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
final
private final Attachment attachment; | ||
private final Set<AssignationLevel> assignationLevels; | ||
private AccessMode accessMode; | ||
private Class<?> valueClass; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
final
*/ | ||
public class AttributeSet { | ||
|
||
private Map<AttributeName, Attribute> attributeMap = new LinkedHashMap<>(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
final + collection.unmodifiableMap
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done. Conversion to unmodifiable map is performed in getter.
attrs.add(attr); | ||
} | ||
} | ||
return new AttributeSet(attrs.toArray(new Attribute[attrs.size()])); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would add a constructor with Collection to avoid to create unnecessary array.
You can look at ObjectModel
it's a bit the same idea.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done, much cleaner
/** | ||
* Creates an attribute set from a list of query params. | ||
*/ | ||
public AttributeSet(String[] queryParams) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It seems to be only needed for backward compatibility with ObserveSpec. So we should maybe mark this as deprecated to not forget to remove it with ObserveSpec.
} | ||
|
||
public Attribute[] getAttributes() { | ||
return attributeMap.values().toArray(new Attribute[attributeMap.size()]); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
return collection ? to avoid to create array
} | ||
|
||
public String[] toQueryParams() { | ||
List<String> queries = new LinkedList<>(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can directly create the array as you know the size.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, but then I would have to use a for (int x = 0... loop, which in my mind is harder to read
|
||
@Override | ||
public String toString() { | ||
return String.join("&", toQueryParams()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We aims java 1.7 (mainly because of android)
String.join is available since java 1.8
I should change the maven configuration to check that.
*/ | ||
public class AttributeSet { | ||
|
||
private Map<AttributeName, Attribute> attributeMap = new LinkedHashMap<>(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It seems we only need to query by CoRELinkParam
so I will go for a map String->Attribute
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we even remove the AttributeName enum then? Referring to attributes by their string representations "pmin", "ver" etc. feels rather logical. Maybe it's enough to have Map<String, AttributeModel> for the static model map?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good question. I didn't think about that but maybe it is not so useful and we could remove it.
If you feel this is not necessary, please remove it. If we could keep it simple we should :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
AttritebuteName enum removed. Much nicer :)
* Returns the attributes as a map with the CoRELinkParam as key and the attribute value as map value. | ||
* @return the attributes map | ||
*/ | ||
public Map<String, Object> getMap() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if we change the internalMap with coreLinkParam->Attribute (see comment above)
We don't need to create a new Map anymore.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, this is basically how I interpreted your previous comment... I'll go for that
81df3e0
to
37c19f9
Compare
I selected the attribute branch and selected to perform a rebase on master, and then I force pushed. And now this pull request looks like hell... What happened? |
😲 ! I will look at this :) |
It seems you made the rebase on "your" master branch not the eclipse repository one. I advice you :
|
Signed-off-by: Daniel Persson <daniel.p.persson@husqvarnagroup.com>
Tada...! Thanks a lot for the help. Git is a scary but fantastic tool. But I think I've understood what we did here, at least. |
I will review it but once it's ok. |
You can decide that, I think. I have already merged attribute into my discover branch several times since I worked on them in parallel for some time, including once just moments ago to get the latest changes included. |
I integrated this in a attributes branch. |
Embryo of Attribute support
Signed-off-by: Daniel Persson daniel.p.persson@husqvarnagroup.com