Skip to content
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

Closed
wants to merge 1 commit into from
Closed

Conversation

danielhqv
Copy link
Contributor

@danielhqv danielhqv commented Feb 28, 2018

Embryo of Attribute support
Signed-off-by: Daniel Persson daniel.p.persson@husqvarnagroup.com

@danielhqv
Copy link
Contributor Author

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.
As I see it, AttributeSet would then be used in place of ObserveSpec in most places.

@@ -0,0 +1,8 @@
package org.eclipse.leshan.core.attr;
Copy link
Contributor

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

Copy link
Contributor Author

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);
Copy link
Contributor

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 {
Copy link
Contributor

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 ?

Copy link
Contributor Author

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));
Copy link
Contributor

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.

Copy link
Contributor Author

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";
Copy link
Contributor

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 ?

Copy link
Contributor Author

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.

Copy link
Contributor

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')",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should use IllegalArgumentException

Copy link
Contributor Author

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'",
Copy link
Contributor

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() {
Copy link
Contributor

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.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@danielhqv
Copy link
Contributor Author

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.

@sbernard31
Copy link
Contributor

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) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should it be static ?

Copy link
Contributor Author

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);
Copy link
Contributor

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 ?

Copy link
Contributor

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.

Copy link
Contributor Author

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);

}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

detail : not needed \n

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK

@sbernard31
Copy link
Contributor

I do not understand why my 2nd comment is outdated ...

@danielhqv
Copy link
Contributor Author

I'm working in parallel with integrating AttributeSet and Discover, so I've added some needed features to AttributeSet as well.

@danielhqv danielhqv force-pushed the attribute branch 3 times, most recently from 4fe63a6 to 61d1e65 Compare March 2, 2018 16:07
* @param attributes the AttributeSet that should be merged
*/
public void merge(AttributeSet attributes) {
for (Attribute sourceAttr: attributes.getAttributes()) {
Copy link
Contributor Author

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...

Copy link
Contributor

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.

Copy link
Contributor Author

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

@danielhqv
Copy link
Contributor Author

This is ready for final review now.

Copy link
Contributor

@sbernard31 sbernard31 left a 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;
Copy link
Contributor

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;
Copy link
Contributor

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<>();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

final + collection.unmodifiableMap

Copy link
Contributor Author

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()]));
Copy link
Contributor

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.

Copy link
Contributor Author

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) {
Copy link
Contributor

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()]);
Copy link
Contributor

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<>();
Copy link
Contributor

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.

Copy link
Contributor Author

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());
Copy link
Contributor

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<>();
Copy link
Contributor

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

Copy link
Contributor Author

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?

Copy link
Contributor

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 :)

Copy link
Contributor Author

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() {
Copy link
Contributor

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.

Copy link
Contributor Author

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

@danielhqv danielhqv force-pushed the attribute branch 2 times, most recently from 81df3e0 to 37c19f9 Compare March 9, 2018 13:33
@danielhqv
Copy link
Contributor Author

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?

@sbernard31
Copy link
Contributor

😲 ! I will look at this :)

@sbernard31
Copy link
Contributor

It seems you made the rebase on "your" master branch not the eclipse repository one.

I advice you :

  • To create a new branch tmp on the commit "added attribute" ( 37c19f9 ), just to keep an eye on your commit.
  • Then reset hard your attribute branch on master of eclipse repo.
  • Once you do that just do a cherry pick of commit
    ( 37c19f9 ) from your attribute branch.
  • push force the attribute branch.
  • check if the mess is gone.
  • remove the tmp branch (only if all is ok)

Signed-off-by: Daniel Persson <daniel.p.persson@husqvarnagroup.com>
@danielhqv
Copy link
Contributor Author

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.

@sbernard31
Copy link
Contributor

I will review it but once it's ok.
Should we integrate this directly in master ? or should I create a branch discover in which we add your PR one by one and once it's finished we integrate it in master ?

@danielhqv
Copy link
Contributor Author

danielhqv commented Mar 9, 2018

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.

@sbernard31
Copy link
Contributor

I integrated this in a attributes branch.
I also clean a bit the code (fixing formatting and removing unused import).
To avoid this you should look at https://github.com/eclipse/leshan/wiki/Code-&-design-guidelines#eclipse-workspace-setup

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants