What is the best approach for having some kind of lazy iterator where the return is evaluated only on...
import java.util.Collection;
import example.Event;
public interface Query
{
public boolean hasMore ();
public Collection<Event> getNext ( long count ) throws Exception;
}
This is the interface I have, which I want to implement.
The implementation is supposed to be like this:
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import example.Event;
import example.Query;
public class ListQuery implements Query {
public ListQuery(List<Event> events, String filter)
throws FilterParseException {
// events is the list of given events
// filter is a string representation of the filter to apply
}
public Collection<Event> getNext(long count) throws Exception {
// returns max. count next entries which match given filter
}
public boolean hasMore() {
// returns if there are more elements matching the given filter
}
}
What I'm thinking about, is the relationship between hasMore() and getNext(). In both cases I have to evaluate if the filter matches an element of the list. Possibly I don't know the implementation of the given list, so it could be an expensive operation. Obviously I cant just use hasNext() from an iterator, because I have to check if the Event matches the given criteria. In my current implementation I have two different iterators and the current position, where the one for hasMore() is moved up if the position of the iterator for getNext() is larger than the one for hasMore().
What I actually would like to do, is to clone the current iterator which I in turn would use for hasMore(), but this is not possible obviously.
Is there a more elegant solution for this problem?
java collections iterator
add a comment |
import java.util.Collection;
import example.Event;
public interface Query
{
public boolean hasMore ();
public Collection<Event> getNext ( long count ) throws Exception;
}
This is the interface I have, which I want to implement.
The implementation is supposed to be like this:
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import example.Event;
import example.Query;
public class ListQuery implements Query {
public ListQuery(List<Event> events, String filter)
throws FilterParseException {
// events is the list of given events
// filter is a string representation of the filter to apply
}
public Collection<Event> getNext(long count) throws Exception {
// returns max. count next entries which match given filter
}
public boolean hasMore() {
// returns if there are more elements matching the given filter
}
}
What I'm thinking about, is the relationship between hasMore() and getNext(). In both cases I have to evaluate if the filter matches an element of the list. Possibly I don't know the implementation of the given list, so it could be an expensive operation. Obviously I cant just use hasNext() from an iterator, because I have to check if the Event matches the given criteria. In my current implementation I have two different iterators and the current position, where the one for hasMore() is moved up if the position of the iterator for getNext() is larger than the one for hasMore().
What I actually would like to do, is to clone the current iterator which I in turn would use for hasMore(), but this is not possible obviously.
Is there a more elegant solution for this problem?
java collections iterator
add a comment |
import java.util.Collection;
import example.Event;
public interface Query
{
public boolean hasMore ();
public Collection<Event> getNext ( long count ) throws Exception;
}
This is the interface I have, which I want to implement.
The implementation is supposed to be like this:
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import example.Event;
import example.Query;
public class ListQuery implements Query {
public ListQuery(List<Event> events, String filter)
throws FilterParseException {
// events is the list of given events
// filter is a string representation of the filter to apply
}
public Collection<Event> getNext(long count) throws Exception {
// returns max. count next entries which match given filter
}
public boolean hasMore() {
// returns if there are more elements matching the given filter
}
}
What I'm thinking about, is the relationship between hasMore() and getNext(). In both cases I have to evaluate if the filter matches an element of the list. Possibly I don't know the implementation of the given list, so it could be an expensive operation. Obviously I cant just use hasNext() from an iterator, because I have to check if the Event matches the given criteria. In my current implementation I have two different iterators and the current position, where the one for hasMore() is moved up if the position of the iterator for getNext() is larger than the one for hasMore().
What I actually would like to do, is to clone the current iterator which I in turn would use for hasMore(), but this is not possible obviously.
Is there a more elegant solution for this problem?
java collections iterator
import java.util.Collection;
import example.Event;
public interface Query
{
public boolean hasMore ();
public Collection<Event> getNext ( long count ) throws Exception;
}
This is the interface I have, which I want to implement.
The implementation is supposed to be like this:
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import example.Event;
import example.Query;
public class ListQuery implements Query {
public ListQuery(List<Event> events, String filter)
throws FilterParseException {
// events is the list of given events
// filter is a string representation of the filter to apply
}
public Collection<Event> getNext(long count) throws Exception {
// returns max. count next entries which match given filter
}
public boolean hasMore() {
// returns if there are more elements matching the given filter
}
}
What I'm thinking about, is the relationship between hasMore() and getNext(). In both cases I have to evaluate if the filter matches an element of the list. Possibly I don't know the implementation of the given list, so it could be an expensive operation. Obviously I cant just use hasNext() from an iterator, because I have to check if the Event matches the given criteria. In my current implementation I have two different iterators and the current position, where the one for hasMore() is moved up if the position of the iterator for getNext() is larger than the one for hasMore().
What I actually would like to do, is to clone the current iterator which I in turn would use for hasMore(), but this is not possible obviously.
Is there a more elegant solution for this problem?
java collections iterator
java collections iterator
asked Oct 27 '09 at 17:28
MauliMauli
8,8702471108
8,8702471108
add a comment |
add a comment |
3 Answers
3
active
oldest
votes
In your getNext implementation, after you assign your return value, you could advance your iterator until you find an appropriate event. This way, your hasMore can safely test hasNext on your iterator to determine whether to return true or false.
I was busy typing up this exact solution as an example. You can advance the current position as such:current = null; while (it.hasNext() && !passesFilter(current = it.next()));
– Gunslinger47
Oct 27 '09 at 17:49
@akf - that's not true, strictly speaking. Example: after the call togetNext()there's only one element remaining in the list that satisfies the filter and it's the actual last element in the list. You've advanced the iterator position to it;hasNext()will return false. You could put it in buffer as suggested byGunslinger47and check that but you'll lose the fail-fast iterator functionality that way
– ChssPly76
Oct 27 '09 at 17:54
Yes, I thought of that. If you advance your iterator and pull the items out as you do so, you will iterate past your next item, which wouldnt be any good. If you maintain yourList<Event>and use that to aid in advancing your iterator to the position just before your next good event, it should work.
– akf
Oct 27 '09 at 17:58
@akf - by "use that to aid" do you mean viaListIterator.previous()or viaList.get()? Either way could potentially be expensive though I suppose you'd only need to call those for the last element of the list. To be fair, I think the original interface is sub-optimal by itself; considering thatgetNext(count)can return less thancountat any time,hasMore()is rather pointless to begin with. Your solution is likely as good as it'll get within current constraints; +1
– ChssPly76
Oct 27 '09 at 18:10
I was thinking in terms of the simpleList.get(). Thanks.
– akf
Oct 27 '09 at 18:12
|
show 1 more comment
Stop torturing yourself :-) and just use this:
Iterables.filter(Iterable, Predicate)
It takes care of these problems for you.
If you don't have your data in anything Iterable, only an Iterator, see the corresponding class Iterators. If you need to implement the Iterator yourself, it may help to extend AbstractIterator in that same package.
Then if you really want to be able to retrieve chunks of results you can use the partition() method of the Itera*s classes.
It looks very much like the easiest solution for my problem.
– Mauli
Nov 4 '09 at 10:21
1
Except of course that anyone looking at this problem these days should use code.google.com/p/guava-libraries which is the successor to the Google collections library.
– Daniel Martin
Nov 7 '11 at 20:46
add a comment |
I am thinking you don't even need two iterators. The hasMore call can iterate all the way until it finds a match and just stay there (if the element that it already points to matches, don't iterate). Now the getNext will use same iterator to iterate and populate return collection until either count is reached or no more matching elements are found.
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f1632396%2fwhat-is-the-best-approach-for-having-some-kind-of-lazy-iterator-where-the-return%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
3 Answers
3
active
oldest
votes
3 Answers
3
active
oldest
votes
active
oldest
votes
active
oldest
votes
In your getNext implementation, after you assign your return value, you could advance your iterator until you find an appropriate event. This way, your hasMore can safely test hasNext on your iterator to determine whether to return true or false.
I was busy typing up this exact solution as an example. You can advance the current position as such:current = null; while (it.hasNext() && !passesFilter(current = it.next()));
– Gunslinger47
Oct 27 '09 at 17:49
@akf - that's not true, strictly speaking. Example: after the call togetNext()there's only one element remaining in the list that satisfies the filter and it's the actual last element in the list. You've advanced the iterator position to it;hasNext()will return false. You could put it in buffer as suggested byGunslinger47and check that but you'll lose the fail-fast iterator functionality that way
– ChssPly76
Oct 27 '09 at 17:54
Yes, I thought of that. If you advance your iterator and pull the items out as you do so, you will iterate past your next item, which wouldnt be any good. If you maintain yourList<Event>and use that to aid in advancing your iterator to the position just before your next good event, it should work.
– akf
Oct 27 '09 at 17:58
@akf - by "use that to aid" do you mean viaListIterator.previous()or viaList.get()? Either way could potentially be expensive though I suppose you'd only need to call those for the last element of the list. To be fair, I think the original interface is sub-optimal by itself; considering thatgetNext(count)can return less thancountat any time,hasMore()is rather pointless to begin with. Your solution is likely as good as it'll get within current constraints; +1
– ChssPly76
Oct 27 '09 at 18:10
I was thinking in terms of the simpleList.get(). Thanks.
– akf
Oct 27 '09 at 18:12
|
show 1 more comment
In your getNext implementation, after you assign your return value, you could advance your iterator until you find an appropriate event. This way, your hasMore can safely test hasNext on your iterator to determine whether to return true or false.
I was busy typing up this exact solution as an example. You can advance the current position as such:current = null; while (it.hasNext() && !passesFilter(current = it.next()));
– Gunslinger47
Oct 27 '09 at 17:49
@akf - that's not true, strictly speaking. Example: after the call togetNext()there's only one element remaining in the list that satisfies the filter and it's the actual last element in the list. You've advanced the iterator position to it;hasNext()will return false. You could put it in buffer as suggested byGunslinger47and check that but you'll lose the fail-fast iterator functionality that way
– ChssPly76
Oct 27 '09 at 17:54
Yes, I thought of that. If you advance your iterator and pull the items out as you do so, you will iterate past your next item, which wouldnt be any good. If you maintain yourList<Event>and use that to aid in advancing your iterator to the position just before your next good event, it should work.
– akf
Oct 27 '09 at 17:58
@akf - by "use that to aid" do you mean viaListIterator.previous()or viaList.get()? Either way could potentially be expensive though I suppose you'd only need to call those for the last element of the list. To be fair, I think the original interface is sub-optimal by itself; considering thatgetNext(count)can return less thancountat any time,hasMore()is rather pointless to begin with. Your solution is likely as good as it'll get within current constraints; +1
– ChssPly76
Oct 27 '09 at 18:10
I was thinking in terms of the simpleList.get(). Thanks.
– akf
Oct 27 '09 at 18:12
|
show 1 more comment
In your getNext implementation, after you assign your return value, you could advance your iterator until you find an appropriate event. This way, your hasMore can safely test hasNext on your iterator to determine whether to return true or false.
In your getNext implementation, after you assign your return value, you could advance your iterator until you find an appropriate event. This way, your hasMore can safely test hasNext on your iterator to determine whether to return true or false.
answered Oct 27 '09 at 17:47
akfakf
33.4k87090
33.4k87090
I was busy typing up this exact solution as an example. You can advance the current position as such:current = null; while (it.hasNext() && !passesFilter(current = it.next()));
– Gunslinger47
Oct 27 '09 at 17:49
@akf - that's not true, strictly speaking. Example: after the call togetNext()there's only one element remaining in the list that satisfies the filter and it's the actual last element in the list. You've advanced the iterator position to it;hasNext()will return false. You could put it in buffer as suggested byGunslinger47and check that but you'll lose the fail-fast iterator functionality that way
– ChssPly76
Oct 27 '09 at 17:54
Yes, I thought of that. If you advance your iterator and pull the items out as you do so, you will iterate past your next item, which wouldnt be any good. If you maintain yourList<Event>and use that to aid in advancing your iterator to the position just before your next good event, it should work.
– akf
Oct 27 '09 at 17:58
@akf - by "use that to aid" do you mean viaListIterator.previous()or viaList.get()? Either way could potentially be expensive though I suppose you'd only need to call those for the last element of the list. To be fair, I think the original interface is sub-optimal by itself; considering thatgetNext(count)can return less thancountat any time,hasMore()is rather pointless to begin with. Your solution is likely as good as it'll get within current constraints; +1
– ChssPly76
Oct 27 '09 at 18:10
I was thinking in terms of the simpleList.get(). Thanks.
– akf
Oct 27 '09 at 18:12
|
show 1 more comment
I was busy typing up this exact solution as an example. You can advance the current position as such:current = null; while (it.hasNext() && !passesFilter(current = it.next()));
– Gunslinger47
Oct 27 '09 at 17:49
@akf - that's not true, strictly speaking. Example: after the call togetNext()there's only one element remaining in the list that satisfies the filter and it's the actual last element in the list. You've advanced the iterator position to it;hasNext()will return false. You could put it in buffer as suggested byGunslinger47and check that but you'll lose the fail-fast iterator functionality that way
– ChssPly76
Oct 27 '09 at 17:54
Yes, I thought of that. If you advance your iterator and pull the items out as you do so, you will iterate past your next item, which wouldnt be any good. If you maintain yourList<Event>and use that to aid in advancing your iterator to the position just before your next good event, it should work.
– akf
Oct 27 '09 at 17:58
@akf - by "use that to aid" do you mean viaListIterator.previous()or viaList.get()? Either way could potentially be expensive though I suppose you'd only need to call those for the last element of the list. To be fair, I think the original interface is sub-optimal by itself; considering thatgetNext(count)can return less thancountat any time,hasMore()is rather pointless to begin with. Your solution is likely as good as it'll get within current constraints; +1
– ChssPly76
Oct 27 '09 at 18:10
I was thinking in terms of the simpleList.get(). Thanks.
– akf
Oct 27 '09 at 18:12
I was busy typing up this exact solution as an example. You can advance the current position as such:
current = null; while (it.hasNext() && !passesFilter(current = it.next()));– Gunslinger47
Oct 27 '09 at 17:49
I was busy typing up this exact solution as an example. You can advance the current position as such:
current = null; while (it.hasNext() && !passesFilter(current = it.next()));– Gunslinger47
Oct 27 '09 at 17:49
@akf - that's not true, strictly speaking. Example: after the call to
getNext() there's only one element remaining in the list that satisfies the filter and it's the actual last element in the list. You've advanced the iterator position to it; hasNext() will return false. You could put it in buffer as suggested by Gunslinger47 and check that but you'll lose the fail-fast iterator functionality that way– ChssPly76
Oct 27 '09 at 17:54
@akf - that's not true, strictly speaking. Example: after the call to
getNext() there's only one element remaining in the list that satisfies the filter and it's the actual last element in the list. You've advanced the iterator position to it; hasNext() will return false. You could put it in buffer as suggested by Gunslinger47 and check that but you'll lose the fail-fast iterator functionality that way– ChssPly76
Oct 27 '09 at 17:54
Yes, I thought of that. If you advance your iterator and pull the items out as you do so, you will iterate past your next item, which wouldnt be any good. If you maintain your
List<Event> and use that to aid in advancing your iterator to the position just before your next good event, it should work.– akf
Oct 27 '09 at 17:58
Yes, I thought of that. If you advance your iterator and pull the items out as you do so, you will iterate past your next item, which wouldnt be any good. If you maintain your
List<Event> and use that to aid in advancing your iterator to the position just before your next good event, it should work.– akf
Oct 27 '09 at 17:58
@akf - by "use that to aid" do you mean via
ListIterator.previous() or via List.get()? Either way could potentially be expensive though I suppose you'd only need to call those for the last element of the list. To be fair, I think the original interface is sub-optimal by itself; considering that getNext(count) can return less than count at any time, hasMore() is rather pointless to begin with. Your solution is likely as good as it'll get within current constraints; +1– ChssPly76
Oct 27 '09 at 18:10
@akf - by "use that to aid" do you mean via
ListIterator.previous() or via List.get()? Either way could potentially be expensive though I suppose you'd only need to call those for the last element of the list. To be fair, I think the original interface is sub-optimal by itself; considering that getNext(count) can return less than count at any time, hasMore() is rather pointless to begin with. Your solution is likely as good as it'll get within current constraints; +1– ChssPly76
Oct 27 '09 at 18:10
I was thinking in terms of the simple
List.get(). Thanks.– akf
Oct 27 '09 at 18:12
I was thinking in terms of the simple
List.get(). Thanks.– akf
Oct 27 '09 at 18:12
|
show 1 more comment
Stop torturing yourself :-) and just use this:
Iterables.filter(Iterable, Predicate)
It takes care of these problems for you.
If you don't have your data in anything Iterable, only an Iterator, see the corresponding class Iterators. If you need to implement the Iterator yourself, it may help to extend AbstractIterator in that same package.
Then if you really want to be able to retrieve chunks of results you can use the partition() method of the Itera*s classes.
It looks very much like the easiest solution for my problem.
– Mauli
Nov 4 '09 at 10:21
1
Except of course that anyone looking at this problem these days should use code.google.com/p/guava-libraries which is the successor to the Google collections library.
– Daniel Martin
Nov 7 '11 at 20:46
add a comment |
Stop torturing yourself :-) and just use this:
Iterables.filter(Iterable, Predicate)
It takes care of these problems for you.
If you don't have your data in anything Iterable, only an Iterator, see the corresponding class Iterators. If you need to implement the Iterator yourself, it may help to extend AbstractIterator in that same package.
Then if you really want to be able to retrieve chunks of results you can use the partition() method of the Itera*s classes.
It looks very much like the easiest solution for my problem.
– Mauli
Nov 4 '09 at 10:21
1
Except of course that anyone looking at this problem these days should use code.google.com/p/guava-libraries which is the successor to the Google collections library.
– Daniel Martin
Nov 7 '11 at 20:46
add a comment |
Stop torturing yourself :-) and just use this:
Iterables.filter(Iterable, Predicate)
It takes care of these problems for you.
If you don't have your data in anything Iterable, only an Iterator, see the corresponding class Iterators. If you need to implement the Iterator yourself, it may help to extend AbstractIterator in that same package.
Then if you really want to be able to retrieve chunks of results you can use the partition() method of the Itera*s classes.
Stop torturing yourself :-) and just use this:
Iterables.filter(Iterable, Predicate)
It takes care of these problems for you.
If you don't have your data in anything Iterable, only an Iterator, see the corresponding class Iterators. If you need to implement the Iterator yourself, it may help to extend AbstractIterator in that same package.
Then if you really want to be able to retrieve chunks of results you can use the partition() method of the Itera*s classes.
edited Nov 27 '18 at 23:01
Kirby
9,62166279
9,62166279
answered Nov 4 '09 at 1:28
Kevin BourrillionKevin Bourrillion
35.5k126282
35.5k126282
It looks very much like the easiest solution for my problem.
– Mauli
Nov 4 '09 at 10:21
1
Except of course that anyone looking at this problem these days should use code.google.com/p/guava-libraries which is the successor to the Google collections library.
– Daniel Martin
Nov 7 '11 at 20:46
add a comment |
It looks very much like the easiest solution for my problem.
– Mauli
Nov 4 '09 at 10:21
1
Except of course that anyone looking at this problem these days should use code.google.com/p/guava-libraries which is the successor to the Google collections library.
– Daniel Martin
Nov 7 '11 at 20:46
It looks very much like the easiest solution for my problem.
– Mauli
Nov 4 '09 at 10:21
It looks very much like the easiest solution for my problem.
– Mauli
Nov 4 '09 at 10:21
1
1
Except of course that anyone looking at this problem these days should use code.google.com/p/guava-libraries which is the successor to the Google collections library.
– Daniel Martin
Nov 7 '11 at 20:46
Except of course that anyone looking at this problem these days should use code.google.com/p/guava-libraries which is the successor to the Google collections library.
– Daniel Martin
Nov 7 '11 at 20:46
add a comment |
I am thinking you don't even need two iterators. The hasMore call can iterate all the way until it finds a match and just stay there (if the element that it already points to matches, don't iterate). Now the getNext will use same iterator to iterate and populate return collection until either count is reached or no more matching elements are found.
add a comment |
I am thinking you don't even need two iterators. The hasMore call can iterate all the way until it finds a match and just stay there (if the element that it already points to matches, don't iterate). Now the getNext will use same iterator to iterate and populate return collection until either count is reached or no more matching elements are found.
add a comment |
I am thinking you don't even need two iterators. The hasMore call can iterate all the way until it finds a match and just stay there (if the element that it already points to matches, don't iterate). Now the getNext will use same iterator to iterate and populate return collection until either count is reached or no more matching elements are found.
I am thinking you don't even need two iterators. The hasMore call can iterate all the way until it finds a match and just stay there (if the element that it already points to matches, don't iterate). Now the getNext will use same iterator to iterate and populate return collection until either count is reached or no more matching elements are found.
answered Oct 27 '09 at 18:08
Rocket SurgeonRocket Surgeon
431618
431618
add a comment |
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f1632396%2fwhat-is-the-best-approach-for-having-some-kind-of-lazy-iterator-where-the-return%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown