Dart how to explicitly say which package class to use? - dart

I have a Dart (Flutter) application that is making use of both the location and map_view packages. My problem is that both of these define a "Location" class.
How can I explicitly state which of the two classes I am using in any particular invocation?
e.g. I tried prefixing the class name with the package name:
location.Location = new Location();
map_view.Location = new Location(45.5231233, -122.6733130);
But Dart doesn't seem to like this syntax.

Found the answer. You have to give the libraries a prefix as per: https://www.dartlang.org/guides/language/language-tour#libraries-and-visibility
after which you can use the prefix in the class name to make it work:
import 'package:location/location.dart' as locLib;
import 'package:map_view/map_view.dart' as mapViewLib;
locLib.Location = new Location();
mapViewLib.Location = new Location(45.5231233, -122.6733130);

Related

How to use MapStruct with Grails?

I have a need in my Grails project to map objects from one type (which is typically a Map) to another type (some POGO). There are some great examples for getting this working with Boot Spring, but not a lot for Grails.
I added the following lines to my build.gradle:
compile 'org.mapstruct:mapstruct:1.4.2.Final'
compileOnly 'org.mapstruct:mapstruct-processor:1.4.2.Final'
annotationProcessor 'org.mapstruct:mapstruct-processor:1.4.2.Final'
...
compileJava {
options.annotationProcessorPath = configurations.annotationProcessor
// if you need to configure mapstruct component model
options.compilerArgs << "-Amapstruct.defaultComponentModel=spring"
}
I have a mapper defined as:
#Mapper(componentModel = "spring")
public interface AuthResponseMapper2
{
#Mapping(source = "access_token", target = "token")
#Mapping(source = "token_type", target = "type")
GetTokenResponse toGetTokenResponse(Map map);
}
However, I don't see a generated class for that mapper; when I try to use it, I get a NoSuchBeanDefinitionException. Not sure where to go from here.
Best is to check if a AuthResponseMapper2Impl class is generated by MapStruct. If it is you need to make sure that the package is scanned by Spring Boot and picked up as a component.
In addition to that mapping from Map into a POJO is currently not supported you can follow mapstruct/mapstruct#1072 for this feature request

Dart build runner generate one dart file with content

I am working on a dart package with includes over 200 models and at the moment i have to write manually one line of "export" for each model, to make the models available for everyone who uses this package.
I want the build runner to generate one dart file which contains every export definition.
Therefore I would create an annotation "ExportModel". The builder should search for each class annotated with this annotation.
I tried creating some Builders, but they will generate a *.g.dart file for each class that is annotated. I just want to have one file.
Is where a way to create a builder that runs only once and creates a file at the end ?
The short answer to your question of a builder that only runs once and creates a single file in the package is to use r'$lib$' as the input extension. The long answer is that to find the classes that are annotated you probably want an intermediate output to track them.
I'd write this with 2 builders, one to search for the ExportModel annotation, and another to write the exports file. Here is a rough sketch with details omitted - I haven't tested any of the code here but it should get you started on the right path.
Builder 1 - find the classes annotated with #ExportModel().
Could write with some utilities from package:source_gen, but can't use LibraryBuilder since it's not outputting Dart code...
Goal is to write a .exports file next to each .dart file which as the name of all the classes that are annotated with #ExportModel().
class ExportLocatingBuilder implements Builder {
#override
final buildExtensions = const {
'.dart': ['.exports']
};
#override
Future<void> build(BuildStep buildStep) async {
final resolver = buildStep.resolver;
if (!await resolver.isLibrary(buildStep.inputId)) return;
final lib = LibraryReader(await buildStep.inputLibrary);
final exportAnnotation = TypeChecker.fromRuntime(ExportModel);
final annotated = [
for (var member in lib.annotatedWith(exportAnnotation)) element.name,
];
if (annotated.isNotEmpty) {
buildStep.writeAsString(
buildStep.inputId.changeExtension('.exports'), annotated.join(','));
}
}
}
This builder should be build_to: cache and you may want to have a PostProcessBuilder that cleans up all the outputs it produces which would be specified with applies_builder. You can use the FileDeletingBuilder to cheaply implement the cleanup. See the FAQ on temporary outputs and the angular cleanup for example.
Builder 2 - find the .exports files and generate a Dart file
Use findAssets to track down all those .exports files, and write an export statement for each one. Use a show with the content of the file which should contain the names of the members that were annotated.
class ExportsBuilder implements Builder {
#override
final buildExtensions = const {
r'$lib$': ['exports.dart']
};
#override
Future<void> build(BuildStep buildStep) async {
final exports = buildStep.findAssets(Glob('**/*.exports'));
final content = [
await for (var exportLibrary in exports)
'export \'${exportLibrary.changeExtension('.dart').uri}\' '
'show ${await buildStep.readAsString(exportLibrary)};',
];
if (content.isNotEmpty) {
buildStep.writeAsString(
AssetId(buildStep.inputId.package, 'lib/exports.dart'),
content.join('\n'));
}
}
}
This builder should likely be build_to: source if you want to publish this file on pub. It should have a required_inputs: [".exports"] to ensure it runs after the previous builder.
Why does it need to be this complex?
You could implement this as a single builder which uses findAssets to find all the Dart files. The downside is that rebuilds would be much slower because it would be invalidated by any content change in any Dart file and you'd end up parsing all Dart code for a change in any Dart code. With the 2 builder approach then only the individual .exports which come from a changed Dart file need to be resolved and rebuilt on a change, and then only if the exports change will the exports.dart file be invalidated.
Older versions of build_runner also didn't support using the Resolver to resolve code that isn't transitively imported from the input library. Recent version of build_runner have relaxed this constraint.

