I am trying to create a JIRA plugin that does the following:
For each issue, takes all linked issues which are linked by "duplicates" or "is duplicated by" (or other predefined link types).
For each such issue, get a list (not necessarily a List object) of the voters on that issue.
My problem is that the javadoc has little to no information. Following a tutorial, I currently have:
public class VotersCount extends AbstractJiraContextProvider {
#Override
public Map<String, Integer> getContextMap(User user, JiraHelper jiraHelper) {
Map<String, Integer> contextMap = new HashMap<>();
Issue currentIssue = (Issue) jiraHelper.getContextParams().get("issue");
// Issue[] linkedIssues = currentIssue.getLinkedIssuesBy(...); //Step 1 mock code
// Voter[] voters = linkedissues[3].getVoters(); //Step 2 mock code
int count = voters.length; //Pretend there is some calculation here
contextMap.put("votersCount", count);
return contextMap;
}
}
(and I use votersCount in the .vm file.)
However, I see no explanation in the javadocs for AbstractJiraContextProvider and getContextMap so I'm not even sure if it's the right approach.
In my own research I found the class ViewVoters which has the method Collection<UserBean> getVoters(), which is something I can work with, but I don't know how to obtain or construct such an object in a way which will interact with a given issue.
I am looking for a working code to replace my 2 lines of mock code.
1) Use one of the methods from IssueLinkService. Maybe getIssueLinks
2) issueVoterAccessor.getVoterUserkeys
Instances of IssueLinkService and IssueVoterAccessor should be injected as parameters to constructor of your VotersCount.
I solved it by using the following:
To get issues linked to Issue issue by specified link types:
LinkCollection linkCollection = ComponentAccessor.getIssueLinkManager().getLinkCollectionOverrideSecurity(issue);
Set<IssueLinkType> linkTypes = linkCollection.getLinkTypes();
// Perform operations on the set to get the issues you want.
for (IssueLinkType linkType : linkTypes) {
List<Issue> l1 = linkCollection.getOutwardIssues(linkType.getName());
List<Issue> l2 = linkCollection.getInwardIssues(linkType.getName());
}
To get all the voters on Issue issue:
ComponentAccessor.getVoteManager().getVoterUserkeys(issue);
I was later shown that one can extend CalculatedCFType and override getValueFromIssue which hands you the current issue as a parameter instead of the using
Issue currentIssue = (Issue) jiraHelper.getContextParams().get("issue");
Related
I am running a hierachical Spring Statemachine and - after walking through the inital transitions into state UP with the default substate STOPPED - want to use statemachine.getState(). Trouble is, it gives me only the parent state UP, and I cannot find an obvious way to retrieve both the parent state and the sub state.
The machine has states constructed like so:
StateMachineBuilder.Builder<ToolStates, ToolEvents> builder = StateMachineBuilder.builder();
builder.configureStates()
.withStates()
.initial(ToolStates.UP)
.state(ToolStates.UP, new ToolUpEventAction(), null)
.state(ToolStates.DOWN
.and()
.withStates()
.parent(ToolStates.UP)
.initial(ToolStates.STOPPED)
.state(ToolStates.STOPPED,new ToolStoppedEventAction(), null )
.state(ToolStates.IDLE)
.state(ToolStates.PROCESSING,
new ToolBeginProcessingPartAction(),
new ToolDoneProcessingPartAction());
...
builder.build();
ToolStates and ToolEvents are just enums. In the client class, after running the builder code above, the statemachine is started with statemachine.start(); When I subsequently call statemachine.getState().getId(); it gives me UP. No events sent to statemachine before that call.
I have been up and down the Spring statemachine docs and examples. I know from debugging that the entry actions of both states UP and STOPPED have been invoked, so I am assuming they are both "active" and would want to have both states presented when querying the statemachine. Is there a clean way to achieve this ? I want to avoid storing the substate somewhere from inside the Action classes, since I believe I have delegated all state management issues to the freakin Statemachine in the first place and I would rather like to learn how to use its API for this purpose.
Hopefully this is something embarrasingly obvious...
Any advice most welcome!
The documentation describes getStates():
https://docs.spring.io/spring-statemachine/docs/current/api/org/springframework/statemachine/state/State.html
java.util.Collection<State<S,E>> getStates()
Gets all possible states this state knows about including itself and substates.
stateMachine.getState().getStates();
to wrap it up after SMA's most helpful advice: turns out the stateMachine.getState().getStates(); does in my case return a list of four elements:
a StateMachineState instance containing UP and STOPPED
three ObjectState instances containing IDLE, STOPPED and PROCESSING,
respectively.
this leads me to go forward for the time being with the following solution:
public List<ToolStates> getStates() {
List<ToolStates> result = new ArrayList<>();
Collection<State<ToolStates, ToolEvents>> states = this.stateMachine.getState().getStates();
Iterator<State<ToolStates, ToolEvents>> iter = states.iterator();
while (iter.hasNext()) {
State<ToolStates, ToolEvents> candidate = iter.next();
if (!candidate.isSimple()) {
Collection<ToolStates> ids = candidate.getIds();
Iterator<ToolStates> i = ids.iterator();
while (i.hasNext()) {
result.add(i.next());
}
}
}
return result;
}
This maybe would be more elegant with some streaming and filtering, but does the trick for now. I don't like it much, though. It's a lot of error-prone logic and I'll have to see if it holds in the future - I wonder why there isn't a function in the Spring Statemachine that gives me a list of the enum values of all the currently active states, rather than giving me everything possible and forcing me to poke around in it with external logic...
I am trying to figure out a way to version complex Data Objects in Java. For this, I intend to store both the initial document and the diffs in a database (as well as the current object for faster access), and then be able to restore any version from the initial document by applying the diffs onto it as patches.
Thus far, I have come across Javers and java-object-diff for that, however...
Javers has no way of patching
In the java-object-diff documentation, it seems like you need both the initial as well as the target version to apply diffs, which seems kinda pointless since I want to get the target version
This seems like something that someone would have implemented a long time ago. However, thus far, I have not been able to figure out a working solution.
Can someone please help me with this?
For reference, I am currently trying to get it to work somewhat like this:
#Test
void applyDiffDeltaShouldCorrectlyApplyDeltaToCity() {
GameCharacter sylvia = GameCharacters.sylvia();
GameCharacter sylviaEdited = GameCharacters.sylviaEdited();
DiffNode characterDelta
= objectDiffer.compare(sylvia, sylviaEdited);
GameCharacter sylviaWithAppliedDelta
= applyDelta(sylvia, characterDelta);
assertEquals(sylviaEdited.getName(), sylviaWithAppliedDelta.getName());
}
public static <T> T applyDelta(T baseObject, DiffNode diff) {
//This won't work, but it would be cool if it did:
T updatedObject = baseObject + diff;
return updatedObject ;
}
I'm trying to get all items from a grid to be exported. The retrieved list should obey all applied filters and sorting. I'm using a ListDataProvider if it matters.
Suggested solutions include:
using ListDataProvider.getItems() or grid.getDataProvider().fetch(new Query<>()).collect(Collectors.toList()) (here)
using grid.getDataCommunicator().fetchItemsWithRange(0,grid.getDataCommunicator().getDataProviderSize()) (here and here)
using grid.getDataCommunicator().fetchFromProvider(..) (here)
Drawbacks:
The items are not sorted/filtered.
Solution for Vaadin 8, method not present in Vaadin 13.
Provided method is protected, so cannot be called.
How to actually get all items from the grid with applied filters and sorting?
Since you cast grid.getDataProvider to a ListDataProvider<Type>, you can get the current filters from the ListDataProvider to use for the fetch Query.
But only using the Filter for the query will disregard the sort order. To take all that information into account you need to use information from both the dataProvider (filter information) and the dataCommunicator (sorting information)
ListDataProvider<Type> dataProvider = (ListDataProvider<Type>) grid.getDataProvider();
int totalSize = dataProvider.getItems().size();
DataCommunicator<Type> dataCommunicator = grid.getDataCommunicator();
Stream<Type> stream = dataProvider.fetch(new Query<>(
0,
totalSize,
dataCommunicator.getBackEndSorting(),
dataCommunicator.getInMemorySorting(),
dataProvider.getFilter()));
List<Type> list = stream.collect(Collectors.toList());
Edit: you say in your answer that this feels "hacky". I see what you mean, but this is the way to do it. I think this behaviour could be made available as a public api on the grid itself: List<Type> list = grid.getCurrentItems();. The grid would then do this internally so you wouldn't see the "hacky" part yourself. I'm sure they know ways to do the same when the dataprovider is not an instance of ListDataProvider. You could open a feature request for this in the github repo
One solution I found works for me. This does not obey to filtering, but sorting, which is currently sufficient for my case. And this seems very hacky:
ListDataProvider<Type> dataProvider = (ListDataProvider<Type>) grid.getDataProvider();
int size = dataProvider.getItems().size();
DataCommunicator<Type> dataCommunicator = grid.getDataCommunicator();
Stream<Type> stream =
dataProvider.fetch(
new Query<Type, SerializablePredicate<Type>>(
0,
size,
dataCommunicator.getBackEndSorting(),
dataCommunicator.getInMemorySorting(),
null));
List<Type> list = stream.collect(Collectors.toList());
The main problems I see here are
All items have to be extracted before (getItems().size()) to get the range for the actual query.
The getFilter() method of the DataCommunicator is protected and cannot be called to retrieve the filter (therefore null (= no filter) is used here).
How can i read a list of users from the configuration file in play framework?
i have tried doing something like this:
users=[{uid:123,pwd:xyz},{uid:321,pwd:abc}]
from the play application
List<Object> uids = Play.application().configuration().getList("users");
will give me this a list of objects, if I iterate through the list i get each object as
{uid=123,pwd=xyz} and {uid=321,pwd=abc}
at this point i don't know how i can elegantly get the value of the uid, i can do some hacky job as omit the first and last bracket and parse for the before after equal sign, but it would be too ugly! any idea? (the application is written in java)
thanks
A Scala implementation that avoids the deprecated getConfigList method would rely on retrieving a Seq[Configuration] as follows:
case class UserConfig(uid: Int, pwd: String)
val userConfigs: Seq[UserConfig] = configuration.get[Seq[Configuration]]("users").map { userConfig =>
UserConfig(userConfig.get[Int]("uid"), userConfig.get[String]("pwd"))
}
Since I had recently the same problem and this is still unanswered,
here is my suggestion:
List<User> users = getConfig().getConfigList("users").stream().map(
config -> new User(config.getString("uid"), config.getBoolean("pwd"))
).collect(Collectors.toList());
As far as I know there are no tuples or anything in Java, you need to use either an object or a list with two elements. I decided to go for an object here, you can also return a list.
A list of uid's sounds to me like:
# List of UID's
users=[123,456,789] // every number represents a UID
Then you can get this list as:
List<Object> uids = Play.application().configuration().getList("users");
And then do what you want with this:
for (Iterator<Object> iterator = uids.iterator(); iterator.hasNext();) {
Object object = (Object) iterator.next();
System.out.println(object);
}
Is this what you are looking for?
BTW, you can read more about Play Framework configuration options: http://www.playframework.com/documentation/2.1.0/Configuration
I'm having a problem with ArgumentCaptor not being able to record the
arguments when calling the same method a number of times.
Basically this does not seem to work:
List<Dummy> mList = mock(List.class);
Dummy dummy = new Dummy();
when(mList.get(anyInt())).thenReturn(dummy);
Dummy d = mList.get(12);
d.setName("John");
mList.add(d);
Dummy g = mList.get(10);
g.setName("Ben");
mList.add(g);
...
verify(mymock, times(3)).doStuff(captor.capture));
assertEquals("John", captor.getAllValues().get(0).getName());
assertEquals("Ben", captor.getAllValues().get(1).getName());
assertEquals("Don", captor.getAllValues().get(2).getName());
The value of getName() is always set to "Don".
I have also tried using InOrder, with the same outcome.
Feature (and me stupiud) or bug?
To better explain the issue I have created a use case:
http://pastebin.com/RE1UzJ4F
Cheers
iwein is correct; however, there are some situations (such as embedded systems) in which memory is scarce and you do not want to use or cannot use immutability.
A workaround I have found is to use a different mock for each invocation, then verify a list of mocks that each have one invocation.
List<Mock> mocks = new ArrayList<Mock>();
...init list w/ mocks using for loop...
List<Object[]> expectedArgs = new ArrayList<Object[]>();
..init list w/ desired args...
mocks.get(0).callMethod(1, 2);
...do that some more...
for(int i = 0; i < mocks.size(); i++) {
Object[] desiredArgs = expectedArgs.get(i);
verify(mocks.get(i)).callMethod((int) desiredArgs[0], (int) desiredArgs[1]);
}
It is not as pretty, but you do not have to make your classes immutable this way.
The java doc for ArgumentCaptor suggests what you are trying, so I'd say this is a bug. However, it is a bug in your code.
The problem is that you're changing the name of the same dummy each time you're invoking setName(..). I'd suggest that you make Dummy immutable and avoid setters wherever you can. That will avoid these types of bugs.
If you cannot make your Dummy immutable to force the issue you should at least pass a different instance from each get. Doing
when(mList.get(anyInt())).thenReturn(new Dummy(), new Dummy(), new Dummy());
Would fix the problem.
I had this problem and ended up using atLeastOnce, like so:
private ActionRequest getRequestedAction() {
ArgumentCaptor<ActionRequest> captor = ArgumentCaptor.forClass(ActionRequest.class);
verify(adapter, atLeastOnce()).requestAction(captor.capture());
return captor.getValue();
}