Using class from another groovy file as a type in a Jenkins pipeline script

I'm a groovy novice, so not sure if this is possible. I need something like an import, but not quite. Here is the simplified code example of what I'm trying to do:
in file FileToProcess.groovy I have
class FileToProcess implements Serializable {
String FileName
FileToProcess(fileName) {
this.FileName = fileName;
}
}
and then in a JenkinsFile I want to do something like
F1 = new FileToProcess('A');
List<FileToProcess> allFiles = new ArrayList<FileToProcess>();
allFiles.add(F1);
​for (FileToProcess file : allFiles) {
System.out.println(file.FileName);
}
Now, on StackOverflow I've found examples of how to instantiate a class from another file, for example here or here, and that solves the line
F1 = new FileToProcess('A');
but it does not show how to use that class as a type in a declaration, for example
List<FileToProcess> allFiles = new ArrayList<FileToProcess>();
gives me "unable to resolve class FileToProcess". I also know that using a class as a type like this should work, because it does when I put the class in the same JenkinsFile, so the problem seems to be just that the class is not visible in the JenkinsFile.
Is there a way to do this?
I'm not sure how you tried to setup your class libraries but I attempted the same while using a class from a pipeline shared library and it worked as intended
https://jenkins.io/doc/book/pipeline/shared-libraries/
I did do it a little differently:
assuming you places the file under src/org/Foo.groovy
import org.Foo
def list = new ArrayList<Foo>
list.add(new Foo('str1'))
list.add(new Foo('str2'))

How to create a dynamic variable in dart

I am moving java script to dart, in java script I create dynamic variable like
window["text" + pageNumber] = 123;
alert(window["text" + pageNumber]);
How can I do it with dart?
In Dart Window (the type of window) is a class. You can't dynamically add properties to a Dart class.
window["text" + pageNumber] = 123; would work with a Map. Object representation in JS is quite similar to a map and therefore this works there.
If another class implements the [] operator you could call it on instances of that class as well but it would still not add properties. What it actually does just depends on the implementation of the [] operator.
There are probably different ways in Dart to achieve what you want, but you didn't add details about what actual problem you try to solve.
You can use normal global variables in Dart like explained in
Global Variables in Dart.
For your use case you can create a global Map variable this way
final Map<String,int> myGlobals = <String,int>{};
to create a map that stores integer values with string names.
Set values with myGlobals['someName'] = 123; and read them with print(myGlobals['someName']);.
If you need to set a global value that is also available for JS libraries you might use, you can use dart-js-interop
import 'dart:js';
import 'dart:html';
main() {
int pagenumber = 5;
context['Window']['text$pagenumber'] = 123;
window.alert('${context['Window']['text$pagenumber']}');
}
Try it on DartPad.
Hint:
"text" + pageNumber doesn't work when pageNumber is not a string.
In Dart you can't add string and numbers.
"text" + pageNumber.toString() would work but 'text$pagenumber' is a more darty way to do this. In string interpolation toString() is called automatically for you.
See also Dart js-interop not working if .dart file isn't included.

Dart 2 libraries in one lib folder causing type 'X' is not a subtype of type 'X'

I have a following problem:
In my application, I have web and lib folders.
Lib folder is supposed to contain utility libraries.
Example:
lib/my_lib.dart
library my_lib;
part 'src/person.dart';
lib/my_lib1.dart
library my_lib1;
import 'my_lib.dart';
part 'src/other.dart';
In my_lib1, I want to use classes defined in my_lib
the classes are as follows:
lib/src/person.dart
part of my_lib;
class Person {
}
lib/src/other.dart
part of my_lib1;
class Other {
Person p;
Other(this.p) {
print(p);
}
}
Now, in web/testpackage.dart
import 'package:TestPackage/my_lib.dart';
import 'package:TestPackage/my_lib1.dart';
void main() {
Person p = new Person();
Other o = new Other(p);
}
Fails with:
Exception: type 'Person' is not a subtype of type 'Person' of 'p'.
Other.Other (package:testpackage/src/other.dart:7:14)
How should I structure my project to prevent that?
My libraries are local to the app, and I don't really want to develop them separately for my toy project.
Problem in that the your library my_lib is a publiclibrary and anyone (and you, of course) can use it elsewhere outside of lib directory.
In this case it must be imported (becuase it's a public library) always as the package library.
To solve this this problem you must change your source code.
From this lib/my_lib1.dart
library my_lib1;
import 'my_lib.dart';
part 'src/other.dart';
To this lib/my_lib1.dart
library my_lib1;
import 'package:TestPackage/my_lib.dart';
part 'src/other.dart';

Resources